gpt4 book ai didi

带有 Intent.VIEW_ACTION 的 Android 安装 apk 不适用于文件提供程序

转载 作者:IT老高 更新时间:2023-10-28 13:25:50 24 4
gpt4 key购买 nike

我的应用有一个自动更新功能,可以下载一个 APK,当下载完成后,一个 Intent.VIEW_ACTION 打开应用并让用户安装下载的 apk

Uri uri = Uri.parse("file://" + destination);
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.setDataAndType(uri,
manager.getMimeTypeForDownloadedFile(downloadId));
activity.startActivity(install);

这适用于所有设备 <24

现在使用 Android 24 显然我们不再允许使用 file:///启动 Intent ,并且在谷歌搜索后建议使用 A File Provider

新代码:

Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri apkUri = FileProvider.getUriForFile(AutoUpdate.this,
BuildConfig.APPLICATION_ID + ".provider", file);
install.setDataAndType(apkUri,
manager.getMimeTypeForDownloadedFile(downloadId));
activity.startActivity(install);

现在 activity.startActivity(install);报错

No Activity found to handle Intent { act=android.intent.action.VIEWdat=content://com.xxxx.xx.provider/MyFolder/Download/MyApkFile.apktyp=application/vnd.android.package-archive flg=0x4000000 }

有什么方法可以在 Android 7 (24) 中打开 APK 查看器?

最佳答案

经过大量尝试,我已经能够通过为低于 Nougat 的任何内容创建不同的 Intent 来解决此问题,就像在 Nougat 导致错误之前使用 FileProvider 创建具有 Android 版本的安装 Intent :

ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.INSTALL_PACKAGE dat=content://XXX.apk flg=0x1 }

在 Android Nougat 上使用普通 Uri 时会产生以下错误:

FileUriExposedException: file:///XXX.apk exposed beyond app through Intent.getData()

我的解决方案适用于模拟器上的 Android N 和运行 Android M 的手机。

File toInstall = new File(appDirectory, appName + ".apk");
Intent intent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri apkUri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".fileprovider", toInstall);
intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(apkUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
Uri apkUri = Uri.fromFile(toInstall);
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
activity.startActivity(intent);

Android Nougat 7.1 更新:

您还需要在 list 中添加权限 REQUEST_INSTALL_PACKAGES。它从 Api Level 23 (Android 6.0 Marshmallow) 开始可用,并且需要从 Level 25 (Android 7.1 Nougat) 开始。

更新:

如果您尝试安装的文件在外部存储上,请记住请求对外部存储的读写权限。并为 Android Nougat 及更高版本设置正确的 FileProvider。

先调用下面的canReadWriteExternal()检查你是否有写权限,如果之前没有调用requestPermission():

private static final int REQUEST_WRITE_PERMISSION = 786;

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Toast.makeText(this, "Permission granted", Toast.LENGTH_LONG).show();
}

private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
requestPermissions(new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
}

private boolean canReadWriteExternal() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
}

以下是外部存储上下载文件夹的文件提供程序示例。 AndroidManifest.xml:

<application ... >
...

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

resources/xml/filepaths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_download" path="Download"/>
</paths>

如果您在安装 .apk 时遇到错误,例如“解析软件包时出现问题”。可能是您没有请求读/写权限,或者您尝试安装的文件不存在或已损坏。

Android Oreo 8.0 更新:

您必须检查当前应用程序是否允许在 Android Oreo 8.0 或更高版本上安装 APK。

您可以使用 canRequestPackageInstalls 检查您的应用是否允许安装 APK PackageManager 类的方法。如果它返回 false,那么您可以使用 ACTION_MANAGE_UNKNOWN_APP_SOURCES 启动 Intent 启动设置对话框的操作,用户可以在其中允许应用安装 APK。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O 
&& !getPackageManager().canRequestPackageInstalls()) {
Intent unknownAppSourceIntent = new Intent()
.setAction(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
.setData(Uri.parse(String.format("package:%s", getPackageName())));

unknownAppSourceDialog.launch(unknownAppSourceIntent);
} else {
// App already have the permission to install so launch the APK installation.
startActivity(intent);
}

确保将以下代码添加到您的 Activity 中以接收 Intent 结果。

ActivityResultLauncher<Intent> unknownAppSourceDialog = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
// User has allowed app to install APKs
// so we can now launch APK installation.
startActivity(intent);
}
});

关于带有 Intent.VIEW_ACTION 的 Android 安装 apk 不适用于文件提供程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39147608/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com