<<
<
2017 年 10 月
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

2016/1/1 から日記を書いています。
今まで 659 件の日記を書きました。

この日記で公開されている写真は 297 枚です。
良かったらギャラリーもご覧になってください。

会社で以前使用していた USB 扇風機であるシルキーウィンドのモーターが弱くなってしまい風がほとんど来なくなってしまったので、今回最新版であるシルキーウィンド S を書い直した。 最初のモデルのシルキーウィンドに関しては 3 年前に購入し職場で結構頻繁に使っていたのだが今まで持った。 レビューを見てみると 2 ~ 3 ヶ月しか持たないような書き込みをしている人も見受けられたが、運悪くハズレを引いてしまったのだろうか。

ともかく、早速会社で使ってみたが、2 段階の風量調節と角度調整 (上向きにできる) 機能は旧モデルと同じだ。 しかし旧モデルとは比べ物にならないくらい静かで、回転音はわずかに聞こえるがほぼ無音である。 風量も十分にあり満足な一品と言える。 ただ Amazon でも現在 2,000 円強するので、安く済ませたい場合は旧モデルがいいのかもしれない。 私はこれより安い 1,000 円未満の USB 扇風機も使っていたことがあったのだが、そちらはやはり値段なりというか風量が十分ではないし耐久性がなくあまり持たなかった。

旧シルキーウィンドを会社で使っていてあまりに気に入ったので自宅でもシルキーウィンド II を購入し使っているのだが、こちらには首振りの機能が付いている。 しかし基本的にこういった小型の扇風機は一人で使うものだと思うので首振り機能が必要な人は少ないのではないだろうか。 動作音・風量・値段のすべてにおいて新型のシルキーウィンド S の方が優れているので、今この旧モデルを買う必要はないだろう。

何かあまり書くことがないが、それでも毎日書く。 それがこの日記のルールである。 毎日継続することに意味がある。

本日はまた例年 12 月並の寒さだったらしい。 昼休みに食べに出かけるときは確かに寒かった。 自宅ではソファーを捨てたタイミングでコタツを妻が出してくれたので、子どもたちも喜んでいるようだ。 私も子どもの頃は実家のコタツに深く入ったりして快適に過ごしていたものだった……。

明日は今日よりは暖かいようだが、それでも少し涼しいようなので明日のお昼はラーメンにしようと思った。 ラーメン屋もこれからが売り時だろう。

HUAWEI の最新フラッグシップモデルである Mate 10 と Mate 10 Pro が発表されたようだ。 今回は Mate 10 Pro の方も日本で販売するらしい。 期待を裏切らない感じで素晴らしい。 Pro の方は薄型化の為かヘッドフォン端子を廃止してきたようだ。 まぁ端末のほうがこうなってきたら私もまた Bluetooth イヤホンに戻すだけだが、やはり不満がある人はいるだろう。 USB-C への変換アダブタがシンプルなものになっているのならば有線もアリかもしれない。

私は今 Mate 9 を使用しているが、特に不満点はなく素晴らしいファブレットだと思っている。 だが、先日書いた通り 1 台で何でもやるというスタイルを辞めたいので、次も 6 インチ級のスマートフォンを買おうとは今のところ考えていない。 要件としては可能であれば防水、最低防滴の普通サイズのスクリーンのスマートフォンといったところか。 Mate 9 が時代遅れになってきてからで良い。

私としてはそれよりも MediaPad M3 の後継機が気になるのだが、情報は出てこなかった。 MediaPad M3 Lite 10 を使いながら続報を待つことにする。

私の住んでいる家のリビングに大きなソファーを置いているのだが、購入して 9 年以上経つが使ったのは最初だけでありほとんどの場合ただの物置になってしまっているので、今回思い切って捨てることにした。 私の住んでいる町では粗大ゴミは特に大きさなど関係なく定額のようだ。 大きいので家の外に出すのが大変ではあるが、ちょっと得した気分だ。

今の家に移り住む時に「やっぱり広いリビングにはソファーだよね」という固定観念から部屋に合いそうなものを置いたのだが、よくよく考えてみたら実家でもソファーは全く使っていなかったし、賃貸住まいの時も同様だった。 ではどこに座っているのかというところだが、子どもは絨毯の上に直接座っているし大人であってもそうしたりちょっとした座椅子を使ったりしている。 そちらの方が何故か楽なのである。 それに冬はコタツを出して使っているのでますますソファーは使わない。

今後ソファーを買うことは無いだろうな、というのが今回の感想となった。

今日は一日中雨で、かつ結構涼しく日中でも 12℃ 程度までしか上がらないということだった。 これは東京で言うところの例年 12 月の気温とのことだが、正直自分としてはそこまで寒いとは思わなかった。 バイク乗りとそうでない人とでは感覚が違うのかもしれないが、バイクに乗っているときの方が余程寒いのでこの程度で騒ぐほどのことはないと感じてしまう。

とにかく、今日はなかなか涼しくていい塩梅だ。 こういう日は日本酒が合うのかもしれないが、私は日本酒は一切飲まない上ビールも夏の終わりに辞めてしまって今は全く飲んでいない。 今後子どももどんどん大きくなっていきお金がかかるようになっていくし、税金も増える一方だ。 そこでどこかから削ろうかというところで真っ先に対象となるのは私の酒代ということだ。 健康にもいいし一石二鳥、要は習慣なので全く問題ではない。

これでやっていけなくなったら次は趣味から削っていくことになるが、バイクや車あたりだろうか。 趣味を減らすと人生体験が貧相になってしまうが、生きるためには仕方がない。 お金のかからない趣味をやるという選択肢もある。 その点英語の学習はなかなかいい趣味だ。 難点は未だにそこまで楽しいとは思えない点だが……。

今日は天気予報通り雨なので家でゆっくり英語の勉強をしたりしていた。 また、土日しかできない部屋の整理も行った。

楽天の買い回りセールが始まったので会社で使う USB 扇風機を購入。 自宅だと扇風機は夏場しか使わないが、会社の場合寒い人に合わせて室温が調節されているのもあって冬であっても扇風機が必要になっている。 リズム時計工業株式会社のシルキーウィンドという製品を愛用しているので今回もそれにした。 ちょうど今年に最新版のシルキーウィンド S が出たようなので丁度いい。 充電式のシルキーウィンド III というのも面白そうだが私の生活の中では USB 扇風機を持ち歩くというシーンが思いつかなかったので買わないだろう。

そういえば、電力不足の際は会社で USB 扇風機でさえも使用禁止にされた時があったが、今ではそんな事も懐かしい。 地震の日は電車も動かず東京の街を頑張って歩いたものだった……。

天気予報によると微妙な感じだったが、明日も雨のようなので仕方なく街乗りに出かけた。 しかし出発した後程なくして雨に降られてしまった。 一応簡易防水がついた装備をしていたのだが、ヘルメットが濡れて視界が悪いのはどうしようもないし、やはり少し肌寒い。 ちなみにペアスロープのサンステートライナー (単体で売っているフリースの方でなく革ジャンにオプションで装着する方) を仕込んでいたのだが、昨年の感想同様そこまでの効果は見込めなかった。 昨年 10 月 30 日に同じような装備で秩父に行った時に寒さで悶絶したので、あと 1 ヶ月くらいの街乗りくらいにしか使えない。 バイクで快適に乗れる季節は実はとても短いのだと再認識した。

そして、今年もバイク用の冬用ボトムの出番となった。 去年使用して大変満足した GSM13655 だが、今日使っていたがやはり素晴らしい。 程よく温かいし、何より簡易防水がついているので不意の雨にも安心なのがいい。 雨に強いのでバイクに乗っていないときでも雨の日に着ていくと安心感がある。 これがあまりに気に入ったので今年の夏にゴールドウインの夏用のパンツも購入したのだが、そちらは冬用よりも更にタイトになっており若干脱ぎにくい上に防水ではないので個人的にはこちらの冬用の製品のほうが勝ると思っている。 恐らく冬用の方は防寒のために中にインナーを仕込む分の余裕を持たせているのだろう。 今年の初めにうっかりマフラーに当ててしまい少し穴が空いてしまったので今年頑張って使って終わりというところだが、来年はこれの上位モデルであるウォームカーゴパンツを買ってみたいところだ。

ゴールドウインは好きなバイクアパレルメーカーなのだが、今年になってホームページがカタログ調のものからオンラインストアに変更されてしまった。 これが以前よりかなり見にくくなってしまったので少し残念だ。 公式で買うより楽天や Amazon で買ったほうが安いので公式がオンラインストア化してもメリットはない。

タブレットは 10.1 インチか 8.4 インチか

今私は HUAWEI のタブレットである MediaPad M3 Lite 10 という 10 インチタブレットを使っているのだが、概ね満足であり感想は以前レビューで書いた通りなのだが最近もう少し不満点が出てきた。 私は同様に HUAWEI のハイエンド大型スマートフォンである Mate 9 を使用しているのだが、それより明らかに Wi-Fi の掴みが悪いのである。 私の自室は Wi-Fi ルータから結構距離が離れているのだが、そこだと Mate 9 はほぼ確実に電波を掴めるのに対し M3 Lite 10 の方は一旦スリープに入れて復帰した時など掴めないことが多く Wi-Fi の ON/OFF を繰り返しても結局接続できないことがあり諦めて Mate 9 のテザリングを入れる (Mate 9 側の LTE の残量が結構あるので) などしてしまっている。 多分これは 8.4 インチのタブレットである MediaPad M3 の方を使用すればこちらは廉価版という位置付けではないので Mate 9 と同様に Wi-Fi 電波を掴むのだろう (未検証)。 仕方がないのかもしれないが、こういう風に見えないが必須の部分で差を付けてくるところが少し残念に思った。 HUAWEI が 10.1 インチの方の MediaPad M3 にあたる上位版を出してくれればいいのだが、需要の関係上望みは薄いだろう。

私は以前 Nexus 7 を使用していたことがあり職場にもあるので今でも触ることがあるのだが、私の感覚で恐縮であるが明らかにタブレットとして常用するには苦痛を感じるほど画面が小さい。 今時のスクリーンが大型化したファブレットと比べると「一回り大型化したファブレット」といった印象しか受けず、これならスマートフォン 1 台のみでいいのではと思ってしまう。 そして、私は以前 Nexus 9 という 8.9 インチのタブレットを使用していたが、これは世の中の人からはいろいろと酷評されたようだが自分としてはサイズを含めて割と満足に使用していた。 何より 4:3 の画面比率が Kindle や PDF を読むのに都合が良かった。 ただ PDF を読むのには画面は大きければ大きいほど良い。 10.1 インチタブレットでも「少し文字が小さいかな」と思ってしまう場面があるほどなので 8.4 インチタブレットだと横画面にしてスクロールしないと厳しいだろう。

常々「大は小を兼ねる」と思っているので迷わず 10.1 インチにしたのだが、今後 HUAWEI が M3 と同様に 8.4 インチでのみハイエンド版を出すのであれば次 (M4) はそちらにしようと思った。 よくよく考えるとファブレットである Mate 9 で明らかに守備範囲外なのが PDF 閲覧、次点 Kindle であと動画鑑賞とゲーム、ブラウジングが続くぐらいだが別に 8.4 インチであったとしても少し快適でなくなるのが PDF 閲覧くらいで Kindle 以降は問題ないと思われる。

そもそもスクリーンサイズが一回り小さいと思っていた Nexus 9 (8.9 インチ) より 0.5 インチ下がるのがどうなのか、Nexus 7 より「1.4 インチしか大きくなっていない」のがどうなのかと思っているのだが、ここはスクリーンサイズを調べてみることにする。 こういうのはディスプレイの実寸法を計算するサイトがあるのでそこを利用する。

端末名 画面サイズ (inch) 解像度 横 (mm) 縦 (mm) ppi (参考)
Mate 9 5.9 1920x1080 130.56 73.44 373.374
Nexus 7 (2013) 7.0 1920x1200 151.68 94.8 323.451
MediaPad M3 8.4 2560x1600 181.76 113.6 359.39
Nexus 9 8.9 2048x1536 180.224 135.168 287.64
iPad 2017 9.7 2048x1536 196.608 147.456 263.918
MediaPad M3 Lite 10 10.1 1920x1200 216.96 135.6 224.174

こう見てみるとやはり Nexus 9 の画面比率 4:3 が効いていて縦 (短辺) の長さが 10 インチタブレットと同じくらいの長さだが横 (長辺) の長さが 8.4 インチタブレットと同じくらいという結果になった。 MediaPad M3 は Nexus 9 よりも縦が 2.15 cm くらい短い。 これがちょっと気になるところな気がするのだがどうなのだろうか……。 ただ Nexus 7 よりは 1.88 cm ほど長い。 Nexus 7 は MediaPad M3 Lite 10 の中間くらいでちょっと Nexus 7 寄り。 ……表にすれば分かりやすいかと思ったが却って迷う結果になってしまった。 やはり使ってみないと分からない。

MediaPad M4 がどうなるのか分からないが、少しサイズが大きくなってくれればありがたいと思うばかりだ。 逆にサイズが小さくなってしまった場合は更に困ってしまうことになるが……。

ファブレットやタブレット 1 台持ちよりスマートフォン + タブレット

以前私は「タブレットとスマートフォンを別々に持つよりもファブレットを 1 台だけ持って使ったほうが便利なのでは」と思って Mate 9 のみを使用していた時があった。 人によってはそれが最適解なのだろうし、大きい端末で通話することが気にならないのであれば MediaPad M3 にも通話アプリが付いているのでタブレットのみの運用というのも可能ではある。 だが、私はバイクのナビとしても使用しているのでタブレットのみという選択肢はあり得ない。 タブレットをバイクにマウントする製品も無いことはないが、やはり脱落の危険性が大幅に増えるので常用するには厳しい。 ナビに使用するのにはそんなに大きいスクリーンサイズは必要としないというのもある。 4.5 インチ程度でも十分だ。

ファブレットでも明らかに使う気になれないのは前述の通り PDF と Kindle だ。 ここが必要ない方はスマートフォンのみでも良いのだろう。 ゲームに関してはファブレットでも十分快適であり、私が今使っている MediaPad M3 Lite 10 だと逆に大きすぎて指の可動範囲が広いのがそんなに快適でないように感じる。 そう考えるとやはり 8.4 インチはなかなか考えられたサイズなのかもしれない。 難しい。

ともかく、そういうわけで次買い換えるとしたら出るであろう MediaPad M4 と Mate 9 より少し小さいスマートフォン、できれば防水端末が良い。 ナビとして使う場合に防水が付いていると安心感がまるで違う。

イヤホンジャックが消える日が来るのだろうか

