[解決済み] プログラムによるAPKのインストール/アンインストール (PackageManager vs Intents)
質問
私のアプリケーションは他のアプリケーションをインストールしますが、どのようなアプリケーションがインストールされたかを追跡する必要があります。もちろん、これは単にインストールされたアプリケーションのリストを保持することによって達成することができます。しかし、これは必要ないはずです。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" として設定するためにこれを使用しただけです。
関連
-
デフォルトのアクティビティが見つからない場合の対処法
-
ConstraintLayoutのいくつかのプロパティの概要(RelativeLayoutの強化版、LinearLayoutの比例プロパティを含む、階層ツールの削減)。
-
Android Bluetooth 開発の基本プロセス
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Windowsにpipをインストールするにはどうしたらいいですか?
-
[解決済み] Intentsを使用して、あるAndroid Activityから別のAndroid Activityにオブジェクトを送信するにはどうすればよいですか?
-
[解決済み] AndroidエミュレーターにAPKファイルをインストールする方法を教えてください。
-
[解決済み] Androidのエラーです。デバイス*に*.apkをインストールできませんでした: タイムアウト
-
[解決済み] MacでAndroid Studioを完全にアンインストールする方法を教えてください。
-
[解決済み】Homebrewは特定のバージョンのformulaをインストールしますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
AAPT2エラーについて:詳しくはログをご確認ください。
-
Android Studio を 3.6.3 にアップデートした後、構成 :classpath のアーティファクトをすべて解決できない。
-
android exception - aapt.exe has stopped working.
-
アンドロイドのエリプサイズを使用する
-
問題 ---- Android ---- ActivityManager: Error: アクティビティクラス{xx/xx.MainActivity}が存在しない
-
アンドロイドリストビュー
-
Androidカスタムドロップダウンリストボックスコントロール
-
アンドロイドスタジオソフトウェア使用詳細説明書
-
アプリの実行エラー。ターゲットデバイスが見つからない問題
-
Android.support.v7.widget.Toolbar が見つかりませんでした。