
前回、前々回でカウントダウンタイマーを作ってみました。
スタートボタンを押すと、カウントダウンされ、
ストップで停止。
で、リスタートボタンで続きから開始されるというものでした。
今回はその続きで、ちょっとだけオマケで、このようにカウントが0になって終了したら、アラームを鳴らしてみたいと思います。アラーム音は、第23回のところで使ったMediaPlayerの復習になります。
使用音楽素材:効果音ラボさんのフリー素材「目覚まし時計のアラーム」
動画
コード
▼activity_main.xml
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 | <? xml version = "1.0" encoding = "utf-8" ?> < androidx.constraintlayout.widget.ConstraintLayout xmlns:android = "http://schemas.android.com/apk/res/android" android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".MainActivity" > < TextView android:id = "@+id/tv" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "00:00" android:textSize = "50sp" android:textStyle = "bold" app:layout_constraintBottom_toBottomOf = "parent" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toTopOf = "parent" /> < Button android:id = "@+id/btnStart" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginTop = "32dp" android:text = "START" app:layout_constraintEnd_toStartOf = "@+id/btnStop" app:layout_constraintHorizontal_bias = "0.5" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toBottomOf = "@+id/tv" /> < Button android:id = "@+id/btnStop" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginTop = "32dp" android:text = "STOP" app:layout_constraintEnd_toStartOf = "@+id/btnRestart" app:layout_constraintHorizontal_bias = "0.5" app:layout_constraintStart_toEndOf = "@+id/btnStart" app:layout_constraintTop_toBottomOf = "@+id/tv" /> < Button android:id = "@+id/btnRestart" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginTop = "32dp" android:text = "RESTART" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintHorizontal_bias = "0.5" app:layout_constraintStart_toEndOf = "@+id/btnStop" app:layout_constraintTop_toBottomOf = "@+id/tv" /> < Button android:id = "@+id/btnReset" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:text = "RESET" app:layout_constraintBottom_toBottomOf = "parent" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintStart_toStartOf = "parent" /> </ androidx.constraintlayout.widget.ConstraintLayout > |
▼MainActivity.kt
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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | package com.example.simplecountdown import android.media.MediaPlayer import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.CountDownTimer import android.widget.Button import android.widget.TextView class MainActivity : AppCompatActivity() { //8)横断的に使うやつを用意 private lateinit var timer:CountDownTimer private var remainingTime:Long = 0 //9)残り時間(後で代入するので一旦0) private lateinit var mp:MediaPlayer //12) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //1)開始時間を設定 val startTime:Long = 10000 //10秒 //1)viewを取得+tvに開始時間を表示 val tv:TextView =findViewById(R.id.tv) val btnStart:Button =findViewById(R.id.btnStart) val btnStop:Button =findViewById(R.id.btnStop) val btnRestart:Button =findViewById(R.id.btnRestart) val btnReset:Button =findViewById(R.id.btnReset) tv.text ="${startTime/1000}" //開始時間を秒で表示 //2)ボタンの有効・無効 btnStart.isEnabled = true btnStop.isEnabled = false btnRestart.isEnabled = false //4)カウントダウンタイマーのオブジェクトを用意 //val timer = //3)スタートボタンを押したらカウントダウン btnStart.setOnClickListener { //5)「4」のtimerをスタート //timer.start() //10)startTimeでカウントダウン開始 timer = countDownTimer(startTime).start() btnStart.isEnabled = false btnStop.isEnabled = true btnRestart.isEnabled = false } //6)ストップボタンを押した時の処理 btnStop.setOnClickListener { timer.cancel() //ストップボタンを無効化 btnStart.isEnabled = true btnStop.isEnabled = false btnRestart.isEnabled = true } //7)リスタートボタンを押した時の処理 btnRestart.setOnClickListener { //10)remainingTimeでカウントダウン開始 timer = countDownTimer(remainingTime).start() btnStart.isEnabled = false btnStop.isEnabled = true btnRestart.isEnabled = false } //11)リセットボタン btnReset.setOnClickListener { timer.cancel() remainingTime = 0 tv.text ="${startTime/1000}" //開始時間を秒で表示 //2)ボタンの有効・無効 btnStart.isEnabled = true btnStop.isEnabled = false btnRestart.isEnabled = false //14)mp停止 mp.stop() mp.release() } } //8)「4」を関数でここに用意 private fun countDownTimer(st:Long):CountDownTimer{ val tv:TextView =findViewById(R.id.tv) val btnStart:Button =findViewById(R.id.btnStart) val btnStop:Button =findViewById(R.id.btnStop) val btnRestart:Button =findViewById(R.id.btnRestart) return object :CountDownTimer(st,100){ //[4-1]途中経過・残り時間 override fun onTick(p0: Long) { //TODO("Not yet implemented") //残り時間を表示 tv.text ="${p0/1000}" //秒単位 remainingTime = p0 //9)残り時間を代入 } //[4-2]終了設定 override fun onFinish() { //TODO("Not yet implemented") tv.text ="タイムアップ" //終了時は3つ全部無効 btnStart.isEnabled = false btnStop.isEnabled = false btnRestart.isEnabled = false //13)MediaPlayerを再生 mp = MediaPlayer.create(this@MainActivity,R.raw.alarm) mp.isLooping =true mp.start() } } } } |
テキスト
それでは音楽ファイルが用意できたらはじめて行きましょう。
一応、復習がてらMediaPlayerの使い方について改めて解説しておくと
①まずres、リソースの中にrawフォルダを作って、その中に音楽ファイルを入れる
②MediaPlayerをインポート
③最後に鳴らしたいところに開始の記述を書く
という流れになります。
12)rawとMediaPlayer
それではまずrawフォルダを用意して、その中に音楽ファイルを入れていきましょう。
てことで、左側のres、リソースを開いてください。
rawフォルダは、最初の段階では用意されていないので
使いたい人が、使いたい時に作ってあげます。
resを右クリック⇒new⇒で、フォルダなんですけどプログラミングではちょっとカッコつけて
ディレクトリといいます
raw と入力してエンター。
これでrawフォルダが出来ましたので、みなさんご用意の音楽ファイルを
入れてください。
ここではファイル名をalarmとしています。
このままドラッグ&ドロップでもいいですし
ctrlを押しながらするとコピーになります。
はいこれでrawフォルダに音楽ファイルが入りました。
ではMediaPlayerをインポートしましょう。
場所はonCreateの上、厳密には クラスの下。
ここにprivate valで宣言してとりあえず名前をつけてあげます。
MediaPlayer略してmp
これに続けてMediaって入れるとMediaPlayerってのがあるので選択。
そうするとMediaPlayerがインポートされて、この人 mp は
MediaPlayerのクラスが使えるようになりました。
ただし、今は名前を付けただけで、本当はこっちにイコールで中身を入れてあげなければいけません。
今はここでは名前だけつけて、中身はonCreateの中で書いていくので、宣言する場所と、中身の場所が違うと。
てことで、中身は後でね、って言う場合は
前回説明のとおり
初期化を遅らせるということでlateinitを使うんでしたね。
private につづけて
lateinitの場合は、valではなくってvar。
これで下準備は完了です。
次にmpを必要なところに書いていきましょう。
1 | private lateinit var mp :MediaPlayer //12) |
13)mpと、start()
それでは、今名前を付けたmpを使って、メディアプレイヤーを再生していきましょう。
音楽を鳴らすタイミングは、もちろんタイマーが終わった時なので、
CountDownTimerの、onFinishの方ですね。
この波カッコの中に書いていきましょう。
mp= MediaPlayer.create~
ここではじめて中身が入ります。
で、前回はここに自分自身ということでthis、とかいて
続けてファイルの場所であるR.raw.alarm と書かいてくださいって説明したと思うんですが。
今回なんかエラーが出ています。
None of the following functions can be called with the arguments supplied
これ、javaをやってた方はピンと来るかもしれないんですけど、
あー、ここは、MainActivity.thisね、と。それで正解ちゃ正解なんですけど、kotlinは書き方だけちょっと違います。
正解を言っておくと
this@MainActivity
と記述します。まず、一から、ちょっと理屈っぽく説明しますね。
そもそもこのthisっていうのは自分自身という意味なんですけど
厳密には「自身のクラス」という意味です。
てことで、今回の場合のthisは、このカウントダウンタイマーのクラスをさすので
画面全体を指定する場合には@(アットマーク)に続けてMainActivityを書いてあげる必要がります。
てことで、ひとまず理屈っぽく説明すると以上になります。
が、ぶっちゃけ、よーわからんなって人はですね
thisって書くところは、「thisか、this@アクティビティ名」、
この2択でなんとかなります。
てことで、これで無事、mpの中に色々入りましたのでもう少し書いていきましょう。
まず1つ目は1曲目が終わったらループをさせたいので
mp.isLooping = true
あとはスタートさせてあげればいいので
mp.start()
これで音楽は流れるようになりました。
ただし今は音楽が流れっぱなしなので、
リセットボタンを押したら音楽を止めてあげましょう。
14)MediaPlayerを停止
アラーム音を停止するのは
リセットボタンが押された時なので
btnResetの波カッコの中に書いていきます。
1 2 3 | //14)mp停止 mp.stop() mp.release() |
まずは音楽を止めて
mp.stop()
メモリを解放します
mp.release()
さあ、これで完成です。
エミュレータを起動して、アラーム音がなるか、確認してみましょう。