Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android PackageInstaller未安装APK_Android_Xamarin_Package_Installation - Fatal编程技术网

Android PackageInstaller未安装APK

Android PackageInstaller未安装APK,android,xamarin,package,installation,Android,Xamarin,Package,Installation,各位用户好 我在Play商店外有一个Android应用程序。它通过下载一个新的APK并使用Intent调用安装程序对话框来更新自身。更新功能在Android 10上不再起作用 我现在需要在Android 10上使用PackageInstaller API,但我无法让它工作。我的应用程序不是设备或个人资料所有者,但由于我不希望静默安装,所以我认为应该可以 我的问题是,一旦我提交了会话,绝对不会发生任何事情 PackageInstaller installer = activity.PackageM

各位用户好

我在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)坏文件描述符,它将指示一个坏的APK。但我怀疑这是因为我可以使用文件管理器顺利安装APK。用谷歌搜索错误并没有让我走到任何地方


如何解决此问题?

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

  • 不要使用using语句或尝试在AddApkToInstallSession方法中处理任何内容。Dispose导致安装失败。改用try/finally和close:
  • 您必须重写“OnNewIntent”方法,因为您需要一个意图来确认APK文件的安装:
  • 覆盖“OnNewIntent”方法的活动必须将LaunchMode设置为
    LaunchMode.SingleTop
  • 用户必须已为您尝试从中安装APK文件的应用程序授予安装APK所需的权限。您可以通过调用
    PackageManager.CanRequestPackageInstalls()
    检查是否存在这种情况。如果此函数返回false,则可以使用以下代码打开“应用程序选项”窗口:
因此,用户可以轻松设置开关以启用此功能

  • 这是我初始化APK安装的主要方法:
  • 如果您正在小米设备上调试,则必须在“开发人员选项”下禁用MIUI优化。否则,安装将失败,并出现“权限被拒绝”错误

首先,请参阅此asnwer of thread exception,它与所使用的流相关,但无法关闭。如果关闭了所有流,请检查您的应用程序。@LeonLu MSFT我没有打开流。当我处理(而不是关闭)流时,会发生EBADF错误。将APK的字节(从Uri的InputStream读取)写入该会话提供的OutputStream,如上面链接所示,并请调用close()关闭会话。@LeonLu MSFT方法CopyTo已将所有字节复制到目标流。而结束会话也没什么不同。@AlphaNERD你找到解决EBADF问题的方法了吗?我正在用android 10上的xamarin做同样的尝试。我遵循你的指导方针,没有错误,但从未打过电话。如果我强制调用启动活动activity.StartActivityForResult(intent,0);我得到:{Android.Content.ActivityNotFoundException:找不到显式活动类{ch…..logymobile/Android.app.Application};您是否在AndroidManifest.xml中声明了此活动?我在清单上遗漏了什么?我看到您正在使用未声明的var PACKAGE_INSTALLED_操作,就好像它是一个常量,因此我理解您只是从另一个条目复制代码(有很多条目复制非工作代码)。该常量声明为PACKAGE\u INSTALLED\u ACTION=“com.example.android.API.content.SESSION\u API\u PACKAGE\u INSTALLED”;但它毫无意义。你为什么要使用这个字符串?它在任何脚本引用中都不存在。如果你还没有让它工作,请停止从其他站点复制粘贴代码。@Windgate PACKAGE_INSTALLED_ACTION只是一个意向操作名称。我想这对任何阅读该解决方案的人来说都是显而易见的。我只是在遵循一个官方和roid示例:我在Xamarin论坛上发布了相同的答案。如果这对你不起作用,那么你显然做错了什么。没有必要为此责备其他人。首先,感谢你的澄清。我花了几天时间试图使用Xamarin论坛中的内容、你发布的同一链接中的内容以及类似的con帐篷在另一个网站上。有太多的条目混合了const(PACKAGE\u INSTALLED\u ACTION)和硬编码字符串(“com.example.android.API.content.SESSION\u API\u PACKAGE\u INSTALLED”)对于我认为这只是一个不推荐的复制+粘贴,带有任何类型的翻译丢失问题。我将清除所有项目,并遵循Begging中的官方Android示例,谢谢。我建议先在模拟器中测试所有内容,而不是在实际设备中测试。一些手机制造商(小米和其他人可能也一样)喜欢在他们的android版本中加入代码,以打破默认安装中应用程序的侧向加载。我花了好几天时间才弄明白这一点,不知道为什么它不起作用。

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;
        }
    }
}
StartActivity(new Intent(
            Android.Provider.Settings.ActionManageUnknownAppSources,
            Android.Net.Uri.Parse("package:" + Android.App.Application.Context.PackageName)));

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