昨今の iPhone では極端な薄型化の為かイヤホンジャックさえも廃止されている。 これは賛否両論あるところだが、もし HUAWEI の端末もこの時流に乗ってきたとしたら私もまた Bluetooth イヤホンに戻すことを考えなくてはならなくなる。 Bluetooth イヤホンは確かにコードが絡まりにくくなるのは長所なのだが、それよりも電池の心配をしなければならないのとペアリングされた複数のデバイスを切り替える時に失敗する場合があるのが気になるところではある。 イヤホンを使うシーンというのは要するに音を漏らすと迷惑である場合がほとんどだと思われるので、例えば電車内などで切り替えたと思ったつもりだったのが切り替わってなくて音を出してしまった……という失敗も何度かあった。 あと「まだ大丈夫だろう」と思って使っていたら突然電池が切れて同様に音を漏らしてしまったケースも何度もあった。 Apple の AirPods は使ったことがないが、値段が高すぎるのでなかなか厳しいところがある。 そもそも iPhone ではないので連携部分の優位性がないので微妙だろうか。

面倒なのでできれば相手をしたくないが

さて、前回Service のプロセスがアプリと同一の場合、つまり通常の場合に Binder を用いて双方向でやり取りする方法に関して考察したが、今回は止むを得ない事情でプロセスを分けなければならなくなった場合に Messenger を用いてプロセス間通信を行う為の実装例に関して記載する。

Service 側の実装に関してコード例を示す:

companion object {

    /** クライアント側からの replyTo 受信. */
    val MESSAGE_RECEIVING_REPLY_TO = 1

    /** クライアントへのメッセージ送信. */
    val MESSAGE_SEND = 2
}

/** サービス側の処理を行うハンドラ. */
private class MyHandler : Handler() {

    /** クライアントの Messenger. */
    var clientMessenger: Messenger? = null

    override fun handleMessage(msg: Message?) {
        when (msg?.what) {
            MESSAGE_RECEIVING_REPLY_TO -> clientMessenger = msg.replyTo
            else -> super.handleMessage(msg)
        }
    }
}

/** ハンドラ. */
private val mHandler = MyHandler()

/** サービス側のメッセンジャ. */
private val mMessenger = Messenger(mHandler)

override fun onBind(intent: Intent?): IBinder = mMessenger.binder

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    // サービス実行から 5 秒後にコールバック実行
    Handler().postDelayed({
        val bundle = Bundle().apply { putString("message", "ほげふが") }
        mHandler.clientMessenger?.send(Message.obtain(null, MESSAGE_SEND, bundle))
    }, 5000)
    return Service.START_STICKY_COMPATIBILITY
}

こちらでもプロセスが同一の場合と同様に onBind()IBinder を返却しているが、こちらは Messenger に対応する Binder である (後で Messenger に復元可能な Binder) ところが異なる。 mMessenger というフィールドを持っているが、これは Handler インスタンスを Messenger クラスでラップしたものである。 Handler クラスの方を拡張することによって相手から投げられたメッセージをどう処理するかを実装する。

上記の実装例では msg.replyTo をフィールドに持っているが、これは Service からみてどのクライアントの Messenger でメッセージを送信すれば良いのかを判別するためのものである。 つまり Service 側の任意のタイミングでクライアント側にメッセージを送信したい場合は以下の手順を踏む必要がある:

  1. Service の接続確立時にクライアント側から replyTo を教えるためのメッセージを Service 側の Messenger を使って送信
  2. Service 側の送信したいタイミングでフィールドに持っている replyTo を使用してクライアントに送信

上記コードでは onStartCommand() 内で 5 秒後に実際にクライアントに対してメッセージを送信している。

Activity / Fragment 側のコード

/** クライアント側の処理を行うハンドラ. */
private class MyHandler(val activity: MainActivity) : Handler() {
    override fun handleMessage(msg: Message?) {
        when (msg?.what) {
            MyService.MESSAGE_SEND -> activity.button.text = (msg.obj as Bundle).getString("message")
            else -> Log.w(javaClass.simpleName, "Unknown what: ${msg?.what}")
        }
    }
}

/** サービスとの bind 時の接続を行う. */
private val mConnection = object : ServiceConnection {
    override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
        mServiceMessenger = Messenger(binder)

        // サービス側に replyTo を介してクライアント側の Messenger を教える
        val message = Message.obtain(null, MyService.MESSAGE_RECEIVING_REPLY_TO)
        message.replyTo = mClientMessenger
        mServiceMessenger?.send(message)
    }

    override fun onServiceDisconnected(name: ComponentName?) {
        mServiceMessenger = null
    }
}

/** サービス側の Messenger. */
private var mServiceMessenger: Messenger? = null

/** クライアント側の Messenger. */
private val mClientMessenger = Messenger(MyHandler(this))

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // サービスを bind する
    val intent = Intent(applicationContext, MyService::class.java)
    startService(intent)
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE)
}

override fun onDestroy() {
    unbindService(mConnection)
    val intent = Intent(applicationContext, MyService::class.java)
    stopService(intent)
    super.onDestroy()
}

Service との接続が確立した時に渡ってきた IBinder を逆に Messenger のコンストラクタに渡すことで Service 側の Messenger を復元している。 それを使用することで Service 側にメッセージを送信することができる。 先ほど記載したように、メッセージの replyToActivity, Fragment 側の Messenger を詰めて送信しておく。

後は Service 側と同様にこちら側でも Handler クラスを拡張して Service から渡ってきたメッセージを処理する為のコードを書く。

