Only the original thread that created a view hierarchy can touch its views.
タイマーで一定間隔おきに現在のボリュームをチェックして、その結果をViewに表示したかった。
KotlinではTimerの書き方が簡略化されているので、次のように書いてみた。
class MainActivity : AppCompatActivity() {
override fun onResume() {
Timer().schedule(1000, 1000) {
// ボリュームを取得
val ringVol = audio.getStreamVolume(AudioManager.STREAM_MUSIC)
if (ringVol == 0) {
// ミュート中
linVolumeNotice.visibility = View.VISIBLE
} else {
linVolumeNotice.visibility = View.INVISIBLE
}
}
}
}
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
オリジナルのスレッドからしかViewは変更できない。
タイマーの起動と停止
Handlerを使ってシングルスレッドにする。
とりあえずこれで出来た。
class MainActivity : AppCompatActivity() {
private var mTimer: Timer? = null
private val mHandler = Handler()
override fun onResume() {
val audio = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val linVolumeNotice = findViewById(R.id.linVolumeNotice) as LinearLayout
mTimer = Timer()
mTimer!!.schedule(object : TimerTask() {
override fun run() {
mHandler.post {
// ボリュームを取得
val ringVol = audio.getStreamVolume(AudioManager.STREAM_MUSIC)
if (ringVol == 0) {
// ミュート中
linVolumeNotice.visibility = View.VISIBLE
} else {
linVolumeNotice.visibility = View.INVISIBLE
}
}
}
}, 1000, 1000)
}
}
今回はOnResume()に書いたので、onPause()にタイマーをキャンセルする処理も必要になる。
override fun onPause() {
//タイマーの停止
mTimer!!.cancel();
mTimer = null;
}
!!が多くて格好悪い。もっといい方法はないのか。