Issue
I use this code for installing APK: https://stackoverflow.com/a/61889386/14152249
My activity launch mode is set to SingleTop. I call InstallPackageAndroidQAndAbove from OnActivityResult (I need to uninstall app before that and I check if it's uninstalled there). Also I modified that code to pass the PendingIntentFlags.UpdateCurrent
flag during the creation of PendingIntent
object. The problem is when APK is successfully installed or when installer is waiting for user action, OnNewIntent is always properly called and then I do some stuff. But when user aborts install, OnNewIntent is not called (occasionally though it DOES get called). I couldn't find anything about such a behavior. How can I fix this? Or maybe it has something to do with the device which I'm debugging on (Xiaomi Mi 9T Pro with MIUI 12 based on Android 10)?
I need to show an alert dialog when app failed to install and stop the process. As a workaround I use StartActivityForResult and then in OnActivityResult I wait for 5 seconds and check if app is installed. But this workaround is bad of course because if installation takes more than 5 seconds then alert dialog will be shown anyway though the app itself will be installed.
Solution
I made a lot better workaround than the one described in my question. It's still a workaround though as I couldn't find an explanation of such strange behavior.
The only thing I need from this is actually notifying about installation fail. I declared a class which inherits PackageInstaller.SessionCallback
. It looks like this:
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) { }
}
Then in my InstallPackageAndroidQAndAbove
method I create an instance of that class and pass it to packageInstaller.RegisterSessionCallback
method. So now InstallPackageAndroidQAndAbove
looks like this:
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);
}
Answered By - solru
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.