首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Android 6.0+ 安裝 APK 閃退問題:FileProvider 適配與 Intent Flags 完整解決方案

     編輯:Java 綜合教學

現象:Android 6.0 (API 23) 以上調用系統安裝器閃退,4.4 (API 19) 正常

原始代碼使用 `file://` Uri 直接啟動 `ACTION_VIEW`,Android 7.0+ 強制要求 `FileProvider` 生成 `content://` Uri,否則拋出 `FileUriExposedException` 導致崩潰。

錯誤代碼

public static void install(Context context, String filePath) {
    Intent i = new Intent(Intent.ACTION_VIEW);
    i.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive");
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(i);
}

根本原因

  • Android 7.0 (API 24) 強制執行 `StrictMode`,禁止跨進程傳遞 `file://` Uri。
  • 系統安裝器包名變更:API ≤ 22 `com.android.packageinstaller`,API ≥ 23 `com.google.android.packageinstaller`(部分廠商定制不同)。
  • 直接指定 `setComponent` 兼容性極差,不推薦。

標準解決方案:FileProvider + Grant Uri Permission

1. 配置 FileProvider(AndroidManifest.xml)

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

2. 定義共享路徑

<!-- res/xml/file_paths.xml -->
<paths xmlns:android="https://schemas.android.com/apk/res/android">
    <files-path name="apk" path="." /> <!-- Context.getFilesDir() -->
    <cache-path name="apk_cache" path="." /> <!-- Context.getCacheDir() -->
    <external-files-path name="apk_ext" path="." /> <!-- Context.getExternalFilesDir(null) -->
</paths>

3. 正確的安裝代碼(兼容 Android 7.0+)

public static void installApk(Context context, File apkFile) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 關鍵:授予臨時讀取權限
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    Uri apkUri;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 7.0+
        apkUri = FileProvider.getUriForFile(context,
                context.getPackageName() + ".fileprovider", apkFile);
    } else {
        apkUri = Uri.fromFile(apkFile);
    }
    intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
    context.startActivity(intent);
}

進階:Android 8.0+ (API 26) 未知來源應用安裝權限

Android 8.0 引入「安裝未知應用」權限,需引導用戶開啟:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    boolean hasPermission = context.getPackageManager()
            .canRequestPackageInstalls();
    if (!hasPermission) {
        // 跳轉到設置頁面
        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
        intent.setData(Uri.parse("package:" + context.getPackageName()));
        context.startActivity(intent);
        return; // 等用戶返回再重試
    }
}

參考資源

總結檢查清單

  1. Manifest 註冊 FileProvider,authorities 唯一(建議 `${applicationId}.fileprovider`)。
  2. xml/file_paths.xml 覆蓋 APK 存儲目錄(files、cache、external)。
  3. Intent 添加 `FLAG_GRANT_READ_URI_PERMISSION`。
  4. 7.0+ 使用 `FileProvider.getUriForFile`,舊版本 `Uri.fromFile`。
  5. 8.0+ 檢查 `canRequestPackageInstalls` 引導授權。
  6. 測試覆蓋:API 19、23、24、26、28、30+ 主流機型。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved