Android:Handlerで正確に周期的な実行

Handlerを使って 500ms間隔で 処理を実行する場合、以下のようにすると思います。ちなみにkotlinです。

    val handler = Handler()
    val runnable = object : Runnable {
        override fun run() {
            doHeavyWork() //重い処理
            handler.postDelayed(this, 500)
        }
    }

しかし、doHeavyWork()に処理時間が多くかかるばあい、その分の時間を差し引かなくてはいけません。例えば、 doHeavyWork() に300msかかるならpostDelayed(this, 200)にします。いや、そもそも doHeavyWork() にかかる時間は機種ごとに違うし、始めからわかってる事なんてほとんどないでしょう。

そこで、以下のようにします。

    val handler = Handler()
    val runnable = object : Runnable {
        override fun run() {
            val t = SystemClock.uptimeMillis()
            doHeavyWork() //重い処理
            handler.postAtTime(this, t + 500)
        }
    }

こんな感じにすると、いい感じになります。しかし、doHeavyWork()が500ms以上かかる場合はそもそも無理。video再生的なものならフレームをスキップするとか工夫が必要です。

ListViewの中のEditTextで編集できない

ListViewの中に編集可能なTextViewを入れると、IMEが表示されるタイミングでListViewのサイズが変わり、編集中のTextViewからフォーカスが外れる。そして、1文字しか入力されない。

ひとまず、AndroidManifest.xmlのActivityの属性に

android:windowSoftInputMode = "adjustPan"

を加えると、解決しているっぽい。

以前作った同じようなListViewはたまたまサイズが小さくて、IMEが表示されてもリサイズされていないだけだった。

NotificationChannelで通知音が消えない

        val channel = NotificationChannel(channelID, title, NotificationManager.IMPORTANCE_DEFAULT)
        channel.setSound(null, null)

このように、setSound(null, null)で通知音が消えるとあったので試したが、どうしても消えない。通知の優先度を落としても消えない。かなり悩んだが、いったんアプリをアンインストールしたらうまくいった。いったん作ったチャンネルを削除しなければいけないのかな?

アプリ公開

BokuMemoというAndroid用メモ帳アプリを公開しました。

タブでメモをグループ化し管理できることと、パソコンのメーラーみたいにリスト表示とプレビューがあるのが特徴です。

windows mobileの時代に同じようなメモ帳を作っていたのですが(非公開)、ふと思い立ってAndroidで作ってみました。休日と平日の1時間くらいでほぼ1か月かかりました。

今回、初めてのAndroidアプリでかなり勉強になりました。kotlinいいですね。ちなみに、Javaはよくわかりません。普段は趣味でC#やC++やC、ごくたまにPythonな感じです。

しかし、GooglePlayで公開するまでが大変だった。今日、一日かかってしまった、、、。

池の白鳥

近所の池に2羽の白鳥が住んでいます。その池が工事中でしばらく通っていなかったのですが、工事が終わったので久しぶりに行きました。この時期になると、白鳥が巣を作っています。今年はその場所がいつもと違っていました。

いつもの場所。
今年の場所。巣作り中。
もう一羽は少し離れたところにいます。

いつもの場所にあるわらは、誰かが敷いたのかな?もう一羽が警戒中なので、ちょっと近寄りずらかった。

つくし

今日は一日休みをもらって、母親を病院へ連れて行きました。実は、しばらく母親が入院していました。今は元気です。その関係で郵便局へ保険の相談にも行きました。入院証明がいるので、また病院へ行かなければいけないですねぇ。

その後、散歩がてら趣味の(?)土筆取り。いい感じで気分転換ができました。

タブのフラグメントが欲しい

TabLayoutとViewPagerとFragmentStatePagerAdapterでタブを作っていて、Fragmentの一覧がほしかった。 FragmentStatePagerAdapter のgetItemかと思ったが、それは新規に作られてしまうのでよろしくないというか違う。調べたら以下のようにしたらできた。

    fun findFragmentByPosition(viewPager : ViewPager, position : Int) : Fragment{
        val adapter = viewPager.adapter!! as FragmentStatePagerAdapter
        return adapter.instantiateItem(viewPager, position) as Fragment
    }

いや、できた気がする。