android App更新7.0許可權
public void InstallApk(){ String filePath = getExternalFilesDir("Download").getAbsolutePath() + File.separator+"軟體名稱"+mVersion+".apk"; Intent install = new Intent(Intent.ACTION_VIEW); if(Build.VERSION.SDK_INT>=24) {//判讀版本是否在7.0以上 Uri apkUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID+".fileprovider", new File(filePath)); install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//新增這一句表示對目標應用臨時授權該Uri所代表的檔案 install.setDataAndType(apkUri, "application/vnd.android.package-archive"); }else { install.setDataAndType(Uri.parse("file://"+filePath), "application/vnd.android.package-archive"); install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } startActivity(install); }
1.1 定義一個FileProvider
直接使用FileProvider
本身或者它的子類,需要在AndroidManifest.xml
檔案中宣告元件的相關屬性,包括:
android:name
,對應屬性值:android.support.v4.content.FileProvider
或者子類完整路徑android:authorities
,對應屬性值是一個常量,通常定義的方式packagename.fileprovider
,例如:cn.teachcourse.fileprovider
android:exported
,對應屬性值是一個boolean變數,設定為false
android:grantUriPermissions
,對應屬性值也是一個boolean變數,設定為true
,允許獲得檔案臨時的訪問許可權
<manifest>
...
<application>
...
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.mydomain.fileprovider" android:exported="false" android:grantUriPermissions="true">
...
</provider>
...
</application>
</manifest>
想要關聯res/xml
資料夾下建立的file_provider.xml
檔案,需要在<provider>
標籤內,新增<meta-data>
子標籤,設定<meta-data>
標籤的屬性值,包括:
android:name
,對應屬性值是一個固定的系統常量android.support.FILE_PROVIDER_PATHS
android:resource
,對應屬性值指向我們的xml檔案@xml/file_provider
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.mydomain.fileprovider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_provider"/>
</provider>
1.2 指定授予臨時訪問許可權的檔案目錄
上一步說明了怎麼定義一個FileProvider
,這一步主要說明怎麼定義一個@xml/file_provider
檔案。Android Studio或Eclipse開發工具建立Android專案的時候預設不會建立res/xml
資料夾,需要開發者手動建立,點選res
資料夾新建目錄,命名xml
,如下圖:
然後,在xml
資料夾下新建一個xml檔案,檔案命名file_provider.xml
,指定根標籤為paths
,如下圖:
在xml檔案中指定檔案儲存的區塊和區塊的相對路徑,在<paths>
根標籤中新增<files-path>
子標籤(稍後詳細列出所有子標籤),設定子標籤的屬性值,包括:
name
,是一個虛設的檔名(可以自由命名),對外可見路徑的一部分,隱藏真實檔案目錄path
,是一個相對目錄,相對於當前的子標籤<files-path>
根目錄<files-path>
,表示內部記憶體卡根目錄,對應根目錄等價於Context.getFilesDir()
,檢視完整路徑:/data/user/0/cn.teachcourse.demos/files
- 程式碼如下:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="my_images" path="images/"/>
...
</paths>
<paths>
根標籤下可以新增的子標籤也是有限的,參考官網的開發文件,除了上述的提到的<files-path>
這個子標籤外,還包括下面幾個:
<cache-path>
,表示應用預設快取根目錄,對應根目錄等價於getCacheDir()
,檢視完整路徑:/data/user/0/cn.teachcourse.demos/cache
<external-path>
,表示外部記憶體卡根目錄,對應根目錄等價於Environment.getExternalStorageDirectory()
,
檢視完整路徑:/storage/emulated/0
<external-files-path>
,表示外部記憶體卡根目錄下的APP公共目錄,對應根目錄等價於Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)
,
檢視完整路徑:/storage/emulated/0/Android/data/cn.teachcourse.demos/files/Download
<external-cache-path>
,表示外部記憶體卡根目錄下的APP快取目錄,對應根目錄等價於Context.getExternalCacheDir()
,檢視完整路徑:/storage/emulated/0/Android/data/cn.teachcourse.demos/cache