Infinito Nirone 7

白羽の矢を刺すスタイル

DroidKaigi 2018 やっていきed

「やっていき」だと未来の話だけど、やっていきが完了した話はどうやって言うのがいいか分からなかったので、edをつけてみました。

はい。DroidKaigi 2018 が無事に終わりました。自分の参加歴はスピーカーとしては 2 回目・スタッフとしては 4 回目(フル参戦)です。

自分の中での一番のハイライトはやはり、Romain Guy 氏と Chet Haase 氏と話ができたこと。今でもまだまだ英語力は足りなくて、このお二人のような気の利いたジョークは日本語でもままならないなって感じもするんですが、何はなくともとにかくいつも YouTube 等の画面の向こう側にいた「めちゃくちゃ話しを聞きたい人たち」が、自分の目の前にいていつでも話ができる状況にとてもテンションが上りました。たとえどんなにミーハーであろうとも、そして実際話したことはエンジニアリングとはあまり関係のないほぼ世間話のような内容だったとしても、これまでで一番貴重な体験になったようにおもいます。

スピーカーとしては、開催一週間くらい前までウンウン悩んでた資料がうまく(?)まとまって、当日は自分のよく知る話をひたすら 50 分ぶっ通しでやる実績を解除しました。去年は 30 分でしたが、今年はもう少し掘り下げたところも話しつつ全体像も捉えられるようにまとめて 50 分となりました。

speakerdeck.com

最後の最後、まとめで「これ実は Android Auto だけが使ってる話じゃないんだよね」と言うことで、タイトルが「Android Auto」である意味を盛大にひっくり返してしまいましたが、今思い返してもよくまぁこんなに内容てんこ盛りにしたなぁと自分でも思うので、次はやりすぎない程度に濃い話ができるようにしたいです。今後の目標は、どこかで完全英語版の発表をやることです。資料だけでなくスピーチも英語にするのが目標です。いやでも、過去に海外で完全英語版のプレゼンはしたことあるな……

年々 DroidKaigi の規模が大きくなってきており、それは参加者数だけでなく、会場の規模も、DroidKaigi に協賛してくださる企業の数も、そしてスタッフの人数も大きく成長し続けています。スタッフとしての事前の準備では会議を重ねて情報を共有し、知見のストックを Kibela で管理する流れが今年から導入されました。また、当日はインカムでものすごい量の情報があちこちから飛び交うので、大事な情報が流れていってしまわないよう運営アプリを作りました。各セッションルームの状況だったり、司会の人が話す内容の共有だったり、その他スタッフ全体に共有する情報を Push したりする目的でつくってみました。アプリの性質上公式アプリのように Google Play Store では公開していませんが、わりと公式アプリと同じような作りになっている部分もあったりします。技術カンファレンスの運営にカンファレンスで習得した技術を導入するというのは、言われてみればそういう目的でカンファレンスが開かれているのだから自然なことのようにも思いますが、今振り返ってみると結構面白い体験でした。

全日程が終了し、いろいろな方が思い思いの打ち上げを楽しんでいるのも見届け、今日は DroidKaigi Day3 ということで最後のお片付けをしました。カンファレンスで使う機材や資材には、会場からお借りしているもの・レンタル業者に依頼して借りているもの・自分たちが所有して使っているもの等といろいろあります。借りたものは所定の手順で返却をすればよいのですが、自分たちの所有しているものは自分たちで持って帰るか処分する必要があります。ある程度は宅配便等で保管場所に送ることもできますが、中には自分たちで倉庫に運ぶ必要のあるものもあります。今日はそういったものたちを運ぶ、ロジスティクスのお仕事の日でした。ハイエースクラスの車を運転した経験がここでいきるとは思ったこともなかったですが、これも貴重な体験でした。

また次回もやっていき!!

DroidKaigi 2018 Day 2 Room 5 で"詳解 Android Auto"という発表をします

droidkaigi.jp

気がついたら仕様の総ページ数が 200 を超えていて、超大作でお送りいたします。 Android Auto という取っ掛かりではありますが、幅広く応用の効く話を中心に据えていて、というか Android Auto の実体がほぼそういう潰しの効くフレームワークの上に成り立っているといって過言ではないのですが、そういう話をします。 2日目のランチ後という時間帯に50分の長丁場なセッションで、かつ自分が見たくて見たくて楽しみにしていたセッションが複数同時に走っていてん゛ん゛ん゛ん゛!゛!゛となっていますが、自分の発表も負けないくらい Android Auto とはなんぞやという話をします。

