19
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Unity Application.persistentDataPath のパスは Android のバージョンと Write Access によって異なる。

Last updated at Posted at 2017-03-17

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-storageinternal-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-storageinternal-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-storageinternal-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-storageexternal-storage へコピー
Internal Only External (Permissions Storage: ALLOW)
Internal Only External (Permissions Storage: DENY) internal-storageexternal-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-storageexternal-storage へコピー
External (Permissions Storage: DENY) External (Permissions Storage: ALLOW)
External (Permissions Storage: DENY) External (Permissions Storage: DENY) internal-storageexternal-storage へコピー

結果

Internal Only, External (Permissions Storage: DENY) のときは、internal-storageexternal-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 にしておけば引き続きデータの読み書きは出来る。

19
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?