主な用途はGooglePlayを経由しない社内アプリなど。
Intent経由でインストーラ呼び出し
Intent経由でインストーラを呼び出せるのでこれを利用する。
// ファイルパス val file: File = File(getExternalFilesDir(""), "test.apk") // ファイルのURI val uri: Uri = FileProvider.getUriForFile( applicationContext, BuildConfig.APPLICATION_ID + ".provider", file ) // インストーラ呼び出し val intent = Intent(Intent.ACTION_VIEW) intent.setDataAndType(uri, "application/vnd.android.package-archive") intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION startActivity(intent)
基本的にデータタイプapplication/vnd.android.package-archiveへファイルのUriを渡してフラグに読み書き権限を付与すれば良い。
Intentに渡すファイルUriはFileProvider.getUriForFileを使用するがAndroid7以降からファイルアクセスの制限がキツくなったためアクセス許可が必要になる。
FileProviderを利用して一時的にアクセス許可をおこなう
FileProviderとはURI経由でアプリ間のファイルアクセスの許可をおこなう仕組み。
インストーラからAPKをインストールするにはAPKへアクセスできるようにする必要がある。
AndroidManifest.xml
application内に以下を追記。<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.provider" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_path" /> </provider>
android:authoritiesはFileProvider.getUriForFileの第2引数と一致させること。
android:resourceのみ変更可能(↓で作成するファイル名を指定する)
app/src/main/res/xml/provider_path.xml
アクセス許可するディレクトリを指定する。
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="name" path="./" /> </paths>
対象ディレクトリは大きく6種類。
https://developer.android.com/reference/androidx/core/content/FileProvider?hl=ja
files-path
Context.getFilesDir()で指定されるディレクトリcache-path
getCacheDir()で指定されるディレクトリexternal-path
外部ストレージのルートディレクトリEnvironment.getExternalStorageDirectory()で指定される。
external-files-path
外部ストレージのアプリのルートディレクトリ。Context.getExternalFilesDir(null)で指定される。
具体的には
ログ出力した場合 /storage/emulated/0/Android/data/パッケージ名/files
Device File Explorerから確認した場合 /sdcard/Android/data/パッケージ名/files/
となる。
今回はこれを使用する。
外部雨ストレージの詳細については以下にまとめている
https://trueman-developer.blogspot.com/2022/09/android10kotlin.html
external-cache-path
外部ストレージのアプリのキャッシュディレクトリ。
Context.getExternalCacheDir()で指定される。
アプリ更新目的なら一時領域のこちらを使用する方が良いかもしれない。
external-media-path
アプリの外部メディア領域のルートディレクトリ。Context.getExternalCacheDir()で指定される。
API21以降のみ。
nameは任意。
pathはサブディレクトリ名を指定する。ルート直下の場合は"./"を指定する。
以上でアプリアップデートの仕組みは実装可能。
初回のみ「この提供元のアプリを許可」を手動でオンにする必要がある。
参考
https://developer.android.com/reference/kotlin/androidx/core/content/FileProvider
https://developer.android.com/training/secure-file-sharing/setup-sharing?hl=ja
http://enjoy-rfid.blogspot.com/2019/03/google-playandroid.html
https://azunobu.hatenablog.com/entry/2019/06/27/120908
https://www.ninton.co.jp/archives/2745