ActivityManager.clearApplicationUserData()を呼び出した後にAndroidアプリを再起動することは可能ですか?


8

現在のAndroidアプリケーションは呼び出す必要があります

 ActivityManager.clearApplicationUserData()

ユーザーがアプリのストレージをクリアするシミュレーション

それはうまくいきます。

呼び出しの副作用はclearApplicationUserData()、アプリが(当然のことながら)閉じられていることです。

ユーザーエクスペリエンスが低下します。

に電話をかけた後、アプリケーションを再起動できませんclearApplicationUserData()

私が使って試してみましたstartActivityAlarm ManagerPending IntentForeground/ Backgroundサービス。

何も機能しません。

呼び出したAndroidアプリを再起動することは不可能clearApplicationUserData()ですか?


1
ユーザーが「強制停止」をクリックしたかのように、アプリは停止状態で終了すると思います。未処理のアラーム、ジョブなどはすべてキャンセルされます。「呼び出したAndroidアプリを再起動することは不可能clearApplicationUserData()ですか?」-私はあなた自身のアプリ内からそれが可能であることを疑います。これがそのメソッドを呼び出す前に発生することを説明するメッセージをユーザーに表示し、ユーザーはランチャーからアプリを再起動できます。
CommonsWare、

1
私はこれがそのビルドの目的だと思います..保留中のインテントを備えたアラームマネージャー、とにかくフォアグラウンド/バックグラウンドが明らかになりますclearApplicationUserData.. 使用する場合、これは望ましいフローになります..ソースコードをチェックアウトできます..
ADM

@CommonsWareはとにかく詳細なログ(または同様のもの)を有効にして、このメソッドの呼び出しで実際に何が起こるかを確認できますか?
Hector

1
「実際に何が起こっているのか」という意味がわかりませんが、Logcatを表示して、何がログに記録されているかを確認できます。Android Studio内から表示している場合は、重大度フィルターを「詳細」に切り替え、終了ドロップダウンが「フィルターなし」に設定されていることを確認して、すべてのメッセージを表示します。
CommonsWare、

2
私は過去に同じような道をたどってきました。最終的には、データベースと共有設定を手動でワイプしてを再起動する方が簡単でしたMainActivity。これが可能な場合は、強くお勧めします!そうでない場合は、おそらく、タスクをスケジュールしてWorkManager(明確なアプリデータの影響を受けない(?)ない)アクティビティを起動するようなものですか?
JakeSteam

回答:


4

1番目の回答:この回答は限られた状況でのみ機能します。完全な回答ではありません)

public boolean clearApplicationUserData()

説明

戻り値trueアプリケーションがアプリケーションのデータの消去を要求した場合。falseさもないと。

参考ウェブサイトに記載されているように、申し込みが締め切られる前に帰還者がいます。そのため、アプリを再起動するために、この帰還者を使用します。

if(ActivityManager.clearApplicationUserData)
{
     doRestart = true;
}

アクティビティonDestroy()onStop()呼ばれるときに再起動アプリ。

   @Override
   protected void onDestroy() {
       super.onDestroy();
       if(doRestart){
           Intent intent = new Intent(this, Activity.class);
           this.startActivity(intent);
       }
   }

    @Override
    protected void onStop() {
        super.onStop();
        if(doRestart){
            Intent intent = new Intent(this, Activity.class);
            this.startActivity(intent);
        }
    }

我々は両方のに再起動アクションを置くonDestroy()と、onStop()アプリが再び再起動されますことを確認するために。

また、OSが停止する前に強制的に停止することをお勧めします。

if(ActivityManager.clearApplicationUserData)
{
     doRestart = true;
     finish(); <= i mean this 
}

それは確かことになり、ので、それはだonDestroy()onStop()呼び出されます。


ActivityManager.clearApplicationUserData()アプリプロセスを呼び出した後、強制終了されます。他のコード行は実行されません。
Onik

@Onikやってみた?Activityが閉じられると、常にonDestroy()が呼び出されます。また、公式ソースはブール値を返すと言っています。それ以外の場合はvoidを返す必要があります。
Mr.AF、

