🐈

[Android][kotlin]ExoPlayerでキャッシュ領域の音源データが再生できなくって困った話

に公開

FileProvider って仕組みのせいらしい。
Android には ExoPlayerという動画再生やら音源再生やらに便利なライブラリがあって、なのにキャッシュ領域のファイルはだんまりで再生できないという。

Abstruct

  • FileProvider の使い方

背景

ダウンロードした音源ファイルはキャッシュ領域にコピーして使うことにしよう。という方針で開発してた時の話。ExoPlayerでキャッシュ領域のmp4を再生しても、全然再生が始まらない。FileUriExposedException が発生してたらしい。

修正内容

下記2点を追加することで再生できるようになった。

1. AndroidManifest.xmlにproviderタグの追加

下記呪文を追記。中身はよくわかってない。。。
※android:authoritiesの部分はアプリ毎につど変更。

AndroidManifest.xml
    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:enableOnBackInvokedCallback="true"
        android:theme="@style/Theme.VideoPhotoBook">

+       <provider
+           android:name="androidx.core.content.FileProvider"
+           android:authorities="com.tks.videophotobook.fileprovider"
+           android:exported="false"
+           android:grantUriPermissions="true">
+           <meta-data
+               android:name="android.support.FILE_PROVIDER_PATHS"
+               android:resource="@xml/file_paths" />
+       </provider>

        <activity

2. res/xml配下に file_paths.xml を追加

パス設定を追加

file_paths.xml
 <?xml version="1.0" encoding="utf-8"?>
 <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-cache-path name="external_cache" path="." />
    <cache-path name="cache" path="." />
 <!-- <external-path name="images" path="Pictures/" /> 外部ストレージのPicturesを公開するときはこれも有効化-->
 </paths>

3. Kotlinコードで使う時

val file = File(context.cacheDir, "sample.png")
val uri: Uri = FileProvider.getUriForFile(context,"${context.packageName}.fileprovider",file)
/* ↑"content://"始まりのURIになる */

4. 他アプリにIntentで渡すとき

val intent = Intent(Intent.ACTION_SEND).apply {
    type = "image/png"
    putExtra(Intent.EXTRA_STREAM, uri)
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) /* ←忘れやすい */
}
startActivity(Intent.createChooser(intent, "共有"))

25.10.04追記

build.gradle.tksに下記が追加されてた。FileProviderを使うなら必要らしい。 
FileProviderがlegacyって。。。

implementation(libs.androidx.legacy.support.v4)

役に立ちますように。。。

Discussion