まとめ

  1. ServicebindService() する
  2. Service とのコネクション確立時に ServiceMessenger を使用して Service に対しクライアント側の MessengerreplyTo に詰めて送信することで教える
  3. Service 側で Handler の拡張クラスの実装によって渡ってきた replyTo を格納しておく
  4. replyTo を使用して任意のタイミングでクライアントに対しメッセージ送信
  5. クライアント側の Handler の拡張クラスでの実装で UI の表示処理などを行う

手順をしっかり理解しないと間違えそうな内容なので、やはり手軽ではないと思う。

先日 Kindle で TOEIC TEST 英単語 出るとこだけ!という単語帳と同作者の文法書を購入した。 相変わらず通勤時間帯に Kindle でサッと取り出して覚えたり音声教材を使用するなりしている。

Kindle 購入前に実物を見なかったのだが、今日たまたま本屋に立ち寄ったので TOEIC の教材が置かれているコーナーに出向き実物を見てみた。 英単語帳の方の紙面の配色が私の好みではなく、多分実物を見ていたら買うのをためらっていたかもしれない……。 しかし Kindle だと色合いなど確認できないし、内容としては気に入っているので結果オーライといったところだろうか。

英文法書の方も見てみたが、何か値段に対して嫌に本が薄い気がした……。 紙面の雰囲気も単語帳と同じ感じでうーん、というところでこれも実物を見ていたら買わなかったかもしれない。

今は便利なことに Google ブック検索があるので家にいながらにして買う前に本の内容がどんな感じか大体確認できてしまう。 今回の購入でもこの Google ブック検索のプレビューであらかじめ紙面がどんな感じか確認してはいた。 だが、このブック検索のプレビューであったとしても、実際に実物を見た時の感覚とは異なる。

文法書もせっかく買ったのでちゃんと一通り流そうと思うが、やはり可能であれば実物をチェックしたほうがいいと思った。

プロセスが同一の場合の例

大抵の場合アプリケーション内に Service を置く場合は必要に迫られない限りアプリケーションと同一プロセスとすると思われる。 この場合 Fragment 側から Service を操作したい場合は bindService を使用し Binder 経由で操作を行うのが一般的だ。

あまり意味のない例で恐縮であるが、例えば以下のような「現在時刻のタイムスタンプを返すサービス」を実装したものとする:

/**
 * 現在時刻を返すサービス.
 */
class MyService : Service() {

    inner class MyBinder : Binder() {
        fun getTime() = Date().time
    }

    /** Binder インスタンス. */
    private val mBinder = MyBinder()

    override fun onBind(intent: Intent?): IBinder {
        Log.d(javaClass.simpleName, "onBind start.")
        return mBinder
    }

    override fun onUnbind(intent: Intent?): Boolean {
        Log.d(javaClass.simpleName, "onUnbind start.")
        return super.onUnbind(intent)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d(javaClass.simpleName, "onStartCommand start.")

        // TODO 本当は何か UI に関係ない部分で待機するような処理が入るはず

        return super.onStartCommand(intent, flags, startId)
    }

    override fun onCreate() {
        super.onCreate()
        Log.d(javaClass.simpleName, "onCreate start.")
    }

    override fun onDestroy() {
        Log.d(javaClass.simpleName, "onDestroy start.")
        super.onDestroy()
    }
}

上記の場合 onBind() でサービス内で定義されている MyBinder を返却しているが、クライアント (Fragment) 側からこのインスタンスを使用してサービスの機能を利用する。 よって、例えば「ボタンを押したらサービスからデータを取ってきて画面に表示する」といった実装を行う場合は以下のようなコードになる:

/** サービスとの bind 時の接続を行う. */
private val mConnection = object : ServiceConnection {
    override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
        mBinder = binder as MyService.MyBinder
    }

    override fun onServiceDisconnected(name: ComponentName?) {
        mBinder = null
    }
}

/** Binder. */
private var mBinder: MyService.MyBinder? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // サービスを bind する
    val intent = Intent(applicationContext, MyService::class.java)
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE)

    // ボタン押下でサービスからデータ取得し表示する
    button.setOnClickListener { text.text = mBinder?.getTime()?.toString() }
}

override fun onDestroy() {
    unbindService(mConnection)
    super.onDestroy()
}

この例だと bindService() しかしていないので Service 側としては onCreate()onBind() は呼ばれるが onStartCommand() はコールされないことに注意する。 onStartCommand() はあくまで startService() した時に呼ばれる処理となっている。

ServiceConnection.onServiceConnected() 内で Service 側で定義したクラスである MyService.MyBinder にキャストしているが、これが可能なためにこの MyService.MyBinder に対し自由にメソッドやフィールドを追加することにより Service に対して好きに処理を行うことができるようになる。

Service から任意のタイミングでクライアントに処理を行わせたい場合

上記の Binder の例はあくまでクライアント側から任意のタイミングで Service に対し処理を行わせたい場合に使用できる。 逆方向である Service からクライアントに対し処理を行わせる場合であるが、以下の 3 通りが考えられる:

今は EventBus などのライブラリを使用すると任意の位置からイベントを伝搬できるのでとても便利だ。 ここでは 1 番目の Binder を用いて実現する方法に関して書く。

例えばサービスが起動された 5 秒後にクライアント側で実装されたコールバックを実行する例を示す。 サービス側の実装として、まずクライアント側で実装すべきコールバックのインターフェースを開示する:

class MyService : Service() {

    /** サービスで 5 秒後に実行されるコールバック. */
    interface Callback {
        fun doIt()
    }

    inner class MyBinder : Binder() {
        fun getTime() = Date().time

        // クライアント側からコールバックを渡す為のメソッドを追加
        fun set(callback: Callback?) {
            mCallback = callback
        }
    }

    /** Binder インスタンス. */
    private val mBinder = MyBinder()

    /** クライアント側で実装されたコールバック */
    private var mCallback: Callback? = null

    override fun onBind(intent: Intent?): IBinder = mBinder

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        // サービス実行から 5 秒後にコールバック実行
        Handler().postDelayed({
            mCallback?.doIt()
        }, 5000)
        return Service.START_STICKY_COMPATIBILITY
    }
}

後は以下のようにクライアント側でコールバックの実装を行い、サービスのコネクションが張れたタイミングでコールバックを Binder を通してサービス側に渡してやれば良い:

private val mCallback = object : Callback {
    override fun doIt() {
        button.text = "サービス側から呼ばれた"
    }
}

/** サービスとの bind 時の接続を行う. */
private val mConnection = object : ServiceConnection {
    override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
        mBinder = binder as MyService.MyBinder
        mBinder?.set(mCallback)  // サービス側に定義したコールバックを渡す
    }

    override fun onServiceDisconnected(name: ComponentName?) {
        mBinder?.set(null)
        mBinder = null
    }
}

/** Binder. */
private var mBinder: MyService.MyBinder? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // サービスを bind する
    val intent = Intent(applicationContext, MyService::class.java)
    startService(intent)
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE)

    // ボタン押下でサービスからデータ取得し表示する
    button.setOnClickListener { text.text = mBinder?.getTime()?.toString() }
}

override fun onDestroy() {
    unbindService(mConnection)
    val intent = Intent(applicationContext, MyService::class.java)
    stopService(intent)
    super.onDestroy()
}

これで 5 秒後にボタンに「サービス側から呼ばれた」という文字列が表示される。

プロセスを分けるとどうなるか

さて Android の場合同一アプリ内であっても別のプロセスを使用した Service を定義することができる。 これは AndroidManitest.xml に以下のように定義を加えることにより実現できる:

<service
    android:name=".MyService"
    android:process=":remote"/>

android:process=":remote" の部分であるが、:remote の箇所は別に :hoge などの他の名前でも良い。 このようにして先ほどのコードを実行してみると ServiceConnection.onServiceConnected()MyService.MyBinder にキャストしている箇所で ClassCastException がスローされるようになる:

private val mConnection = object : ServiceConnection {
    override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
        mBinder = binder as MyService.MyBinder  // 駄目. binder は BinderProxy が渡ってくる!!
    }
}

デバッグ実行で見てみると分かるが Service 側で渡した Binder の参照がそのまま渡ってくるのではなく BinderProxy というプロキシクラスのインスタンスが渡ってくるようになる。 その為このようにキャスト前提の実装にしてしまうと失敗する。 また EventBus などのライブラリもプロセス間通信には使用することができない。

この場合は公式にある通り Messenger を使用するわけだが、長くなったのでそのコード例は次回とする。

先週泊まりで行ったのでそこまで欲求は無かったのだが、折角の三連休最終日なのでちょっと行くことにした。 九十九里浜に行くことにしたが節約のために全て下道を使うことにした。 首都圏ツーリングプランだと篠崎 IC から東金 IC までしか対象にならず使い物にならないので仕方がない。

今日は昨日と同様に暑く、今年もう終わりだと思っていたメッシュジャケットをまた使うことにした。 暑いとはいっても夏の暑さとは違うのでメッシュジャケットさえ着れば冷房を着ているかのような涼しさだ。 九十九里浜に至る有料道路を通ったのだが、自動二輪は 150 円とまあまあの値段。 ただ、料金所で二輪専用レーンが用意されているのはいいのだが、硬貨をただ投げ込むような方式でお釣りが用意されておらず、自分は 500 円玉しか持っていなかったので困り果ててしまい呼び鈴を鳴らすことになった。 結果人が出てきてお釣りは貰えたのだが、何とも微妙だった……。

九十九里浜に着いたのだが、海のシーズンは終わりとはいえ三連休最終日なのでそこそこ人がおり「海の駅九十九里」の食堂は人がいっぱいで入れない状態だった。 仕方がないので食べずに館内と外を眺めた上でそこを後にし、砂浜まで歩いていって海を見ながらしばし休憩した。 やはりバイク日和だからなのかバイクがとても多かった。 走っている途中に小学生のランドセルを着けたハーレーを見かけて「あぁ、これが話に聞いていたアレか」と思った。 ランドセルは革でできているのでクルーザーのサイドバッグの代わりとして使えるだろうという主張のようだが、確かに遠くから見るとサイドバッグに見える……。

帰りは行きと違う下道で帰った。 千葉方面は船橋・幕張・市川あたりがやたらと混むのでそこを避けて北側を回り込むように抜けるとそこそこ快適である。