1
もちろん試しましたが、なぜこんなに詳しい情報でコメントを書くのでしょうか?別のメソッド呼び出し動作がある場合、API実装に違いがあると思います。これにより、ソリューションのOSバージョンが固有になります。
Onik

@ Mr.AF回答に時間を割いていただきありがとうございます。私はあなたの解決策を確実に試します
Hector

@Onikは私の次の回答を参照してください:)
Mr.AF

3

私の提案は些細に聞こえるかもしれませんが、電話をかけないことを検討しActivityManager.clearApplicationUserData()ますか?

ここでドキュメントがこのメソッドについて言っていること:

アプリケーションがディスクから自身のデータを消去することを許可します。これは、ユーザーがデバイス設定UI内からアプリのデータを消去することを選択した場合と同じです。アプリに関連付けられているすべての動的データ(そのプライベートデータと外部ストレージのプライベート領域にあるデータ)を消去しますが、インストールされているアプリケーション自体もOBBファイルも削除しません。

したがって、この動作を模倣するには、内部ストレージディレクトリと外部ストレージディレクトリをクリアする必要があります。これらにアクセスするための権限は必要ありません。


2

2番目の答え:私はそれにもっと多くの貢献が必要です)

が呼び出されたときにアクティビティを再開するためのソリューションを見つけるために、8時間後にAndroid OSおよびAndroid Developers Webサイトで調査しましたclearApplicationUserData。最後に、私は素晴らしい/ハッキングソリューションを見つけることができます。

このソリューションはジダンドリブルのように見えます:)

ソリューションを紹介しましょう。最初に、タスク、通知、アラームなどのclearApplicationUserDataように呼び出されたときにアプリケーションのすべての手掛かりをクリアします。そのため、明示的なアクティビティの呼び出しは不可能です。

暗黙的な方法は、アクティビティを呼び出す唯一の可能な方法です。

いくつかのテストを行った後、manifest登録されたアプリケーションintent-filters は削除されず、システムブロードキャストをリッスンできることがわかりました。

およそ、98%のシステムブロードキャストのはによって受信されないクリアアプリケーションとすることを2%は非常にすぐに放送されない場合があります残りました。

じゃあ何をすればいいの ?うーん?人に来る私は解決策を見つけなければなりません...

ビンゴ、 それをシステムブロードキャストするために何かをトリガーする必要があります <=ハッキングに見えます:)

だから私はWIFI_STATE_CHANGEDを選ぶことにしまし

  • 簡単アクセス許可
  • システムは遅延時にそれをブロードキャストします<= これにより、ブロードキャストの前にアプリが確実に閉じられます

manifest.xml

<receiver
   android:name=".PackageDataClearedReceiver"
   android:enabled="true"
   android:exported="true">
     <intent-filter android:priority="100">
       <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
       <action android:name="android.net.wifi.STATE_CHANGE" />
     </intent-filter>
 </receiver>

MainActivity.java

public class MainActivity extends AppCompatActivity {
    ActivityManager am;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AppCompatButton btn = findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        am = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
                        if (am != null) {
                            ExecutorService pool = Executors.newFixedThreadPool(2);
                            final Collection<Future> futures = new HashSet<Future>();
                            futures.add(pool.submit(new Runnable() {
                                @Override
                                public void run() {
                                    WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
                                    wifiManager.setWifiEnabled(true);
                                    wifiManager.setWifiEnabled(false);
                                    am.clearApplicationUserData();
                                }
                            }));
                            for (Future future : futures) {
                                future.isDone();
                            }
                        }

                    }
                }).start();
            }
        });
    }
}

デモ

ここに画像の説明を入力してください

覚えておいてください、それはそれを完璧に機能させるためにもっと開発する必要がある単なる実行可能な最小の製品です。


ユーザーにメッセージを表示するためにWIFI状態の変化をすでに検出しているため、このアプローチは私のアプリケーションでは機能しません。WIFI状態が変化するたびに2番目のソリューションでアプローチを行う場合、メインアクティビティを開始します
Hector

