20211127のAndroidに関する記事は4件です。

ktlint を導入した話

はじめに 今更ながら ktlint を導入する機会があったので、その手順などをまとめました。 参考:ktlint とは? ざっくり、Kotlin Style Guide を元にコードスタイルのチェックをしてくれたり、lint で検出した部分にフォーマットをかけてくれたりしてくれる Kotlin 用の静的コード解析ツールになります。 公式ページ ktlint HP サンプルソース GitHub simple-ktlint-android 導入 1. やりたいこと ktlint でコードをフォーマットしたい さらに、ビルド時にフォーマットが走るようにしたい 2. 準備 Android Studio: 3.4.1 ktlint: 0.4.0 3. 導入 (ktlint の README のとおり)Gradle へ依存関係の追加と、ktlint を実行するためのタスクを追加します。 app/build.gradle configurations { ktlint } dependencies { ktlint "com.pinterest:ktlint:0.40.0" } task ktlint(type: JavaExec, group: "verification") { description = "Check Kotlin code style." classpath = configurations.ktlint main = "com.pinterest.ktlint.Main" args "src/**/*.kt" } check.dependsOn ktlint task ktlintFormat(type: JavaExec, group: "formatting") { description = "Fix Kotlin code style deviations." classpath = configurations.ktlint main = "com.pinterest.ktlint.Main" args "-F", "src/**/*.kt" } プロジェクトのルートディレクトリで $ ./gradlew ktlint を実行すると結果が出力されます。また、 $ ./gradlew ktlintFormat を実行すると、lint で検出されたコードにフォーマットをかけてくれます。 Option #1 チェックにひっかかっても途中で終了させないようにするために ignoreExitValue true を設定します。 task ktlint(type: JavaExec, group: "verification") { ignoreExitValue true } task ktlintFormat(type: JavaExec, group: "formatting") { ignoreExitValue true } Option #2 ビルド時にフォーマットをしたいので以下も追加します。 app/build.gradle tasks.whenTaskAdded { task -> task.dependsOn ktlintFormat } これにより毎回コマンドを実行しなくても、ビルド時にフォーマットしてくれるようになります。コミット後のフォーマットの修正漏れの予防にもなります。 ちょっとひとこと お読みいただきありがとうございます。 今回は基本的な ktlint の導入と使い方をまとめました。 皆様の参考になれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

2021食べチョクAndroidが取り入れた技術まわりを振り返っていく