ちなみに先日の Shibuya.apk では Romain Guy 氏に握手してもらって最高でした!

ProductFlavor ごとに apply from で読み込む外部 Gradle ファイルを切り替える

flavor1flavor2 という 2 つの productFlavor があり、flavor ごとに名前が同じで値の異なる変数を使いたいとき、flavor1 向けの変数を定義した flavor1.gradleと flavor2 向けの変数を定義した flavor2.gradleを用意したとして、どのように apply from で読み込むファイルを切り替えるか。

flavor1.gradle

ext {
  versionMajor = 1
  versionMinor = 2
}

flavor2.gradle

ext {
  versionMajor = 1
  versionMinor = 2
}

versionCode や versionName は productFlavor ごとに変えられて、flavor1 や flavor2 といった flavor のなかで apply from が効くので次のようにします。

android {
  productFlavors {
    flavor1 {
      apply from: 'flavor1.gradle'
      versionCode = versionMajor * 100 + versionMinor
      versionName = "${versionMajor}.${versionMinor}"
    }
    flavor2 {
      apply from: 'flavor2.gradle'
      versionCode = versionMajor * 100 + versionMinor
      versionName = "${versionMajor}.${versionMinor}"
    }
  }
}

変数にしたのにそれぞれの productFlavor で versionCode と versionName を入れてやらないといけないのは冗長ですが仕方がない。。。

BuildType と ProductFlavor のマトリクスで BuildConfigField や ManifestPlaceholders を生成したい

BuildConfigField は、BuildConfig という自動生成されるクラスに定義する定数をビルドスクリプトから制御する仕組みです。 そしてもうひとつ、ManifestPlaceholders は AndroidManifest のプレースホルダーに放り込む値をビルドスクリプトから制御する仕組みです。

これらを活用すると、BuildVariants を変えただけで気軽にアプリの振る舞いを変えたり、ContentProvider の Authority の衝突を防いで異なる BuildVariants の apk を同じ端末内に共存させたりといったことができるようになります。

ContentProvider の衝突を防ぐという目的では、次のように debug と release のそれぞれの BuildType で別々の Authority を定義するのが一般的です。

android {
  buildTypes {
    debug {
      manifestPlaceholders = [
        authorityHogehogeProvider : "com.sample.hogehoge.debug.provider.HogehogeProvider"
      ]
      BuildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.debug.provider.HogehogeProvider\""
    }
    release {
      manifestPlaceholders = [
        authorityHogehogeProvider : "com.sample.hogehoge.provider.HogehogeProvider"
      ]
      buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.provider.HogehogeProvider\""
    }
  }
}

こうしておけば、AndroidManifest.xmlは main ソースセット配下の一個だけで済みます。

<manifest>
  <application>
    <provider
      android:name=".provider.HogehogeProvider"
      android:authorities="${authorityHogehogeProvider}"
      android:label="HogehogeProvider"
      android:exported="false"/>
  </application>
</manifest>

ここで、この ContentProvider を flavor1 と flavor2 という2つの ProductFlavor でそれぞれ持つことを考えます。 先程の buildTypes で manifestPlaceholders を分けるコードのみでは、flavor1 と flavor2 とで ContentProvider が衝突するため共存できません。 ProductFlavor と BuildType の組み合わせで manifestPlaceholders や BuildConfigField を制御する場合は、次のようにすべての BuildVariants を走査して対応するものを差し込むロジックを書きます。

