代碼還原與註釋
// ========== APK 安裝/啟動 ==========
// 1. 獲取目標包名
String packageName = apkInfos.get(position).packageName;
// 2. 獲取該包的「啟動 Intent」(MAIN/LAUNCHER Activity)
Intent launchIntent = packageManager.getLaunchIntentForPackage(packageName);
if (launchIntent == null) {
// 無啟動 Activity (可能是 Service-only、Library、或被禁用)
Log.d(TAG, "Cannot get launch intent for: " + packageName);
return;
}
// 3. 關閉當前對話框,啟動目標 App
dialog.dismiss();
startActivity(launchIntent); // 隱式啟動,系統解析最佳匹配
// ========== APK 協載 ==========
// 1. 構造 package: scheme Uri
Uri packageUri = Uri.fromParts("package", packageName, null);
// 2. 創建 ACTION_DELETE Intent,系統會彈出確認協載對話框
Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageUri);
dialog.dismiss();
startActivity(uninstallIntent);
核心 API 解析
| API | 作用 | 關鍵點 |
PackageManager.getLaunchIntentForPackage() |
返回該應用的 MAIN/LAUNCHER Activity Intent |
若應用無 Launcher Activity 或被禁用,返回 null |
Uri.fromParts("package", pkg, null) |
生成 package:com.example.app Uri |
標準協載/應用詳情頁 Uri 格式 |
Intent.ACTION_DELETE |
觸發系統協載流程 |
需用戶確認,不可靜默協載 (需系統簽名/ROOT) |
Intent.ACTION_VIEW + package: Uri |
打開應用詳情頁 (設置頁) |
替代舊版 ACTION_APPLICATION_DETAILS_SETTINGS |
進階:靜默安裝/協載 (需特殊權限)
// 安裝 (Android 6.0+ 需 REQUEST_INSTALL_PACKAGES 權限 + 文件提供者)
Intent installIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
installIntent.setData(fileUri); // FileProvider 生成的 content:// Uri
installIntent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
installIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
startActivityForResult(installIntent, REQUEST_INSTALL);
// 協載 (需 android.permission.DELETE_PACKAGES 系統簽名權限,普通 App 不可用)
pm.deletePackage(packageName, observer, 0);
常見坑與最佳實踐
- ❌ 直接用
new Intent(Intent.ACTION_MAIN).setPackage(pkg)
- 無法保證啟動 Launcher Activity,可能進入非入口頁面。
- ❌ 協載後不刷新列表
- 監聽
Intent.ACTION_PACKAGE_REMOVED 廣播更新 UI。
- ✅ 文件提供者 (FileProvider) 適配 Android 7.0+
- 安裝/分享文件必須用
content:// Uri,禁止 file://。
- ✅ 判斷應用是否已安裝
pm.getPackageInfo(pkg, 0) != null 或 pm.getLaunchIntentForPackage(pkg) != null。