Hello StackOverflow users,
i have an Android app outside of the Play Store. It updates itself by downloading a new APK and invoking the installer dialog using an Intent. The update functionality does not work anymore on Android 10.
I need to use the PackageInstaller API on Android 10 now, but i can't get it to work. My app is not a device or profile owner, but since i don't want a silent install so i think it should be fine.
My problem is that as soon as i commit the session absolutely nothing happens.
PackageInstaller installer = activity.PackageManager.PackageInstaller;
PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall);
int sessionId = installer.CreateSession(sessionParams);
PackageInstaller.Session session = installer.OpenSession(sessionId);
var input = new FileStream(pfad, FileMode.Open, FileAccess.Read);
var packageInSession = session.OpenWrite("package", 0, -1);
input.CopyTo(packageInSession);
packageInSession.Close();
input.Close();
//That this is necessary could be a Xamarin bug.
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Intent intent = new Intent(activity, activity.Class);
intent.SetAction("com.example.android.apis.content.SESSION_API_PACKAGE_INSTALLED");
PendingIntent pendingIntent = PendingIntent.GetActivity(activity, 0, intent, 0);
IntentSender statusReceiver = pendingIntent.IntentSender;
// Commit the session (this will start the installation workflow).
session.Commit(statusReceiver);
I took a look at the DDMS and got nothing relevant out of it. One thing that might be of interest is that when i Dispose()
the streams, i get an IOException: write failed (EBADF) bad file descriptor
which would indicate a bad APK. But i doubt it's that because i can install the APK using a file manager without a hitch. Googling the error didn't lead me anywhere.
How can i fix this problem?
Why APK won't install on Android? First, make sure that your Android version supports the APK version you want to install. Also, remove the Play Store version of the app before installing an APK. Don't forget to check the storage space and permission to install apps from unknown sources.
If not already done: Settings -> Apps -> All -> Package Installer Clear Cache & Data, Force Stop, reboot. If this doesn't work repeat, but reboot into recovery and wipe the cache partition. Still having issues try AppInstaller.
packageinstaller is the package name of a pre-installed system app on the Android OS called Package Installer. For reference, Google Chrome's package name is com. android. chrome. Package Installer is the service that runs in the background when you install, update, or uninstall apps on your Android device.
Samsung devices On your device, tap Settings > Apps. Tap Special access > Install unknown apps. Tap the browser from where you will download the APK, such as Chrome. If prompted, toggle Allow from this source on.
There are a couple of things you need to make sure in order for the apk installation to succeed in Android Q:
private static void AddApkToInstallSession(Context context, Android.Net.Uri apkUri, PackageInstaller.Session session)
{
var packageInSession = session.OpenWrite("package", 0, -1);
var input = context.ContentResolver.OpenInputStream(apkUri);
try
{
if (input != null)
{
input.CopyTo(packageInSession);
}
else
{
throw new Exception("Inputstream is null");
}
}
finally
{
packageInSession.Close();
input.Close();
}
//That this is necessary could be a Xamarin bug.
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
protected override void OnNewIntent(Intent intent)
{
Bundle extras = intent.Extras;
if (PACKAGE_INSTALLED_ACTION.Equals(intent.Action))
{
var status = extras.GetInt(PackageInstaller.ExtraStatus);
var message = extras.GetString(PackageInstaller.ExtraStatusMessage);
switch (status)
{
case (int)PackageInstallStatus.PendingUserAction:
// Ask user to confirm the installation
var confirmIntent = (Intent)extras.Get(Intent.ExtraIntent);
StartActivity(confirmIntent);
break;
case (int)PackageInstallStatus.Success:
//TODO: Handle success
break;
case (int)PackageInstallStatus.Failure:
case (int)PackageInstallStatus.FailureAborted:
case (int)PackageInstallStatus.FailureBlocked:
case (int)PackageInstallStatus.FailureConflict:
case (int)PackageInstallStatus.FailureIncompatible:
case (int)PackageInstallStatus.FailureInvalid:
case (int)PackageInstallStatus.FailureStorage:
//TODO: Handle failures
break;
}
}
}
LaunchMode.SingleTop
PackageManager.CanRequestPackageInstalls()
. If this function returns false, you can open the application options window by using this code:StartActivity(new Intent(
Android.Provider.Settings.ActionManageUnknownAppSources,
Android.Net.Uri.Parse("package:" + Android.App.Application.Context.PackageName)));
so the user can easily set the switch to enable 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, 0);
var statusReceiver = pendingIntent.IntentSender;
// Commit the session (this will start the installation workflow).
session.Commit(statusReceiver);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With