1. 程式人生 > >Android7.0版本更新無法安裝apk

Android7.0版本更新無法安裝apk

許可權

   在適配7.0手機的時候,發現部分手機下載到最新版本以後,無法自動安裝問題.

   通過查詢才發現, 在AndroidAPI23以後, 部分許可權要動態獲取. 也就是說在下載前需要動態獲取檔案的讀寫許可權,在小米5適配出現這樣問題

   從前幾屆谷歌大會,我們可以知道, 隨著android版本越高 , android對於移動裝置隱私的保護力度越來越大, 從Android6.0引入動態許可權控制到Android7.0的"私有目錄被限制訪問", 這些改變為使用者帶來更加安全的使用者體驗, 同時也給開發帶來了一些新的要求. 

目錄限制訪問

    在目錄及檔案的訪問和保護方面,Android比IOS要做的不夠好. 我們知道在android應用中可以可以隨意讀寫手機儲存中任意檔案, 但是這些帶來了很多的安全問題,比如:由於私有檔案許可權放權給所有的應用程式, 我們在使用和 

MODE_WORLD_WRITEABLE許可權時會觸發異常(SecurityException)

適配7.0

    1.在AndroidManifest.xml檔案中新增如下程式碼

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="{應用程式的包名}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>

</provider>

注意:

name: provider可以使用V4包提供FileProvider, 或者自己定義

    authorities: app的包名.fileprovider

    exported: 必須是false 表示provider不需要對外開放

    grantUriPermissions: 必須設定為true, 表示授予URL臨時訪問許可權

2. 在res->xml下建立file_path.xml檔案

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="files_root"
        path="Android/data/{應用程式的包名}/" />
    <external-path
        name="external_storage_root"
        path="." />

</paths>

注意:

path: 需要臨時授權訪問的路徑(.代表所有的路徑)

name: 表示給訪問路徑起的名字

path節點的區別:

    <root-path/>: 可以訪問儲存卡中的資料

    <files-path/>: 代表根目錄: Context.getFilesDir()

    <external-path/>: 代表根目錄: Environment.getExternalStorageDirectory()

    <cache-path/>: 代表根目錄: getCacheDir()

如果要想了解path的詳細用法,大家可以搜一下,講的更加詳細, 本文只作簡單解釋

3. 在下載完成啟動安裝進行適配不同的安裝包的開啟方式

File file = new File(apkPath);//更新包檔案

 Intent intent = new Intent();

intent.setAction(Intent.ACTION_VIEW);

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

// Android7.0及以上版本

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

Uri contentUri = FileProvider.getUriForFile(context, "應用包名" + ".fileProvider", file);//引數二:應用包名+".fileProvider"(和步驟中的Manifest檔案中的provider節點下的authorities對應)

intent.setDataAndType(contentUri, "application/vnd.android.package-archive");

 } else {

// Android7.0以下版本

 intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

}

 context.startActivity(intent);

如果有地方寫的不對的,歡迎各位同仁指正