Android で Application.persistentDataPath が返す値が Write Acces によって変わるので調べました。
Unity 5.3.6 で返すパスに仕様変更があるので、Unity 5.3.6 までのバージョンで作成したアプリケーションの Unity 5.3.6 以降へのバージョンアップには気をつけないとデータが消える恐れがあります。
手元にある Android 端末と Unity 4.7.2f1 と 5.3.6f1 で検証しました。
Application.persistentDataPath
永続的なデータディレクトリのパス。
セーブデータなどのユーザーデータを保存する場所。
https://docs.unity3d.com/jp/current/ScriptReference/Application-persistentDataPath.html
Player Settings / Write Access
Internal Only を指定しても開発環境と本番環境で Application.persistentDataPath が異なる値を返す可能性があるので注意です!
外部記憶装置なら特に権限を必要としないで読み込み出来るのでデバッグしやすいからかも?
External (SDCard) に設定すると、SD カードなどの外部記憶装置への書き込みアクセスを可能にします。開発ビルド (Development Build) では、自動的に有効化されます。
https://docs.unity3d.com/jp/current/Manual/class-PlayerSettingsAndroid.html
External Storage
外部ストレージと呼ばれる領域でも SD カードではない取り外しの出来ない内蔵のストレージを参照している端末もある。
Android 4.4 以降は権限を要求することなく外部ストレージへの読み書きが出来る。
Windows PC に例えると
古い Android 端末
Cドライブ: 内蔵ドライブ (Android 内部ストレージ)
Dドライブ: USB 接続の外付けハードディスク (Android 外部ストレージ)
新しい Android 端末
Cドライブ: 内蔵ドライブ パーティション 0 (Android 内部ストレージ)
Dドライブ: 内蔵ドライブ パーティション 1 (Android 外部ストレージ)
Eドライブ: USB 接続の外付けハードディスク (Android 外部ストレージ)
すべての Android 互換端末は、ファイルの保存先として共有の「外部ストレージ」をサポートしています。 これは、リムーバブル ストレージ メディア(SDカードなど)か、(取り外しできない)内部ストレージです。 https://developer.android.com/guide/topics/data/data-storage.html?hl=ja#filesExternal
Android 4.4 以降、アプリのプライベート ディレクトリにあるファイルの読み取りや書き込みの際は、READ_EXTERNAL_STORAGE または WRITE_EXTERNAL_STORAGE のパーミッションは不要になりました。
https://developer.android.com/guide/topics/data/data-storage.html?hl=ja#AccessingExtFiles
一部の端末では、永続的なストレージ領域を「内部」と「外部」のパーティションに分割しており、リムーバブル記憶媒体が備わっていない場合でも常に 2 つのストレージ スペースがあり、外部ストレージが取り外し可能であるか否かにかかわらず、API の動作は同じです。
https://developer.android.com/training/basics/data-storage/files.html?hl=ja#InternalVsExternalStorage
Unity 5.3.6 での仕様変更
Android: Application.temporaryCachePath and Application.persistentDataPath always return external paths starting KITKAT. (789870)
https://unity3d.com/jp/unity/whats-new/unity-5.3.6
KITKAT は Android 4.4 のコードネーム。
Android 4.4 以降は、Write Access の値に関わらず外部ストレージのパスを返すように仕様変更。
Android 4.4 以降は権限を要求することなく読み書きが出来るからだろう。
Player Settings / Write Access 毎の Application.persistentDataPath の値
Write Access: Internal Only
Unity 4.7.2
Android | Path | 実体 |
---|---|---|
4.1.2 (200SH) | /data/data/{package name}/files/ | 内部ストレージ |
4.2.2 (SO-02F) | /data/data/{package name}/files/ | 内部ストレージ |
5.0.2 (HTV31) | /data/data/{package name}/files/ | 内部ストレージ |
6.0.1 (SCV31) | /data/user/0/{package name}/files/ -> /data/data/{package name}/files/ | 内部ストレージ |
Unity 5.3.6
Android | Path | 実体 |
---|---|---|
4.1.2 (200SH) | /data/data/{package name}/files/ | 内部ストレージ |
4.2.2 (SO-02F) | /data/data/{package name}/files/ | 内部ストレージ |
5.0.2 (HTV31) | /storage/emulated/0/Android/data/{package name}/files/ | 外部ストレージ |
6.0.1 (SCV31) | /storage/emulated/0/Android/data/{package name}/files/ | 外部ストレージ |
Write Access: External (SDCard)
Unity 4.7.2
Android | Path | 実体 |
---|---|---|
4.1.2 (200SH) | /storage/sdcard0/Android/data/{package name}/files/ | SD カード |
4.2.2 (SO-02F) | /storage/emulated/0/Android/data/{package name}/files/ | 外部ストレージ |
5.0.2 (HTV31) | /storage/emulated/0/Android/data/{package name}/files/ | 外部ストレージ |
6.0.1 (SCV31) | (Permissions Storage: ALLOW) /storage/emulated/0/Android/data/{package name}/files/ | 外部ストレージ |
6.0.1 (SCV31) | (Permissions Storage: DENY) /data/user/0/{package name}/files/ -> /data/data/{package name}/files/ | 内部ストレージ |
Unity 5.3.6
Android | Path | 実体 |
---|---|---|
4.1.2 (200SH) | /storage/sdcard0/Android/data/{package name}/files/ | SD カード |
4.2.2 (SO-02F) | /storage/emulated/0/Android/data/{package name}/files/ | 外部ストレージ |
5.0.2 (HTV31) | /storage/emulated/0/Android/data/{package name}/files/ | 外部ストレージ |
6.0.1 (SCV31) | (Permissions Storage: ALLOW) /storage/emulated/0/Android/data/{package name}/files/ | 外部ストレージ |
6.0.1 (SCV31) | (Permissions Storage: DENY) /storage/emulated/0/Android/data/{package name}/files/ | 外部ストレージ |
結果
Write Access: External (SDCard) を指定すると androidmanifest.xml に外部ストレージへの読み書き権限の要求が追記されます。
WRITE_EXTERNAL_STORAGE 権限で読み込みも出来る。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
WRITE_EXTERNAL_STORAGE を追記した場合、 Android 6 以降、Permissions Storage の問で ALLOW を選択するまでは起動するたび問われる。
ALLOW を選択後も、 Application の設定から Permissions Storage 許可の変更は可能。
4.1.2 (200SH): Write Access: External (SDCard) だけが SDカードのパスを返した。
SDカードを抜いた場合、Internal Only と同じパスを返した。
その他は内臓のストレージを参照。
Unity 4.7.2 Android 6.0.1 は、 Permissions Storage の許可の有無で返すパスが変わる。
Unity 5.3.6 Android 4.4 以降は、Permissions Storage の許可の有無によらず返す値は同じ。
Unity 4.7.2 で作成したアプリケーションで Application.persistentDataPath に保存したデータは Unity 5.3.6 で作成したアプリケーションで上書きした場合、読み込めるか?
internal-storage: /data/data/{package name}/files/
external-storage: /storage/emulated/0/Android/data/{package name}/files/
Android 4.1.2 (200SH)
Unity 4.7.2 Write Access | Unity 5.3.6 Write Access | 読み込めるか? | 挙動 |
---|---|---|---|
Internal Only | Internal Only | ○ | |
Internal Only | External (SDCard) | ☓ | |
External (SDCard) | Internal Only | ☓ | UnauthorizedAccessException: Access to the path "/storage/sdcard0/Android/data/{package name}/files/{file name}" is denied. external-storage を internal-storage にコピーしようとして失敗? |
External (SDCard) | External (SDCard) | ○ |
Android 4.2.2 (SO-02F)
Unity 4.7.2 Write Access | Unity 5.3.6 Write Access | 読み込めるか? | 挙動 |
---|---|---|---|
Internal Only | Internal Only | ○ | |
Internal Only | External (SDCard) | ☓ | |
External (SDCard) | Internal Only | ☓ | UnauthorizedAccessException: Access to the path "/storage/sdcard0/Android/data/{package name}/files/{file name}" is denied. external-storage を internal-storage にコピーしようとして失敗? |
External (SDCard) | External (SDCard) | ○ |
Android 5.0.2 (HTV31)
Unity 4.7.2 Write Access | Unity 5.3.6 Write Access | 読み込めるか? | 挙動 |
---|---|---|---|
Internal Only | Internal Only | ○ | |
Internal Only | External (SDCard) | ☓ | |
External (SDCard) | Internal Only | ☓ | UnauthorizedAccessException: Access to the path "/{file name}" is denied. external-storage を internal-storage にコピーしようとして失敗? |
External (SDCard) | External (SDCard) | ○ |
Android 6.0.1 (SCV31)
Unity 4.7.2 Write Access | Unity 5.3.6 Write Access | 読み込めるか? | 挙動 |
---|---|---|---|
Internal Only | Internal Only | ○ | internal-storage を external-storage へコピー |
Internal Only | External (Permissions Storage: ALLOW) | ☓ | |
Internal Only | External (Permissions Storage: DENY) | ○ | internal-storage を external-storage へコピー |
External (Permissions Storage: ALLOW) | Internal Only | ○ | 同じパス |
External (Permissions Storage: ALLOW) | External (Permissions Storage: ALLOW) | ○ | 同じパス |
External (Permissions Storage: ALLOW) | External (Permissions Storage: DENY) | ○ | 同じパス |
External (Permissions Storage: DENY) | Internal Only | ○ | internal-storage を external-storage へコピー |
External (Permissions Storage: DENY) | External (Permissions Storage: ALLOW) | ☓ | |
External (Permissions Storage: DENY) | External (Permissions Storage: DENY) | ○ | internal-storage を external-storage へコピー |
結果
Internal Only, External (Permissions Storage: DENY) のときは、internal-storage を external-storage へコピーした後に読み込む挙動となっていた。
external-storage へ変更を加えても internal-storage はコピー時点のまま変更は加わらなかった。
まとめ
Internal Only -> External (SDCard) への変更は、データが引き継がれない場合がある。その場合、自前で /data/data/{package name}/files/ をコピーするなどの対応が必要。
External (SDCard) -> Internal Only への変更は古い Android 端末で正常に処理が行われない可能性がある。
Android 6 以降は、Unity 4.7.2 の Write Access がどちらの値でも、Unity 5.3.6 の Write Access: Internal Only にしておけば引き続きデータの読み書きは出来る。