PackageInstaller 失败后不调用 OnNewIntent
OnNewIntent is not called after PackageInstaller failure
我使用此代码安装 APK:
我的 activity 启动模式设置为 SingleTop。我从 OnActivityResult 调用 InstallPackageAndroidQAndAbove(我需要在此之前卸载应用程序,然后检查它是否已在那里卸载)。我还修改了该代码以在创建 PendingIntent
对象期间传递 PendingIntentFlags.UpdateCurrent
标志。问题是当 APK 成功安装或安装程序等待用户操作时,OnNewIntent 总是被正确调用,然后我做了一些事情。但是当用户中止安装时,不会调用 OnNewIntent(尽管偶尔会调用它)。我找不到任何关于这种行为的信息。我怎样才能解决这个问题?或者它可能与我正在调试的设备有关(小米 9T Pro 和基于 Android 10 的 MIUI 12)?
我需要在应用安装失败时显示警告对话框并停止进程。作为一种解决方法,我使用 StartActivityForResult,然后在 OnActivityResult 中等待 5 秒并检查是否安装了应用程序。但是这个解决方法当然是不好的,因为如果安装时间超过 5 秒,那么尽管应用程序本身将被安装,但无论如何都会显示警告对话框。
如你所见,为了确保你的OnNewIntent
被调用,你必须在[=14]的创建过程中传递这个标志:PendingIntent.FLAG_UPDATE_CURRENT
=] 对象。因此,如果您按照您分享的示例进行操作,则:
PendingIntent pendingIntent = PendingIntent.GetActivity(activity, 0, intent, 0);
应该是这样的:
PendingIntent pendingIntent = PendingIntent.GetActivity(activity, 0, intent, PendingIntentFlags.UpdateCurrent);
我的解决方法比我的问题中描述的要好得多。这仍然是一种解决方法,因为我找不到对这种奇怪行为的解释。
我唯一需要的实际上是通知安装失败。我声明了一个继承 PackageInstaller.SessionCallback
的 class。它看起来像这样:
public class PackageInstallObserver : PackageInstaller.SessionCallback
{
private PackageInstaller PackageInstaller { get; }
public event EventHandler InstallFailed;
public PackageInstallObserver(PackageInstaller packageInstaller) => PackageInstaller = packageInstaller;
public override void OnActiveChanged(int sessionId, bool active) { }
public override void OnBadgingChanged(int sessionId) { }
public override void OnCreated(int sessionId) { }
public override void OnFinished(int sessionId, bool success)
{
PackageInstaller.UnregisterSessionCallback(this);
PackageInstaller.Dispose();
if (!success) InstallFailed?.Invoke(this, EventArgs.Empty);
}
public override void OnProgressChanged(int sessionId, float progress) { }
}
然后在我的 InstallPackageAndroidQAndAbove
方法中创建该 class 的实例并将其传递给 packageInstaller.RegisterSessionCallback
方法。所以现在 InstallPackageAndroidQAndAbove
看起来像这样:
public void InstallPackageAndroidQAndAbove(Android.Net.Uri apkUri)
{
var packageInstaller = PackageManager.PackageInstaller;
var sessionParams = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall);
int sessionId = packageInstaller.CreateSession(sessionParams);
var session = packageInstaller.OpenSession(sessionId);
AddApkToInstallSession(apkUri, session);
// Create an install status receiver.
var intent = new Intent(this, this.Class);
intent.SetAction(PACKAGE_INSTALLED_ACTION);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.UpdateCurrent);
var statusReceiver = pendingIntent.IntentSender;
// Create an observer and register it
var observer = new PackageInstallObserver(packageInstaller);
observer.InstallFailed += OnInstallFailed; // Subscribe to event
packageInstaller.RegisterSessionCallback(observer);
// Commit the session (this will start the installation workflow).
session.Commit(statusReceiver);
}
我使用此代码安装 APK:
我的 activity 启动模式设置为 SingleTop。我从 OnActivityResult 调用 InstallPackageAndroidQAndAbove(我需要在此之前卸载应用程序,然后检查它是否已在那里卸载)。我还修改了该代码以在创建 PendingIntent
对象期间传递 PendingIntentFlags.UpdateCurrent
标志。问题是当 APK 成功安装或安装程序等待用户操作时,OnNewIntent 总是被正确调用,然后我做了一些事情。但是当用户中止安装时,不会调用 OnNewIntent(尽管偶尔会调用它)。我找不到任何关于这种行为的信息。我怎样才能解决这个问题?或者它可能与我正在调试的设备有关(小米 9T Pro 和基于 Android 10 的 MIUI 12)?
我需要在应用安装失败时显示警告对话框并停止进程。作为一种解决方法,我使用 StartActivityForResult,然后在 OnActivityResult 中等待 5 秒并检查是否安装了应用程序。但是这个解决方法当然是不好的,因为如果安装时间超过 5 秒,那么尽管应用程序本身将被安装,但无论如何都会显示警告对话框。
如你所见OnNewIntent
被调用,你必须在[=14]的创建过程中传递这个标志:PendingIntent.FLAG_UPDATE_CURRENT
=] 对象。因此,如果您按照您分享的示例进行操作,则:
PendingIntent pendingIntent = PendingIntent.GetActivity(activity, 0, intent, 0);
应该是这样的:
PendingIntent pendingIntent = PendingIntent.GetActivity(activity, 0, intent, PendingIntentFlags.UpdateCurrent);
我的解决方法比我的问题中描述的要好得多。这仍然是一种解决方法,因为我找不到对这种奇怪行为的解释。
我唯一需要的实际上是通知安装失败。我声明了一个继承 PackageInstaller.SessionCallback
的 class。它看起来像这样:
public class PackageInstallObserver : PackageInstaller.SessionCallback
{
private PackageInstaller PackageInstaller { get; }
public event EventHandler InstallFailed;
public PackageInstallObserver(PackageInstaller packageInstaller) => PackageInstaller = packageInstaller;
public override void OnActiveChanged(int sessionId, bool active) { }
public override void OnBadgingChanged(int sessionId) { }
public override void OnCreated(int sessionId) { }
public override void OnFinished(int sessionId, bool success)
{
PackageInstaller.UnregisterSessionCallback(this);
PackageInstaller.Dispose();
if (!success) InstallFailed?.Invoke(this, EventArgs.Empty);
}
public override void OnProgressChanged(int sessionId, float progress) { }
}
然后在我的 InstallPackageAndroidQAndAbove
方法中创建该 class 的实例并将其传递给 packageInstaller.RegisterSessionCallback
方法。所以现在 InstallPackageAndroidQAndAbove
看起来像这样:
public void InstallPackageAndroidQAndAbove(Android.Net.Uri apkUri)
{
var packageInstaller = PackageManager.PackageInstaller;
var sessionParams = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall);
int sessionId = packageInstaller.CreateSession(sessionParams);
var session = packageInstaller.OpenSession(sessionId);
AddApkToInstallSession(apkUri, session);
// Create an install status receiver.
var intent = new Intent(this, this.Class);
intent.SetAction(PACKAGE_INSTALLED_ACTION);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.UpdateCurrent);
var statusReceiver = pendingIntent.IntentSender;
// Create an observer and register it
var observer = new PackageInstallObserver(packageInstaller);
observer.InstallFailed += OnInstallFailed; // Subscribe to event
packageInstaller.RegisterSessionCallback(observer);
// Commit the session (this will start the installation workflow).
session.Commit(statusReceiver);
}