StackOverflowユーザーの皆様
AndroidアプリはPlayストアの外にあります。新しいAPKをダウンロードし、インテントを使用してインストーラーダイアログを呼び出すことにより、アプリ自体が更新されます。更新機能は、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()
したときに、不正なAPKを示すIOException: write failed (EBADF) bad file descriptor
を取得することです。しかし、それは私が問題なくファイルマネージャーを使用してAPKをインストールできるので、それは疑わしいです。エラーをグーグルすることは私をどこにも導きませんでした。
この問題を解決するにはどうすればよいですか?
Android Q:
_
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;
}
}
}
_
LaunchMode.SingleTop
_に設定する必要がありますPackageManager.CanRequestPackageInstalls()
を呼び出します。この関数がfalseを返す場合、次のコードを使用してアプリケーションオプションウィンドウを開くことができます。_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);
}
_