いももちのきもち

悪戦苦闘の歴史のメモ

isFromMockProviderはdeprecatedなのでLocationCompat.isMockに置き換える

itはLocation isFromMockProviderはdeprecated

APIレベル31からLocation.isFromMockProviderはdeprecatedです。代わりにisMockの使用が推奨されます。

developers.google.com

This constant is deprecated. Use Location.isMock() on Android S and above, otherwise use LocationCompat.isMock() from the compat libraries instead.

31より下の端末ではLocationCompat.isMockを使えば良さそうです(31以上でもこれで済みそうですが) developer.android.com

`@RunWith(AndroidJUnit4::class)`のimportの変更

テストが放置されている古いプロジェクトでテストを更新していると、runnerのところがdeprecated表示になっていた

developer.android.com

androidx.test.runner.AndroidJUnit4 を非推奨にし、androidx.test.ext.junit.runners.AndroidJUnit4 に置き換え

なるほど androidTestImplementation("androidx.test.ext:junit-ktx:1.1.3") (ktx版があった)

こちらをdependencyに追加し、import先を変更するだけで更新が済んだ。 後で確認してみると、最近のAndroid Studioで作った雛形プロジェクトに最初から含まれるExampleInstrumentedTestも最初からextの方で書かれていた、そりゃそうだ

synchronizedの小ネタ

仕事のKotlinのAndroidプロジェクトでsynchronizedを利用しているコードがあったのだが、実は意図していない挙動をしていたのでメモ

1. Booleanをsynchronizedして広すぎる範囲をロックしていた

maku77.github.io

falseもtrueもどこでも共通なので、synchronizedにbooleanを取るとそれらの処理は直列に処理されてしまうのでした。 業務で出会ったコードでは、バックグラウンドからの復帰時の互いに関係のない2つの処理が直列になっていたので、ロックオブジェクトでロックさせるようにしたところ並列で処理されるようになりました。

2. Kotlinのsuspend funcではsynchronizedで排他処理が効かない

qiita.com

ロックが外れる瞬間があるので、排他処理できないです。 suspendではmutex.lockを使います・

その他

qiita.com

ロックと言えばすぐdeadlockが思い浮かびますね。 ただsynchronizedの中でさらにsynchronizedしなければならないような状況はあるのかな...でも例えばサーバだと複数リソースのロックとるときは普通にあるので、まああるのかな。

kotlinlang.org マルチスレッドを扱う手法はKotlin公式を確認するのが一番です。

NaNを含むjsonで例外発生を避ける

以前kotlinx.serializationでjsonを組み立てるときに、ごくまれにNaNが入るフィールドがあり、kotlinx.serialization.json.internal.JsonEncodingExceptionが発生していたのでした。

allowSpecialFloatingPointValues = trueを指定すればNaNのままで通せます。

{"value":NaN}

上記のようにNaNが入るjsonは、jsonとしては正しくないものの、JVM界隈ではポピュラーなんだそうです。

LocationのgetSpeedはNaNを返すことがある

仕事で得た知識をもっと外に出しておこうと思ったので気が変わらないうちに書いておく。



https://developer.android.com/reference/android/location/Location#getSpeed()
たとえばFusedLocationProviderClient.requestLocationUpdatesで位置情報としてLocationを得たときに、getSpeedはNaNを返すことがある(週に数件は見た)。
返り値はfloatなので、floatであるNaNが返り得るのはわかるが、どういうときにNaNが返るかはわからなかった(位置情報測定開始後、初回はspeed=0.0になる)。

This is only valid if hasSpeed() is true.

getSpeed()の前にhasSpeed()チェックをかませるのが想定実装だったようだが、実際プロダクトではisNaN()でNaNのときは0.0に置き換える対応でその後の問題発生を回避した。

mackerel-agentでcron監視始めました

slackに定期的に投稿する仕組みをcronを使って作ったので、mackerelに慣れる練習がてらcronがちゃんと生きているか一応監視することにしました。
yum install mackerel-check-pluginsして
/etc/mackerel-agent/mackerel-agent.confに下記を書き加えます。

[plugin.checks.check_cron]
command = "check-procs --pattern crond"

$ sudo /etc/init.d/mackerel-agent reload

f:id:toricor:20171014190340p:plain
監視が始まりました。簡単ですね。