@Hector yup、それは私がそれが最小の実行可能な製品であると言ったように、それはあなたのニーズにはるかに開発とカスタマイズが必要です。あなたはそれをカスタマイズする必要があります
Mr.AF

@Hector必要に応じてアクティビティを再開するためにレシーバーに条件を設定する必要があります
Mr.AF

0

うまくいけば、これはまだ助けとして役立つでしょう

質問: clearApplicationUserData()を呼び出したAndroidアプリを再起動することは不可能ですか? 回答:いいえ

clearApplicationUserData()を呼び出したら、以下のメソッドを呼び出します。

private void triggerRebirth(Context context) {
     PackageManager packageManager = context.getPackageManager();
     Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
     ComponentName componentName = intent.getComponent();

     Intent mainIntent = Intent.makeRestartActivityTask(componentName);
     context.startActivity(mainIntent);
     Runtime.getRuntime().exit(0);
}

ハッピーコーディング。


-1

APIを介してデバイス上のアプリデータをクリアすると、アプリclearApplicationUserData()はインストールされたばかりのようにリセットされます。あなたが見つけたように、あなたのアプリに登録されたすべてのアラームとブロードキャストもクリアされます。アプリをフォアグラウンドで維持する最も効率的な方法は、APIを使用するのではなく、他の人が指摘したように、自分でデータをクリアすることです。次に例を示します。https//stackoverflow.com/a/9073473/949224


ただし、APIを使用することが決定され(すべてのデータが消去されることが保証されます)、アプリが強制停止された場合は、次のように提案します。

アプリデータをクリアする直前に起動できる小さなコンパニオンアプリを作成します。コンパニオンアプリは、おそらく短時間のタイムアウト後に、アプリを再起動します。

    Intent launchIntent = getPackageManager().getLaunchIntentForPackage("example.com.testrelaunchapp");
    if (launchIntent != null) {
        startActivity(launchIntent);//null pointer check in case package name was not found
    } else {
        Log.w( TAG, "Unable to resolve launch activity of relauncher companion app");
    }

    ((ActivityManager)getSystemService(Context.ACTIVITY_SERVICE))
                    .clearApplicationUserData();   

コンパニオンアプリ自体は後で閉じる必要があり、理想的にはアクティビティスタックなどから非表示にする必要があります。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final Intent launchIntent = getPackageManager().getLaunchIntentForPackage("example.com.yourmainapp");
    if (launchIntent != null) {
        Handler handler = new Handler(getMainLooper());
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Log.i( TAG, "About to act on launchIntent");
                launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                startActivity(launchIntent);
                finish();
                System.exit(0);
            }
        }, 1000);
    }    
 }     

私はこれがAndroid 6.0で機能することを確認しましたが、汎用性があり、全面的に機能することを保証するものではありません。必要に応じて、コンパニオンアプリのUIをなくし、電話のランチャーから非表示にするためにすべきことは他にもあります。また、APKを独自のアプリ内のファイルとしてバンドルし、初回実行時にインストールすることもできます。その場合、ユーザーは「不明なソース」(Playストア以外)からのインストールを有効にする必要があります。これは、必要に応じて、適切なシステム設定へのインテントを介して行うことができますが、これが必要な理由をユーザーがよく説明する必要があります。

だから、先ほど言ったように、より簡単な方法は、データとアプリの権限を自分でクリアすることです。


私はそれが実行可能な解決策ではないと思います。あなたのソリューションはそれを不可能にする追加のインストール済みパッケージを必要とするからです。さらにパッケージやコンパニオンアプリを追加できるとしたら、さまざまな方法でアクティビティを開始できます。
Mr.AF

自分のアプリから別のアプリをインストールするようユーザーに促すことは確かに可能です。問題は、操作方法の一部としてこの動作が必要かどうかです。私が述べたように、私はそれをお勧めしませんが、それが他の人に役立つ場合に備えて、原則的にそれを原則的に言及する価値はあります。
dr_g
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.