1. 程式人生 > >Android7.0及以上下載後自動安裝無法執行

Android7.0及以上下載後自動安裝無法執行

在最近的專案中,用到了下載新版然後自動安裝更新的功能,但是發現在7.0手機上無法正常安裝,查閱資料,發現在android 7.0的行為變更中有說明,檔案共享發生了變化(自動安裝就是系統的安裝程式呼叫本專案的檔案,等同於在跨應用訪問資料)

對於面向 Android 7.0 的應用,Android 框架執行的 StrictMode API 政策禁止在您的應用外部公開 file:// URI。
如果一項包含檔案 URI 的 intent 離開您的應用,則應用出現故障,並出現 FileUriExposedException 異常。

要在應用間共享檔案,您應傳送一項 content:// URI,並授予 URI 臨時訪問許可權。
進行此授權的最簡單方式是使用 FileProvider 類。如需瞭解有關許可權和共享檔案的詳細資訊,請參閱共享檔案。 --摘自Android developer

這需要你在要共享的檔案的專案中的AndroidManifest中進行配置


        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="建議是包名.fileprovider"
android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" <!--這裡配置一個xml檔案,寫明要共享的資料夾,也就是你要安裝的apk的所在資料夾--> android:resource="@xml/provider_paths"
/> </provider>

上面的xml檔案配置如下

<?xml version="1.0" encoding="utf-8"?>
<resource xmlns:android="http://schemas.android.com/apk/res/android">
    <paths>
        <!--
        我的檔案放在內部快取目錄,所以用的cache-path 
        path  代表該路徑下的子資料夾,如果apk不是直接在快取目錄,
        而是在快取目錄下一級的目錄中就要寫明,否則可以為空-->
        <!--
        external-path 為外部儲存路徑
        files-path 為內部儲存路徑
        name的值就像是一個常量,代表這path填寫的路徑,可以在請求資料Uri拼接使用,比如cotent://xxxx/download
        就等於content://xxxx/(path裡的內容)
        -->
        <cache-path path="" name="download"/>
    </paths>
</resource>

注意:FileProvider來自於V4包,需要引入相關包
在自動安裝的程式碼中就可以使用了

 File apkFile = new File(this.getCacheDir() + File.separator+apkName); //這是我的檔案路徑,各自根據自己的寫
 if(Build.VERSION.SDK_INT>=24) {//判讀版本是否在7.0以上
            Uri apkUri = FileProvider.getUriForFile(this, "com.example.holo.beikong.fileprovider"
            , apkFile);//在AndroidManifest中的android:authorities值
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            install.setDataAndType(apkUri, "application/vnd.android.package-archive");
            startActivity(install);
        } else{
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(install);
        }