【Android/Kotlin】スマートフォンでカップ麺タイマーをつくる3:タイマーが0になったらSoundPoolで音を鳴らす

投稿日:2021年2月9日
最終更新日:2021年2月9日

カップ麺タイマーに通知のアラームを追加

前回はカウントダウンするタイマーが0になったときにバイブレーション機能を使ってスマホを振動させてみたが、これだけだと通知としてちょっと不親切なので、今回はオーディオファイルを再生してアラームを鳴らす機能を追加してみる。

 

環境

開発PC環境

Windows 10
Android Studio 4.1.1

実行Android環境

機種:Xperia X Performance SOV33

Androidバージョン:7.0

 

オーディオファイル(mp3)の置き場所

https://soundeffect-lab.info/の「目覚まし時計のアラーム」という効果音を使わせて頂いた。ダウンロードしたmp3ファイルをalarm.mp3に名前を変えて、resフォルダ以下に「raw」というフォルダをつくって置く。

 

Kotlinのコードとレイアウト

今回は参考文献のコードを参考に以下のようにMainActivityのKotlinコードを書いた。前回はCountDownTimerのonFinishでバイブレーションを呼び出したが、同じタイミングでSoundPool.playを呼び出して音を再生している。SoundPoolはAndroidのAPI level 21 (Android 5.0 Lollipop)から使い方が変わってたので、Lollipop以降のAndroidを想定したコードになっている。ゆくゆくはそれ以前のスマホも対応できるようにはしたいが。

package com.example.cupnoodletimer
import android.content.Context
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.*
import android.widget.Button
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
val TIMERTIME: Long = 180000;
lateinit var timerText: TextView
lateinit var timer: CountDownTimer
var isRunning: Boolean = false;
lateinit var soundPool: SoundPool
var soundAlarm = 0
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val startButton: Button = findViewById(R.id.buttonStart)
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.build()
soundPool = SoundPool.Builder()
.setAudioAttributes(audioAttributes)
.setMaxStreams(1)
.build()
soundAlarm = soundPool.load(this, R.raw.alarm, 1)
startButton.setOnClickListener {
if (isRunning) {
timer.cancel()
setTime(TIMERTIME)
isRunning = false
startButton.text = "START"
} else {
timer = object : CountDownTimer(TIMERTIME, 1000) {
override fun onTick(millisUntilFinished: Long) {
setTime(millisUntilFinished)
}
override fun onFinish() {
setTime(0)
isRunning = false
startButton.text = "RESTART"
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
val vibrationEffect = VibrationEffect.createOneShot(5000, VibrationEffect.DEFAULT_AMPLITUDE)
vibrator.vibrate(vibrationEffect)
} else {
vibrator.vibrate(5000)
}
soundPool.play(soundAlarm, 1.0f, 1.0f, 0, 0, 1.0f)
}
}
timer.start()
isRunning = true
startButton.text = "RESET"
}
}
}
private fun setTime(t: Long) {
timerText = findViewById(R.id.textViewTime)
var time: Long = t
var minutes: Long = (time / 1000) / 60
var seconds: Long = (time / 1000) % 60
timerText.setText("%d:%02d".format(minutes, seconds))
}
}

こちらがレイアウトの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/textViewTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="3:00"
android:textSize="72sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/buttonStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="START"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewTime" />
</androidx.constraintlayout.widget.ConstraintLayout>

実行画面も前回と変わらないので省略するが、これでタイマーが0になったときにアラームで通知されるようになった。ただ、実装してから気づいたけどSoundPoolで音を鳴らすとスマホで設定した音量ではアラームが再生されず、あくまでSoundPool.playのrightVolumeとleftVolumeで設定した音量でされてしまう。

これだと音量を小さく設定していても大きな音でアラームが鳴ってしまってちょっと困るので、次回は現在のスマホの設定ボリュームを取得して、その値をrightVolume/leftVolumeに設定するようにコードを変えてみたいと思う。

 

参考文献

今回は以下のサイトを参考にさせて頂きましたm(_ _)m

[Android & Kotlin] SoundPool で効果音を鳴らす

 

Androidアプリをつくって遊ぼう日記まとめ

以下にAndoirdアプリで遊んでみた軌跡を残しています。興味があればのぞいてみてください。

【Android】Androidアプリをつくって遊ぼう日記

0

投稿者: wakky

映画と旅行が大好きなエンジニア。お酒、ゲーム、読書も好き。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください