问题描述
我想从我的Xamarin Android应用程序的文件系统安装第三方应用程序.我在Android 10之前成功使用的代码非常简单和简单.
Intent intent = new Intent(Intent.ActionView); Uri data = Uri.FromFile(file); intent.SetDataAndType(data, "application/vnd.android.package-archive"); context.StartActivity(intent);
此代码不适用于Android 10,因为action_view和action_install_package在Android 10中已弃用.如图10所示,我们现在需要使用packageInstaller API.
我试图使用packageInstaller API编写一种方法.不幸的是它不起作用.
packageInstaller API
public static void InstallPackageAndroidQAndAbove(Context context, string filePath, string packageName) { var packageInstaller = context.PackageManager.PackageInstaller; var sessionParams = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall); sessionParams.SetAppPackageName(packageName); int sessionId = packageInstaller.CreateSession(sessionParams); var session = packageInstaller.OpenSession(sessionId); var input = new FileStream(filePath, FileMode.Open, FileAccess.Read); var output = session.OpenWrite(packageName, 0, -1); input.CopyTo(output); output.Close(); input.Close(); input.Dispose(); session.Fsync(output); var pendingIntent = PendingIntent.GetBroadcast(context, sessionId, new Intent(Intent.ActionInstallPackage), 0); session.Commit(pendingIntent.IntentSender); }
在呼叫期间发生异常"无法识别的流".
我希望有人可以帮助我.
非常感谢你提前.
推荐答案
xamarin android代码,用于使用packageInstaller API安装APK.
//Change to your package name const string PACKAGE_INSTALLED_ACTION = "com.example.android.apis.content.SESSION_API_PACKAGE_INSTALLED"; public static void InstallPackageAndroidQAndAbove(Context context, string filePath) { var packageInstaller = context.PackageManager.PackageInstaller; var sessionParams = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall); int sessionId = packageInstaller.CreateSession(sessionParams); var session = packageInstaller.OpenSession(sessionId); addApkToInstallSession(filePath, session); // Create an install status receiver. Intent intent = new Intent(context, context.Class); intent.SetAction(Globals.PACKAGE_INSTALLED_ACTION); PendingIntent pendingIntent = PendingIntent.GetActivity(context, 0, intent, 0); IntentSender statusReceiver = pendingIntent.IntentSender; // Commit the session (this will start the installation workflow). session.Commit(statusReceiver); } private static void addApkToInstallSession(string filePath, PackageInstaller.Session session) { using (var input = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { using (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(); } // Note: this Activity must run in singleTop launchMode for it to be able to receive the //intent protected override void OnNewIntent(Intent intent) { base.OnNewIntent(intent); Bundle extras = intent.Extras; if (Globals.PACKAGE_INSTALLED_ACTION.Equals(intent.Action)) { int status = extras.GetInt(PackageInstaller.ExtraStatus); String message = extras.GetString(PackageInstaller.ExtraStatusMessage); switch (status) { case (int)PackageInstallStatus.PendingUserAction: // This test app isn't privileged, so the user has to confirm the install. Intent confirmIntent = (Intent)extras.Get(Intent.ExtraIntent); StartActivity(confirmIntent); break; case (int)PackageInstallStatus.Success: Toast.MakeText(this, "Install succeeded!", ToastLength.Long).Show(); 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: Toast.MakeText(this, "Install failed! " + status + ", " + message, ToastLength.Long).Show(); break; default: Toast.MakeText(this, "Unrecognized status received from installer: " + status, ToastLength.Long).Show(); break; } } }
问题描述
I want to install a 3rd party app from the filesystem from my xamarin android app. The code I used successfully before Android 10 was pretty straightforward and easy.
Intent intent = new Intent(Intent.ActionView); Uri data = Uri.FromFile(file); intent.SetDataAndType(data, "application/vnd.android.package-archive"); context.StartActivity(intent);
This code does not work on Android 10 because of ACTION_VIEW and ACTION_INSTALL_PACKAGE were deprecated in Android 10. Looks like we now need to use the PackageInstaller API.
I tried to write a method using the PackageInstaller API. Unfortunately it doesn't work.
Code with PackageInstaller API
public static void InstallPackageAndroidQAndAbove(Context context, string filePath, string packageName) { var packageInstaller = context.PackageManager.PackageInstaller; var sessionParams = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall); sessionParams.SetAppPackageName(packageName); int sessionId = packageInstaller.CreateSession(sessionParams); var session = packageInstaller.OpenSession(sessionId); var input = new FileStream(filePath, FileMode.Open, FileAccess.Read); var output = session.OpenWrite(packageName, 0, -1); input.CopyTo(output); output.Close(); input.Close(); input.Dispose(); session.Fsync(output); var pendingIntent = PendingIntent.GetBroadcast(context, sessionId, new Intent(Intent.ActionInstallPackage), 0); session.Commit(pendingIntent.IntentSender); }
An exception "Unrecognized stream" occurs during the call.
I hope someone can help me.
Thank you very much in advance.
推荐答案
Xamarin Android Code for installing an apk with the PackageInstaller API.
//Change to your package name const string PACKAGE_INSTALLED_ACTION = "com.example.android.apis.content.SESSION_API_PACKAGE_INSTALLED"; public static void InstallPackageAndroidQAndAbove(Context context, string filePath) { var packageInstaller = context.PackageManager.PackageInstaller; var sessionParams = new PackageInstaller.SessionParams(PackageInstallMode.FullInstall); int sessionId = packageInstaller.CreateSession(sessionParams); var session = packageInstaller.OpenSession(sessionId); addApkToInstallSession(filePath, session); // Create an install status receiver. Intent intent = new Intent(context, context.Class); intent.SetAction(Globals.PACKAGE_INSTALLED_ACTION); PendingIntent pendingIntent = PendingIntent.GetActivity(context, 0, intent, 0); IntentSender statusReceiver = pendingIntent.IntentSender; // Commit the session (this will start the installation workflow). session.Commit(statusReceiver); } private static void addApkToInstallSession(string filePath, PackageInstaller.Session session) { using (var input = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { using (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(); } // Note: this Activity must run in singleTop launchMode for it to be able to receive the //intent protected override void OnNewIntent(Intent intent) { base.OnNewIntent(intent); Bundle extras = intent.Extras; if (Globals.PACKAGE_INSTALLED_ACTION.Equals(intent.Action)) { int status = extras.GetInt(PackageInstaller.ExtraStatus); String message = extras.GetString(PackageInstaller.ExtraStatusMessage); switch (status) { case (int)PackageInstallStatus.PendingUserAction: // This test app isn't privileged, so the user has to confirm the install. Intent confirmIntent = (Intent)extras.Get(Intent.ExtraIntent); StartActivity(confirmIntent); break; case (int)PackageInstallStatus.Success: Toast.MakeText(this, "Install succeeded!", ToastLength.Long).Show(); 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: Toast.MakeText(this, "Install failed! " + status + ", " + message, ToastLength.Long).Show(); break; default: Toast.MakeText(this, "Unrecognized status received from installer: " + status, ToastLength.Long).Show(); break; } } }