判断android 7.0之后的版本,android7.0之后版本,FileProvider適配問題

前言:這是我的第一篇博客,之前一直有寫博客的想法,不知道從何下手而一直往后拖,近來因為一些原因越來越意識到自己的知識的不足,終於下定決心彌補,希望通過堅持寫博客能給自己一些提高。本文是前兩個月遇到的情況,更新APP的時候在一些系統7.0以上的手機會崩潰,所以花了一上午的時間研究,在此再做記錄。

概述

android7.0中有一些新的變化,(官方文檔),例如多窗口的支持,FileProvider等等,今天我們只對FileProvider做講解,這也是我們在開發過程中必須要做的適配。

在7.0以上系統的手機上,Android框架執行的StrictMode API政策禁止在應用外部公開file//URI;傳遞file://URI會報出FileUriExposedException異常。如果要在應用間共享文件,應發送一項content//URI,最簡單的方式就是使用FileProvider類。

使用方法

1,在ManiFest中的的節點中注冊一個FileProvider,因為FileProvider是ContentProvider的子類;

94dd99017a79d16bcbf4beb96f63a118.png

name:配置當前FileProvider的實現類,一般為固定的。也可以寫繼承FileProvider的實現類

authorities:配置一個FileProviderde 名字,必須是當前系統內的唯一值,一般為【包名+字符串】(例:com.example.demo.customName,如上圖格式會自動引用gradle中的applicationId)

exported:表示該FileProvider是否需要公開,一般不需要,本人測試:必須false否則拋異常

grantUriPermissions:是否允許授權的文件臨時訪問權限,本人測試:必須true否則拋異常

2,配置可分享的文件的路徑

name:是固定的,

resource:需要在res目錄下新建xml文件夾,這里指向xml文件夾下的provider_paths文件,此文件的根節點為paths;

paths 標簽內,必須配置最少一個 xxx-path 標簽

//path=""---------表示為當前指定目錄 如下:

//root-path:表示根目錄,『/』。

//files-path:表示 content.getFileDir() 獲取到的目錄。

//files-path:表示 content.getFileDir() 獲取到的目錄。

//files-path:表示 content.getFileDir() 獲取到的目錄。

//files-path:表示 content.getFileDir() 獲取到的目錄。

//external-cache-path:表示 ContextCompat.getExternalCacheDirs() 獲取到的目錄

3,使用content:// 調用FileProvider.getUriForFile()

/**@param context 上下文對象

*@param authority 這里是前面在 AndroidManifest.xml 中 配置的 android:authorities 。

*@param file 要獲取URI的file對象

*/

Fileprovider.getUriForFile(Context context,String authority,File file)

// 調用此方法,會自動得到一個 file:// 轉換成 content:// 的 一個 Uri 對象,可以供我們直接使用。

生成的 Content URI 是這樣的

content://com.example.demo.customName/*****

host 部分為 元素的 authorities 屬性值(applicationId + customname),

path 片段為 res/xml 文件中指定的子目錄別名

4,授予臨時讀寫的權限

在配置 provider 標簽的時候,有一個屬性 android:grantUriPermissions=”true” ,它表示允許它授予 Uri 臨時的權限。

當我們生成出一個 content:// 的 Uri 對象之后,其實也無法對其直接使用,還需要對這個 Uri 接收的 App 賦予對應的權限才可以。

授權類型的常量,被定義在 Intent 類中。

授權的方式分為兩種:

使用Context.grantUriPermission() 為其他 App 授予 Uri 對象的訪問權限。

/****

*

*@param toPackage 表示授予權限的 App 的包名。

*@param uri 授予權限的 content:// 的 Uri。

*@param modeFlags 讀寫權限。

*/

@Override

public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {

super.grantUriPermission(toPackage, uri, modeFlags);

}

//這種情況下,授權的有效期限,從授權一刻開始,截止於設備重啟或者手動調用 Context.revokeUriPermission() 方法,才會收回對此 Uri 的授權。

示例代碼:(此處借鑒鴻洋大神的圖片 博客—->)

80505fc25ab4ad3f93b2fd42de274b98.png

配合 Intent.addFlags() 授權。 setFlags() == addflags()

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

示例代碼:

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.setAction("android.intent.action.VIEW");

intent.addCategory("android.intent.category.DEFAULT");

Uri data;

// 判斷版本大於等於7.0

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

data = FileProvider.getUriForFile(context,"com.example.demo.fileprovider", file);

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |

Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

} else {

data = Uri.fromFile(file);

}

一旦授權,直到該 App 被完全退出,這段時間內,該 App 享有對此 Uri 指向的文件的對應權限,我們無法再主動收回此權限

常見使用場景

1,自動安裝文件

2,調用系統相機拍照

3,調用系統裁剪

總結:終於完成了第一篇技術博客,發現真心不容易,在這里向各位堅持寫博客的大佬致敬,本人也會堅持寫下去,努力提升自己的水平,不拖android開發工程師的后腿。

由於本人水平有限,代碼可能會出現超出本人認知范圍的Bug,歡迎各位大佬批評指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值