アプリを強制的に再起動させていと思うことが時々あります。アプリをリセットしたい場合などです。これはPendingIntent, AlarmManager を使えば可能です。
1 2 3 4 5 6 7 8 9 |
12-26 02:59:39.411 12883-12883/com.example.testrestart D/debug: onCreate() 12-26 02:59:39.415 12883-12883/com.example.testrestart D/debug: onStart() 12-26 02:59:39.417 12883-12883/com.example.testrestart D/debug: onResume() 12-26 02:59:45.229 12883-12883/com.example.testrestart D/debug: onPause() 12-26 02:59:45.853 12883-12883/com.example.testrestart D/debug: onStop() 12-26 02:59:45.853 12883-12883/com.example.testrestart D/debug: onDestroy() 12-26 02:59:50.230 12883-12883/com.example.testrestart D/debug: onCreate() 12-26 02:59:50.233 12883-12883/com.example.testrestart D/debug: onStart() 12-26 02:59:50.235 12883-12883/com.example.testrestart D/debug: onResume() |
Android 8.1.0
AlarmManager, PendingIntent
Android 10 からは、バックグラウンドで実行されているアプリに対してアクティビティを開始できる状況に制限ができました。
バックグラウンドからのアクティビティの起動に関する制限
そのためAlarmMangerでの再起動はできなくなりました。
代替えとしては別プロセスから元のプロセスをkillしてから再起動させるなどの方法です。
killProcess(int pid)
~~~~
以下はAndroid 9までの方法になります。
アプリを再起動させたいので、Activityの遷移と同じようにして遷移先を自分自身にしてIntentを使うとどうでしょうか。
1 2 3 4 |
// intent 設定で自分自身のクラスを設定 Intent intent = new Intent(context, MainActivity.class); startActivity(intent); // finish(); |
Activityの画面遷移のようにしてもうまく行きません。不安定な動きになります。
一度終了させ、onDestroy()にさせてからAlarmManagerを使って再起動させるとうまくいくようではあります。
繰り返すと問題があるかもしれませんが…
サンプルコード
まとめのコードです。AlarmManagerで5秒を設定してアプリの終了起動をActivityのstatusを使って観察してみます。
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import java.text.SimpleDateFormat; import java.util.Locale; public class MainActivity extends AppCompatActivity { private Context context; private int waitperiod; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d("debug","onCreate()"); context = getApplicationContext(); waitperiod = 5000; // 5sec Button button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { restart(context, waitperiod); } }); } void restart(Context cnt, int period){ // intent 設定で自分自身のクラスを設定 Intent mainActivity = new Intent(cnt, MainActivity.class); // PendingIntent , ID=0 PendingIntent pendingIntent = PendingIntent.getActivity(cnt, 0, mainActivity, PendingIntent.FLAG_CANCEL_CURRENT); // AlarmManager のインスタンス生成 AlarmManager alarmManager = (AlarmManager)cnt.getSystemService( Context.ALARM_SERVICE); // 1回のアラームを現在の時間からperiod(5秒)後に実行させる if(alarmManager != null){ long trigger = System.currentTimeMillis() + period; alarmManager.setExact(AlarmManager.RTC, trigger, pendingIntent); } // アプリ終了 finish(); } @Override protected void onStart() { super.onStart(); Log.d("debug","onStart()"); } @Override protected void onRestart() { super.onRestart(); Log.d("debug","onRestart()"); } @Override protected void onResume() { super.onResume(); Log.d("debug","onResume()"); } @Override protected void onPause() { super.onPause(); Log.d("debug","onPause()"); } @Override protected void onStop() { super.onStop(); Log.d("debug","onStop()"); } @Override protected void onDestroy() { super.onDestroy(); Log.d("debug","onDestroy()"); } } |
レイアウトです。ボタンがあるだけです
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center" android:background="#dfe" tools:context=".MainActivity"> <Button android:id="@+id/button" android:text="@string/button" android:layout_margin="40dp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> |
リソースです。ボタンタイトルだけですが
string.xml
1 2 3 4 |
<resources> <string name="app_name">TestRestart</string> <string name="button">Restart</string> </resources> |
サンプル動画
Activityのライフサイクルに沿った状態で処理されているようです。
ログを見ると
51.293 onPause()
…
56.304 onCreate()
アプリがDestroyされて起動するまで5.011秒かかったことになっています。
関連記事:
References:
AlarmManager | Android Developers
PendingIntent | Android Developers
アクティビティ | Android Developers