第23回コベチケの会

コベリンの最近の取り組みとして、業務などで役立ちそうな知見を共有する会を開催することになりました。 そのついでに発表に使ったアジェンダもそのまま公開してしまおうという豪快な企画です。

※ アジェンダをそのままコピペして公開したものなので若干見にくい箇所もあるかもしれませんが、ご了承ください。

最近の取り組みのやつ @mironal

:tada: TwitterAPIKit に掲載された. https://developer.twitter.com/en/docs/twitter-api/tools-and-libraries/v2 :tada:

feather for Twitter でツイートしてるユーザーを集める

v1 API で source:feather_for_ios lang:ja exclude:retweets という query を使っている. keyword の指定はなし.

  • source: ツイッタークライアントを指定する query
  • lang:ja: 日本語だけを指定する. source だけだと検索できないので入れている
  • exclude:retweets: RT は除外. あくまでも feather でツイートされたものだけを調べる

v2 API や Filter Stream (検索 Stream) API では source の指定ができないので v1 を使っている.

このツイートのユーザーをひたすら集めていく. ダブリを消すために User ID で uniq もしている.

json をざっくり見渡す

↑の方法で集めた情報は 10MB 以上のデカ目の json になった。 ユーザー数的には2万人以上集まっている。

まずどんな雰囲気かなとこの json を眺めたいけど、このぐらいのサイズになるとエディタで開いても全然わからんので何らかの加工をする必要がある。

けどいきなりコードを書くのは愚の骨頂。

そこで使えるツールたち

  • jq: みんなしってるやつ
    • 複雑なことができる一方で、やや使うのが難しい
  • gron: json を grep しやすくするやつ

例えばみんなのフォロワーの数はどんな感じなんだろう? とざっくり眺めたかったとする

output.json はさっき集めたユーザがたくさん入ってる json のファイル

gron では gron output.json | grep ".followers_count" で以下のような結果が得られる.

image.png (87.7 kB)

jq だと cat output.json | jq "[.users[] | .followers_count]" 的な感じで得られる. image.png (19.3 kB)

gron + grep のほうが単純.

一方で filter したりするには jq を使う

例えばファボの数が多い人だけ集めたいという場合には

cat output.json| jq "[.users[] | select(.favourites_count >= 5000)]"

という感じ. select の条件で色々フィルタリングできる.

全体を何らかの key で ソートしたい場合には sort_by を使う

cat output.json| jq "[.users[] | select(.favourites_count >= 5000)] | sort_by(.id_str)"

さらに、要素数. ここでは「条件に当てはまる人は何人いるのか?」を知りたければ length を使う.

cat output.json| jq "[.users[] | select(.favourites_count >= 5000)] | length"

jq 使えばコード書かなくてもかなり色々できるから便利。でもできること多すぎて毎回どうやるか忘れるから毎回ググってる.

Appleの2種類のpush通知の証明書 @takkumattsu

Appleのpush通知の証明書

この前久しぶりにやったのでメモ

そもそもpush通知の証明書は2種類ある

  • 1年で期限が切れるp12形式の証明書
  • 更新が必要ないp8形式

昔からあるのはp12形式、App ID一つ一つ(アプリ1つ)に対して証明書を作って更新する必要がある。20個アプリを作っている会社は1年ごとに20個証明書を更新する必要があった

それに対してp8形式はTeamIDに対して作成できる形式で、同じTeamIDであれば使いまわすことが出来きる。そして更新も必要ない! (ドキュメントが見つからなかったけど2つまでしか作れない https://developer.apple.com/forums/thread/666164)

push通知の証明書はdevelopment用/product用二つあるけどp8を使えば一つで済む.

結論 p8形式を使おう 本番の環境と開発環境で同じキーを使うので誤送信とかを考えたらp12でそれぞれ分けたほうがいいかも

p12を使うメリットはほぼないので今やるならp8一択かな 開発会社が違ってp8をどうしても渡したくないみたいな場合にp12を使うとか?

  • p8のほうが簡単だけど運用を考えると本番と開発環境で別の証明書を使ったほうが誤送信とかを防げるので一概にいいともいえない

@numa08

StateFlowをComposableな関数でcollectするなら、collectAsStateWithLifecycleを使ったほうが良さそうな話。

StateFlowとJetppack Compose

以前は非同期処理の結果をViewModelからUIに通知する場合、LiveDataが使われていたが今はStateFlow/SharedFlowを使う場合が多い。CoroutineのAPIそのままなので、LiveDataへの変換も不要だしJetpack ComposeではcoolectAsStateを使えば普通の値のように使える。

一方で、LiveDataでは実現できたライフサイクルに応じた値の参照がやりにくくなった点はときどき問題になる。

class MainViewModel : ViewModel() {
    val dateTime: StateFlow<LocalDateTime> = run {
        val stateFlow = MutableStateFlow(LocalDateTime.now())
        // 本当はHiltとかで外部から依存性注入をする
        val dateTimeRepository = DateTimeRepository()
        viewModelScope.launch {
            dateTimeRepository.dateTime.collect {
                stateFlow.emit(it)
            }
        }
        viewModelScope.launch {
            // デバッグ用
            stateFlow.subscriptionCount.collect {
                Log.d("TEST", "subscription count $it")
            }
        }
        stateFlow
    }
}

@Composable
fun MainScreen(
    viewModel: MainViewModel
) {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colors.background
    ) {
        val dateTime by viewModel.dateTime.collectAsState()
        LogComposition()
        Greeting("Android : ${dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)}")
    }
}

collectAsStateの実装

単純にFlow.collectしているだけなので画面がバックグラウンドに移っても、collectされたままとなる。

collectAsStateWithLifecycleの実装

パラメータに指定したライフサイクルの間だけcollectしている。デフォルトでON_START→ON_STOPが指定されるので、端末の画面上にUIが表示されている時だけcollectされるようだ。