Android PackageInstaller未安装APK [英] Android PackageInstaller not installing APK

查看:760
本文介绍了Android PackageInstaller未安装APK的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好StackOverflow用户

Hello StackOverflow users,

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

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.

我现在需要在Android 10上使用PackageInstaller API,但我无法使其正常工作.我的应用不是设备或个人资料所有者,但由于我不想进行静默安装,因此我认为应该没问题.

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

我看了看DDMS,但没有发现任何相关信息.可能感兴趣的一件事是,当我Dispose()流时,我得到一个IOException: write failed (EBADF) bad file descriptor,这表明APK错误.但是我怀疑这是因为我可以使用文件管理器安装APK而没有任何障碍.谷歌搜索错误并没有带我到任何地方.

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.

我该如何解决此问题?

推荐答案

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

There are a couple of things you need to make sure in order for the apk installation to succeed in Android Q:

  • 请勿使用using语句或尝试在AddApkToInstallSession方法内放置任何内容.处置会导致安装失败.使用try/finally,然后关闭:

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,则可以使用以下代码打开应用程序选项窗口:
      • The Activity where you override the "OnNewIntent" method must have LaunchMode set to LaunchMode.SingleTop
      • The user must have given the application from which you try to install the APK file the necessary permissions to install APK's. You can check if this is the case by calling 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.

        • 这是初始化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优化.否则,安装将失败,并显示权限被拒绝错误.
        • 这篇关于Android PackageInstaller未安装APK的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