take_rock_5
@take_rock_5 (イ タケ)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

毎日、指定した時刻に指定した処理を実行するというアプリを作成したい

毎日、指定した時刻に指定した処理を実行するというアプリを作成したいと思っております。
AlarmManagerの機能にてほぼ目的の動作をできたのですが、”間に再起動の動作が入ったとしても続けさせたい"というところが、なかなか実現できないのですが、やり方を教えて頂ければと思っております。

自分が参考としているコードは下記です。
このコードのここを変えたらできるなど、を教えて頂ければと思います。
(再起動後に時間の設定をし直さなくても、再起動前に設定した時刻に処理をされたい。)

※下記コードには記載していませんが、
 端末の再起動後に自動でアプリを立ち上げるというプログラムは自力で作成は可能です。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    //設定時刻表示用
    String sdata;
    //初期値用 x:時 y:分
    int x=0;
    int y=0;

    //時間になったら起動するパラメータ
    PendingIntent pendingIntent;
    AlarmManager manager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        read();
    }

    //開始ボタンを押した時
    public void aet(View view) {
        write();

        //開始ボタンを押したら画面を隠す
        //finish();

        //タイマー起動
        //ベースコンテキストを取得
        Context context = getBaseContext();

        //アラームマネージャーの作成と設定
        manager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);

        //インテントの作成   指定時刻にSubActivityを起動
        Intent intent = new Intent(context,SubActivity.class);

        //ペンディングインテントの作成
        pendingIntent = PendingIntent.getActivity(context,0,intent,0);

        //カレンダーの作成
        Calendar calendar = Calendar.getInstance();     //現在時間が取得される

        //指定時間をセット
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(Calendar.HOUR_OF_DAY, x);
        calendar.set(Calendar.MINUTE, y);
        calendar.set(Calendar.SECOND, 0);

        //指定間隔を分単位でする場合
        manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                1000 * 60 * 1, pendingIntent);
        System.out.println("開始時------------------>" + pendingIntent);


        //指定間隔を予め用意されている間隔でする場合
        //manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        //        AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);


    }

    //終了ボタンを押した時
    public void stop(View view) {

        System.out.println("終了時------------------>" + pendingIntent);

        //繰り返しアラームの停止
        if (manager!= null) {
            manager.cancel(pendingIntent);
        }

        //finish();
    }

    //アプリケーション設定値登録
    private void write(){
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = sharedPreferences.edit();

        //プレーンテキストから値取得
        TextView jikoku=findViewById(R.id.jikoku);
        sdata=jikoku.getText().toString();
        String ttt=(sdata.substring(0,2));
        String mmm=(sdata.substring(3));

        TextView pct = findViewById(R.id.percent);
        String text = pct.getText().toString();

        //数値に変換
        int tt = Integer.parseInt(ttt);
        int mm = Integer.parseInt(mmm);
        int ps = Integer.parseInt(text);

        //SharedPreferencesに保存
        editor.putInt("SET_TIME", tt);
        editor.putInt("SET_Minutes", mm);
        editor.putInt("percent", ps);

        //実際の保存
        editor.apply();

        read();

    }

    //アプリケーション設定値取得
    private void read() {

        //値を読み出す
        SharedPreferences pref  = PreferenceManager.getDefaultSharedPreferences(this);

        //SharedPreferencesからの呼び出し時刻
        int time = pref.getInt("SET_TIME", 0);
        int Minutes = pref.getInt("SET_Minutes", 0);

        //バッテリーボーダーラインの呼び出し
        int percent = pref.getInt("percent", 40);


        x=time;
        y=Minutes;

        //テキストにセット
        String sjikoku = format(Locale.JAPANESE, "%02d:%02d", x, y);
        TextView textView = findViewById(R.id.jikoku);
        textView.setText(sjikoku);

        //バッテリーボーダーラインを文字列に変換
        String pp = Integer.valueOf(percent).toString();
        TextView spct = findViewById(R.id.percent);
        spct.setText(pp);

    }

    //時刻表示テキストビューをタップしたらタイムピッカーを表示
    public void set2(View view) {
        TextView date = findViewById(R.id.jikoku);
        TimePickerDialog dialog = new TimePickerDialog(this,
                //ここで初期値          x:時 y:分   タイムピッカーに初期値をセット
                new DateSetHandler(date), x, y, true);
        dialog.show();
    }

    //タイムピッカーの日付をTextViewに表示するリスナー
    public class DateSetHandler implements TimePickerDialog.OnTimeSetListener {
        private TextView jikoku;

        public DateSetHandler(TextView date) {
            this.jikoku = date;
        }

        //タイムビーカーで設定した時分を取得
        @Override
        public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
            calendar.set(Calendar.MINUTE, minute);

            //実際に日付をTextViewにセット
            jikoku.setText(format("%tR", calendar));
            //タイムピッカーの時刻をsdataに退避
            sdata= format("%tR", calendar);
        }

    }


}

SubActivity.java

