Activityを再起動させたいと思うことが時々あります。リセットしたい場合などです。これは以前はPendingIntent, AlarmManager を使えば可能でしたが、Intentで自身を再起動させる方法が使えます。
2021.2.1
Restart
例えばこのようにIntentを発行して起動させることができます。
1 2 3 |
Intent intent = new Intent(this, MainActivity.class); finish(); startActivity(intent); |
ただし、finish()以外にTaskの処理などどのように終了させるかが選べます。
こちらが参考になります
How do I programmatically “restart” an Android app?
サンプルコード
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 |
//package your.package.name; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.widget.Button; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d("debug","onCreate()"); Button button = findViewById(R.id.button); button.setOnClickListener(v -> restart() ); } void restart(){ Intent intent = new Intent(this, MainActivity.class); // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); // finish(); // finishAfterTransition(); finishAndRemoveTask(); startActivity(intent); } } |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" 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" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> |
strings.xml
1 2 3 4 |
<resources> <string name="app_name">TestRestart</string> <string name="button">Restart</string> </resources> |
AlarmManager, PendingIntent
Android 8までは、AlarmManager, PendingIntent を使って再起動できました。
但し、バックグラウンドで実行されているアプリに対してアクティビティを開始できる状況に制限ができました。
バックグラウンドからのアクティビティの起動に関する制限
そのためAlarmMangerでの再起動はできなくなりましたが、Android 8まではこのようにやることができました。
アプリを再起動させたいので、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 97 |
//package your.package.name; 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