前回の腱鞘炎から 10 日が経って、やっと打てるかなと思い少しずつ打つようにしていったらまた同じ症状が出始めた。 休んでいる間に実力が落ちてしまっていたので、結局それを取り戻しただけでまた休止することになる……。 特にタイプウェルを打つとなるのは、どうしてもミス上等の乱打気味の打ち方になってしまい指に負担がかかってしまうからのようだ。

最終目標を総合 XE と決めており、少なくともいける自信は十分にあったので非常に悔しいのだが、タイプウェルはしばらく止めることにする。 指が痛くなるとタイピングだけでなく全てのことにおいて気力が減退してしまうのが辛すぎる。

いくらタイピングしても指が痛くならない人がいるようだが、少し羨ましい。

点検が完了したと連絡があったので今日は YSP に BOLT を取りに行った。 リアブレーキパッドとエアクリーナーエレメントを交換。 総走行距離 24,321 km なので確かにエアクリも替え時か。 次回は 2 年点検だがその時点で 3 万キロ越えている感じだろうか。

代車は 125 cc スクーターだったが、改めて乗ってみると思ったより加速が鋭い。 エンジンは非力かもしれないがそのぶん車体が軽いので相対的にそんなにパワー不足を感じないのだろう。 ただ、見た目が原付に見えるのか BOLT に乗っている時に比べて車間距離を詰めてくる後ろの車が多い気がした……。

しかし少し代車乗っただけだが、いざ BOLT に乗り換えるとハンドルが遠いな、と感じる。 私の BOLT はハンドルをハリケーンのものに交換しているので純正より手前に寄ってはいるが、それでも近くはない。 ドラッグスターのような一般的なクルーザーとはやはり違うな、と思った。

先月から英語の再勉強を行っているわけだが「何を目標にしようか」というところで英検でなく TOEIC をメインにすることにした。 英検は直近では高校卒業程度の難易度である 2 級を受ければ割とすぐに受かりそうな感じではあるが、その後の準 1 級との間のレベル差がかなりあり目標を見失ってしまう。 その点 TOEIC はいかに 990 点に近づけるかというテストなので定期的に受験すれば成長を実感しやすい。

マイルストーンを細かく打って練習したほうがモチベーションを維持しやすい。 タイピングでいうところのタイプウェルのレベル分けがとても細かいのも理に適っているというわけだ (もしタイプウェルが XA, SS, SJ しか無かったら途方に暮れてしまうだろう)。 まず私は学生時代も含めて TOEIC を受験したことがないので 600 点を目指す。 初回で 600 点取得できれば儲けものだが果たしてどうか。

Kindle で単語帳を購入

とりあえず英文法も一通りこなしそうなところで TOEIC の単語帳を購入しようと思ったのだが、私としてはいきなり難しい単語帳に進めてしまうと分かる単語が全然なくて困ってしまうところなので、ネットで検索して評判のいい比較的初心者向けのものにした。

TOEIC TEST 英単語 出るとこだけ!を Kindle で購入。 Kindle でも 17 % 程度しか安くならないので紙でも良かったかもしれないが、単語帳の場合 Kindle だといつでもスマホを取り出して確認できるのが最大の利点だと思った。 実は同じ作者の英文法の参考書も Kindle で購入したのだが、こういうのは書籍のほうが良かった。 失敗した。 書籍の場合赤シートで答えを隠しながら問題を解いていくことができるし、単語帳ほどどこでも見たいという欲求はない。

さて、この単語帳であるが、Kindle 版でもアルクの Web サイトから音声データをダウンロードすることができる。 早速ダウンロードしスマホとタブレットの /Music フォルダに突っ込んで音楽アプリで聞く。 単語の意味と例文を 1 つ 1 つ読み上げてくれる。 今の時代はスマホだけで単語帳の確認とリスニングが特にテクニックや別の器具が必要なく簡単に出来てしまうわけだ。 これは便利だ……。

私は高校生の時大学受験用の英単語帳として英単語ターゲット 1900 という名著を使用していた。 当時この 1900 の中の難単語 400 以外の 1500 語をほぼ完全に記憶したものだ。 一方、この単語帳は厳選された 630 語とあるし、その厳選された単語の難易度も見たところそれほど高くなく知っている単語もいくつかあったので新たに 630 語全部記憶するわけではない。 この程度であれば無理なく続けていけそうなので今のところ気にいっている。 電車の中や帰宅した後の隙間の時間などに音声データを聴いて記憶を定着させ、例文を聴いて多少のリスニング対策としている。

ちなみに TOEIC の英単語帳には名著として金のフレーズがあるのは知っていたのだが今のところこの新版には Kindle 版がないので選択肢から外しておいた。 今やっている英単語帳が終わっても Kindle 版が出ていなかったら書籍版を買ってやろうと思う。

1 ~ 2 ヶ月程度で全部記憶することができるだろうか。 その後は人生 TOEIC 初受験してみたいところだ。