public class SubActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sub);

        TextView textView = findViewById(R.id.textView);
        textView.setText("起動しました。");


    }

    //終了ボタンが押された時
    public void syuryou(View view) {
        finish();
    }
}

activity_main.xml

<?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">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="193dp"
        android:layout_height="36dp"
        android:gravity="center"
        android:text="@string/kaisi"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.197"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.074" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="193dp"
        android:layout_height="36dp"
        android:gravity="center"
        android:text="@string/bzan"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.197"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.201" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="55dp"
        android:layout_height="37dp"
        android:gravity="center"
        android:text="@string/pst"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.865"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.199" />

    <TextView
        android:id="@+id/jikoku"
        android:layout_width="116dp"
        android:layout_height="54dp"
        android:ems="10"
        android:gravity="center"
        android:textSize="25sp"
        android:onClick="set2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.84"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.06"
        android:autofillHints="" />

    <EditText
        android:id="@+id/percent"
        android:layout_width="54dp"
        android:layout_height="55dp"
        android:ems="10"
        android:gravity="center"
        android:hint="@string/zan"
        android:inputType="number"
        android:textSize="25sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.7"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.188"
        android:autofillHints="" />

    <Button
        android:id="@+id/button"
        android:layout_width="171dp"
        android:layout_height="90dp"
        android:text="@string/start"
        android:textSize="50sp"
        android:onClick="aet"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.38" />

    <Button
        android:id="@+id/button2"
        android:layout_width="171dp"
        android:layout_height="90dp"
        android:text="@string/stop"
        android:textSize="50sp"
        android:onClick="stop"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.641" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_sub.xml

<?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=".SubActivity">

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="syuryou"
        android:text="@string/modoru"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.571" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="304dp"
        android:layout_height="156dp"
        android:text="@string/textview"
        android:textSize="36sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.495"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.107" />
</androidx.constraintlayout.widget.ConstraintLayout>

strings.xml


<resources>
    <string name="app_name">step05</string>
    <string name="bzan">バッテリー残量</string>
    <string name="kaisi">お知らせ開始時刻</string>
    <string name="pst"></string>
    <string name="jikoku">00:00</string>
    <string name="zan">40</string>
    <string name="start">開始</string>
    <string name="stop">終了</string>
    <string name="modoru">終了</string>
    <string name="textview">TextView</string>
</resources>
0

4Answer

端末再起動後にアプリを呼び出す書き方が分からないのかと思いましたが、そこは分かるのですね。そしてその必要性がわかるということはAlermを端末起動後に設定しなければいけないこともわかるのですよね。
では逆にどこのコードが分からないのでしょうか?

ご質問者様がご存知のように、AlarmManagerは再起動後時に揮発します。そのため登録時に内部DBあたりに処理を書き込み、再起動時のイベント内で揮発しない場所のデータを読み直して再登録することが多いと思います。

SharedPreferencesを利用してデータの保存も出来ているようなので、BOOT_COMPLETEDのレシーバの中でreadに相当するものを呼び出せば良いだけなはずです。
提示されたコードはMaInActivityの中に処理が全て書いてあるので、IntentServiceか何かに処理を切り分ければ分かりやすいのではないかと思います。

コードを明らかにしてくれるのは大変良いのですが、「エラーなどコードに直結する問題」と「コードより大きなレイヤーでの問題」があり、今回は後者に近いと思います。
まず「〜の処理を〜で設計したらここがわからなかった」など質問を具体化してもらえると解決が早くなるかと思います。(もしくは質問が「AlarmManagerを再起動後も有効にし続ける方法があるか」ならそのようにハッキリ書くと「(多分)無いです、再起動後に再登録してください」と言えます)

0Like

Comments

  1. 私Androidネイティブの開発者ではないので間違えていたらすみません

丁寧に説明頂いてありがとうございます。
質問の内容がぼやける質問の仕方で申し訳ございません。

BOOT_COMPLETEDのレシーバの中でreadに相当するものを呼び出せば良いだけなはずです。
に関してですが、おそらく下記のSampleですと、// Set the alarm here.のところに書けば良いものと思っているのですが、例えば、そのままread(){}の{}の中身をコピーしてもエラーになります。どの様な書き方をしたら、正しくAlarmが開始されますでしょうか?
大変おこがましい質問で申し訳ございません。

    public class SampleBootReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
                // Set the alarm here.
            }
        }
    }
0Like

おこがましいだなんてとんでもない、そこで詰まっていたのですね。
ではサンプルを作成したいと思うので少々お待ち下さい。発生したエラーなども教えていただけますと助かります。

0Like

Comments

  1. @take_rock_5

    Questioner

    詳細なコードは載せれないのですが、現在時刻の「時間と分」と設定時刻の「時間と分」をアプリ起動から数十秒毎に参照し続けて、一致したときに処理を行うという書き方で、目的の動作が可能となったことを報告致します。サンプルに関しては、参考に頂きたいというのはありますが、もし可能ならという形で捉えて頂ければと思います。ご丁寧に回答頂き感謝致します。

Your answer might help someone💌