1. ホーム
  2. android

[解決済み] プログラムによるAPKのインストール/アンインストール (PackageManager vs Intents)

2022-04-30 02:16:45

質問

私のアプリケーションは他のアプリケーションをインストールしますが、どのようなアプリケーションがインストールされたかを追跡する必要があります。もちろん、これは単にインストールされたアプリケーションのリストを保持することによって達成することができます。しかし、これは必要ないはずです。installedBy(a, b)の関係を維持するのはパッケージマネージャの責任であるべきです。実際、APIによると、それはそうです。

public abstract String getInstallerPackageName (文字列 packageName) - あるパッケージをインストールしたアプリケーションのパッケージ名を取得します。これは、パッケージがどのマーケットから来たかを識別します。

現在の取り組み

インテントを利用したAPKのインストール

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(intent);

インテントを使用してAPKをアンインストールします。

Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package",
getPackageManager().getPackageArchiveInfo(apkUri.getPath(), 0).packageName,null));
startActivity(intent);

これは明らかに、Android Market などのパッケージのインストール/アンインストールの方法とは異なります。彼らはよりリッチなバージョンのPackageManagerを使用しています。これは、AndroidのGitリポジトリからAndroidのソースコードをダウンロードすることで見ることができます。以下は、Intentのアプローチに対応する2つの隠しメソッドです。残念ながら、これらは外部の開発者が利用できるものではありません。しかし、おそらく将来的にはそうなるのでしょう。

より良いアプローチ

PackageManagerを使ったAPKのインストール

/**
 * @hide
 * 
 * Install a package. Since this may take a little while, the result will
 * be posted back to the given observer.  An installation will fail if the calling context
 * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
 * package named in the package file's manifest is already installed, or if there's no space
 * available on the device.
 *
 * @param packageURI The location of the package file to install.  This can be a 'file:' or a
 * 'content:' URI.
 * @param observer An observer callback to get notified when the package installation is
 * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be
 * called when that happens.  observer may be null to indicate that no callback is desired.
 * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
 * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
 * @param installerPackageName Optional package name of the application that is performing the
 * installation. This identifies which market the package came from.
 */
public abstract void installPackage(
        Uri packageURI, IPackageInstallObserver observer, int flags,
        String installerPackageName);

PackageManagerを使用したAPKのアンインストール

/**
 * Attempts to delete a package.  Since this may take a little while, the result will
 * be posted back to the given observer.  A deletion will fail if the calling context
 * lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the
 * named package cannot be found, or if the named package is a "system package".
 * (TODO: include pointer to documentation on "system packages")
 *
 * @param packageName The name of the package to delete
 * @param observer An observer callback to get notified when the package deletion is
 * complete. {@link android.content.pm.IPackageDeleteObserver#packageDeleted(boolean)} will be
 * called when that happens.  observer may be null to indicate that no callback is desired.
 * @param flags - possible values: {@link #DONT_DELETE_DATA}
 *
 * @hide
 */
public abstract void deletePackage(
        String packageName, IPackageDeleteObserver observer, int flags);

相違点

  • インテントを使用する場合、ローカルパッケージマネージャーは、インストールがどのアプリケーションから行われたかを認識しません。具体的には、getInstallerPackageName(...) は null を返します。

  • hidden メソッド installPackage(...) は、インストーラパッケージ名をパラメータとして受け取り、この値を設定することができる可能性が高いです。

質問

インテントを使用してパッケージのインストーラ名を指定することは可能ですか? (インストールインテントのおまけとして、インストーラパッケージの名前を追加できるかも?)

ヒント:Androidのソースコードをダウンロードしたい場合は、ここに記載されている手順を実行することができます。ソースツリーをダウンロードする。*.java ファイルを抽出し、パッケージ階層に従ってフォルダーに格納するには、この巧妙なスクリプトをチェックアウトすることができます。 EclipseでAndroidのソースコードを見る .

解決方法は?

現在、サードパーティアプリケーションでは利用できません。 リフレクションなどを使ってinstallPackage()にアクセスしても、システムアプリケーションしか利用できないため、役に立たないことに注意してください。 (これは、ユーザーによってパーミッションが承認された後の、低レベルのインストール機構であるため、通常のアプリケーションがアクセスするのは安全ではないからです)

また、installPackage()関数の引数は、プラットフォームのリリース間でしばしば変更されているため、これにアクセスしようとすると、プラットフォームのさまざまなバージョンで失敗します。

EDIT

また、この installerPackage はかなり最近 (2.2?) 追加されたもので、もともと誰がアプリをインストールしたかを追跡するためには使われていませんでした -- Android Feedback を実装するために、アプリのバグを報告するときに誰を起動するかをプラットフォームが決定するために使われています。 (これはAPIのメソッド引数が変更されたときの一つでもあります。) 少なくとも導入後しばらくの間、Marketはインストールしたアプリの追跡にはまだこれを使わず (今も使っていない可能性が非常に高い)、代わりに、フィードバックを担当するAndroid Feedbackアプリ (Marketとは別のもの) を "owner" として設定するためにこれを使用しただけです。