使用系統(tǒng)多媒體界面需要在我們的應(yīng)用和其他應(yīng)用之間通過Intent傳遞音頻、圖片、視頻文件的信息。隨著Android版本的升級(jí),對(duì)應(yīng)用數(shù)據(jù)安全性方面的限制越來越多。
Android 6以后不允許應(yīng)用在外部存儲(chǔ)隨便創(chuàng)建目錄,只能在Android規(guī)定的應(yīng)用自己的文件目錄下創(chuàng)建目錄,該目錄可以用方法getExternalFilesDir(null)來獲得,其實(shí)際位置為:
? ? ? ? Android/data/<package-name>/files/
Android 7以前的版本可以直接使用“file://”格式的uri在應(yīng)用之間傳遞文件信息,格式為:
? ? ? ? file:// + <路徑> + <文件>
例如:file:///storage/emulated/0/Android/data/com.zzk.a1501systemactivity/files/test/audio.acc
Android 7及更高版本使用了更嚴(yán)格的文件分享模式,禁止開發(fā)人員在應(yīng)用外部以 “file://”格式的uri分享應(yīng)用自己目錄下的文件,否則會(huì)出現(xiàn) FileUriExposedException 異常。如果需要向其他應(yīng)用公開應(yīng)用自己目錄下的文件,需要使用FileProvider。
FileProvider是ContentProvider的一種,格式為:
? ? ? ? content:// + <FileProvider名>+<路徑別名>+<文件>
由于采用別名代替了實(shí)際路徑,避免了直接暴露文件位置,所以更加安全。例如:
? ? ? ? content://com.zzk.a1501systemactivity.fileProvider/testdir/audio.aac
使用FileProvider向其他應(yīng)用傳遞文件需要以下步驟:
- 聲明FileProvider
- 編寫一個(gè)xml文件,列出共享目錄和別名
- 生成Content URI
- 授予對(duì)方應(yīng)用訪問權(quán)限
- 提供Content URI給其他應(yīng)用
下面我們具體解釋一下這幾個(gè)步驟。
FileProvider需要在應(yīng)用配置文件AndroidManifest中聲明,和ContentProvider的聲明類似。例如:?
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
聲明中name屬性為FileProvider對(duì)應(yīng)的Java類(androidx.core.content.FileProvider),已經(jīng)在Android庫中存在,不用自己編寫。authories一般采用應(yīng)用包名+“.fileProvider”保證唯一性。meta-data中的FILE_PROVIDER_PATHS指定一個(gè)名為file_paths.xml的文件,在該文件中聲明要傳遞的文件所在路徑的別名。這個(gè)xml文件位于res/xml/目錄下,內(nèi)容類似于:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path
name="testdir"
path="test"/>
</paths>
這里聲明了一個(gè)testdir,實(shí)際對(duì)應(yīng)的路徑為external-files-path代表的 /Android/data/com.zzk.a1501systemactivity/files/ 路徑下的test目錄。
除了<external-files-path>標(biāo)簽外,還可以使用下面的標(biāo)簽:
- <root-path>: 設(shè)備根目錄/
- <files-path>: context.getFilesDir()的目錄
- <cache-path>:context.getCacheDir()的目錄
- <external-path>:Environment.getExternalStorageDirectory()的目錄
- <external-files-path>:ContextCompat.getExternalFilesDirs()下標(biāo)為0的目錄
- <external-cache-path>:ContextCompat.getExternalCacheDirs()下標(biāo)為0的目錄
- <external-media-path>:context.getExternalMediaDirs()下標(biāo)為0的目錄
接下來是生成Content URI,需要使用 FileProvider 類提供的公有靜態(tài)方法 getUriForFile 生成 Content URI。比如:
Uri uri = FileProvider.getUriForFile(MainActivity.this, fileProviderAuthority, audioFile);
getUriForFile方法的第一個(gè)參數(shù)是上下文;第二個(gè)參數(shù)是FileProvider的authorities,需要和配置文件中聲明FileProvider時(shí)給出的定義(android:authorities="${applicationId}.fileProvider")相同,一般采用“<應(yīng)用包名>.fileProvider”以保證唯一性。第三個(gè)參數(shù)是要傳遞的文件。文章來源:http://www.zghlxwxcb.cn/news/detail-620414.html
接下來就可以把該uri放到Intent中,再授予對(duì)方讀/寫權(quán)限,就可以傳遞給其他應(yīng)用使用了。示例代碼如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-620414.html
Intent intent = new Intent(Intent.ACTION_VIEW); // 創(chuàng)建intent
intent.setDataAndType(uri, "audio/*"); // 把文件的Content URI放入intent
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 授予對(duì)方讀取文件的權(quán)限
startActivity(intent); // 傳遞給其他應(yīng)用
到了這里,關(guān)于Android多媒體功能開發(fā)(2)——FileProvider的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!