Android N 通過Intent安裝APK

圖片發(fā)自簡書App

封面圖還是要有的

之前使用Intent 安裝APK文件,使用下面的代碼可以直接調(diào)起安裝界面。

public void installAPK(Context context, File apkFile){
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setDataAndType(Uri.fromFile(apkFile),"application/vnd.android.package-archive");
    context.startActivity(intent);
}

最近把targetSdkVersion升級到了26才發(fā)現(xiàn)app在Android 8.0的手機上無法正常安裝,一查才知道從Android N(也就是Android API 24)開始直接執(zhí)行上面的代碼會報android.os.FileUriExposedException異常,需要使用FileProvider來處理對Content URI讀取的臨時授權(quán)問題。直接上解決方案

首先,需要在AndroidManifest.xml文件中的<application>標簽中定義FileProvider

<application>
    ...
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:exported="false"
        android:grantUriPermissions="true"
        android:authorities="com.mrtrying.installappdemo.fileprovider">
        ...
    </provider>
    ...
</application>

注意:這里<provider>標簽中的android:authorities為設(shè)置授權(quán)的URI,一般都是授權(quán)自己app包名下的fileprovider,也就是應(yīng)用包名.fileprovider;而android:exported屬性為false則表示該FileProvider不是需要是公共的。另外,android:grantUriPermissions屬性為true表示允許給文件臨時訪問權(quán)限。

然后,在res/xml目錄下定義一個apk_path.xml文件,內(nèi)容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="apk_path"
        path="."/>
</paths>

<paths>中必須有子元素,這里使用<external-path>標簽對應(yīng)的是使用Environment.getExternalStorageDirectory()路徑,name屬性則是名稱,path則是表示臨時授權(quán)的子目錄路徑(不是單個文件),使用.表示所有路徑,這個可以根據(jù)需求添加。

將定義好的apk_path.xml文件通過<meta-data>添加到之前在AndroidManifest.xml文件中定義的<provider>中,將<meta-data>標簽的android:resource屬性設(shè)置為@xml/apk_path

<provider
    android:name="android.support.v4.content.FileProvider"
    android:exported="false"
    android:grantUriPermissions="true"
    android:authorities="com.mrtrying.installappdemo.fileprovider">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/apk_path"/>
</provider>

最后,只需要在代碼中使用FileProvider來獲取URI就大功告成了

public void installAPK(Context context, File apkFile){
    Intent intent = new Intent(Intent.ACTION_VIEW);
    Uri uri;
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        //第二個參數(shù)需要與<provider>標簽中的android:authorities屬性相同
        uri = FileProvider.getUriForFile(this,"com.mrtrying.installappdemo.fileProvider",apkFile);
    }else{
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        uri = Uri.fromFile(apkFile);
    }
    intent.setDataAndType(uri ,"application/vnd.android.package-archive");
    context.startActivity(intent);
}

FileProvider的使用可以參考官方文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容