簡體   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