【问题标题】:Xamarin Android 10 Install APK - No Activity found to handle IntentXamarin Android 10 安装 APK - 找不到处理 Intent 的活动
【发布时间】:2019-10-04 16:41:25
【问题描述】:

我想从我的 xamarin android 应用程序的文件系统安装第 3 方应用程序。我在 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 中已弃用。看来我们现在需要使用 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);

    }

调用过程中出现“无法识别的流”异常。

我希望有人可以帮助我。

非常感谢您。

【问题讨论】:

  • 嗯,您是否尝试过使用类似 stackoverflow.com/a/4605040/11104068 的东西,但将 uri 编辑为本地文件
  • 很遗憾,这也没有用。
  • 我希望您正在检查 INSTALL_PACKAGES 的运行时权限
  • 我在安装/清单期间给予许可。错误消息也会比我猜的更具体

标签: android xamarin.android apk android-install-apk android-10.0


【解决方案1】:

用于使用 PackageInstaller API 安装 apk 的 Xamarin Android 代码。

//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;
                    }
                }


            }

【讨论】:

  • 此代码确实安装了新版本(竖起大拇指),但由于某种原因,它无法重新打开已安装的应用程序。你有遇到同样的问题吗?
  • 我在关闭packageInSession 时收到了write failed: EBADF (Bad file descriptor)。我要加载的文件是我在调试时从 VisualStudio 部署的 apk。 (基本上同一个正在运行)。
  • @Oiproks 看看这个帖子forums.xamarin.com/discussion/180083/…
  • @Oiproks 请参考这个 SO 答案:stackoverflow.com/a/61889386/1465881
  • 我在很多条目中都发现了相同的代码,所以我认为它是复制粘贴。您说用包名替换 const 字符串 PACKAGE_INSTALLED_ACTION ,但没有说要更改整个字符串或仅更改其中的一部分,因此不清楚。您还使用 session.OpenWrite("package", 0, -1),但您确定“package”不能再成为包名吗?我尝试了替换和替换字符串,但它不起作用。
猜你喜欢
  • 2017-02-27
  • 2020-01-24
  • 2022-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-29
  • 1970-01-01
相关资源
最近更新 更多