androidアプリのストレージ戦略
TRANSCRIPT
Standard Strategy
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="internalOnly"... >
内部ストレージへのインストールを推奨(デフォルト値)※API Level 8を懐かしむページです
Standard Strategy
・Service・Alarm Service・IME・Account Manager・Sync Adapters・Device Administrators・listening for "boot completed"
外部ストレージへのインストールでは次の機能は動きませんし、いまは誰もやってません
Q. どうしても外部ストレージが使いたいです。SDカードへのアクセスはこうやるんですか?
/sdcard/mnt/sdcard/mnt/sdcard/external_sd/storage/sdcard0
牧歌的。
Standard Strategy
private void createNewFile() {Intent intent = new Intent(
Intent.ACTION_CREATE_DOCUMENT);intent.setType("text/plain");intent.putExtra(Intent.EXTRA_TITLE,
"Untitled.txt");startActivityForResult(intent,
CREATE_DOCUMENT_REQUEST);}
ファイルを作る
Standard Strategy
private void save(Uri uri, String text) throws FileNotFoundException, IOException {
OutputStream outputStream = null;try {
outputStream = getContentResolver().openOutputStream(uri);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
writer.write(text);writer.flush();
} finally {IOUtil.forceClose(outputStream);
}}
書き込む
拡張ストレージ
マルチユーザ対応にあたり、ユーザごとに独立した拡張ストレージが必要に。いままではシングルユーザのため、ファイル構造が見えていても問題なかった。現在はPC接続時にUSBデバイス(MTP)として表示。音楽や動画、写真、データを置く。デバイス上のプライマリストレージ
WRITE_EXTERNAL_STORAGE適用範囲
外部ストレージ
デバイス上のセカンダリストレージ基本的にはUSBメモリのようなポータブルストレージが対象。
アクセスは制限。Storage AccessFramework経由のみ許可
機密データは置けない
Standard Strategy
Context.getExternalFilesDirs()Context.getExternalCacheDirs()Context.getObbDirs()
Android 4.4~では複数の拡張ストレージに対応
Standard Strategy
Android 6.0~ではUSBメディアのサポートも開始
Storage Access Frameworkで制御可能(外部ストレージとして)
direct access is explicitly blocked for privacy and security reasons.
SDカードの内部ストレージ化
暗号化およびフォーマットされ、製品のライフサイクルに組み込まれるかわりに内部ストレージとして使える(アプリのインストール可能)
フォーマットはext4, f2fs
SDカード好きすぎでは…
Standard Strategy
アプリのプライベートディレクトリにアクセス制限(700)を追加
所有者でも緩和できないMODE_WORLD_READBLEやMODE_WORLD_WRITEBLEを使うとSecurityExeptionが発生
Standard Strategy
自身のアプリ外への file:// URI の公開を禁止する StrictModeが適用
ファイルURIを含むIntentはFileUriExposedExceptionになる
FileProviderで回避
Scoped Directory Access
StorageManager sm = (StorageManager)getSystemService(Context.STORAGE_SERVICE);
StorageVolume volume = sm.getPrimaryStorageVolume();
Intent intent = volume.createAccessIntent(
Environment.DIRECTORY_PICTURES);startActivityForResult(intent, request_code);
ディレクトリを直接呼び出す
similar to using URIs returned by the Storage Access Framework.
Q. つまりどういうことですか?
ざっくりと
内部 拡張 外部フォーマット Ext4, f2fs exFATなどアクセス File IO Storage Access Frameworkアプリから見た公開度
private private public
public
マルチユーザ対応 OK OK NG
Q. バックアップ用途でSDカードは向いているのですか?
一長一短です。小さければShared PreferencesにしてBackupオプションを使うと楽です。サーバがあればインターネットの向こう側も楽ですが基本的にアプリ以外で同じ苦労をしているに過ぎません
選択肢は多い
Q. SDカードのマウント状態はわかりますか?
EnvironmentにAPIがあります結局ファイル制御なのでR/Wのエラーハンドリングをきっちりするといいでしょう
信頼性は低い