Androidアプリのバックアップ・リストア 辺りを試してみた

後半の技術系のメモ追記はする予定

キッカケ的なこと

昔の端末 Nexsus7 2013 に入っていた

絶版マンガ図書館 の「馬頭ちーめい先生」のブレイクエイジ が読みたくなって

今使ってるZenfone端末に移動していました*1

今は制度が変わって

というのに変わってるんですけど、

  • マネタイズの為に
    • 毎日100ページのみ読める*2
    • さらに読みたければ課金してください
    • または広告経由でアプリインストールしてポイントを得てください
    • 完全オフラインで読み切りならpdfを300円で購入してください

な形なんですよね・・。

このアプリ、未だに

  • 内蔵ストレージのみサポート
  • バックアップ機能はなし
    • 基本端末別にデータをダウンロードさせる*3

な形なんで、フリーミアムモデル って大変なんだなーと


実際のバックアップ作業

Helium

アプリケーションプライベート領域のデータをバックアップするためのソフト

adb backup を内部で使用しているらしい。

詳細な使い方は

を使えば、PCレスにできそうですけど あれAndroid5 までしか端末内にadbコマンドが存在しないしな〜(汗

Android 6端末以降に adbのNDKバイナリみたいなのを導入する方法はないものか。。

保存先は内部の方が良いよう

  • 其の場合、下記の位置に保存されます
    • 内蔵ストレージ/carbon

SDのコンテンツデータ関係(本データ)

最近色々とOSのバージョンアップごとに、SD関係の権限が弄られているため

内蔵ストレージ/Download/jcomiPlusContents

みたいな形で

Downloadフォルダの中に作られていたりしてるのが現状だったりします*5

ShareLink で転送

でファイル転送可能

転送先は下記に転送されているようです

  • 内蔵ストレージ/carbon
    • 転送先の端末にも Helium を入れておく *7
    • Helium を使ってリストア
  • 内蔵ストレージ/jcomiPlusContents.
    • Filerアプリ等では左記に移動 => 内蔵ストレージ/Download/jcomiPlusContents

領域区分ってなんでしたっけ?

名称 説明 関数
アプリケーション領域 /data/data/<パッケージ名> Activity::getFilesDir
内部ストレージ(Top) /storage Environment ::getExternalStorageDirectory
内部ストレージ(アプリ) /storage/<パッケージ名> Environment::getExternalFilesDir
外部ストレージ(一般的なディレクトリ) /storage/sdcard/ ExternalEnvironment::getStoragePublicDirectory
外部ストレージ(TOP) /storage/sdcard Environment::getExternalStorageDirectory
外部ストレージ(アプリ) /storage/sdcard/Android/data/<アプリのパッケージ名> Context.getExternalFilesDirs
  • 外部ストレージ(アプリ) のみ Android5以上であれば権限確認は要らない。

    • ない場合は 内部ストレージ(アプリ) のディレクトリパスが取得できる形らしい(Android4.4から)
  • ようは内部ストレージって、

    • 昔SDカードが必須だったアプリを動かすためのエミュレーション処理
    • linuxマウントしていますからシームレスに使えますよ
    • でも getExternalFilesDirsの0番目を大概指定しているアプリが多いから
      • 内蔵ストレージが自動的に使われると
File[] dirs = getExternalFilesDirs(null);

// =>
// dirs[0].path() == /storage/emulated/0/Android/data/<パッケージ名>/files
// dirs[1].path() == /storage/ext_sd/Android/data/<パッケージ名>/files

SD権限って今どうなってるの?

基本記述

  • AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)){
     //書き込み可能
}

辺りの判定は基本変わらず。

Android 4.4から

SDカード上の「アプリのパッケージ固有フォルダ」

<SDカードのパス>/Android/data/<アプリのパッケージ名>
  • 下記の感じでアクセスする感じ
if (Build.VERSION.SDK_INT >= 19) {
    File[] extDirs = getExternalFilesDirs(Environment.DIRECTORY_DOWNLOADS);
    Log.d(TAG, extDirs[extDirs.length-1].toString());
    String extSdDirPath = extSdDir.getAbsolutePath();
}

Android 5から

Storage Access Framework 経由が必須 *8

  • よくセキュリティ的にiOSと比較されて叩かれるネタなので、

    • google標準端末もSDは基本載せない傾向にあるかな
    • キャリア端末は、CPUアップ、内蔵ストレージ少なめなのでSD対応は必須のはずなんだけど??
      • 日本固有の問題扱いにされているんだろうか??

低スペック端末判定といえば

ActivityManagerCompat.isLowRamDevice()

が Android5辺りで提供されていましたが*9

ココらへんの対応とかもう捨て去ってるような感じなんでしょうか。。

Android 7から

SD上のユーザディレクトリのアクセスに関しても

FileProviderの設定が必須 *10

inthecheesefactory.com

developer.android.com

yuki312.blogspot.jp

ファイル共有とかってどうなってるんでしたっけ?

ShareActionProvider

6系からはこっち使わないと推奨挙動ではないみたいです。

ShareCompat

中身はIntent発行しているだけなので微妙かも。

特に規定設定のチェック入れると、外し方がわからないという苦情を過去経験したことあったな。。(遠い目

デフォルトに設定したアプリを解除できるアプリとかありますが

どのアプリ/アクション に対して規程設定したのかわからないのは基本みたいorz

  • ファイルを添付して転送する共有処理
Intent intent = new Intent();
//intent.setPackage("com.android.bluetooth"); //bluetoothとかアプリを限定したい時☆

//複数ファイル送る時
// 単一なら intent.setAction(Intent.ACTION_SEND);
intent.setAction(Intent.ACTION_SEND_MULTIPLE);

// ArraryList<Uri> files   
// Uri uri = Uri.fromFile(sendFile) 
// ファイル単一なら intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, files);

intent.setType("image/*");//textなら text/plain
//startActivity(Intent.createChooser(intent, "select some pic"));//毎回選択させる☆
startActivity(intent);

メールとかにも添付可能にするなら

intent.putExtra(Intent.EXTRA_EMAIL, new String[] {"test@exsample.com"});
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
intent.putExtra(Intent.EXTRA_TEXT, "test");

辺りを付与

独自共有候補を作る方法

面白そうなのでメモ

qiita.com

疑問に思っていること

  • Intent.ACTION_SEND とか使っても共有アプリ一覧に出てこないアプリが有る
  • 設定しても添付(候補に出てこない)できないアプリ候補には出てくるか受信時にエラーになる場合の差分が不明*11
    • OKなアプリ
    • NGなアプリ
      • IPMsg

SDとかに書き出していても駄目ですし

AssetFileProvider/FileProvider とか専用の物を使わないと駄目なのでしょうか?

ここらへんは調査が必要かなと

*1:専用ファイル形式なので、他のアプリで読めない

*2:毎回通信してるっぽくて結構エラー終了が多いらしい

*3:アカウント登録で本棚情報参照は出来るようになったようですが。。<汗

*4:アプリ起動時に起動していないと、アプリの操作ができない

*5:アプリケーション固有フォルダは4.4から、4.3とか対応する為しかたない?

*6:Mac版はないです。ASUSのヘルプページにいくとAndroid Transfer使えと書いてある

*7:転送先でHeliumインストーラ+復元 なバックアップ方法も有るようなんですが<汗

*8:SAF自体は Android4.4からある

*9:メーカ側がOSの設定値に設定。インド向けとかの廉価版低スペック端末用のフラグらしい

*10:上記のアプリディレクトリに関しても

*11:受信側アプリの対応が必要??