へいへいブログ

自分のために書く。Android、英語。📝

Notes - Fragmented Podcast: 105: Jake Wharton on the Android Kotlin Guides

f:id:shaunkawano:20171210142608p:plain (参照: http://fragmentedpodcast.com/episodes/105/)

本記事では、Fragmented Podcast: 105: Jake Wharton on the Android Kotlin Guidesを聴いた上で、全ての内容ではないですが出来る限り多くの情報をメモ書きという形ですが英語で簡単にまとめています。

元々は自分自身の内容理解のためにポッドキャストを聴きながら書いておりましたが、本記事を読みながらポッドキャストを聴くことで少しは内容理解の手助けになればと思います。尚、本記事にはポッドキャストでの会話の全内容をまとめているわけではありません。あくまで筆者個人の雑な解釈を書きまとめたメモ程度のものであると思っていただければ幸いです。(内容において不備、誤字脱字等ありましたらご連絡いただければと思います。)

TL;DR

  • Jake Wharton working on android/kotlin-guides on github
    • Influenced by Google Java style guide
    • Hosting on GitHub makes it easy for people to not only access but also contribute
    • Different from JetBrains' style guide; following this style guide has no conflict with following JetBrains' style guide, but may not be vice-versa
  • Style guide to provide a set of rules to follow, and Interop guide to provide practices and things to care for those developers who ..
    • Introduce Kotlin into existing Java project
    • Consume Kotlin code from Java
    • Provide APIs in Kotlin that may be consumed from Java

105: Jake Wharton on the Android Kotlin Guides http://fragmentedpodcast.com/episodes/105/

About android/kotlin-guides

Q. Is this the defacto style guide for Kotlin? What was the reason for it?

There are two guides: Style guide and Interop guide

  1. Style guide for regular Android app developers to style..
    • code structure, and
    • new Kotlin files
  2. Interop guide for developers to easily co-exist both Kotlin and Java code without feeling awkward especially when calling codes from one language to the other.

Reasons:

  • Android has never had a style guide for non-Google developers
  • There was AOSP style guide but it was only for developers of ASOP. And, Android has been around for 10 years; Most apps have Java code so there needs to be something that people can follow to feel natural when introducing Kotlin code into existing Java code base or consuming APIs of Kotlin language from Java code base.

Q. Why NOT Google Kotlin Guide, and Android specific?

  • Currently Google makes use of Kotlin language for Android platform, so we want something tailored for it, fairly quickly, rather than something very general.
  • It is influenced by Google Java style guide

Q. What about current JetBrains' style guide?

android/kotlin-guides is consciously made not to have conflict with the guide from JetBrains. However, following JetBrains' Kotlin style guide does not mean it is 100% valid for android/kotlin-guides because JetBrains' kotlin-guide is more focused on Kotlin language itself and its future, but android/kotlin-guides cares about natural, comfortable interaction between Java and Kotlin languages as well.

IntelliJ platform does not support code formatting exactly as style guide recommends. (Information from KotlinConf)

Q. How did you start making android/kotlin-gudes?

Goal: - Easy to access - Easy to contribute

Docs on android.developer.com are difficult to contribute for developers.

  • Started with Google doc -> internal review -> API counsel ..etc.. Eventually to github.com with Jekyll

Q. How did you decide what to put in kotlin-guides, especially controversial ones as personal preference or something with non-logical reasons?

  • Looking up
  • Feedback from people from JetBrains who are making their guide in parallel

Q. One of the difficult choices? - for example, 2 spaces -> 1 tab(4 spaces)

  • Google Java style guide specify 2 spaces
  • JetBrains' kotlin guide specifies 1 tab
  • The almost all codebase at Square was also 2 spaces when Jake joined
  • "It seems everything is so far a part"

Q. Why "Style Guide" and "Interop Guide"?

Style Guide

Style guide aims to have rules that are unambiguous and can potentially be enforced or even formatted by an automated tool. - Meant to be 'Hard rules' - Everything should be deterministic, unambiguous just single way of doing something

Interop Guide

  • 'Rules but a bit of interpretation'
  • Something you need to think a bit
  • For people to have mixed (Java & Kotlin) sources

Eventually adding something more subjective.. - Design patterns - Best practices or patterns - Something people can decide whether or not they apply

Highlights of the guides

Style guide: Use-Site Targets

Style guide: Logical Ordering

Q. What is a good logical ordering?

  • The most important part of the guide is there is no "One true order"
  • The rule here is that "there is no rule"
  • Too strict ordering may harm the ability to understand what is going on.

Q. Why is the column limit 100 characters?

  • It is already being used
  • It is what Google Java style guide is using too
  • It is not considered as something that needs to be changed

Q. About "Higher syntactic level"

  • Stolen from Java style guide
  • When performing line breaking, you do not want to break
  • If you perform line breaking, you want to keep the inner function calls and their arguments together

Q. Expression Functions

  • Sometimes it is easier to have normal function body that have multiple expression bodies
  • By having expression functions it is tempting to delcare all functions as expression functions but sometimes it makes harder to read or understand the body of the function.

For contribution

The reason the guide is on GitHub is because we want people to contribute If there is ambiguity, wording miss, incorrect or not conveying the right thing please please contribute. - Already bunch of fixes and so on - Contents from KotlinConf - Thinking to release once every 2 or 3 weeks until the guide stabilizes - Do not want to overwhelm people with changes - Going to provide change logs to easily figure out what is changes

Use of annotations recommended by the style guide

  • You don't have to follow the every single rules but if you start writing codes from the scratch

Q. Do we / should we use Hungarian notations?

  • The language itself actively discourages you from using any kind of prefix.

e.g. Kotlin property delcaration which is consumed from Java

val mName: String = ...
pubic String getMName() { // Super weird!
    return ...;
}

Q. Interop Guide

Java (for Kotlin consumption)

The motivating factor here is that every new API that is added to Android Framework itself or support libraries are consumed from both languages by developers, so there is a strong need to have a set of rules that you can follow or interpret when you are writing these APIs to make sure that they actually feels nice from both languages.

Kotlin (for Java consumption)

We assume that in the near future, more libraries will be written in Kotlin first and those APIs may be consumed from people using Java, so the API Kotlin code needs to be feel idiomatic for them as well. That is the rason why there is a separation.

About "No hard keyword"

  • Kotlin has a notion of both "hard" and "soft" keyword
    • class
    • if
    • else
    • try
    • class
    • when

For example, You can't name a class 'name' or 'if'.

  • Keywords for Kotlin uses are different from keywords for Java uses.
  • If you were to write a new API the style guide strongly recommends not to use those keywords.

Q. Defensive copies

  • Kotlin does have a notion of 'read only' property
  • 2 parts of this: val(= read only), two versions of Collections

Whenever you return a list in a public API where you are sure or there is a possibility that the value will be refenced from Java then it should wrap it or make a defensive copy from Java

  • Guava has it's own version of immutable list
  • JetBrains is also working on Kotlinx.collection.immutable.

Links

Firebaseのサポート(CS)について

この記事は、FirebaseのようなBaaSを利用している方で、欲しい機能がサポートされていない場合に「欲しい機能サポートされていないらしい...orz」と途方に暮れてしまっているだけの方がもしかしたらいるかもしれないと思ったので、そういう人向けに、「ダメ元でもサポートに連絡することをお勧めします!」という記事です。

TL;DR

  • サービスを利用していて困ったことや欲しい機能があったらサポートに連絡してみましょう。
  • Firebaseのサポートは返信が丁寧です。(返信スピードが早い・更新情報があればその都度連絡してくれるので返信頻度が良い意味で多いです。)
  • (Firebaseに限っては)Firebaseサポートからフィードバックや機能リクエストを送ることができます。

アプリケーションを開発する上で、Firebaseを利用しているエンジニアは多いと思います。

Firebaseとは、ゲームを含めたモバイルアプリケーションや、Webアプリケーション開発の手助けや、既存アプリのビジネス拡大を行なうための機能群を提供するツールです。

f:id:shaunkawano:20171203193623p:plain

元々FirebaseはFirebase, Inc.が独自に開発していたツールだったのですが、2014年の10月にGoogleが買収しました。(Google I/O 2015や2016, 2017年では多くのFirebaseに関するセッションがありました。)また、2017年1月にはTwitterがGoogleにFabricを売却したことも発表され、その後FabricからFirebase Crash Reportingへの移行も推奨されています。(自分はまだできていません..)

Firebaseのサポートについて

そんなFirebaseですが、コンソールを使っている時や機能開発をしている際に、「こんな機能は提供されていないのかな、サポートされていないのかな?」と思う場面が何度かありました。そのうち二回ほど、ググってみたりFAQをあさってみたが見つからない、というような場合に出くわし、サポートにメールを送ってみたりしていました。ニュアンスとしては、「もしかしてxxのような機能を提供する予定ですか?」「xxすることができると嬉しいのですが、、」というようなものです。

担当者の方から、「連絡ありがとうございます!エンジニアリングチームに確認して改めて返信するので、ちょっとまってね」というような旨のメールです。

返信メールがその日のうちに返信メールが返ってきてとにかくフィードバックが早いなという印象でした。 自分の場合は、今後サポート予定ですでにスケジュールに組まれているのか、サポート予定だけど実装スケジュールは未定なのか、今のところサポート予定ではない、等を教えていただくことができました。必ずしも自分がリクエストした機能がサポートされるとは限りませんが、上記のようなスケジュール感を共有してもらえるのは開発者としてもありがたいです。

ということで、(Firebaseに限った話ではないですが、)Firebase等のBaaSを利用していてモヤモヤしていること等あれば気軽にまずはサポートに連絡してみることをお勧めします。

以上です!

firebase.google.com

最後に

Firebaseに関する説明や発表の動画は、FirebaseのYoutubeチャンネルにたくさんアップロードされています。

www.youtube.com

プラットフォーム毎にSDKが提供されており、このSDKを利用することで0から開発するにはかなり時間やお金といったコストのかかってしまうような機能を簡単にアプリケーションに導入することができます。

提供されている機能の一覧や詳細については下記ドキュメントを御覧ください:

firebase.google.com

業務で開発・運用しているアプリケーションでは、Realtime Database, Authentication, Cloud Messagingを利用しています。

※すごくFirebase推しですがFirebaseの回し者ではありません。

"XXX is a boxed field but needs to be un-boxed to execute YYY. This may cause NPE so Data Binding will safely unbox it. You can change the expression and explicitly wrap XXX with safeUnbox() to prevent the warning."の警告を見て、Data Binding周りを調べたことについて

TL;DR

  • Data Bindingライブラリで<data>タグと<variable>タグを利用してXML上に変数定義をする際には、プリミティブ型で定義できる際には積極的にプリミティブ型を使っていこう
  • 参照型の変数を定義した際には、Data Bindingライブラリが内部でunboxingする
  • safeUnbox()を利用することもできる

詳細

本記事執筆時点のライブラリバージョンは下記です:

  • com.android.support:appcompat-v7: 27.0.1
  • com.android.databinding:compiler: 3.0.0

Data Bindingライブラリを使ってXML上に変数を定義してViewの見た目を変えるとします。下記は、isLoadingであればProgressBarを表示、そうでなければProgressBarを非表示(View.GONE指定)にする簡単なXMLの例です:

<data>
  <import type="android.view.View"/>
  <variable
    name="isLoading"
    type="Boolean"
  />
</data>
...
  <ProgressBar
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintBottom_toBottomOf="parent"
      android:visibility="@{isLoading ? View.VISIBLE : View.GONE}"
      />
...

一見なにも問題ないように見えますが、この状態でプロジェクトをビルドすると、タイトルのような警告が表示されます。

safeUnbox()

Booleanは参照型なので、値にnullが代入される可能性があります。nullが代入される可能性があるということは、NullPointerExceptionが発生する可能性が生まれるということです。

今回のコードを改善しようとするなら、2つ改善策がありそうです。

1つ目は、変数定義の際のtypeに、unboxする必要のない型を指定することです。ここではBoolean型(=参照型)の代わりにboolean型(=プリミティブ型)を指定すれば良さそうです。

<data>
  <import 
    type="android.view.View" />
  <variable
    name="isLoading"
    type="boolean"
  />
</data>
...

二つ目は、これはタイトルの警告文言にも記載されているのですが、

w: 警告: XXX is a boxed field but needs to be un-boxed to execute YYY. This may cause NPE so Data Binding will safely unbox it. You can change the expression and explicitly wrap XXX with safeUnbox() to prevent the warning.

safeUnbox()というData Bindingライブラリが用意してくれているstaticメソッドを利用することもできるようです。

<ProgressBar
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:visibility="@{safeUnbox(isLoading) ? View.VISIBLE : View.GONE}"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintBottom_toBottomOf="parent"
      />

このsafeUnbox()というメソッドはandroid.databindingパッケージに内包されているDynamicUtilクラスのstaticメソッドでした。

package android.databinding;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.databinding.BindingConversion;
@javax.annotation.Generated("Android Data Binding")
public class DynamicUtil {
    public static int safeUnbox(java.lang.Integer boxed) {
        return boxed == null ? 0 : (int)boxed;
    }
    public static long safeUnbox(java.lang.Long boxed) {
        return boxed == null ? 0L : (long)boxed;
    }
    public static short safeUnbox(java.lang.Short boxed) {
        return boxed == null ? 0 : (short)boxed;
    }
    public static byte safeUnbox(java.lang.Byte boxed) {
        return boxed == null ? 0 : (byte)boxed;
    }
    public static char safeUnbox(java.lang.Character boxed) {
        return boxed == null ? '\u0000' : (char)boxed;
    }
    public static double safeUnbox(java.lang.Double boxed) {
        return boxed == null ? 0.0 : (double)boxed;
    }
    public static float safeUnbox(java.lang.Float boxed) {
        return boxed == null ? 0f : (float)boxed;
    }
    public static boolean safeUnbox(java.lang.Boolean boxed) {
        return boxed == null ? false : (boolean)boxed;
    }
}

ただ、実際にはこのメソッド呼び出しをXML上で明示的に行わなくても、Data Bindingライブラリが生成するJavaソースコード(下記)内でこのメソッドを呼び出して安全にunboxしてくれているようなので、これに関しては書いても書かなくてもどちらでも良さそうです。(詳しいことはしっかりとは調べれていませんので、言い切る自信はないですが)

// read android.databinding.DynamicUtil.safeUnbox(isLoading)
androidDatabindingDynamicUtilSafeUnboxIsLoading = android.databinding.DynamicUtil.safeUnbox(isLoading);

DynamicUtilsafeUnbox()について今回初めて知ったのでメモとして記載した次第です!以上です!

参考リンク

https://stackoverflow.com/questions/42872201/data-binding-safeunbox-warning

Androidの(海外開催含む)カンファレンス情報について

Androidアプリケーション開発者に関わらず、国内、国外の大きなカンファレンスが行われる際、どのようなカンファレンスなのか(どこでいつ頃あるのか、登壇者は誰なのか、等)気になることがあります。Androidアプリケーション開発に関するカンファレンスに関しては、今後どのようなイベントがあるのかをひと目で確認できるサイト・Githubレポジトリが存在します。知っているよ!という方もいるかと思いますが本記事ではそれをさらっと紹介します。

サイトはこちら:

androidstudygroup.github.io

GitHubレポジトリはこちら:

github.com

カンファレンス毎の下記情報が閲覧できます:

  • カンファレンス開催日
  • カンファレンス名
  • カンファレンス開催地
  • カンファレンス
  • 発表申込を受付中かどうか

上記レポジトリは世界中のAndroidアプリケーション開発者やカンファレンス主催者のPull Requestによって更新されています。 また、Call For Papers期間中(発表申込を受付中)の場合にはそれもひと目でわかるように緑のラベルのようなものがつけられていて親切です。

以上です。

これからJavaで書かれたAndroidアプリケーションのソースコードをKotlinに書き換える際に気をつける、やるべきこと2点

Kotlin歴2ヶ月程度で勉強中なのですが、現在プロジェクトのソースコードを少しずつですがKotlinに置き換えていて、本日11/7時点でKotlin率は40%弱です。

この記事の内容は、そんな自分がKotlin置き換え始めた頃の失敗、問題点を雑に振り返り、

JavaソースコードをKotlinに書き換える際には下記2つを行なうのが良いのではないかという提案です:

  1. 自動変換コードは常に疑う
  2. デコンパイルされたバイトコードのレビューをする

尚、内容はYahoo JAPAN!様で開催されたBonfire#2にて発表したものから抜粋しています。(発表資料はこの記事の下部にあります)

Kotlin置き換え始めた頃の自分の問題点

1. 自動変換を信用しすぎていたこと

Android Studioを用いたAndroidアプリケーション開発において、JavaソースコードをKotlinに置き換える際には、自動変換のツールが用意されています。

Macの場合は、

⌘ Option Shift K

のショートカットを利用することで、IDE側で.javaファイルを.ktファイルに置き換えてくれます。素晴らしい!

KotlinはNull安全な言語です。Kotlin言語を使った開発では、値がnullになりえるのか、そうでないのかを明示的に記述する必要があります。

もちろん上記の自動変換によってある程度動くコードには変換されるのですが、手直しは必ず必要です。自動変換されたコードが問題なく動作するコードであっても、そのコードがKotlinらしい文法のコード、パフォーマンス性の高いコードであるという保証はありません。「自動変換のコードは絶対に使わず自分の手できれいなコードを書け!」というわけではなくて、「そんなの当たり前じゃん」と言われればそれまでですが、自動変換されて動くからと言って信用はせずどのようなコードに変換されているのか、もしKotlinを始めた方であれば必ず見て、もっと良い書き方はないかと模索するのが良いかもということが伝えたい事です。

ということで、自動変換は常に疑いましょう。手直しは必ず必要です。また、一件問題なさそうなコードであっても入念にチェックしておくに越したことはありません。

たとえばonActivityResultoverrideしているActivityクラスをJavaからKotlinに置き換えるとしましょう。

変換後のonActivityResultのKotlinのソースコードがこのような形になったとしましょう。一件問題ないようにみえますが、どうでしょうか?

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
  super.onActivityResult(requestCode, resultCode, data)
  ...
}

