phicdy devlog

Androidアプリ開発やその他技術系の記事をたまに書きます

AndroidとかiOSとかモバイル多め。その他技術的なことも書いていきます。

Droidkaigi 2023に参加しました

2023/09/14-09/16で開催されたDroidkaigi 2023に参加しました。オフラインでの参加は4年ぶりになります(去年はオンライン参加)。

前回のオフライン参加

phicdy.hatenablog.com

去年はオンラインで参加しましたが、あまり自分が見たいセッションが配信対象ではなくオフラインで参加すればよかったなと思い残したところがありました。そのため今年の開催を見てすぐオフライン参加を決めました。 当日は前職、前々職のAndroidエンジニアと会え、近況を共有したりコミュニケーションを取ることができました。会社を離れて何年も経つといろいろ変わっていて時間の変化を感じました。

当日はセッションだけでなくスポンサーブースのスタンプラリーや軽食の提供、ランチ、バリスタなどオフラインならではの楽しめるコンテンツが多くありました。 特にバリスタが作るカフェラテは絶品で毎日2杯飲んでいました。

セッション

今回は自分があまり知らないことを知る、ということをテーマに参加しました。自分が普段扱っているトピックよりはあまり知らない分野を中心にセッションに参加しました。

見たセッション

Day1

Day2

感想

Jetpack Composeの利用がかなり進んでいて多くの知見が共有されるようになってきたように感じました。現職ではまだ導入がそこまで進んでいないんですが、移行を進めていくモチベーションが湧いてきました。 あとオフラインで参加すると中途採用で探すのに苦労しているAndroidエンジニアがこんなにいるんだ・・・と毎回思います。

launchd/launchctlで定期実行する際に詰まったポイント

Macではcronよりlaunchdで定期実行が推奨されているらしいので設定してみた。

support.apple.com

基本的には下記記事を参考にplistファイルを作ればよいが1つだけ詰まったポイントがあった。

qiita.com

/bin/bashスクリプトを実行するときOperation not permittedになるときの対処

設定 → セキュリティとプライバシー → フルディスクアクセスに/bin/bashを入れる必要がある。このやり方が地味に難しく、一旦フルディスクアクセスを開いた状態でFinderを別に開く。移動 → フォルダへ移動から/binで移動し/binを開く。bashをフルディスクアクセスにドラッグ&ドロップすれば追加できる。

stackoverflow.com

GradleのVersion CatalogとRenovateでAndroidアプリのライブラリアップデートを管理する

個人アプリのライブラリアップデートがしんどくなってきてちらほら見かけていたRenovateを試してみた

github.com

Renovateの設定

GithubであればRenovateのアプリを追加すれば簡単に初期設定が完了する。

github.com

初期設定が完了するとrenovate.jsonというファイルが作成されるPRが作られる。

github.com

自動マージやスケジューリングやグルーピングなどいろんな設定があるが一旦下記のようにしてみた。自動マージはテストライブラリにとどめている。

{
  "extends": [
    "config:base",
    ":timezone(Asia/Tokyo)"
  ],
  "packageRules": [
    {
      "groupName": "Jetpack Compose",
      "matchPackagePatterns": [
        "^androidx\\.compose:",
        "^androidx\\.compose\\.animation:",
        "^androidx\\.compose\\.compiler:",
        "^androidx\\.compose\\.foundation:",
        "^androidx\\.compose\\.material:",
        "^androidx\\.compose\\.runtime:",
        "^androidx\\.compose\\.ui:"
      ]
    },
    {
      "groupName": "androidx.activity",
      "matchPackagePatterns": [
        "^androidx\\.activity:"
      ]
    },
    {
      "groupName": "androidx.lifecycle",
      "matchPackagePatterns": [
        "^androidx\\.lifecycle:"
      ]
    },
    {
      "groupName": "androidx.test",
      "matchPackagePatterns": [
        "^androidx\\.test:",
        "^androidx\\.test\\.ext:",
        "^androidx\\.test\\.espresso:"
      ],
      "automerge": true,
      "major": {
        "automerge": false
      }
    },
    {
      "groupName": "kotlinx.coroutines",
      "matchPackagePatterns": [
        "^org\\.jetbrains\\.kotlinx:kotlinx-coroutines"
      ]
    }
  ]
}

Renovateが対応しているGradleのVersion Catalogに移行する

自分のプロジェクトではモジュール間でバージョンを揃えるためにトップのbuild.gradleにextでバージョンを設定していたが、Renovateはextで設定したバージョンは検知してくれなかった。

Renovateが検知できるライブラリの指定方法はいくつかある。

  • build.gradle/build.gradle.kts files in the root of the repository
  • .gradle/.gradle.kts files in a subdirectory as multi-project configurations
  • dependencies whose version is defined in a *.properties file
  • .versions.toml files in any directory or .toml files inside the gradle directory (Gradle Version Catalogs docs)

github.com

せっかくなのでこちらも気になっていたGradleのVersion Catalogに移行してみた。

GradleのVersion Catalog

Version CatalogはGradleの7.0から使える機能でGradle公式でバージョン管理ができるようになった

docs.gradle.org

いろんな設定方法があるがRenovateはtomlファイルを作らないと検知してくれないのでlibs.versions.tomlファイルを作る方式で設定する。

[versions]
jetpack_compose = "1.1.0"

[libraries]
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "jetpack_compose" }
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "jetpack_compose" }
compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "jetpack_compose" }
compose-material = { module = "androidx.compose.material:material", version.ref = "jetpack_compose" }
compose-material-icons = { module = "androidx.compose.material:material-icons-core", version.ref = "jetpack_compose" }
compose-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "jetpack_compose" }
compose-livedata = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "jetpack_compose" }