本日 Google のハイエンドスマートフォンである Pixel の後継である Pixel 2 / Pixel 2 XL が発表されたようだ。 Pixel もそうだったが普通に「日本での発売予定はない」と書かれている。 Pixel の時は結構落胆したものだが 2 回目ともなると全く心動じるところがない。

Pixel になる前の Nexus ブランドの時はとてもお世話になった。 Nexus 5, Nexus 5X, Nexus 7 (2013), Nexus 9 と使用したが以下の点がとても優秀だと思った:

後期になるにつれて上記の利点は薄まってきたが、それでも実際のハードウェアは別のメーカーが作っているとしても Google 謹製という安心感はとても良かった。 今になってみると上記の利点は HUAWEI 製端末が引き継いでいるように見える。

ただ HUAWEI 端末で良くないなと思うのは、極端に安い端末 (1 ~ 2 万円) はとにかく性能が低くいかにもな中華端末だな、という印象を受けることだ。 このような端末を買ってしまったユーザーが HUAWEI は安かろう悪かろうなメーカーだ、と評価してしまうかもしれないのは残念だ。

ヘーホンホヘホハイ

ベーコンポテトパイは私が学生時代の頃にはマクドナルドのレギュラーメニューだった。 当時はホットアップルパイと共に 120 円で売られていたと思うのだが、ホットアップルパイの方は 1 回くらいしか食べたことがないがこのベーコンポテトパイは何度もリピートした。 それくらい美味しくて手軽な一品だった。

最近は期間限定で販売されている。 しかし昨日マクドナルドでチラシを受け取った時にベーコンポテトパイらしき写真を見つけたので今年もまた期間限定販売かと思ったのだが、商品名をよく見るとヘーホンホヘホハイと書かれていた……。 しかもご丁寧に「ベーコンポテトパイでも注文できます」と注意書きがされている。

何とも盛大に滑っているが、「公式がこんなことをやるとは」という意外性と共に少なくとも強烈に印象に残る手法で上手いと思った。 朝マック時間帯でも注文できるのか、早速この商品名で注文している人がいたようだ。 まぁ私は普通に「ベーコンポテトパイ」で注文すると思う。

ヘーホンホヘホハイは今日からの期間限定である。 しかし月見バーガーといい、私が好きなメニューを繰り返し出されるとなかなか困ってしまう。 健康を考えると連日行きたくはないのだが、今回ばかりは仕方がないところだろうか。

私は nanaco を公共料金の支払いに利用しているのだが、今回 JCB プロパーカードを解約するのでチャージ用のクレジットカードを変更することにした。 巷では大体が VISA と MasterCard が使えるが JCB が使えないというパターンだが nanaco の場合は JCB が OK なのだが VISA や MasterCard はそれだけでは駄目で UC や DC などのブランドに属していないといけない。 私は楽天カードは MasterCard にしてしまったので登録できず、仕方がないので三菱東京 UFJ-VISA が DC カードなのでそれを利用した。 ポイントは付かないが仕方がない。 しかしそれなら nanaco を止めてもう現金でいい気もした……。 全部銀行自動引き落としにでもしてしまった方がいいのだろうか。

nanaco のクレジットカードの登録から利用可能になるまで 24 時間かかる。 ちょっと面倒だが仕方がない。 これでも昔に比べたら随分便利になったものだ。

しかしこういったプリペイド式の電子マネーを多数持っていても使い分けに困るところではある。 私は楽天カードマンなので Edy メインなのだが、正直 Edy と Suica さえあれば生活圏内の用途はほぼカバーできてしまう。 ただプリペイド式なので使おうとした時に残高が足りなくて歯痒い思いをすることがたまにある。 Android スマートフォンの NFC で Edy チャージできるのには驚かされたが、それでもまさしく今使おうとした時に残高が足りなかった場合にすぐに使えるものでもない。

朝晩は結構涼しくなってきたが、この時期は服装に困るところで今日も迷ったがいつもの半袖 T シャツのまま出勤した。 季節感を出すためにはジャケットなどを羽織ったほうが良いのは確かだが、それだと駅まで向かう道は良いのだが電車内で暑くて困ることになる。 満員電車だと脱いだジャケットを手に持っておくのも億劫だ。 これが車やバイク通勤だと話が違ってくるので、今の時期はそちらの方がいいような気がした。

今日は YSP に 6 カ月点検の予約をしていたので出向いていってお願いした。 ブレーキパッドがフロントはまだ残っているがリアが少ないので交換するべきとのことだった。 リアはフロントに比べて全然使っていなかったので意外だった。 聞いたらクルーザーは上から踏みつける格好になる関係上どうしてもリアのほうが減りやすいとの事だった。

今回は初めて代車を借りることができたのだが、シグナス X (125 cc スクーター) だった。 私がスクーターに乗るのは学生時代の自動車教習以来である。 自宅まで何とか乗ってきたが、確かにトルク不足を感じるが必要十分に走るという印象で慣れれば全く問題ないだろうと思った。 原付 2 種スクーターがこれだけ街を走っているのも分かる気がした。 何よりシート下に荷物が入るのがいい。 とはいっても 125 cc (正確には 124 cc) なので高速にも乗れないしツーリングなど行く気も起きない。 まさに首都圏で活躍する足代わりの乗り物という感じだ。