onActivityResultの第三引数のdataの値はnullに成り得ます。この場合、KotlinではNull許容であるということを明示的に示す?マークを付与する必要があります。?マークがついていない変数等にnullが動的に代入された場合NullPointerExceptionが発生しアプリが終了してしまいます。

ということでこのように記述する必要があります:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  super.onActivityResult(requestCode, resultCode, data)
  ...
}

自動変換が便利で、ある程度信用しきっていた部分があったため、自分の場合この問題に出くわして( ゚д゚)ハッ!としました。何度も書きますが、自動変換は常に疑いましょう。手直しは必ず必要です。

2. (デコンパイルされたバイト)コードレビューをしていなかったこと

Javaにおけるstaticな定数をKotlinで定義したい場合にはcompanion objectを利用できます。

companion object {
  val SOME_VALUE = 1
}
  
println(“$SOME_VALUE")

このようなコードは一件問題ないように見えるのですが、このKotlinのソースコードが生成するバイトコードデコンパイルしてみると、

public static final int SOME_VALUE = 1;
public static final class Companion {
  public final int getSOME_VALUE() {
    return MainActivity.SOME_VALUE;
  }
}
…

String var2 = "" + Companion.getSOME_VALUE();
System.out.println(var2);

このようになっています。定数に対するgetterが定義されているしメソッド名もヮ(゚д゚)ォ!な感じになっていて、Javaで書く際には決して書かないようなコードが生成されています。

Kotlinでは、プロパティに対してデフォルトでsetter / getterが定義可能であれば定義される仕組みとなっています。

たとえばあるクラス内にvar someValue = 1というプロパティを定義した場合、KotlinではsetSomeValue()getSomeValue()メソッドが新たに生成されます。

ここでは詳しくは記載しませんが、varは可変なプロパティを宣言する際に利用します。なのでsetterが定義されます。対してvalは不変なプロパティ宣言の際に利用され、valによって定義されたプロパティにはデフォルトでgetterが生成されます。

先程のコードを改めて確認すると、今回の場合は定数定義を行いたいだけなので、Kotlinには新たにgetterの生成は行ってほしくありません、そのような場合には、

  1. String型もしくはプリミティブ型のプロパティ: const val定義
  2. 1.以外のプロパティ: @JvmFieldアノテーション付与

を行なうことで解決できます。

  1. constキーワードは、object内のトップレベルもしくはメンバーとして定義されているString型、プリミティブ型の変数に対してのみ付与できます。const定義されたプロパティはコンパイル時定数(=Compile-Time-Constants)として定義され、getter生成が省略されます。
companion object {
  const val SOME_VALUE = 1
}
  
println(“$SOME_VALUE")

このようなコードを記述して生成されたバイトコードデコンパイルすると、

public static final int SOME_VALUE = 1;
public static final class Companion {
  …
}

String var2 = "1";
System.out.println(var2);

先程のバイトコードとは違い、getterがなくなっていることがわかります。(getterがなくなったことで、コードが幾分か効率化されたこともわかります)

  1. @JvmFieldアノテーションconstが利用できないプロパティに対して付与でき、Kotlinに対してgetterを生成せず、Javaにおけるフィールドとして公開することを伝えるためのものです。

Kotlinのバイトコードデコンパイルすることで、自分のKotlinのソースコードをもっと効率化できないか、無駄なメソッドが生成されていないか等を確認することができます。

まとめ

世の中では「Kotlinかわいい😍」というツイートをよく見かけますが、Null許容を表す一文字の?をつけるのか、そうでないのかによって大きな違いが生まれるのがKotlinです。怖いでしょ!?Javaでよくない!?とKotlinを否定しているのではありません。僕も思います!Kotlinかわいいです😍 !

ただ、JavaソースコードをKotlinに置き換える際には特に、変換後のKotlinのコードに不備や問題はないか、チェックすることが必要なのかもと思います。(自分の場合は、デコンパイルされたバイトコードを意識して確認するようにしています。)

Kotlinの良さに気づいた時、「Kotlinかわいい😍 」と目が♡になってしまい盲目になりKotlinに噛まれることのないよう、特にこれからJavaソースコードをKotlinに置き換えていく方に向けて、下記の二点をオススメします:

  1. 自動変換を行う際には常に変換後のコードをチェック
  2. 可能であればバイトコードデコンパイルしてレビュー

最後に、下記は、Yahoo! JAPAN Bonfire#2での登壇資料です。上記内容以外に自分がハマったこと等についていくつか紹介しています:

おまけ: 来年2月に開催されるDroidKaigiにて、fluxについて発表します。初の30分という長い時間と英語のプレゼンなので緊張しますが、選ばれたからにはしっかりやろうと思います!

以上です!

AS3.0-stable + RobolectricによるUnitテストでResourceNotFoundExceptionが出る際の対策

バージョンは下記:

現象はタイトルの通りで、上記バージョンのAndroidとRobolectricを使ってUnitテストを実行すると、AndroidのResourcesにアクセスする際にResourceNotFoundExceptionが発生しテストが失敗するというものです。(ちなみに自分の場合は、ローカルでの実行は正常に動きCI(Bitrise)上での実行時のみ失敗する、というものでした。)

あくまで自分のケースのみ有効かもしれませんが、下記に解決策を紹介します:

ResourceNotFoundExceptionに対する解決策

app/build.gradleandroid {}内にtestOptionsを追加し、Unitテスト実行時の設定を記述します。

testOptions {
  unitTests {
    includeAndroidResources = true
  }
}

includeAndroidResourcesに関するドキュメントは下記です: UnitTestOptions - Android Plugin 3.0.0-dev DSL Reference

このoptionをtrueにすることで、Unitテストの実行前にアセット、リソースやマニフェストのマージをプラグインが行ってくれるそうです。

これを指定することでResourceNotFoundExceptionを防ぎテストを正常に実行できるようになりました。

(テスト実行時にthreetenbpに依存している場合の)ZoneRulesExceptionに対する解決策

includeAndroidResourcesオプションを設定することで大半のテストは正常に実行されるようになったのですが、今度は下記のようなエラーログが出てテストが終了するという現象がありました。

    org.threeten.bp.zone.ZoneRulesException
    at android.net.LocalSocketImpl.bind(LocalSocketImpl.java:303)
    at android.net.LocalServerSocket.__constructor__(LocalServerSocket.java:48)
    at android.net.LocalServerSocket.<init>(LocalServerSocket.java)
    at com.facebook.stetho.server.LocalSocketServer.bindToSocket(LocalSocketServer.java:142)
    at com.facebook.stetho.server.LocalSocketServer.listenOnAddress(LocalSocketServer.java:78)
    at com.facebook.stetho.server.LocalSocketServer.run(LocalSocketServer.java:74)
    at com.facebook.stetho.server.ServerManager$1.run(ServerManager.java:40)

アプリではThreeTenABPを利用しているのですが、

IllegalStateException: TZDB.dat missing from assets

というエラーログと共にテストが実行できないことに過去に悩まされた結果、

参考: IllegalStateException: TZDB.dat missing from assets · Issue #24 · JakeWharton/ThreeTenABP · GitHub

上記issueに記載されている解決策を元にテスト実行時にはThreeTenBPに依存するようにしていました。今回ZoneRulesExceptionが出たタイミングでこの依存を試しに解消してみたところテストが正常に通ることがわかりました。(oh..)

予想としてはincludeAndroidResourcesが影響しているものと思っているのですが、具体的なところまでは調査できていません。

下記に今回調査する際にお世話になったサイト一覧を記載しておきます。雑ですが、以上です!

AndroidにおけるColorUtilsを用いた色の配合

Androidsupport.v4.graphicsパッケージにはColorUtilsというユーティリティクラスが存在します。

ColorUtils | Android Developers

Androidアプリケーション開発では、このユーティリティクラスを用いることで簡単に2つの色をコード上から動的に配合することができます。

blendARGB関数には2つの色を表すInt型と、0~1のratio=割合を表すfloat型のオブジェクトを引数として渡すことができます。 0に近ければ第一引数に渡した色が濃く、1に近づくごとに第二引数に渡した色が濃くなります。

このratio値をViewの動きに合わせて変化させることで、ユーザーの動きに合わせて色を動的に配合することができます。たとえば、ViewPagerのonPageScrolledコールバックの値を利用することで、ページ間移動の動きに合わせて色を変化できます。

具体的な例やサンプルgif等については下記サンプルレポジトリを御覧ください。

github.com

また、ColorUtilsについては先日のpotatotipsでも発表しました。

下記はそちらの発表資料です。合わせてご覧ください。

雑ですが、以上です!