この記事は ビビッドガーデン Advent Calendar 2021 の1日目です。 食べチョクAndroidアプリは1周年を迎えました? 2020/11/2にリリースした食べチョクAndroidアプリは先日1歳のお誕生日を迎えました? 1stリリースへの開発期間は3ヶ月ととても短く、更に先行していたiOSアプリに追いつくためにもリリースから一定期間は機能開発に集中する時間が続いていました。 そんな食べチョクAndroidにおいてもリリースから半年を過ぎた頃から少しずつではありますがモダンな開発に近づけていく努力を行っていけるようになりました。今回はそんな食べチョクAndroidアプリの1年間の軌跡を振り返っていきたいと思います。 リリース前(~2020/11) Bitrise iOS/AndroidアプリのCIはどちらもBitriseを利用しています。 このときは PR時にdebug build/release buildが正しくビルドできるかを検証するWorkflow Firebase App Distributionに指定ブランチアプリをアップロードするWorkflow Firebase TestLabでRoboテストを実行するWorkflow の簡易的なWorkflowを作って稼働していました。 dependabot リリース前ではありましたがGradleでのライブラリバージョン管理としてdependabotを導入しました。 個人的にライブラリのバージョン最新化ツールをAndroidプロジェクトで導入するのは初めてだったのですが それまでAndroid Studioのハイライト表示だけだと見落としがちなバージョン管理をPRとして常に最新化できる仕組みは非常に便利みを感じており、今でも稼働させています。 codeclimate 静的解析ツールとして導入していました。 ルールを細かく設定すればKotlinでも使いやすいのでしょうが、弊社プロダクトだと扱いづらい印象を受け、現在は別のツールに置き換えました。 開発初期〜現在までAndroidプロジェクトは1〜2人体制のため、満足なコードチェックをできないこともあり静的解析の指摘だけでも遵守していくためにも導入しています。 ktlint 必要最低限のKotlinの制約を担保するために導入していました。 Danger 上記のktlintとあわせてPR時に実行していました。 リリース時(2020/11) Bitrise > deploy workflow 加速していくリリース作業をより簡略化するためにDeploy用のWorkflowを作成しました。 今でも大枠は変わらないのですがこのときはGoogle Play内部テスト版へのアップロードを行うだけのフローを作成していました。 ちなみにこのタイミングでGoogle Play ConsoleのUIアップデートが入り、署名鍵・アップロード鍵を誤ってアップロードして1stリリースが延期する事態になりました それまで割と順調に進んでいた開発だっただけに、最後の最後でつまづいてしまったのは今振り返るといい思い出です? Slack > AWS Lambda > Bitrise起動コマンドを作成 Bitrise/Slackのスラッシュコマンドを使えば同じことはできるのですが iOS/AndroidともにdeployがCI上実現できてしまうこともあり、権限ユーザーを絞る仕組みを作りました。 ざっくり説明すると、lambda functionではSlackからの特定コマンド時に送信されるAPI Keyを認証し、Slackの特定チャットルームからの起動に限定させ、 そのルームに属するメンバーのポストだけを受け付けるようにし、あとはBitriseのAPIを叩いて指定Workflowを動かすといった仕組みです。 今でも定常的に使われており、iOSでもテスター用のデバイスUDID登録 や上述の deployタスク を起動したりとほぼ毎日稼働しています。 コラム:リリースから半年 ここから半年間は基本的に機能実装や改善がメインとなり、開発体制のアップデートや技術負債の解消などにあまり時間を使えない状況が続いていました。 この記事を作成するにあたり、GithubReleasesを参照していたのですが、特にリリースしてから1~2ヶ月はバグFIXに取り組む時間が多かったようです笑 弊社ではリリースしてしまったユーザーに影響のある不具合のことを総じてdefectと呼称し、defectの解消を最優先事項として取り組むというルールを設けています。 そして解消したdefectはその後再発防止の為、ポストモーテムの場でチームに共有、具体的な再発防止策を講じて堅牢性を高めていくようなアクションをとっています。 このリリース初期時に特にdefectが多かったのですが、地道な解消と講じた再発防止策の成果あって、今は低い水準でキープしています リリースから半年〜 UnitTest/instrumentation Testの導入 恥ずかしながら半年間ここまでテストがありませんでした… これまでは機能開発・dependabotのPRの確認として手動のリグレッションテストが欠かせず、1リリースのクローズにとても時間を要していました。 まずは壊れたことがすぐに分かることを目標にかんたんな画面遷移や主要機能のログイン・購入のUIテストの作成から努めました。 今はQAエンジニアの助けを借りながら、まずは実現すべき必要最低限のUIテストパターンを洗い出し、それらの実装率を高めていくような取り組みを行っています。 まだ導入して半年ですが今現在のUnitTest+InstrumentationTestの実装率は33%と少しずつではありますが「壊れたことがすぐわかる」から、「壊れないプロダクト」に変わりつつあるかなと感じています。 またこの同タイミングにてBitriseにtestを実行するWorkflowを追加し、日時で定時実行するように運用しております。 ktlint+Danger >> pre-commit+ktlint それまでktlint+Dangerである程度のKotlinのお約束を担保し続けていましたが、まだ少数である開発体制の中、PRごとにGithub Actionで稼働させるよりも、pre-commitでlintを実行するのはどうかと思い試してみています。 今のところはGithub Actionの稼働時間の減少とcommit前の検査でストレスなく検証できていますが メンバーが増えたときの制約がゆるくなってしまうので、やはりDangerでの検証は必要かなと考えています。 codeclimate >> detekt Kotlinのlintをktlintに、コード制約をcodeclimateに担わせていましたが、 codeclimateのルール設定が少し難しく、import文なども指摘されることや非常に強力なDuplicateWarningなどで少しつらみがあったので Kotlin純正でktlintを更に制約強くしたdetektの導入・移行をしています。こちらは21年11月末時点で現在進行系で行っています。 というのも最終的にはdetekt+Dangerの構成にしてチェックを行いたいのですが、試しにdetektを実行してみると3桁を超えるWarningが… このままではActionでチェックさせることはできなかったため、一旦はローカル・CIで実行できるように調整しています。 CIでは日時実行するようにしており、どのWarningがどれだけでているか・またその改善推移をスプレッドシートに吐き出すスクリプトを作って管理しております。 毎日総数がSlackのbotチャンネルに通知され、チームメンバーに状況が晒されているので、改善のモチベーションにつながっています? 自分の中で善行と呼称して毎朝心を清めるための活動として継続しています。日々修行 Google Playストアへのdeployを半自動化 もともとdeploy workflowはBitriseから起動できるようにしていましたが、 バージョン用issueのクローズ milestoneのクローズ バージョンPRのクローズ Releaseの作成… などは手作業で行っていました。 申請提出作業からリリース後のクローズ作業、合わせて20分程度の作業となっていたところを、トータル5分(スクリプト投げて待つだけ)に短縮することに成功しました。 詳細はまた別の記事で紹介できればと思いますが、 次回リリースバージョンの準備 バージョン用milestoneの作成 バージョン用issueの作成・milestoneの紐付け deploy・審査提出 バージョン用branch >> mainへのPR バージョン用issueへのin:reviewラベルの付与 draft Releaseの作成 バージョン用milestoneのクローズURLを付与 Google Play inner testへのdeployタスク リリースクローズ バージョンPRのマージ バージョン用milestoneのクローズ バージョン用issueのクローズ ReleaseのPublish 上記をそれぞれ実行するスクリプトを作成し、Gradle/Bitriseからそれぞれ実行できるようにしています。 また半自動化としているのは、inner test版からproductionへのステージング処理、審査通過後のステータス通知などについてはそのまま手動となっているからです。 inner testからのステージングについては、inner test版での検証を踏んでから審査提出、という流れにしているため一旦は最適かと考えていますが、 審査ステータスの変更については、PublishAPIのtrackステータスに審査通過が無いことや、メール通知が無いことから自動化できず、 Androidアプリ版のGoogle Play Consoleでの通知を確認するだけに留まっています。 審査ステータスのよいオブザーブ方法をご存知のかたはコメントいただけると助かります さいごに 食べチョクAndroidアプリの1年を軽く振り返ってみましたが、まだまだ改善できるようなところばかりだなーと改めて感じています。 もちろんdetektの改善は継続して続けていきますが、一層のテストコードの拡充・効率化、少数体制だからこそのより強いコード制約・自動化など やれることはまだまだ山積みだと思っております。 そんな中ビビッドガーデンではより多くのAndroidエンジニアを求めています! 今回の記事では紹介できなかった話や一次産業の課題解決に取り組んでいる具体的な活動などについてもカジュアルにお話する場も用意しておりますので、 気になった方はこちらを覗いて見てください。 また、趣味の家庭菜園についてもお話できたりするので、家庭菜園系フルリモートエンジニアについて興味のある方はぜひ一度おはなししてみませんか!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Android12 targetSDKVersion31にしたら起きること

