Android 7.0 FileProvider 使用說明

FileProvider

FileProvider 這個組件在Android 22.0.0 (也就是 Android 5.0 ) 版本下加入進Android系統,該組件是ContentProvider的子類,功能就是用來提供文件在跨進程間的訪問能力。你們千萬不要以爲是Android 7.0 才加入進來的。html

爲何Android 7.0 文件共享要使用FileProvider

這個緣由是由於,Android 7.0 版本之後,對於StrictMode的審查又嚴格了一步,就如在Android 3.0之後加入的NetWorkOnMainThread的異常同樣,Google對於會對Android系統形成體驗或者安全問題的部分會使用嚴格模式來限制程序開發者。 
對於文件訪問在Android 7.0之前可使用file://uri的方式訪問,可是這個地方有個問題,就是即便不是你自身應用產生的文件,只要知道對方的uri則就能夠調用到,這樣在安全性上就產生了風險。因此Android 7.0後新增了對文件跨進程訪問的限制,這個限制會形成,若是使用file://uri的方式訪問,則會出現android.os.FileUriExposedException的異常。java

FileProvider 使用

Step 1 AndroidManifest ,註冊FileProvider

 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
      <application
          ...>
          <provider
              android:name="android.support.v4.content.FileProvider"
              android:authorities="org.unreal.update"
              android:grantUriPermissions="true"
              android:exported="false">
              <meta-data
                  android:name="android.support.FILE_PROVIDER_PATHS"
                  android:resource="@xml/update_files" />
          </provider>
          ...
      </application>
  </manifest>

 

須要注意的地方是 
android:authorities 參數,如同ContentProvider,此處須要你提供一個uri的authorities,以便於content://android:authorities/uri訪問到,android:authorities能夠隨意定義android

Step 2 res下建立xml文件夾,並在xml文件夾下建立update_files.xml

<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <paths>
        <files-path path="files" name="files" />
        <cache-path path="files" name="cache" />  
        <external-path path="files" name="external" />
        <external-files-path path="files" name="externalfiles"/>
        <!-- 此標籤須要 support 25.0.0以上纔可使用-->
        <external-cache-path  path="files" name="externalcache"/>  
    </paths>
</resources>

 

name:名稱標誌字符串,不能夠同名! 
path:文件夾「相對路徑」,完整路徑取決於當前的標籤類型。安全

標籤 路徑
…….. * 表明 當前文件夾及其子文件夾
file-path 物理路徑爲Context.getFilesDir() + /files/*
cache-path 物理路徑爲Context.getCacheDir() + /files/*
external-path 物理路徑爲Environment.getExternalStorageDirectory() + /files/*
external-files-path 物理路徑爲Context.getExternalFilesDir(String) + /files/*
external-cache-path 物理路徑爲Context.getExternalCacheDir() + /files/*

在簡書看到 zhuhf 大神的關於FileProvider的文章後,發現還有一個隱藏的標籤app

文章地址: http://www.jianshu.com/p/55eae30d133cide

<root-path name="name" path="path" />

 

標籤 路徑
…….. * 表明 當前文件夾及其子文件夾
root-path 物理路徑至關於 /path/*

Step 3 經過getUriForFile獲取到uri

data = FileProvider.getUriForFile(context,"以前在AndroidManifest中配置的android:authorities", "7.0後文件的路徑");
// 給目標應用一個臨時受權
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
               | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

 

FLAG_GRANT_READ_URI_PERMISSION:表示讀取權限; 
FLAG_GRANT_WRITE_URI_PERMISSION:表示寫入權限; 
根據你的需求,是讀取呢,仍是寫入自行選擇ui

例子 安裝APK

private void installApk(File apk) {
        if (!apk.exists()) {
            return;
        }
        Uri data;
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // UpdateConfig.FILE_PROVIDER_AUTH 便是在清單文件中配置的authorities
            data = FileProvider.getUriForFile(context, UpdateConfig.FILE_PROVIDER_AUTH, apk);
            // 給目標應用一個臨時受權
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        } else {
            data = Uri.fromFile(apk);
        }
        intent.setDataAndType(data, "application/vnd.android.package-archive");
        context.startActivity(intent);
        android.os.Process.killProcess(android.os.Process.myPid());
    }
相關文章
相關標籤/搜索