android开发 文件分享到应用,Android开发之——7.0适配之应用之间共享文件(FileProvider)...
前言
Android 7.0強制啟用了被稱作StrictMode的策略,帶來的影響就是你的App對外無法暴露file://類型的URI了。
如果你使用Intent攜帶這樣的URI去打開外部App(比如:打開系統相機拍照),那么會拋出FileUriException異常。
官方給出解決這個問題的方案,就是使用FileProvider:
我們來看一段代碼:
String cachePath = getApplicationContext().getExternalCacheDir().getPath();
File picFile = new File(cachePath, "test.jpg");
Uri picUri = Uri.fromFile(picFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, picUri);
startActivityForResult(intent, 100);
這是常見的打開系統相機拍照的代碼,拍照成功后,照片會存儲在picFile文件中。
這段代碼在Android7.0之前是沒有任何問題的(奇葩情況忽略),但是如果你嘗試在7.0的系統上運行,會拋出FileUriException異常。
使用FileProvider
FileProvider使用大概分為以下幾個步驟:
manifest中申明FileProvider
res/xml中定義對外暴露的文件夾路徑
生成content://類型的Uri
給Uri授予臨時權限
使用Intent傳遞Uri
我們分別看下面這幾個步驟的具體實現吧
manifest中申明FileProvider
...
...
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
...
...
android:name:provider你可以使用v4包提供的FileProvider,或者自定義你自己的,只需要在name申明就好了,一般使用系統的就足夠了。
Android:authorities:類似schema,命名空間之類,后面會用到。
Android:exported:false表示我們的providr不需要對外開發。
Android:grantUriPermissions:申明為true,你才能獲取臨時共享權限。
res/xml中定義對外暴露的文件夾路徑
新建file_paths.xml,文件名隨便起,后面會引用到。
name:一個引用字符串
path:文件夾"相對路徑",完整路徑取決于當前的標簽類型。
path可以為空,表示指定目錄下的所有文件、文件夾都可以被共享。
這個元素內可以包含一下一個或多個,具體如下:
物理路徑Context.getFilesDir()+"/path/"
物理路徑Context.getCacheDir()+"/path/"
物理路徑Environment.getExternalStorageDirectory()+"/path/"
物理路徑Context.getExternalFilesDir(String)+"/path/"
物理路徑Context.getExternalCacheDir()+"/path/"
注意:external-cache-path在support-v4:24.0.0這個版本并不支持,直到support-v4:25.0.0才支持。
番外:以上是官方提供的幾種path類型,不過如果你想使用外置SD卡,可以用這個:
物理路徑相當于/path/
這個官方文檔并沒有給出,我們可以查看源碼可以發現:
![][2]
### 編寫好file_paths.xml,我們在manifest中的provider這樣使用:
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
## 生成content://類型的Uri
我們通常通過File生成Uri的代碼是這樣:
File picFile=xxx;
Uri picUri=Uri.fromFile(picFile);
這樣生成的Uri,路徑格式為file://xxx。前面我們也說了這種Uri是無法再App之間共享的,我們需要生成content://xxx類型的Uri,方法就是通過context.getUriFromFile來實現:
File imagePath=new File(Context.getFilesDir(),"images");
File newFile=new File(imagePath,"default_image.jpg");
Uri contentUri=getUriForFile(getContext(),"com.mydmain.fleprovider",newFile);
imagePath
使用的路徑需要和你在file_paths.xml申明的其中一個符合(或者子文件夾:"images/work")。當然,你可以申明N個你需要共享的路徑:
//...
getUriForFile
第一個參數是Context;第二個參數,就是我們之前在manifest#provider中定義的android:authorities屬性的值;第三個參數是File.
給Uri授予臨時權限intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
FLAG_GRANT_READ_URI_PERMISSION:表示讀取權限;
FLAG_GRANT_WRITE_URI_PERMISSION:表示寫入權限;
你可以同時或單獨使用這兩個權限,視你的需求而定。
使用Intent傳遞Uri
以開頭的拍照代碼作為示例,需要這樣改寫:
// 重新構造Uri:content://
File imagePath = new File(Context.getFilesDir(), "images");
if (!imagePath.exists()){imagePath.mkdirs();}
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(),
"com.mydomain.fileprovider", newFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
// 授予目錄臨時共享權限
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(intent, 100);
參考:
Android 7.0適配-應用之間共享文件(FileProvider)
Android 7.0 行為變更 通過FileProvider在應用間共享文件吧
快速使用FileProvider解決Android7.0文件權限問題
Android 7.0 FileProvider的使用
總結
以上是生活随笔為你收集整理的android开发 文件分享到应用,Android开发之——7.0适配之应用之间共享文件(FileProvider)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python如何判断字典中是否存在某个键
- 下一篇: python数组 swig_python