android {
  productFlavors {
    flavor1 {}
    flavor2 {}
  }

  buildTypes {
    debug {}
    release {}
  }

  applicationVariants.all { variant ->
    def flavorName = variant.productFlavors.get(0).name
    def typeName = variant.buildType.name

    if (flavorName.equals("flavor1")) {
      if (typeName.equals("debug") {
        // BuildVariant: flavor1Debug
        variant.mergedFlavor.manifestPlaceholders = [
          authorityHogehogeProvider : "com.sample.hogehoge.flavor1.debug.provider.HogehogeProvider"
        ]
        variant.buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.flavor1.debug.provider.HogehogeProvider\""
      } else if (typeName.equals("release") {
        // BuildVariant: flavor1Release
        variant.mergedFlavor.manifestPlaceholders = [
          authorityHogehogeProvider : "com.sample.hogehoge.flavor1.release.provider.HogehogeProvider"
        ]
        variant.buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.flavor1.release.provider.HogehogeProvider\""
      }
    } else if (flavorName.equals("flavor2") {
      if (typeName.equals("debug") {
        // BuildVariant: flavor2Debug
        variant.mergedFlavor.manifestPlaceholders = [
          authorityHogehogeProvider : "com.sample.hogehoge.flavor2.debug.provider.HogehogeProvider"
        ]
        variant.buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.flavor2.debug.provider.HogehogeProvider\""
      } else if (typeName.equals("release") {
        // BuildVariant: flavor2Release
        variant.mergedFlavor.manifestPlaceholders = [
          authorityHogehogeProvider : "com.sample.hogehoge.flavor2.release.provider.HogehogeProvider"
        ]
        variant.buildConfigField "String", "AUTHORITY_HOGEHOGE_PROVIDER", "\"com.sample.hogehoge.flavor2.release.provider.HogehogeProvider\""
      }
    }
  }
}

ProductFlavor は複数定義可能なので、複数ある場合はvariant.productFlavors.get(n)nも適宜どの ProductFlavor に対して BuildConfigField や ManifestPlaceholders を差し込むかによって変えます。 BuildConfigField は variant が直接持っていますが、ManifestPlaceholders は variant.mergedFlavor 配下に対して設定します。variant.buildTypeにもmanifestPlaceholdersがありますが、こちらには設定できないことに注意しましょう。

2017年振り返り

はやりのビッグウェーブ*1に乗って2017年を振り返りたいと思います。 ちなみに、1月のツイートを遡るだけでも随分な数になったし、何を思ってそれを言ったのかよく覚えていないものもたくさんあってちょっと後悔しています。

1月

あけおめを言うでもなくシステムUI調整ツールでうるう秒がどうなるかチェックするところから始まった2017年でした。今年も一年良くも悪くも Android にどっぷり浸かっていました。 年始は初日の出を見に多摩湖まで行って、ちょっとギリギリの時間だったので既に多くの人が詰めかけていましたが間に合いました。帰ってきて、うるう秒を確認して、なんやかんやして飛行機で名古屋に飛ぶということをしました。

毎年やんやかんや三が日のうちに浅草寺へ行くんです。目的は大凶のおみくじ。いつだったか知らずにおみくじをひいて大凶をあてて以来、年始にどんな大凶を引き当てることができるかでワクワクしているのですが、今年は吉でした。でも待ち人は来なかった。

はい。

年始に一度ためした Alacritty ですが、結局最近になるまで放ったらかしにしてしまっていて、久しぶりに触ったら良い感じに動いているので常用することにしました。ただし Terminal.app みたいなタブができないのでなんとかしないといけないんですが、今まで gnu-screen で満足していたものの久しぶりに入れようとしたら完全に綺麗さっぱり gnu-screen のことを忘却していたので、これを期に tmux デビューしました。とりあえず Alacritty で直接日本語入力できない・ターミナル上の文字をCommand+Cできない以外は満足しています。

はいコンテキスト過ぎるつぶやきですが、いきいきフレッシュちんちん豆という商品が実在するという話です。

あと1月はRobolectricとMockitoでウンウンうなっていたようです。

2月

DroidKaigi 直前の季節感ですね。2017年も良い感じにコントリビュートできて幸せです。

これは声を大にして言いたいと思ったけど今年は歯磨き粉みたいなチョコミントのお菓子が発売されていてこれはないなと思いました。でもだからといってチョコミントは歯磨き粉ではありません!

たしかこの日はじめて自由が丘の Bianchi Cafe and Cycles に行った気がする。

今年は夏前に50kg台に減らして、今もとに戻ってしまったので完全に進捗ダメです。

DroidKaigi 2017 では WindowManager の話をして、そのあと Oreo で「WindowManager シュッと整理しました」と発表がありましたね😇。

今年は筋肉食堂にも何度か足を運びました。アサイーボウルプロテインに浸かっていておいしい。

3月

オフィスが今の場所に引っ越す前は表参道のまい泉に近くて毎週ランチ行ってました。また行きたい。

自転車レース(ヒルクライム)に出る実績を解除しました。富士山、美ヶ原、嬬恋村と3回、とてもいいヒルクライムになりました。

はい。

次の DroidKaigi もたいがいニッチな話をするのですが、2017 の DroidKaigi も割りとニッチだと思っていたところ結構聞きに来てくださる人がおおくてびっくりしました。

叶ってよかった。

このビールたちを全部飲み切るのに半年以上かかったようです。

シリーズAの発表が3月だったの、もう随分と昔のように感じています。

4月

会社で花見をしようとしたところ残念なことに雨がふってきたのでオフィス内のディスプレイに桜の写真を表示して疑似花見をしました。

このあと見事に忘れました。

超うまかったのでまた行きましょう。

年始頃は完全無欠コーヒーやってたんですが、味が単調で飽きるのと、なによりココナッツオイルでお腹の調子が制御不能になってバラムツ食べすぎたみたいになるのがしんどすぎるのでやめてしまったし、やめてもダイエットは出来ていたのでまあ自分でちゃんとセルフコントロールしながらコンスタントに体重落としていけばいいよねって思いました。おかげで使い切れなかったココナッツオイルが冷蔵庫に眠っています。

つくばまで往復チャリライド、行きの道を少し間違えてなかなかしんどかったです。国道4号を北上して久喜までいき、そこから東に進路を変えましたが茨城県に入ってからつくば市にいたるまでが結構長かったのをよく覚えています。日が沈む前に帰ってこれてよかった。

本人からいいねがついているの今気がついた。

Oisix さんとこでもくもくした時ナマの野菜をぼりぼりしたの最高でした。

5月

結局今年は何度か肉料理のそれがしに行きました。

子の権現、このときは北側から登ったのでこの坂は降りるだけでしたが、乗ったまま降りるのはとてもおっかないとおもったのでホテホテ歩きました。次はこちらから登っていくぞ…

都民の森へグループライドしたのはいい思い出。

これの松郷峠まではやったんですよね。キツかったです。

そういえばこんな峠三昧なコースも走りましたね。

今年一恥ずかしかったやつだ。

結局 Kotlin 成分は 20% 弱まで増えました。

6月

はい。

はい。

はい。

頑張りました。来年はもっと頑張ります。目指せブロンズ!

美味しかったのは覚えているがどこだったかはもう覚えていない。

これここ最近毎年なっていて、疲れが溜まっているとか、太り気味だとか、いろんな要因があるらしいですが自分の場合は毎年春に周期的になるのです。体調を整えればそのうち治るのですが、耳鳴りと言うとあまり良いものではないのは事実なので、もしなにか急に耳鳴りがすると感じたら何を置いてでもすぐに病院へ行きましょう。

富士ヒルの翌週は家族旅行ということで大分へ。

帰りの大分空港でご飯。 このあと羽田への着陸で高度を下げ始めるあたりからずっと飛行機が揺れっぱなしで気持ち悪くなって早く終わってくれ頼む!!と思ってたら着陸やり直しになってフラフラになりました。

ミドルグレードの端末としてはよく出来ている、限りなくバニラAndroidに近い端末です。なかなか良いんですが、地味に大きいのが玉に瑕というところでしょうか。

ツールド美ヶ原の前日に行ったここのとんかつ屋さん、めちゃうまでした。

早朝の雨も上がって良い感じに大会が開催されました。序盤のいちばんきつい登りで、グレーチングの上を通ったときに後輪がズルリと滑ったときはちょっと焦りましたが転ぶこと無く登りきりました。

7月

伊豆に行きました。

逗子に行きました。

茅野から松本までビーナスラインを走りました。

翌月の中旬までアメリカに滞在しました。

アメリカの山も厳しかった。

8月

結局帰国まで治らずじまい。

サンノゼにいると日本食に困らないんですが、世界の山ちゃんまで来るとは思っていませんでした。

これ、今年一おすすめの動画です。

SFO からも近いし、カルトレインの駅からも歩いて行ける距離なので最高。

日本でも売ってくれないかな…

カリフォルニアのパレスサイクリングって感じですが適度にアップダウンもあるし観光地もあるので最高です。ただし風が強め。

アメリカ出張は実は急な話だったので、父親が「機会があるならアメリカで日食を見てくるといい」と言う話を聞いていたこともすっかり忘れていたのですが、良い感じに日食を観測できました。 でもそのあとの Android O の発表が肩透かし感あってびっくり…

アメリカの家の構造について知見を得ました。でもテレビ貴様は許さん。

尊い

ダメです。

9月

結局最終的に4000円くらいにまでは膨れ上がりました。 何もしてないけど資産が増えるってすごいですね!

これすごくいいんです。さわり心地もソフトでかつグリップ感があります。

今年一頑張ったヒルクライム。しかしキツかったな。 来年はこの先にある渋峠にも行きたい。

昨今の事件で話題に事欠かない相撲界隈ですが、両国国技館のエンターテインメント感はすごいなと思いました。

Essential Phone はいいぞ。 Andy Rubin 氏にもいろいろよくわからない噂がつきまとっているようですが、彼は退職ではなく休職で既に復帰しているということはここに残しておこうと思います(よくEssentialからAndyおらんくなったという話をきくので)。

ツールド東北は台風の影響でコースがカットされましたが楽しめました。そして AirBnB のホストのおばちゃんがすごいよくしてくれた。

これすごい分かるんですよ。自分の場合は自転車ですが。

最近はウェッブサービスでアニメもテレビ番組も映画も配信されている時代なので、あえて BD を買う理由も殆ど無いように思うのですが、しかし「この世界の片隅に」と「聲の形」はどうしても形あるものとして持っていたくて買いました。

10月

アメリカからデザイナーの同僚が出張できているときにそういう話になったのですが、みんな考えてたことは同じなんだなぁと。

DevFest Tokyo での発表は Android の進化の系譜ということで、API がどうかわってきたかを振り返りました。資料が意外と難産でした…

いつも米心は最高である。

今年一やばいGIF。

ジャパンカップを初観戦。雨降ってましたが見れてよかった〜。

ミーハー丸出しですが楽しかったので良し!

ジャパンカップ翌日はLottoNL Jumboチームのアフターパーティーに参加しました。後日 cyclowired の記事に自分が写ってる写真が載っているのを見つけました。

www.cyclowired.jp

埼玉のラルプデュエズと名高い根性坂に敗北。

いまでもつい懐かしくなって遊んでしまう。。

11月

海浜幕張までチャリで行ったのは端的に言って間違っていた…でも帰りにいい景色が見れたのでよし。

尊い。自転車と組み合わせたら無限にいろんな景色が撮れるし、ちょうど紅葉の季節で捗りました。

ツール・ド・フランスさいたまクリテリウムも見に行きました。今年は会場でいろいろ楽しめた!

クリテリウム後にいわたんちでB級映画見ました。

金色に輝くステータスになりました!

今から楽しみ過ぎる…

尊い

尊い

米心アゲイン。尊い

そういえばまだここに行けていないので来年行きたい。

12月

はー行けてよかった。

目白はのぞき坂。ここからほぼ毎日自転車通勤の日は帰りにここを通っています。 Strava で記録も見れてよい。

最の高。

尊い

尊い

ガンダムのことはわからないけど今年二度目のガンダム見学。

2017年も Proguard に消耗しました。

まとめ

来年もよろしくお願いします。

RxEither を RxJava2 に対応してみた

もともとのモチベーションとして、Java で Either を扱いたくて色々探していました。 そのなかで RxJava との運用もカバーしてくれている RxEither を見つけたのですが、あいにく RxJava 1.x で止まっていたので RxJava 2.x に対応させてみることにしました。

github.com

github.com

基本的にはパッケージの変更と、Action1 とか Func1 とかを Consumer やら Function やら Predicate やらに書き換えていく作業をポチポチとやっていきます。 テストもあるので、そちらもパッケージ変更とクラスの変更をやります。あとはテストを実行してオールグリーンになるのを見届けました。

一つ気がかりというか困ったのは、RxJava 2.x の Consumer や Function はメソッドのシグネチャthrows Exceptionとあるので、どこかで try-catch が必要になるのですが、このライブラリが依存している SealedUnion2 というライブラリでの Union2 の定義には throws Exception がないので、どうしても Left や Right で try-catch を書かないといけないというところです。握りつぶすのもあまり良くないなと思ったので今のところは RuntimeException でラップしていますが、いまいちしっくりこない…