- 投稿日:2022-03-03T20:45:29+09:00
【Android】Perffetoを用いて爆速でパフォーマンス計測を行う方法
はじめに Perfettoを用いてシステムトレースするには、(方法によっては)計測用のコマンドを作成して、実行結果を持ってきてGUI上で確認するなど、少し手間がかかる場合があります。 なので本記事では、Perfettoを用いて(自分が試した中で)最も短時間で計測できる方法を紹介します。(Android StudioのProfiler使えばもっと速いととかはなし 笑) Perfettoとは? Perfettoは、Androidデバイス内のシステムトレースをするツールのことです。 システムトレースとは、例えばCPUやメモリの使用率、各プロセスの情報などを記録することを言います。 以前に、このPerfettoを用いてZOZOTOWNアプリのボトルネックを特定・改善した話を書きました。 上記の記事では、Perfettoでどのようにボトルネックを特定し、どのように改善したかを書いているので、実用的な使い方を知りたい方は参考になるかと思います。 Perfettoでの計測方法 公式では下記の4つの計測方法が紹介されています。 ヘルパースクリプトを使用する方法 Androidデバイス内の/system/bin/perfettoを使用する方法 Perfetto UIを使用する方法 Androidデバイス内のSystem Tracing Appを使用する方法 どれが一番速いか? 1の「ヘルパースクリプトを使用する方法」がもっとも速く計測ができると思います。 (公式でも推奨されています。) 2,4はトレース結果のファイルをデバイスからPCに、移動させ、Perfetto UIなどでOPENする手間がかかります。 (ちなみに、2についてはAndroid Pより古いAndroid端末にはコマンドが存在しません) 3は、トレース結果のファイルをGUI上でOPENする必要はありません。しかし毎回画面をぽちぽちしてトレース用の設定をしなければならないことに加えて、ときどきトレースが始まらないなどの問題があります。 1はトレース用の設定を与えたスクリプトを実行後、自動でブラウザが開きトレース結果を確認することができます。 手順 レイアウト生成処理のパフォーマンス計測を行う方法は下記の通りです。(Macを想定しています) # OS9 or OS10の非Pixel端末の場合 $ adb shell setprop persist.traced.enable 1 # ヘルパースクリプトのダウンロード $ curl -O https://raw.githubusercontent.com/google/perfetto/master/tools/record_android_trace $ chmod u+x record_android_trace # トレース実行 $ ./record_android_trace -o result view 結果 自動でPerfetto UIが開き、トレース結果が表示されます! おわりに Perfettoを用いて、最も短時間でパフォーマンス計測できる方法を紹介しました。 最近では、Android StudioのProfilerに機能が充実してきたので、その機能使うともっと速いかもしれないです! 参考資料 Android Developers | システムトレースの概要 Perfetto Quickstart: Record traces on Android
- 投稿日:2022-03-03T15:54:48+09:00
【Android】絵文字判定
はじめに 絵文字かどうかを判定する方法について説明。こちらの記事でも書いたが、ここではgetEmojiMatchを使用する方法について説明。 コード ビルド依存関係を追加 emoji2ライブラリを追加。 build.gradle implementation "androidx.emoji2:emoji2:1.1.0" 処理内容 getEmojiMatchメソッドの第1引数は判定したいテキスト、第2引数はmetadataVersionを入れている。 fun CharSequence.isEmoji(): Boolean { val editorInfo = EditorInfo() EmojiCompat.get().updateEditorInfo(editorInfo) val metadataVersion = (editorInfo.extras[EmojiCompat.EDITOR_INFO_METAVERSION_KEY] as? Int) ?: 0 return EmojiCompat.get().getEmojiMatch(this, metadataVersion) == EmojiCompat.EMOJI_SUPPORTED }
- 投稿日:2022-03-03T10:41:44+09:00
Android + Gradle 探訪 - 後編: buildSrc や Version Catalog
最近は Gradle の構成を Groovy ではなく KTS (一連の Gradle の Kotlin DSL) で書いたり buildSrc や Version Catalog に依存をまとめるのがナウそうですが, Android Studio で作成した新規プロジェクトはシンプルな Groovy で記述されています. Kotlin DSL などについて まったくわかっていないので (Groovy もだけど), この機会に Empty Compose Activity Project を題材にして, 最近の Gradle の構成や記述について調べようと思いました. 前編: モジュール共通の定義 さて,前回の ext の節で書いたように,KTS の移行とは関係はないのですが 最近ではマルチモジュールでも共通で参照できるように 依存するライブラリの記述をまとめておくやりかたがよく使われているようです. (要出典) ここで紹介するのは, ひとつは buildSrc に定義をまとめておいて参照するやりかた. もうひとつは Gradle の Version Catalog として定義をまとめて参照するやりかたです. buildSrc buildSrc というディレクトリをつくりまして, ここにプロジェクトで共通の定数・処理を置くと, いろんなモジュールで使えて便利だねということです. つまり,ライブラリのバージョンであるとか, そういった定数をまとめておくのがパターンになっているということです. なので,今回はそのパターンで buildSrc に定数を定義しましょう. KotlinConf 2018 の公演でいうと, 26:55 〜 buildSrc での管理について紹介されています: buildSrc/build.gradle.kts まず buildSrc というディレクトリをつくります. その中に build.gradle.kts をまず置きます: buildSrc/build.gradle.kts plugins { `kotlin-dsl` } repositories { mavenCentral() } 同じく Kotlin DSL として記述できるようにしておきます. ファイル作成後,リラックスして待っていると .gradle ディレクトリができていて,なにやら構成されたことがわかります: バージョンを定義する 次に buildSrc/src/main/kotlin というフォルダをつくり, そこに Deps.kt を配置して, このファイルにライブラリの依存についての定数をまとめることにします. buildSrc/src/main/kotlin/Deps.kt package dependencies object Versions { object AndroidX { const val compose = "1.0.1" } } dependencies パッケージに Versions.AndroidX.compose という階層で, Jetpack Compose まわりのライブラリのバージョンについて定義してみます. そうすると,app/build.gradle.kts で import して, そのまま使うことができるわけです: app/build.gradle.kts import dependencies.Versions android { composeOptions { kotlinCompilerExtensionVersion = Versions.AndroidX.compose } } dependencies { implementation("androidx.core:core-ktx:1.7.0") implementation("androidx.compose.ui:ui:${Versions.AndroidX.compose}") implementation("androidx.compose.material:material:${Versions.AndroidX.compose}") implementation("androidx.compose.ui:ui-tooling-preview:${Versions.AndroidX.compose}") // 以下略… } 依存ライブラリを定義する さらに,ライブラリの定義ごと定数としてまとめることを考えます: buildSrc/src/main/kotlin/Dependencies.kt package dependencies object Versions { object AndroidX { const val compose = "1.0.1" } } object Deps { object AndroidX { const val coreKtx = "androidx.core:core-ktx:1.7.0" const val composeUi = "androidx.compose.ui:ui:${Versions.AndroidX.compose}" const val composeMaterial = "androidx.compose.material:material:${Versions.AndroidX.compose}" const val composeUiToolingPreview = "androidx.compose.ui:ui-tooling-preview:${Versions.AndroidX.compose}" const val lifecycleRuntimeKtx = "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1" const val activityCompose = "androidx.activity:activity-compose:1.3.1" } // 以下略… } 書き方は自由ですが,このような階層でまとめたとしましょう. そうすると,app/build.gradle.kts はこのように書けることになります: app/build.gradle.kts import dependencies.Deps dependencies { implementation(Deps.AndroidX.coreKtx) implementation(Deps.AndroidX.composeUi) implementation(Deps.AndroidX.composeMaterial) implementation(Deps.AndroidX.composeUiToolingPreview) implementation(Deps.AndroidX.lifecycleRuntimeKtx) implementation(Deps.AndroidX.activityCompose) // 以下略… } こうしておくことで,ライブラリ関係の依存が一箇所にまとまるので, 複数モジュールで構成されたプロジェクトでは, それぞれの build.gradle.kts に定義が分散せずに 管理が楽になることが期待できますね. (あと,頑張れば共通の Gradle の記述自体を追い出すこともできそうです) Version Catalog 別の手法としては Gradle の Version Catalog を使うことができそうです. ただ,Version Catalog は Gradle バージョン 7.4 より前では Feature Preview です: そのため,使用するにはまず settings.gradle.kts で Feature Preview を有効にします: settings.gradle.kts enableFeaturePreview("VERSION_CATALOGS") 次に,gradle/libs.versions.toml に Compose のバージョンを定義してみます: gradle/libs.versions.toml [versions] compose = "1.0.1" こうすれば Gradle 側で libs.* として参照できるので, 複数のモジュールで共通定義のバージョンを記述することができます: app/build.gradle.kts android { composeOptions { kotlinCompilerExtensionVersion = libs.versions.compose.get() } } libs.versions.compose は org.gradle.api.provider.Provider<String> が返ってくるので, get() で String として取り出せば使うことができます. さらに依存ライブラリの定義を追加していきます. 今回は例としてこういうかたちにしてみました (どういう構成にするかは自由です): gradle/libs.versions.toml [versions] compose = "1.0.1" [libraries] androidx-core-ktx = "androidx.core:core-ktx:1.7.0" androidx-compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" } androidx-compose-material = { module = "androidx.compose.material:material", version.ref = "compose" } androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" } androidx-lifecycle-runtime-ktx = "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1" androidx-activity-compose = "androidx.activity:activity-compose:1.3.1" junit = "junit:junit:4.13.2" androidx-test-ext-junit = "androidx.test.ext:junit:1.1.3" androidx-test-espresso-core = "androidx.test.espresso:espresso-core:3.4.0" androidx-compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "compose" } androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" } [bundles] base = ["androidx-core-ktx", "androidx-lifecycle-runtime-ktx"] compose = ["androidx-compose-ui", "androidx-compose-material", "androidx-compose-ui-tooling-preview", "androidx-activity-compose"] test-base = ["junit"] android-test-base = ["androidx-test-ext-junit", "androidx-test-espresso-core"] android-test-compose = ["androidx-compose-ui-test-junit4"] debug-compose = ["androidx-compose-ui-tooling"] 直接 androidx-core-ktx = "androidx.core:core-ktx:1.7.0" のように定義したり, 共通のバージョンを使うときは androidx-compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" } のように [versions] で定義したものを参照して書くことができます. (ちなみに後者は TOML の Inline Table なので 1 行で書かなければいけないようです) 最後の [bundles] は [libraries] で定義したライブラリを 任意のグループとして名前をつけてまとめることができるので便利です. こうすれば複数のモジュールで共通定義の依存を記述することができます (できていれば libs. あたりで補完が出てきてくれます): app/build.gradle.kts dependencies { versionCatalogs { implementation(libs.bundles.androidx.base) implementation(libs.bundles.androidx.compose) testImplementation(libs.bundles.testing.base) testImplementation(libs.bundles.testing.androidx.compose) debugImplementation(libs.bundles.debug.androidx.compose) } } [bundles] に定義した依存がそのまま 1 つのエントリのように記述できるので便利ですね. 最後に いろいろ紹介したのですが, IDE の対応が十分ではないなどデメリットもあるということで, プロジェクトにあったものを選択できるとよいですね. 独断と偏見では KTS + buildSrc で依存管理というプロジェクトが最近は多いのではないでしょうか. (データはありません) そのうち Android Studio のスケルトンプロジェクトが ナウい感じを示してくれると勝手に期待しています.
- 投稿日:2022-03-03T10:14:30+09:00
Android + Gradle 探訪 - 前編: Groovy → KTS (Kotlin DSL) 書き換え
最近は Gradle の構成を Groovy ではなく KTS (一連の Gradle の Kotlin DSL) で書いたり buildSrc や Version Catalog に依存をまとめるのがナウそうですが, Android Studio で作成した新規プロジェクトはシンプルな Groovy で記述されています. Kotlin DSL などについて まったくわかっていないので (Groovy もだけど), この機会に Empty Compose Activity Project を題材にして, 最近の Gradle の構成や記述について調べようと思いました. 後編: ガイド 公式の移行ガイドがあるので見てみます: あとは,具体例として KotlinConf 2018 での講演や: gradle/kotlin-dsl-samples にあるサンプルの記述と照らし合わせるのも わかりやすくてよさそうに思いました. (この Repository は Archive されているのですけれど) 例 例として Empty Compose Activity の新規プロジェクトを作成してみます (Android Studio Bumblebee 2021.1.1 Patch 2 + Gradle 7.0). ごく標準的な,ルートには settings.gradle, build.gradle, そして app レベルには app/build.gradle があるような構成ですね: settings.gradle settings.gradle pluginManagement { repositories { gradlePluginPortal() google() mavenCentral() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } } rootProject.name = "myproj20220215" include ':app' build.gradle /build.gradle buildscript { ext { compose_version = '1.0.1' } }// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { id 'com.android.application' version '7.1.1' apply false id 'com.android.library' version '7.1.1' apply false id 'org.jetbrains.kotlin.android' version '1.5.21' apply false } task clean(type: Delete) { delete rootProject.buildDir } app/build.gradle /app/build.gradle plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' } android { compileSdk 31 defaultConfig { applicationId "io.github.manganoito.myproj20220215" minSdk 21 targetSdk 31 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary true } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion compose_version } packagingOptions { resources { excludes += '/META-INF/{AL2.0,LGPL2.1}' } } } dependencies { implementation 'androidx.core:core-ktx:1.7.0' implementation "androidx.compose.ui:ui:$compose_version" implementation "androidx.compose.material:material:$compose_version" implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' implementation 'androidx.activity:activity-compose:1.3.1' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" } 基本 これをどうやって KTS にするかというと, まず,Groovy では可能で,Kotlin ではできない記述を置き換える必要がありそうです: 文字列は Groovy ではシングルクォーテーションが使えましたが,Kotlin ではダブルクオーテーションである必要があります 関数呼び出しの括弧は Groovy では省略できましたが,Kotlin では省略できません 変数への代入は,Groovy では = を省略できましたが,Kotlin では省略できません ▲ Prepare your Groovy scripts | Migrating build logic from Groovy to Kotlin から ところで (1) は自明なのですが,(2), (3) が微妙にわからないですよね. どれが関数呼び出しで,どれが代入なのかがパッと見わからない. (雰囲気でわかるといえばわかるのですが) ひとつは Go To > Implementation(s) などで調べてやっていくことですが… もうひとつとしては, ここで大まかに書き換えたとしても結局エラーは出てしまうので, 先に進んでしまって KTS にしてから構文エラーをひとつずつ潰していく…… という地道な作業を行うほうが楽そうです. (もちろん git などで管理して失敗したら退却する準備をしておいたうえで) なので,おおまかに書き換えたら次のステップに進んでしまいます. Groovy → KTS として扱うようにするには? さて,Groovy から KTS として扱ってもらうには *.gradle を *.gradle.kts にリネームすれば OK です. よくわからないけど便利にできている. しかしながら,リネームしたあとに前の段階で構文をあわせたのにもかかわらず, まだビルドが通らない箇所があることに気づくと思います. それぞれ対応する Kotlin DSL の記述に調整してビルドが通るようにしていきます. settings.gradle → build.gradle → app/build.gradle と ひとつずつ順を追ってエラーをつぶしながら移行させていきましょう. ext まず,依存するライブラリ共通のバージョンを定義するのに /build.gradle 内の ext というブロック1で Groovy では書かれていたわけですが, これは使えないということで別の記述にしてみます. build.gradle.kts buildscript { extra.apply { set("compose_version", "1.0.1") } } こうするとおなじように Extra Properties を定義できるのですが, 大きなプロジェクトでは昨今の複数のモジュールの管理を考えて 別の便利なパターンを使うのもいいかなと思いました. (後編の記事で紹介しています) plugins 次に id "com.android.application" version "7.1.2" apply false とあって, これはどういう書き方なのだろう…となるのですが, これは id が単純な関数呼び出しで, version と apply がその返り値の PluginDependencySpec に対する infix の拡張関数の呼び出しとなるので id だけを括弧で囲みます: build.gradle.kts plugins { id("com.android.application") version "7.1.2" apply false id("com.android.library") version "7.1.2" apply false id("org.jetbrains.kotlin.android") version "1.5.21" apply false } task task clean(type: Delete) となっているところが構文エラーで落ちるので, これをどう書き換えるのかな,となります: builde.gradle task clean(type: Delete) { delete rootProject.buildDir } Custom Taskというやつで, この例でいえば org.gradle.api.tasks.Delete で定義されたものを使うようになっているということです. 公式のガイドを見ると,tasks あたりを使う感じになるようなので, 完全に雰囲気で tasks.register<Delete>("clean") に書き換えます: build.gradle.kts tasks.register<Delete>("clean") { delete(rootProject.buildDir) } 変更後同期して特にエラーがみられず, Build > Clean Project が無事できれば OK です. minifyEnabled ここまで書き換えれば,プロジェクトルートにある build.gradle.kts は いい感じになったのではないかと思います. ビルドが通ることを確認したら, 次は app レベルの app/build.gradle.kts もリネーム & 書き換えしていきます. そうしていくと… いきなり minifyEnabled がない! と怒られてしまうのですが, app/build.gradle.kts android { buildTypes { release { - minifyEnabled = false + isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } } 単に isMinifyEnabled になっているので名前を変えてあげます. compose_version 更に "androidx.compose.ui:ui:$compose_version" みたいにしているところで,さっき変えたばかりの Extra Property が見つからないよというエラーになるので,明示的に定義することにします. app/build.gradle.kts val compose_version: String by project こうすれば使えるようになります. Delegated Property なのが Kotlin な感じでオシャレ. ビルドできるように こうやってぬるりと書き換えていくことで, ひとまず Empty Compose Activity Project については Groovy → KTS へ移行することができたはずです. さらに さて,ext の節で書いたように,KTS の移行とは関係はないのですが 最近ではマルチモジュールでも共通で参照できるように 依存するライブラリの記述をまとめておくやりかたがよく使われているようです. これについては後編の記事で紹介します: Extra Properties というようですね ↩