[解決済み] アプリがアンインストールされることを検出するにはどうすればよいですか?重複
質問
私たちが知っているのは、通常の (実際にはどのような) ウイルス対策アプリケーションでも、アンインストール前に次のような簡単なダイアログが表示されるということだけです: "You're going to uninstall app, are sure?" - "yes/no".
はい、私は、次のような intent-filter を使用して、パッケージの削除意図を傍受できることを知っています。
<activity
android:name=".UninstallIntentActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.DELETE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
</activity>
しかし,問題は,これが のいずれかを を遮断してしまうこと、さらに、私のアプリと純正インストーラの間で選択ダイアログを発生させてしまうことです。そのため、ユーザーが純正インストーラを選択した場合、私は何もできなくなります。
私の目標は、ユーザーが私のアプリをアンインストールするのを防ぐことではなく、私のアプリによって行われた変更をロールバックすることだけです。
これらのアンチウイルスアプリから学ぶと、このような操作が可能であることがわかりますが、どのように可能なのか説明してください。
アップデートについて
このようなことが現実に起こるとは思っていない人がいるようです。 アバスト モバイル セキュリティ :
<ブロッククオートAnti-Theft は、そのコンポーネントを様々な自己防衛技術によって偽装することで、アンインストールから自身を保護します。 様々な自己防衛のテクニックでアンインストールを防ぎます。
もう一つの例です。カスペルスキー インターネット セキュリティ for Android -。 アンインストールするための特別な手順はこちらです。 と表示され、秘密のコードを入力する必要があります。
いずれにせよ、アンインストールを阻止したり、最終的な処理を行うために、アンインストール手順を傍受する方法があるということです。
どのように解決するのですか?
2 日間この問題についていろいろと調査した結果、デバイスを root 化することなく解決する野生の方法を見つけました。)
まず、解決策を達成するためのハイライトは次のとおりです。
1. ユーザが 設定 -> アプリの管理 -> 特定のアプリケーションを選択します。 というブロードキャストを受信します。 android.intent.action.QUERY_PACKAGE_RESTART のブロードキャストを受信しました。 を、アプリケーションのパッケージ名をextrasとして受信します。
2. この後 アンインストール ボタン (パッケージインストーラ付き) をクリックすると、 - という名前のアクティビティが開かれます。 com.android.packageinstaller.UninstallerActivity という名前のアクティビティが開きます。
制御の流れはこうなります。
アプリの設定で、ユーザーがアンインストールボタンをクリックする ---> ダイアログを表示する/別のアクティビティを開始するなどの制御を行う ---> アンインストール前の作業を終了する ---> アンインストール確認画面に戻る ---> ユーザーがアプリを確認しアンインストールする
使用方法。
アプリケーションにBroadcastReceiverを実装し、アクション(")を待ち受けるようにします。 android.intent.action.QUERY_PACKAGE_RESTART そして、onReceive()メソッド内でパッケージ名をマッチさせます。ブロードキャストが希望のアプリケーションパッケージの選択のために受信された場合、ActivityManagerを使用してフォアグラウンドの実行中のアクティビティを監視し続けるバックグラウンドスレッドを開始することになります。
いったんフォアグラウンドのアクティビティが " であることを見つけると、そのアクティビティを監視します。 com.android.packageinstaller.UninstallerActivity が見つかります。 というアクティビティが見つかったら、ユーザーがアプリケーションのアンインストールを望んでいることを確認します。この時点で、アンインストール前に行うべきタスク(ダイアログの表示、またはアンインストールウィンドウに重なる別のアクティビティの開始など)を実行します。タスクを実行した後、ユーザーがアンインストールプロセスの確認を続行できるようにします。
実装・ソースコード
manifest.xmlで
パーミッションを追加します。
<uses-permission android:name="android.permission.GET_TASKS"/>
と放送受信を行う。
<receiver android:name=".UninstallIntentReceiver">
<intent-filter android:priority="0">
<action android:name="android.intent.action.QUERY_PACKAGE_RESTART" />
<data android:scheme="package" />
</intent-filter>
</receiver>
UninstallIntentReceiver.java (ブロードキャストレシーバクラス)
public class UninstallIntentReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// fetching package names from extras
String[] packageNames = intent.getStringArrayExtra("android.intent.extra.PACKAGES");
if(packageNames!=null){
for(String packageName: packageNames){
if(packageName!=null && packageName.equals("YOUR_APPLICATION_PACKAGE_NAME")){
// User has selected our application under the Manage Apps settings
// now initiating background thread to watch for activity
new ListenActivities(context).start();
}
}
}
}
}
ListenActivitiesクラス - フォアグラウンドの活動を監視するための
class ListenActivities extends Thread{
boolean exit = false;
ActivityManager am = null;
Context context = null;
public ListenActivities(Context con){
context = con;
am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
}
public void run(){
Looper.prepare();
while(!exit){
// get the info from the currently running task
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(MAX_PRIORITY);
String activityName = taskInfo.get(0).topActivity.getClassName();
Log.d("topActivity", "CURRENT Activity ::"
+ activityName);
if (activityName.equals("com.android.packageinstaller.UninstallerActivity")) {
// User has clicked on the Uninstall button under the Manage Apps settings
//do whatever pre-uninstallation task you want to perform here
// show dialogue or start another activity or database operations etc..etc..
// context.startActivity(new Intent(context, MyPreUninstallationMsgActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
exit = true;
Toast.makeText(context, "Done with preuninstallation tasks... Exiting Now", Toast.LENGTH_SHORT).show();
} else if(activityName.equals("com.android.settings.ManageApplications")) {
// back button was pressed and the user has been taken back to Manage Applications window
// we should close the activity monitoring now
exit=true;
}
}
Looper.loop();
}
}
既知の制限事項。
ユーザが アンインストール ボタンをクリックすると、アンインストール前のタスクが実行され、確認ウィンドウが表示され、アンインストールを確認するか、または キャンセル することができます。
上記のアプローチは、今のところ、ユーザがをクリックした場合のケースをカバーしていません。 キャンセル ボタンをクリックした場合をカバーしていません。しかし、これはいくつかの修正で簡単に取り組むことができます。
例.ブロードキャスト " が表示された場合、行った変更を元に戻すロジックを実装できます。 android.intent.action.PACKAGE_REMOVED "が最終的に受信されなかった場合。
この方法がお役に立つことを願っています :) 私の意見では、これが、デバイスをルート化せずに問題を解決できる唯一の方法です!
[アップデート 1] : アンインストールタスクが以下のようなものであったかを確認する方法を提案します。 キャンセルされた :
以前はまったく別の複雑なアイデア(ブロードキャスト、ActivityManagerなどを含む)を持っていましたが、ここに書いている間に別のアイデアが頭に浮かんできました。)
ユーザーが [Manage Apps] 設定で [Uninstall] ボタンをクリックし、アンインストール前のタスクを実行した後、アプリで SharedPreference を設定して、アンインストール前のタスクを実行し、アンインストールの準備ができたことを知らせるだけです。この後、何も気にする必要はありません。
ユーザーがアンインストールを続行する場合、必要なタスクはすでに実行されているため、問題ありません。
一方、ユーザーが最終的に キャンセル ボタンをクリックして去っていくのであれば、気にする必要はありません。ユーザーが再びアプリケーションを実行するまでは。さて、アプリケーションのメインアクティビティの "onStart()" / "onResume()" 内で、SharedPreference の値をチェックし、それがアンインストール用に設定されていれば、それはユーザーが最終的にアンインストールを進めなかったということを意味するでしょう。そして今、アプリケーションを完全に実行するために、以前に行った変更 (実行されたアンインストール前のタスクを取り消す) を元に戻すことができます。
関連
-
[解決済み】Android "ビュー階層を作成した元のスレッドだけが、そのビューに触れることができる"
-
[解決済み] android.os.NetworkOnMainThreadException' を修正するにはどうすればよいですか?
-
[解決済み] インスタンス状態の保存を使用してアクティビティ状態を保存するにはどうすればよいですか?
-
[解決済み] アプリケーションからAndroidのWebブラウザでURLを開くにはどうすればよいですか?
-
[解決済み] Androidのランドスケープモードを無効にする方法を教えてください。
-
[解決済み] SDカードからファイルを削除する方法を教えてください。
-
[解決済み] ArrayAdapter<myClass> の使用方法
-
[解決済み] データベースでリサイクルビューを使用する
-
[解決済み] Gmailの3分割アニメーションシナリオの完全動作サンプル?
-
[解決済み] 非推奨のandroid.support.v4.app.ActionBarDrawerToggleの置き換え方法
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Android: (サービスから)現在のフォアグラウンドのアクティビティを取得するにはどうすればよいですか?
-
[解決済み] handler.postDelayed()を停止する。
-
[解決済み] AppCompat-v7 21でアクションバー/ツールバーにアイコンを表示する。
-
[解決済み] Gmailの3分割アニメーションシナリオの完全動作サンプル?
-
[解決済み] 通知をクリックした後にアプリケーションを開く
-
[解決済み] Android端末がHDPI画面かMDPI画面かを確認する方法は?
-
[解決済み] EditTextをReadOnlyにする
-
[解決済み] フラグメント間の値の受け渡し方法
-
[解決済み] キャンバスに複数行のテキストを描画する
-
[解決済み] Androidでツールバーの戻るボタンの色を変えるには?