質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

1553閲覧

CountDownTimer ホーム画面に戻ったり、スリープ状態にしても止まらず動き続けてしまう

Ksuke_Android

総合スコア7

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2020/03/16 07:09

編集2020/03/19 03:29

Windows10, Android Studio3.5.2(Java)で時間制限のあるゲームを作っています。

ゲーム開始と同時にタイマーのカウントダウンが始まり、BGMが流れるのですが、
スマホをスリープ状態にしたりホーム画面に戻ってもBGMが流れっぱなしになり、
カウントダウンも止まらず動き続けてしまいます(再度アプリ画面に戻るとカウントが進んでいる)。

スリープ状態にしたりホーム画面に戻ったりしたときに、BGM、タイマーのカウントダウンが止まり、
アプリの画面に戻った時に再び開始するようにするにはどうしたらいいでしょうか?

ソースコードすべてのせると長いので、該当部分をのせます↓

Java

1 2public class MainActivity extends AppCompatActivity { 3 4 Button playAgainButton; 5 6 7 TextView timerTextview; 8 int score = 0; 9 int numberOfQusetions = 0; 10 11 12 13 //ゲーム開始時のカウントダウンタイマーの残り時間を表す定数 14 final int remainingTime = 21; 15 //カウントダウンタイマーのカウントダウンの間隔を表す定数 16 final int countDownInterval = 1000; 17 18 MediaPlayer bgm; 19 20 21 TextView scoreTextView; 22 23 24 25 //playaAgainボタンを押したときの挙動を定義 26 public void playAgain(View view) { 27 score = 0; 28 numberOfQusetions = 0; 29 bgm = create(getApplicationContext(), R.raw.startshort); 30 31 //残り何秒か表示 32 timerTextview.setText(remainingTime + "s"); 33 34 //何問中何問正解しているか表示 35 scoreTextView.setText("0/0"); 36 37     //playAgainButtonを見えなくする 38 playAgainButton.setVisibility(View.INVISIBLE); 39 40 //新しい問題と選択肢を表示 41 newQuetion(); 42 43 44 45 //BGM再生開始 46 bgm.start(); 47 48 //4つのボタン(選択肢)出現 49 buttonShow(); 50 51 52 53    //カウントダウンタイマーをスタートさせる 54 new CountDownTimer(remainingTime * 1000, countDownInterval) { 55 56 //CountDownTimerクラスのメソッドを上書き 57 @Override 58 //カウントダウンしている間の挙動 59 public void onTick(long millisUntilFinished) { 60 61 //残り何秒か表示 62 timerTextview.setText(String.valueOf(millisUntilFinished / 1000) + "s"); 63 64 } 65 66 @Override 67 //カウントダウンが0になった時の挙動 68 public void onFinish() { 69 70 bgm.stop(); 71 72 73 //playAgainButton出現 74 playAgainButton.setVisibility(View.VISIBLE); 75 76 } 77 78 }.start(); 79 80 } 81

追記

コードが長いので、機能を絞ったアプリを新たに作り、
コメントで教えていただいたCountDownTimerを拡張したクラスを新しいファイルにコピペしてつかってみました。

イメージ説明

MainActivity.Javaに

Java

1 //BGM 2 MediaPlayer bgm; 3 //効果音 4 MediaPlayer se1; 5 6 CountDownTimer timer; 7 8 //BGMが流れているか 9 boolean bgmPaused =false; 10 11 12     //アプリ中断時、BGMとカウントダウンを止める 13     @Override 14 public void onPause() { 15 super.onPause(); 16 bgm.stop(); 17 bgmPaused = true; 18 bgm.release(); 19 20 timer.pause(); 21 22 } 23      24 25     @Override 26  public void onResume() { 27 super.onResume(); 28 29 if(bgmPaused) { 30 bgm.start(); 31 bgmPaused = false; 32 timer.resume(); 33 } 34 } 35 36

アプリ中断時onPauseメソッドだけであれば、BGM、カウントダウンの停止ができるようになったのですが、
アプリを再び開いたときにBGM、カウントダウンを再開させようとonResumeメソッドを書いたところ、
アプリを再び開くとアプリが「繰り返し停止しています」と表示されるようになってしまいました。

(bgmをpauseしたところから再生再開するメソッドがなさそうだったのでbgm.pauseではなくbgm.stopを使っています)

どのように書いたらアプリ再開時にうまく動作するでしょうか?

↓MainActivity全体

Java

1package com.example.countdowntimer1; 2 3import androidx.appcompat.app.AppCompatActivity; 4 5import android.media.MediaPlayer; 6import android.os.Bundle; 7import android.view.View; 8import android.widget.Button; 9import android.widget.TextView; 10 11import static android.media.MediaPlayer.create; 12 13public class MainActivity extends AppCompatActivity { 14 15 TextView timerTextView; 16 Button playAgainButton; 17 18 //BGM 19 MediaPlayer bgm; 20 //効果音 21 MediaPlayer se1; 22 23 CountDownTimer timer; 24 25 //BGMが流れているか 26 boolean bgmPaused =false; 27 28 29 30 public void playAgain(View view) { 31 bgm = create(getApplicationContext(), R.raw.startshort); 32 bgm.start(); 33 34 //シャキーンを効果音に設定 35 se1 = create(getApplicationContext(), R.raw.shakin1); 36 37 38 timer = new CountDownTimer(10000,1000) { 39 40 41 @Override 42 public void onTick(long millisUntilFinished) { 43 timerTextView.setText(String.valueOf(millisUntilFinished / 1000) + "s"); 44 45 } 46 47 @Override 48 public void onFinish() { 49 timerTextView.setText("Finish!"); 50 se1.start(); 51 bgm.stop(); 52 } 53 }; 54 55 timer.start(); 56 57 58 } 59 60 //ここから追加したコード 61 //アプリ中断時、BGMとカウントダウンを止める 62 @Override 63 public void onPause() { 64 super.onPause(); 65 bgm.stop(); 66 bgmPaused = true; 67 bgm.release(); 68 69 timer.pause(); 70 71 } 72 73 @Override 74 public void onResume() { 75 super.onResume(); 76 77 //BGMが停止していたら 78 if(bgmPaused) { 79 bgm.start(); 80 bgmPaused = false; 81 timer.resume(); 82 83 } 84 } 85 //ここまで 86 87 @Override 88 protected void onCreate(Bundle savedInstanceState) { 89 super.onCreate(savedInstanceState); 90 setContentView(R.layout.activity_main); 91 92 timerTextView = findViewById(R.id.timerTextView); 93 playAgainButton = findViewById(R.id.playAgainButton); 94 95 96 } 97} 98 99 100

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

quadii.shii

2020/03/16 07:21

コードブロックを```Java~```で囲んで、可能であればインデントも再現いただけると読みやすいです。
Ksuke_Android

2020/03/16 08:42

コードをコピペした際にはインデントついていたのですが、プレビューではついておらず、わからないまま投稿してしまいました。ご指摘ありがとうございます。修正しました。
quadii.shii

2020/03/16 10:17

見やすくなりました。修正ありがとうございます。
guest

回答1

0

ベストアンサー

概要

アプリを起動したり、終了したり、バックグラウンドに入れたり、もう一度前面に出したりといった操作に合わせて、挙動を制御するにはAndroidのライフサイクルを理解する必要があります。

「Android ライフサイクル」などでググればたくさん情報が出てきます。
以下は公式サイトですが、
https://developer.android.com/guide/components/activities/activity-lifecycle?hl=ja

公式サイトでは情報量が多すぎて苦手という人の場合は、短くまとめてくれている個人サイトもあるのでそれらを参考にできます。

実装

手っ取り早く説明すると、ホームボタンを押してバックグラウンドに入れるときの処理はonStop()onPause()内に記述し、起動時または復帰時の処理はonStart()onResume()に実装します。

それぞれに呼び出される順番やタイミングが決まっていますが、私は深く考えずに適当に使っています。

貴方の実装を見る限りではCountDownTimerというクラス(抽象クラスでしょうか)のメソッドのいくつかをオーバライドして使っておられるようです。
本来ならCountDownTimerクラスのソースも掲載していただくのが正なのですが、こちらのクラスにonPauseやonResumeという名前のメソッドを実装してActivityのonPause内やonResume内で呼び出すのが一番スマートだと思います。

Java

1public class MainActivity extends AppCompatActivity { 2 3 // 省略 4 5 // ここでインスタンス化 6 private CountDownTimer timer = new CountDownTimer(remainingTime * 1000, countDownInterval) { 7 8 //CountDownTimerクラスのメソッドを上書き 9 @Override 10 //カウントダウンしている間の挙動 11 public void onTick(long millisUntilFinished) { 12 13 //残り何秒か表示 14 timerTextview.setText(String.valueOf(millisUntilFinished / 1000) + "s"); 15 16 } 17 18 @Override 19 //カウントダウンが0になった時の挙動 20 public void onFinish() { 21 22 bgm.stop(); 23 24 25 //playAgainButton出現 26 playAgainButton.setVisibility(View.VISIBLE); 27 28 } 29 30      // このあたりを追加 31 public void onResume() { 32 // 再開時の処理 33 } 34 35 public void onPause() { 36 // 中断時の処理 37 } 38 } 39 40 @Override 41 public void onPause() { 42 timer.onPause(); 43 } 44 45 @Override 46 public void onResume() { 47 timer.onResume(); 48 } 49 50 51 //playaAgainボタンを押したときの挙動を定義 52 public void playAgain(View view) { 53 54 // 省略 55 56    //カウントダウンタイマーをスタートさせる 57 timer.start() 58 59 }

このやり方で注意が必要なのは、アクティビティライフサイクルを学習していただけばわかりますが、アプリが起動時にもonResumeは呼ばれますので、その時点でtimerのonResumeが呼ばれてもよいような実装になっていなくてはなりません。
初期化抜けなどがあるとヌルポが出るので注意が必要です。

追記

コメントいただいた通り、私どもは知らなかったのですがCountDownTimerというのはAndroid標準の抽象クラスなのですね。

その場合、ライフサイクルに合わせて中断したり再開したりという機能を追加することは難しいかと思います。

「count down timer suspend」で検索したら

こういうのが出てきたので貼っておきます。
CountDownTimerをさらに拡張した抽象クラスを作ってくれた人がいるようです。

この中のpauseとresumeをオーバライドすれば動きそうですね。

投稿2020/03/16 10:39

編集2020/03/16 13:54
quadii.shii

総合スコア257

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

quadii.shii

2020/03/16 13:34

知りませんでした。こういうのがあるのですね。ありがとうございます。
quadii.shii

2020/03/16 13:37

と、なると中断機能の追加は無理そうです。
Ksuke_Android

2020/03/19 03:31

コメントありがとうございます。色々試してみてうまくいかなかったので追記しました。
jimbe

2020/03/19 03:38

onPause で bgm.release() すると MediaPlayer が解放され, onResume の bgm.start() で失敗しているのではないでしょうか.
Ksuke_Android

2020/03/19 06:36

コメントありがとうございます。 bgm.release()を消したら、アプリを再開した際、アプリが停止することなく中断時のカウントからカウントダウンが再開するようになりました! また、bgm.stop()をbgm.pause()に変えたら、アプリ再開時にBGMも中断時の部分から再生されました!
Ksuke_Android

2020/03/19 06:39

コメントありがとうございます。 bgm.release()を消したら、アプリ再開時に中断時のカウントからカウントダウンが始まるようになりました! また、bgm.stop()をbgm.pause()に変えたら、アプリ再開時に中断時の部分からBGMが再生されるようになりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問