gpt4 book ai didi

Android 10 - 找不到处理 Intent 的 Activity

转载 作者:行者123 更新时间:2023-12-02 14:27:15 24 4
gpt4 key购买 nike

我的第 3 方应用程序可以让最终用户从我们的服务器下载更新的 APK,然后应用程序将在下载完成后调用该 APK 上的安装包管理器。同样的方法适用于所有版本的 Android 操作系统,但现在它会在 Android 10 (api 29) 上崩溃。我还没有看到任何人有类似的问题,任何帮助将不胜感激!

以下是我在应用程序中调用 APK 文件的方法:

Intent intent = new Intent(Intent.ACTION_VIEW);
final File apkFile = new File(Files.getApkFileName());
Log.v("dt.update", "Start update from " + apkFile.getAbsolutePath());
intent.setDataAndType(Uri.fromFile(apkFile), application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

这是每次返回的堆栈跟踪,仅在 Android 10/API29 上:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.MyAppHere, PID: 11107
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=file:///storage/emulated/0/Download/updatedapp.apk typ=application/vnd.android.package-archive flg=0x10000000 }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2051)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1709)
at android.app.Activity.startActivityForResult(Activity.java:5192)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:676)
at android.app.Activity.startActivityForResult(Activity.java:5150)
at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:663)
at android.app.Activity.startActivity(Activity.java:5521)
at android.app.Activity.startActivity(Activity.java:5489)
at android.view.View.performClick(View.java:7140)
at android.view.View.performClickInternal(View.java:7117)
at android.view.View.access$3500(View.java:801)
at android.view.View$PerformClick.run(View.java:27351)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

最佳答案

ACTION_VIEW(适用于 APK)和 ACTION_INSTALL_PACKAGE 在 Android 10 中已弃用。您需要切换到 PackageInstaller API。

This sample app演示安装简单 APK 的基础知识。核心位于MainMotor:

/*
Copyright (c) 2019 CommonsWare, LLC

Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
by applicable law or agreed to in writing, software distributed under the
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.

Covered in detail in the book _Elements of Android Q

https://commonsware.com/AndroidQ
*/

package com.commonsware.q.appinstaller

import android.app.Application
import android.app.PendingIntent
import android.content.Intent
import android.content.pm.PackageInstaller
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

private const val NAME = "mostly-unused"
private const val PI_INSTALL = 3439

class MainMotor(app: Application) : AndroidViewModel(app) {
private val installer = app.packageManager.packageInstaller
private val resolver = app.contentResolver

fun install(apkUri: Uri) {
viewModelScope.launch(Dispatchers.Main) {
installCoroutine(apkUri)
}
}

private suspend fun installCoroutine(apkUri: Uri) =
withContext(Dispatchers.IO) {
resolver.openInputStream(apkUri)?.use { apkStream ->
val length =
DocumentFile.fromSingleUri(application, apkUri)?.length() ?: -1
val params =
PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
val sessionId = installer.createSession(params)
val session = installer.openSession(sessionId)

session.openWrite(NAME, 0, length).use { sessionStream ->
apkStream.copyTo(sessionStream)
session.fsync(sessionStream)
}

val intent = Intent(application, InstallReceiver::class.java)
val pi = PendingIntent.getBroadcast(
application,
PI_INSTALL,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)

session.commit(pi.intentSender)
session.close()
}
}
}

当 Activity 或 fragment 调用 install() 并向 APK 提供 Uri 时,我使用 PackageInstaller 来安装它:

  • PackageManager 获取 PackageInstaller
  • 创建一个 SessionParams 并从中打开一个 session
  • 将 APK 的字节(从 UriInputStream 读取)写入该 session 提供的 OutputStream
  • 调用 commit() 以实际开始安装过程,并将结果通过 PendingIntent 传送回应用
  • 调用close()关闭 session

该 API 很笨重,但它旨在处理各种场景,包括“App Bundle”式多 APK 安装。

关于Android 10 - 找不到处理 Intent 的 Activity,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58085899/

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