サービス(バックグラウンド処理)&通知(非推奨)
Serviceクラスを継承したクラスをつくる(SoundManageService.kt)
Kotlin+Javaフォルダを右クリックして[New] -> [Service] -> [Service] を選択します
Class Name:任意の名前(SoundManagerService)
Exported:チェックを外す
Enabled:チェックしたまま
class SoundManagerService : Service() {
companion object {
private const val CHANNEL_ID = "soundmanagerservice_notification_channel"
}
private var _player: MediaPlayer? = null
// チャネル名や重要度を設定したchannelを生成し、createNotificationChannelする
override fun onCreate() {
_player = MediaPlayer()
val name = getString(R.string.notification_channel_name)
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance)
val manager = getSystemService(NotificationManger::class.java)
manager.createNotificationChannel(channel)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val mediaFileUri = Uri.parse("android:resource://${packageName}/${R.row.mountain_stream}")
_player?.let {
it.setDataSource(this@SoundManagerService, mediaFileUri) <--- データソース(音声ファイル)をセットする
it.setOnPreparedListener(PlayerPreparedListener())
it.setOnCompletionListener(PlayerCompletionListener())
it.prepareAsync() <--- 非同期でメディア再生を準備する
}
return START_NOT_STICKY <--- サービスが強制終了された場合に再起動しないようにする
}
// サービスを終了させたときの処理
override fun onDestroy() {
_player?.let {
if(it.isPlaying) { it.stop() }
it.release()
}
}
// メディアの再生準備が完了したときのリスナクラス
private inner class PlayerPreparedListener: MediaPlayer.OnPreparedListener {
override fun onPrepared(mp: MediaPlayer) {
// メディアを再生する
mp.start()
// 通知からアクティビティを起動させる
val builder = NotificationCompat.Builder(this@SoundManageService, CHANNEL_ID)
builder.setSmallIcon(android.R.drawable.ic_dialog_info)
builder.setContentTitle(getString(R.string.msg_notification_title_start))
builder.setContentText(getString(R.string.msg_notification_text_start))
val intent = Intent(this@SoundMangerService, MainActivity::class.java)
intent.putExtra("fromNotification", true)
val stopServiceIntent = PendingIntent.getActivity(this@SoundManageService, (), intent, PendingIntent.FLAG_IMMUTABLE)
builder.setContentIntent(stopServiceIntent)
builder.setAutoCancel(true) <--- 通知メッセージをタップすると自動で消去されるようにする
val notification = builder.build()
startForeground(200, notification)
}
}
// メディア再生が終了したときのリスナクラス
private inner class PlayerCompletionListener: MediaPlayer.OnCompletionListener {
override fun onCompletion(mp: MediaPlayer) {
// 通知を出す
val builder = NotificationCompat.Builder(this@SoundManageService, CHANNEL_ID)
builder.setSmallIcon(android.R.drawable.ic_dialog_info)
builder.setContentTitle(getString(R.string.msg_notification_title_finish))
builder.setContentText(getString(R.string.msg_notification_text_finish))
val notification = builder.build()
val manager = NotificationManagerCompat.from(this@SoundManageService)
manager.notify(100, notification) <-- 100はNotificationを識別するための番号
// メディア再生をストップする
stopSelf()
}
}
}
AndroidManifest.xml
// AndroidManifest.xmlにサービスが登録されているか確認する
<Service
android:name=".SoundManageService"
android:enabled="true" <--- サービスを利用するかどうか
andriod:exported="false"> <--- サービスを外部のアプリから利用できるかどうか
</Service>
// 通知のパーミッション
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission andriod:name="andriod.permission.FOREGROUND_SERVICE" />
MainActivity.kt
// 再生ボタンタップ時の処理
fun onPlayButtonClick(view: View) {
val intent = Intent(this@MainActivity, SoundManageService::class.java)
startService(intent)
val btPlay = findViewById<Button>(R.id.btPlay)
val btStop = findViewById<Button>(R.id.btStop)
btPlay.isEnabled = false
btStop.isEnabled = true
}
// 停止ボタンタップ時の処理
fun onStopButtonClick(view: View) {
val Intent = Intent(this@MainActivity, SoundManageService::class.java)
stopService(intent)
val btPlay = ...
val btStop = ...
btPlay.isEnabled = true
btStop.isEnabled = false
}
ーーーーーーーーーーーーーーーーーーー
ーーーーーーーーーーーーーーーーーーー
ーーーーーーーーーーーーーーーーーーー
通知チャネルの作成
class SoundManageService : Service() {
private var _player: MediaPlayer? = null
}