[bundles]
compose = ["compose-ui", "compose-ui-tooling", "compose-foundation", "compose-material", "compose-material-icons", "compose-material-icons-extended", "compose-livedata"]

のように設定すると各build.gradleで libs.compose.ui のように使える(ハイフンはドット区切りになる)。Jetpack Composeのようにまとめて使う場合が多いのはbundlesに設定すると libs.bundles.compose のようにまとめて使える。

おわりに

Renovateは自動でPRを作ってくれるのはもちろん、リリースノートへのリンクやダッシュボードからのまとめてのrebaseなど効率よくライブラリアップデートができるようになっていて体験がよかった。いつか有料になりそうな気もするが無料の間はしばらく使ってみようと思う。

coil(というよりOkHttp)でディスクキャッシュのキーをURLから変更するのは難しい

Jetpack Composeでcoilを使うべく調査中。 coilのディスクキャッシュはOkHttpのディスクキャッシュを使っているがそのキーをURLから変更するのは難しそう。

環境

  • coil-compose 1.4.0
  • okhttp 4.9.3

coilのキャッシュ

coil自体はディスクキャッシュの機構は持たず、OkHttpでディスクキャッシュの設定をする。

coil-kt.github.io

val imageLoader = ImageLoader.Builder(context)
    .okHttpClient {
        OkHttpClient.Builder()
            .cache(CoilUtils.createDefaultCache(context))
            .build()
    }
    .build()

メモリキャッシュはcoilの機構があり、キーを自由に指定することができる

coil-kt.github.io

// Get
val bitmap: Bitmap? = imageLoader.memoryCache[memoryCacheKey]

// Set
imageLoader.memoryCache[memoryCacheKey] = bitmap

OkHttpのディスクキャッシュ

OkHttpClient.BuilderのcacheにはCacheクラスのインスタンスを指定する。このクラスはKotlinでopenではないので継承して拡張することはできない。

github.com

Cacheクラスは内部でinternalなDiskLruCacheを持ちinternalなputメソッドでeditをしている。ここにキーとして渡しているのがリクエストのURLになっている。internalなため外からキャッシュに追加することはできない。

  internal fun put(response: Response): CacheRequest? {
    ...

    val entry = Entry(response)
    var editor: DiskLruCache.Editor? = null
    try {
      editor = cache.edit(key(response.request.url)) ?: return null
      entry.writeTo(editor)
      return RealCacheRequest(editor)
    } catch (_: IOException) {
      abortQuietly(editor)
      return null
    }
  }

ちなみに削除のremoveもinternalのためキーを指定して行うことができない。全削除するdeleteのみが公開されている。

キーを変えたい場合はどうするか?

  • キーとしたい値が変わったタイミングでディスクキャッシュを全部削除する
  • メモリキャッシュで我慢する
  • Glideを使いAndroidViewにする

あたりかなと思う。

Glideからの移行でここだけが困るなとなった。

Coflicting 'on' color for a given backgroundエラーの修正

f:id:phicdy:20211229143730p:plain

Jetpack Composeのテーマ設定をしていたら上記のようなエラーが出ていた。 エラー文を読むとonの色設定がコンフリクトしているらしい。例えばonPrimaryはprimary時の背景なので同じ色ならエラーなのかなと思ったが別の色を指定しているしよくわからなかった。

private val LightThemeColors = lightColors(
    primary = White,
    primaryVariant = White,
    secondary = Green700,
    background = White,
    surface = White,
    onPrimary = Black,
    onSecondary = White,
)

環境

修正

private val LightThemeColors = lightColors(
    primary = White,
    primaryVariant = White,
    secondary = Green700,
    background = White,
    surface = White,
    onPrimary = Black,
    onSecondary = White,
    onSurface = Black,
    onBackground = Black
)

onSurfaceとonBackgroundをデフォルト設定のまま持ってきたらエラーが消えた。どうやらデフォルト設定のままにしているとうまく判定ができない模様。

Gradle plugin 7.0.2にアップデート後Github Actionがコケる問題の対処

最新の環境にアップデートすべくGradle plugin 7.0.2にアップデートしたところなぜかGithub Actionがコケるようになってしまったのでその対処。 ちなみにローカルでビルドする分には問題なく、Bitriseはたまにコケる程度だった。

環境

状況

ユニットテストやlint、リリースビルドなどCI全般がコケた。10回くらいリトライしていれば通ることもある程度。失敗したときのログにはgradle daemon disappeared unexpectedlyと出るのみで詳細なログはなかった。

対処

いろいろ試した結果、JDK11から使用されるG1ガベージコレクタが原因のようだった。

developer.android.com

これをJDK8までの平行ガベージコレクタに戻したところ安定して動くようになった。

org.gradle.jvmargs=-XX:+UseParallelGC

効果がなかった変更としては以下

最後に

結局のところ原因ははっきりしておらずG1ガベージコレクタの何が悪さしているのかがよくわかっていない。Bitriseはほぼ安定しているのもモヤっとする。

tmuxのウィンドウの右上にgitの現在のブランチを表示する

環境

  • tmux 3.0a

~/.tmux.confの設定

set -g status-right "#(cd #{pane_current_path}; git rev-parse --abbrev-ref HEAD)"
# 長いブランチだと表示できないので表示文字数を増やす
set -g status-right-length 30

色を変えたかったので指定

set -g status-right "[fg=cyan]#(cd #{pane_current_path}; git rev-parse --abbrev-ref HEAD)"