Android7.0行為變更之適配File Provider的方法
兩個小解釋:
FileProvider是ContentProvider特殊的子類,ContentProvider通過創(chuàng)建content:// Uri來替代file:/// Uri。
在Android 7.0的以上的系統(tǒng)中,嘗試傳遞file://URI可能會觸發(fā)FileUriExposedException
FileProvider的這個概述包括以下主題:
1.定義FileProvider
2.指定可用文件
3.檢索文件的Content URI
4.授予URI的臨時權限
5.將內(nèi)容URI提供給其他應用程序
第一步:定義FileProvider:
//清單文件中 <provider android:name="android.support.v4.content.FileProvider"http://固定 android:authorities="${applicationId}.yourname"http://根據(jù)您控制的域?qū)傩栽O置為URI權限 android:exported="false"http://FileProvider不需要公開 android:grantUriPermissions="true">//允許您授予對文件的臨時訪問權限 ... </provider>
第二步:指定可用文件
//新建一個xml文件用于存放應用需要共享的目錄文件 //以下paths元素告訴FileProvider您打算為images/私有文件區(qū)域的子目錄請求內(nèi)容URI <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path name="my_images" path="images/"/> ... </paths>
該元素必須包含一個或多個以下子元素:
//代表內(nèi)部存儲空間應用私有目錄下的 files/ 目錄,等同于 Context.getFilesDir() 所獲取的目錄路徑; <files-path name = “ name ” path = “ path ” /> //代表內(nèi)部存儲空間應用私有目錄下的 cache/ 目錄,等同于 Context.getCacheDir() 所獲取的目錄路徑; <cache-path name = “ name ” path = “ path ” /> //代表外部存儲空間根目錄,等同于 Environment.getExternalStorageDirectory() 所獲取的目錄路徑; <external-path name = “ name ” path = “ path ” /> //代表外部存儲空間應用私有目錄下的 files/ 目錄,等同于 Context.getExternalFilesDir(null) 所獲取的目錄路徑; <external-files-path name = “ name ” path = “ path ” /> //代表外部存儲空間應用私有目錄下的 cache/ 目錄,等同于 Context.getExternalCacheDir(); <external-cache-path name = “ name ” path = “ path ” /> //代表外部媒體區(qū)域根目錄中的文件。等同于Context.getExternalMediaDirs()。 <external-media-path name = “ name ” path = “ path ” />
這些子元素都使用兩個相同的屬性:
name="name"
一個URI路徑段。 用于給 path 屬性所指定的子目錄名稱取一個別名 為了提高安全性,此值將隱藏您要共享的子目錄的名稱。該值的子目錄名稱包含在該 path屬性中。
path="path"
你正在分享的子目錄。雖然該name屬性是一個URI路徑段,但該path值是實際的子目錄名稱。請注意,該值是指一個子目錄,而不是獨立文件名。您無法通過文件名共享單個文件,也無法使用通配符指定文件的子集。
第三步:檢索文件的 Content URI
//使用 FileProvider 類提供的公有靜態(tài)方法 getUriForFile 生成 Content URI //第一個參數(shù):context上下文 //第二個參數(shù): Manifest 文件中注冊 FileProvider 時設置的 authorities 屬性值 //第三個參數(shù):要共享的文件,并且這個文件一定位于第二步我們在 path 文件中添加的子目錄里面 Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".myprovider", myFile);
第四步:授予URI的臨時權限
授權方式有兩種:
第一種方式:
//調(diào)用方法: //參數(shù)1:授權訪問 URI 對象的其他應用包名 //參數(shù)2:授權訪問的 Uri 對象 //參數(shù)3:授權類型FLAG_GRANT_READ_URI_PERMISSION 或者 FLAG_GRANT_WRITE_URI_PERMISSION (或者二者同時授權。這種形式的授權方式,權限有效期截止至發(fā)生設備重啟或者手動調(diào)用 revokeUriPermission() 方法撤銷授權時) grantUriPermission(package, Uri, mode_flags)
第二種方式:
//配合intent使用 //權限有效期截止至其它應用所處的堆棧銷毀,并且一旦授權給某一個組件后,該應用的其它組件擁有相同的訪問權限。 Intent.setFlags() 或者 Intent.addFlags() Intent.setData(Uri uri);
第五步:將內(nèi)容URI提供給其他應用程序
//通過以下方法啟動其他應用并傳遞授權過的 Content URI 數(shù)據(jù)。當然,也有其他方式提供服務。 startActivity()
或者
startActivityResult()
或者
setResult()
官方原文(需要自備梯子,想自己搭的教程點擊這里): Google Develpers - FileProvider
以下是一個我這邊的例子:
場景:版本更新完成時打開新版本 apk 文件實現(xiàn)自動安裝
//在 res/xml 目錄下新建一個filepath文件 并指定子目錄路徑信息 <?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="external_path" path="."/> <cache-path name="cache_path" path="."/> </paths>
//Manifest 文件中注冊 FileProvider 對象,并鏈接上面的 path 路徑文件 <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.xxx.FileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepath"/> </provider>
//授權 打開安裝管理器安裝apk包 Intent intent = new Intent(Intent.ACTION_VIEW); intent.addCategory("android.intent.category.DEFAULT"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); Uri uri = UriUtil.getUriForFile(BitZApplication.mContext.get(), new File((String) msg.obj)); intent.setDataAndType(uri, "application/vnd.android.package-archive"); startActivity(intent); //UriUtil工具類: public static Uri getUriForFile(Context context, File file) { if (context == null || file == null) { throw new NullPointerException(); } Uri uri; if (Build.VERSION.SDK_INT >= 24) { uri = FileProvider.getUriForFile(context, "com.xxx.FileProvider", file); } else { uri = Uri.fromFile(file); } return uri; }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Android使用ContentProvider初始化SDK庫方案小結(jié)
- 基于Android FileProvider 屬性配置詳解及FileProvider多節(jié)點問題
- Android ContentProvider實現(xiàn)手機聯(lián)系人讀取和插入
- Android利用ContentProvider獲取本地數(shù)據(jù)的方法
- Android7.0中關于ContentProvider組件詳解
- Android 中自定義ContentProvider與ContentObserver的使用簡單實例
- Android 中ContentProvider的實例詳解
- Android控件AppWidgetProvider使用方法詳解
- Android編程之桌面小部件AppWidgetProvider用法示例
- Android實現(xiàn)花瓣飄落效果的步驟
相關文章
Android開發(fā)使用RecyclerView添加點擊事件實例詳解
這篇文章主要為大家介紹了Android開發(fā)使用RecyclerView添加點擊事件實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08android 選項卡(TabHost)如何放置在屏幕的底部
如何將TAB放置在屏幕的底端,有很多的新手都想實現(xiàn)這種效果,本文搜集整理了一些,感興趣的朋友可以參考下哦2013-01-01Android Studio設置顏色拾色器工具Color Picker教程
這篇文章主要介紹了Android Studio設置顏色拾色器工具Color Picker教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03Flutter 利用CustomScrollView實現(xiàn)滑動效果
我們可以使用ListView將幾個GridView組合在一起實現(xiàn)了不同可滑動組件的粘合,但是這里必須要設置禁止 GridView 的滑動,防止多個滑動組件的沖突。這種方式寫起來不太方便,事實上 Flutter 提供了 CustomScrollView 來粘合多個滑動組件,并且可以實現(xiàn)更有趣的滑動效果。2021-06-06Android 8.0不能自動安裝APK問題的解決方法(完美適配)
這篇文章主要給大家介紹了關于Android 8.0不能自動安裝APK問題的解決方法(完美適配),這里的自動安裝是指下載完成后,自動彈出安裝界面,而不是靜默安裝APK,文中介紹的非常詳細,需要的朋友可以參考下2018-07-07Kotlin之在Gradle中無參(no-arg)編譯器插件的使用詳解
這篇文章主要介紹了Kotlin之在Gradle中無參(no-arg)編譯器插件的使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11Android Studio自動排版的兩種實現(xiàn)方式
這篇文章主要介紹了Android Studio自動排版的兩種實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03