今働いている会社でそろそろtargetSDKVersion31への移行を行なっていく必要があり調査していて、発生したことをメモ書きしていきます。 アプリで対応する必要があった項目 ・コンポーネントのエクスポートの安全性を改善 ・ペンディング インテントの可変性 コンポーネントのエクスポートの安全性を改善 インテントフィルタの設定が入っている場合にはexportedのフラグ設定が必須になりました。元々デフォルトでインテントフィルタ設定がされてたらONになっていたがそれを明示的に指定するように。 そもそも内部でしか利用しないようなパターンがあったときに、勝手にONになっていたため知らず知らずのうちにアプリを公開してしまうっていうのを防ぐのが目的っぽい。 ビルド時にエラーで怒られます。対象のAndroidManifest.xmlのタブで「Marged Manifest」をタップするとエラー確認できます。 色々動かしていて分かったこととしては、システム側から起動されるような処理の場合、exported=falseでも問題なく動作したことです。基本的にアプリの外部から呼ばれるものはexported=trueにしなきゃいけないのかな?っと思っていたのですが、大丈夫そうでした。 利用しているライブラリでも影響を受けていたので記載 androidx.test:core:1.4.0 にアップデートで解消しました。 ペンディングインテントの可変性 PendingIntent利用時にPendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_IMUTABLEの設定が必要になります。 こちら、ビルド時ではなく実行時にException発生するので注意です。 アプリ側でも警告文は出るので、一度PendingIntentを利用しているところをチェックした方が良さそうです。 基本的にFLAG_IMUTABLEを設定するでOKですが、アプリ側との連携などが必要で起動先から情報を更新してもらうような機能の場合はFLAG_MUTABLEが必要になります。 説明で記載があるのはBubbleを使った例などでした。 notificationなどは特に変更など必要ないのでFLAG_IMUTABLEの対応で問題ないと思います。 アプリでMUTABLEに設定が必要だった箇所としてはジオフェンスで、その際に受信時にintentにデータを詰めているためMUTABLEを設定しないと受信時にデータがnullで返却するため動作しない状況でした。 あらかじめシステム側からデータが返却されることが分かっている場合、MUTABLEでの設定が必要かと思います。 また、ライブラリでは下記が影響を受けてました。下記のバージョンにアップデート。 androidx.media:media:1.4.3 androidx.work:work-runtime-ktx:2.7.0  com.google.android.gms:play-services-analytics:17.0.1 サードパーティ製のライブラリが影響受けてそうな項目 ・おおよその位置情報 ACCESS_FINE_LOCATIONとACCESS_COARSE_LOCATIONの両方を指定した場合はUI上でユーザがおおよその位置にするか正確な位置にするかを選択できるようになりました。そのため、正確な精度を強制するのはできなくなった感じです。 ・フォアグラウンド サービスの起動に関する制限 基本的にはバックグラウンド時にフォアグラウンドサービスの利用ができなくなったので、WorkManagerを利用する必要がありそう。 ・新しいBluetooth権限  これだけメインのところに載ってなかった。権限が追加されているのでBluetoothを利用するアプリは追加が必要かも。 まとめ 今回のアップデート対応ではビルド時にエラーになる項目と、実行時にエラーになるパターンもあったので注意です。 ライブラリ側でもアップデートしないといけないところが多くて、意外と更新が必要だった印象です。 targetSDKVersion31にすることでSplashScreenAPIを使うことができるようになるので、アップデートが完了したらそちらも利用していきたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Android】マルチモジュールって何?

この記事は マルチモジュールって何だろうと思い、恥を忍んでAndroidのお師匠さんに聞いてみた私が、「マルチモジュール完全に理解した」になるまでの物語である。 先生、マルチモジュールって何ですか? これまでpackageとして管理していたある機能を持つまとまりを、モジュールとしてライブラリのように切り離して扱う方法のこと。 ...ハァ? あの...モジュールって何ですか...? ていうか、パッケージって何...(小声) packageとは app->com.ウンニャラカンニャラの下にあるフォルダ(?) 以下の画像におけるviewやviewModelがパッケージとなる moduleとは かの有名などすこい先生のリポジトリを見てみましょう。 GitHubClientForJetpackCompose 自動生成されるものは省きますが、例えばdataやuiなどがモジュールに当たります。 このように、今までappディレクトリの中のcom.~~配下で管理していたui(view, viewModel)やdata(repository, usecase)をappと同じディレクトリでモジュールとして切り離し、ライブラリのように扱うのがマルチモジュール(らしい)です。 じゃあ、appには何が入ってるの? いままでapp配下で管理していたuiやdataなどのパッケージを、app外に出すということは、逆にapp内には何が存在しているのか。 もはや、appの存在意義は何なのか。 app配下にはAndroidManifestなど、build時に必要なファイルが格納されている。 appの実行を通じて、他のモジュールも実行され、最終的にアプリがビルドされる流れであるので、appの存在意義としては、アプリのエントリポイントのようなものと言えるでしょう。 参考:Android開発におけるモジュール分割
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む