繁体   English   中英

Android PackageInstaller 未安装 APK

[英]Android PackageInstaller not installing APK

你好 StackOverflow 用户,

我在 Play 商店之外有一个 Android 应用程序。 它通过下载新的 APK 并使用 Intent 调用安装程序对话框来更新自身。 更新功能不再适用于 Android 10。

我现在需要在 Android 10 上使用 PackageInstaller API,但我无法让它工作。 我的应用程序不是设备或配置文件所有者,但由于我不想进行静默安装,所以我认为应该没问题。

我的问题是,一旦我提交会话,绝对不会发生任何事情。

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);

我查看了 DDMS,并没有从中得到任何相关信息。 可能感兴趣的一件事是,当我Dispose()流时,我收到IOException: write failed (EBADF) bad file descriptor ,这表明 APK 有问题。 但我怀疑这是因为我可以使用文件管理器顺利安装 APK。 谷歌搜索错误并没有把我带到任何地方。

我该如何解决这个问题?

为了在 Android Q 中成功安装 apk,您需要确保以下几点:

  • 不要使用 using 语句或尝试在 AddApkToInstallSession 方法中处理任何内容。 Dispose 会导致安装失败。 使用 try/finally 和 close 代替:

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();
}
  • 您必须覆盖“OnNewIntent”方法,因为您需要一个意图来确认 APK 文件的安装:

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;
        }
    }
}
  • 您覆盖“OnNewIntent”方法的活动必须将 LaunchMode 设置为LaunchMode.SingleTop
  • 用户必须已向您尝试从中安装 APK 文件的应用程序授予安装 APK 所需的权限。 您可以通过调用PackageManager.CanRequestPackageInstalls()来检查是否是这种情况。 如果此函数返回 false,您可以使用以下代码打开应用程序选项窗口:
StartActivity(new Intent(
            Android.Provider.Settings.ActionManageUnknownAppSources,
            Android.Net.Uri.Parse("package:" + Android.App.Application.Context.PackageName)));

因此用户可以轻松设置开关以启用此功能。

  • 这是我初始化 APK 安装的主要方法:

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);
}
  • 如果您在小米设备上调试,则必须在开发者选项下禁用 MIUI 优化。 否则安装将因权限被拒绝错误而失败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM