20200315のAndroidに関する記事は13件です。

シワ(Sign in with Apple) 対応

Sign in with Appleとは

Apple ID を利用したサインイン方法。
サードパーティーログインを使用しているアプリは2020/04までにSign in with Appleに対応する様に義務化した。

App Storeに提出されるすべての新しいAppやアップデートは、2020年4月30日までにこれらのガイドラインに従う必要があります。
引用元:https://developer.apple.com/jp/news/?id=03042020d

そうです。いつものAppleの無茶振りです。
対応しないとリジェクトされてしまう為、仕方なく実装する事に、、
まずは仕様から

アプリへの公開情報

アプリに公開される情報は大きく分けて以下の2つです。

  • 名前
  • メールアドレス
    • 公開メールアドレス
    • プライベートメールアドレス

これらの値はSign in with Apple新規登録時かユーザーがアプリと紐付け解除を行った後の初回のみ設定する事が出来ます。

名前

アプリに連携する名前はアプリ毎にユーザーが設定することができます。
デフォルトではiCloud アカウントに設定している姓名が入ってきますが、公開したくない場合は任意の名前に変更可能になっています。

公開メールアドレス

ユーザーがiCloudの登録に使用しているメールアドレス。
* 実際のメールアドレスなので転送を停止する機能などは今回対象外

プライベートメールアドレス

認証時にユーザーがメールアドレス(Apple ID)を非公開設定すると、Appleが自動生成したランダムな英数字のメールアドレスをアプリ(サービス)に連携する。その結果ユーザーは自身のメールアドレスを公開する事なくアプリでログインが可能になる。
* アプリとのメールやりとりはAppleが アプリ→自動生成メールアドレス→プライベートメール という形でメールを転送してくれる。(設定の必要あり)
* ユーザーはメールの転送を停止したり、転送先のメールアドレスを変更する事が出来る。

このプライベートメールアドレスは出来るとユーザーにとって何が嬉しいのか?
サービス登録時に実際のメールアドレスを使用するとサービスの利用を停止した後にもメールアドレスを保持されて悪用されるリスクがある。そこでこのプライベートメールアドレスを使用すると実際のメールアドレスはサービスに公開せず、利用停止したい場合には紐付け解除(プライベートメールアドレスの破棄)を行えば悪用されなくなるというメリットがある。

アプリとの紐付けの解除

iCloudの管理画面からアプリとの紐付け解除を行うことが出来る。
ユーザーにとって

※iOS13以上では[設定>Apple ID(一番上の箇所)>パスワードとセキュリティ>Apple IDを使用中のApp]からでも解除出来る

CSRF対策

Sign in with AppleはCSRF対策の為にAppleの認証APIを実行する際にstateを指定することができる。
簡単に言うとなりすまし防止の為にアプリで送信時に作成したstateとAppleの認証時に返されたstateが一致しているかを確認する。

完璧に仕様が分かったことで対応する事を以下に記載。

対応内容

あくまでアプリが対応する内容を記載する。

  • コーディング
    • iOS13以上の対応
    • iOS12未満の対応(必須ではない)
    • Android対応(必須ではない)
  • Apple Developerでの設定
    • Sign in with Appleの有効化
    • メールのホワイトリスト追加
    • ServiceIDの登録
  • Xcodeの設定
    • Sign in with Apple有効化
  • デザイン対応
    • ガイドラインに沿ったデザイン

iOS13での対応

Appleのログインボタンを生成する。

LoginViewController.swift
    func setupProviderLoginView() {
        let authorizationButton = ASAuthorizationAppleIDButton()
        authorizationButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside)
        self.loginProviderStackView.addArrangedSubview(authorizationButton)
    }

ユーザーの姓名とメールアドレスを受け取る様な認証のリクエストをAppleに対して行う。

LoginViewController.swift
    @objc
    func handleAuthorizationAppleIDButtonPress() {
        let appleIDProvider = ASAuthorizationAppleIDProvider()
        let request = appleIDProvider.createRequest()
        request.requestedScopes = [.fullName, .email]

        let authorizationController = ASAuthorizationController(authorizationRequests: [request])
        authorizationController.delegate = self
        authorizationController.presentationContextProvider = self
        authorizationController.performRequests()
    }

Delegateで結果を受信する。

LoginViewController.swift
extension LoginViewController: ASAuthorizationControllerDelegate {
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
            // 成功した場合       
            let userIdentifier = appleIDCredential.user
            let fullName = appleIDCredential.fullName
            let email = appleIDCredential.email
        }
    }

    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        // エラーが発生した場合
    }
}

iOS12以下での対応

WebViewを利用してApple JSに対応する必要があります。
サーバサイドの実装が必要だったりAppleボタンを自作しなければならなかったりするので
出来ればiOS13以降のみの対応の方が無難だと思います。

デザイン対応

Appleのガイドラインの記載を抜粋。
* Appleのボタンを目立つようにする
* 他サードパーティのログインボタンよりも小さくしないこと
* スクロールしないでもAppleのボタンが表示されるようにする
* ボタンの色は背景色と被らないようにする
などなど

ガイドラインに従わないとリジェクトされます。
実際に初めてSign in with Apple対応した時にはボタンと背景の色やフォントサイズなどでリジェクトされました。
(iOS12対応の為にボタンは自作しました)

https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/

まとめ

iOS12以下に対応する為には、自作したボタンをAppleのデザインに合わせたり認証をWebViewで行ったりしないとならなく別対応が必要なので骨が折れますが、
iOS13のみなら基本Appleが提供しているSDKを使用すれば比較的簡単に開発が済みます。
最近(2020/03時点)リジェクトが厳しくなっている気がするのでデザインのガイドラインなどはしっかり読んで対応した方が良いです。

参考URL

* サンプルコード
https://developer.apple.com/documentation/authenticationservices/adding_the_sign_in_with_apple_flow_to_your_app

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

既存のプロジェクトでJetpack Composeを動かす方法について

モチベーションとしてはDroidKaigi App 2020でちょっと動かして見たかったんですが、そのうちすぐ状況が変わるとは思いますが、結構ハマるのでメモしています。
見た後に始めれば、ハマらずにすっと動かせるのではないかと思ったので、公開しています。

Compose導入の現状の問題点と解決策

Android Gradle Plugin(AGP) 4.1-alpha01でCrashlyticsが対応していない

Composeを使うにはAGPが4.1-alphaか4.0-alphaでないといけないです。
Composeというよりは、AGP 4.1-alpha01の問題で、CrashlyticsのGradle Pluginがまだ対応できていなくてビルドできないので、一旦外します。ここはAGPの問題なので、4.0のalphaなどを使えば一応通るはずです。
https://issuetracker.google.com/issues/150397894
変更ログ
https://github.com/DroidKaigi/conference-app-2020/commit/f3442dc7aecfa32f7938f012bb3be787246a82ef

Annotation processorsと一緒に使えない問題

現状、aptと一緒に使えないという問題 ( https://issuetracker.google.com/issues/143232368 https://youtrack.jetbrains.com/issue/KT-34583 ) があるので、それに対応する必要があります。

  • Composeを使うモジュールを分けて、そこではaptを使わずに実装していくアプローチ

tiviでは、ui-episodedetails-composeモジュールやcommon-ui-composeモジュールに分離しています。

https://github.com/chrisbanes/tivi/pull/544

  • aptを使えるようにしたpatchバージョンを使う

patchバージョンがあります。

https://developer.android.com/jetpack/androidx/releases/compose のページに書いてあるpatchバージョンです

dependencies {
    def compose_version = "0.1.0-dev06"

    kotlinPlugin "androidx.compose:compose-compiler:$compose_version"
    implementation "androidx.compose:compose-runtime:$compose_version"
}
composeOptions {
    // これがpatchあたったバージョン。
    kotlinCompilerVersion "1.3.61-dev-withExperimentalGoogleExtensions-20200129"
    kotlinCompilerExtensionVersion "0.1.0-dev06"
}

現状、フルで新しい機能を試していくにはモジュールを分けて行い、
妥協して作っていくならpatchバージョンと言う感じな気がします。(他にいい方法あれば教えて下さい)

patchバージョンを使った場合の問題点

DroidKaigiではKlockというKotlin Multi Platformで使える日付のクラスが使えるライブラリを使っていますが、そのinline classでビルドエラーになりました。
このように問題が起こった場合は、モジュールを分けるのが現状良いかもしれません。
(patchの問題かもなので、普通にaptで動くようになってまだ再現するようだったら報告を考えています)

e: java.lang.IllegalStateException: Backend Internal error: Exception during code generation
Element is unknownThe root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor(InlineClassAbi.kt:72)
    at org.jetbrains.kotlin.codegen.CompilationErrorHandler.lambda$static$0(CompilationErrorHandler.java:35)
    at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm(JvmBackendFacade.kt:93)
    at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm$default(JvmBackendFacade.kt:64)
    at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm(JvmBackendFacade.kt:52)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.generateModule(JvmIrCodegenFactory.kt:36)
    at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.doGenerateFiles(KotlinCodegenFacade.java:47)
    at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:39)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:641)
...
Caused by: java.lang.IllegalStateException: Unhandled special name in mangledNameFor: <get-unixMillisLong>
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor(InlineClassAbi.kt:72)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements.buildReplacement(MemoizedInlineClassReplacements.kt:197)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements.createStaticReplacement(MemoizedInlineClassReplacements.kt:172)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements.access$createStaticReplacement(MemoizedInlineClassReplacements.kt:41)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements$getReplacementFunction$1.invoke(MemoizedInlineClassReplacements.kt:55)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements$getReplacementFunction$1.invoke(MemoizedInlineClassReplacements.kt:41)
...   
    at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.downlevel(CompilerPhase.kt:24)
    at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper.runBody(CompilerPhase.kt:127)
    at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper.invoke(CompilerPhase.kt:105)
    at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:42)
    at org.jetbrains.kotlin.backend.jvm.JvmLower.lower(JvmLower.kt:288)
    at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm(JvmBackendFacade.kt:91)
    ... 37 more


e: java.lang.IllegalStateException: Backend Internal error: Exception during code generation

Execution failed for task ':feature:session:compileDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork
   > Internal compiler error. See log for more details

諦めて、モジュールにComposeを切り出す

一応ビルド成功。
変更はこちらにあります。
https://github.com/DroidKaigi/conference-app-2020/compare/5ea4077..ae364d6
image.png

まとめ

Compose、まだまだ色々大変ですが、やっていきましょう :muscle:




以下は調査ログです。

以下少しだけCompose導入で戦った記録 (prebuiltの取得の仕方とか、ローカルAndroidXデプロイの仕方などは参考になるかも)

Dep.kt
    object Compose {
        val composeReleaseVersion = "dev06"
        val composeVersion = "0.1.0-$composeReleaseVersion"
        val composeCompilerExtensionVersion = "0.1.0-$composeReleaseVersion"
        val compose = "androidx.compose:compose-runtime:$composeVersion"
    }
build.gradle
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = Dep.Compose.composeCompilerExtensionVersion
    }
build.gradle
dependencies {
...
    implementation(Dep.Compose.compose)

エラー。

e: java.lang.NoSuchMethodError: org.jetbrains.kotlin.codegen.state.GenerationState$Builder.isIrBackend(Z)Lorg/jetbrains/kotlin/codegen/state/GenerationState$Builder;

https://stackoverflow.com/a/59684701/4339442
Kotlinのバージョンがだめらしい。 :thinking:

Dep.kt
    object Kotlin {
        val version = "1.3.70"
        val stdlibCommon = "org.jetbrains.kotlin:kotlin-stdlib-common:$version"
        val stdlibJvm = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$version"

→ 同じエラー。

Jetpack Composeの自力ビルド + ローカルパブリッシュ

リリースされていないバージョンを試してみる。
今snapshotビルドは動かなくなってしまったみたいなので、自分でビルドしてローカルにデプロイする。
最新のAndroidXのライブラリをローカルのmavenリポジトリにpublishして使う
https://qiita.com/takahirom/items/d0859c8ac125f026cd72

cd frameworks/support/ui # frameworks/supportでないので注意
./gradlew publishMavenPublicationToMavenLocal

deployされたことを確認。

ls ~/.m2/repository/androidx/compose/compose-runtime/                                                                                                                                        
compose-runtime/0.1.0-dev07/ compose-runtime/maven-metadata-local.xml

MavenLocalを追加

build.gradle
    repositories {
        mavenLocal()

2度目のエラー。
DrawerLayoutの依存するinterfaceがないらしい。

e: Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
    class androidx.drawerlayout.widget.DrawerLayout, unresolved supertypes: androidx.customview.widget.Openable

MavenLocalの位置がよくなかったので、一番下に移動

build.gradle
    repositories {
        ...
        mavenLocal()
    }

振り出しに戻る

e: java.lang.NoSuchMethodError: org.jetbrains.kotlin.codegen.state.GenerationState$Builder.isIrBackend(Z)Lorg/jetbrains/kotlin/codegen/state/GenerationState$Builder;

AndroidXをKotlin 1.3.70で動かす

/buildSrc/build_dependencies.gradle
if (isUiProject) {
    build_versions.kotlin = "1.3.70"

これだとprebuildに色々ないと言われて、ビルドできない。またmavenリポジトリを追加しまくってもmavenリポジトリにない謎のリポジトリがあってできなかった。

そこでこれでprebuiltの取得をやってみたら、prebuiltの取得に成功したが、一部リポジトリは成功しなかった。

cd frameworks/support
./development/importMaven/import_maven_artifacts.py --name=org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.70

以下のブランチをfetchすることで依存関係を取得できた

https://android-review.googlesource.com/c/platform/prebuilts/androidx/external/+/1230140

git fetch "https://android.googlesource.com/platform/prebuilts/androidx/external" refs/changes/40/1230140/3 && git checkout FETCH_HEAD

ビルドしたところ普通にコンパイルエラーめっちゃ出て心が折れました。

> Task :compose:compose-compiler-hosted:compileKotlin FAILED
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt: (34, 1): Class 'ComposeIrGenerationExtension' is not abstract and does not implement abstract member public abstract fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext, backendContext: BackendContext?): Unit defined in org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt: (35, 5): 'generate' overrides nothing
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposePlugin.kt: (47, 5): 'processOption' overrides nothing
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt: (281, 44): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt: (292, 14): None of the following functions can be called with the arguments supplied:
public constructor IrFunctionReferenceImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
public constructor IrFunctionReferenceImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt: (141, 38): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt: (149, 38): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt: (159, 41): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt: (185, 45): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (146, 17): Type mismatch: inferred type is ClassConstructorDescriptor but Int was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (149, 17): Type mismatch: inferred type is Int but IrStatementOrigin? was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (150, 17): Too many arguments for public constructor IrConstructorCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol, typeArgumentsCount: Int, constructorTypeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (235, 16): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (245, 13): Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
private final fun IrMemberAccessExpression.copyRemappedTypeArgumentsFrom(other: IrMemberAccessExpression): Unit defined in androidx.compose.plugins.kotlin.compiler.lower.DeepCopyIrTreeWithSymbolsPreservingMetadata
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (185, 46): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (268, 63): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (292, 33): Unresolved reference: descriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (344, 25): Type mismatch: inferred type is FunctionDescriptor but Int was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (438, 16): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt: (239, 40): Unresolved reference: descriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt: (352, 21): Unresolved reference: descriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (25, 56): Unresolved reference: WrappedFunctionDescriptorWithContainerSource
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (26, 56): Unresolved reference: WrappedPropertyGetterDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (27, 56): Unresolved reference: WrappedPropertySetterDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (28, 56): Unresolved reference: WrappedSimpleFunctionDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (247, 16): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (258, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (261, 17): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (264, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (265, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (266, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (268, 17): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (270, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (366, 44): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (383, 65): Unresolved reference: WrappedSimpleFunctionDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (386, 17): Unresolved reference: WrappedPropertyGetterDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (391, 17): Unresolved reference: WrappedPropertySetterDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (396, 17): Unresolved reference: WrappedFunctionDescriptorWithContainerSource
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (398, 17): Unresolved reference: WrappedSimpleFunctionDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (410, 16): None of the following functions can be called with the arguments supplied:
public constructor IrFunctionImpl(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: FunctionDescriptor, returnType: IrType) defined in org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
public constructor IrFunctionImpl(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, symbol: IrSimpleFunctionSymbol, returnType: IrType, visibility: Visibility = ..., modality: Modality = ...) defined in org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
public constructor IrFunctionImpl(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, symbol: IrSimpleFunctionSymbol, name: Name, visibility: Visibility, modality: Modality, returnType: IrType, isInline: Boolean, isExternal: Boolean, isTailrec: Boolean, isSuspend: Boolean, isOperator: Boolean, isExpect: Boolean, isFakeOverride: Boolean) defined in org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (423, 18): Cannot infer a type for this parameter. Please specify it explicitly.
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (468, 13): Type mismatch: inferred type is ClassConstructorDescriptor but Int was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (469, 19): The integer literal does not conform to the expected type IrStatementOrigin?
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (440, 21): Unresolved reference: putValueArgument
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (492, 49): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (499, 49): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (536, 41): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (539, 41): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (574, 17): Unresolved reference: putValueArgument
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (583, 9): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (591, 9): Unresolved reference: dispatchReceiver
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (700, 41): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (749, 41): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (824, 41): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (836, 9): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (842, 9): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (843, 9): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (859, 9): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (878, 13): Type mismatch: inferred type is ClassConstructorDescriptor but Int was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (879, 13): An argument is already passed for this parameter
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (901, 5): None of the following functions can be called with the arguments supplied:
public constructor IrDelegatingConstructorCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol) defined in org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
public constructor IrDelegatingConstructorCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol, typeArgumentsCount: Int) defined in org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
public constructor IrDelegatingConstructorCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int) defined in org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (988, 1): Class 'FrameRecordClassDescriptor' is not abstract and does not implement abstract member public abstract fun getDefaultFunctionTypeForSamInterface(): SimpleType? defined in org.jetbrains.kotlin.descriptors.ClassDescriptor

FAILURE: Build failed with an exception.


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

既存のプロジェクトでJetpack Composeを動かす方法について(2020/03/15時点)

モチベーションとしてはDroidKaigi App 2020でちょっと動かして見たかったんですが、そのうちすぐ状況が変わるとは思いますが、結構ハマるのでメモしています。
見た後に始めれば、ハマらずにすっと動かせるのではないかと思ったので、公開しています。

Compose導入の現状の問題点と解決策

Android Gradle Plugin(AGP) 4.1-alpha01でCrashlyticsが対応していない

Composeを使うにはAGPが4.1-alphaか4.0-alphaでないといけないです。
Composeというよりは、AGP 4.1-alpha01の問題で、CrashlyticsのGradle Pluginがまだ対応できていなくてビルドできないので、一旦外します。ここはAGPの問題なので、4.0のalphaなどを使えば一応通るはずです。
https://issuetracker.google.com/issues/150397894
変更ログ
https://github.com/DroidKaigi/conference-app-2020/commit/f3442dc7aecfa32f7938f012bb3be787246a82ef

Annotation processorsと一緒に使えない問題

現状、aptと一緒に使えないという問題 ( https://issuetracker.google.com/issues/143232368 https://youtrack.jetbrains.com/issue/KT-34583 ) があるので、それに対応する必要があります。

  • Composeを使うモジュールを分けて、そこではaptを使わずに実装していくアプローチ

tiviでは、ui-episodedetails-composeモジュールやcommon-ui-composeモジュールに分離しています。

https://github.com/chrisbanes/tivi/pull/544

  • aptを使えるようにしたpatchバージョンを使う

patchバージョンがあります。

https://developer.android.com/jetpack/androidx/releases/compose のページに書いてあるpatchバージョンです

dependencies {
    def compose_version = "0.1.0-dev06"

    kotlinPlugin "androidx.compose:compose-compiler:$compose_version"
    implementation "androidx.compose:compose-runtime:$compose_version"
}
composeOptions {
    // これがpatchあたったバージョン。
    kotlinCompilerVersion "1.3.61-dev-withExperimentalGoogleExtensions-20200129"
    kotlinCompilerExtensionVersion "0.1.0-dev06"
}

現状、フルで新しい機能を試していくにはモジュールを分けて行い、
妥協して作っていくならpatchバージョンと言う感じな気がします。(他にいい方法あれば教えて下さい)

patchバージョンを使った場合の問題点

DroidKaigiではKlockというKotlin Multi Platformで使える日付のクラスが使えるライブラリを使っていますが、そのinline classでビルドエラーになりました。
このように問題が起こった場合は、モジュールを分けるのが現状良いかもしれません。
(patchの問題かもなので、普通にaptで動くようになってまだ再現するようだったら報告を考えています)

e: java.lang.IllegalStateException: Backend Internal error: Exception during code generation
Element is unknownThe root cause java.lang.IllegalStateException was thrown at: org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor(InlineClassAbi.kt:72)
    at org.jetbrains.kotlin.codegen.CompilationErrorHandler.lambda$static$0(CompilationErrorHandler.java:35)
    at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm(JvmBackendFacade.kt:93)
    at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm$default(JvmBackendFacade.kt:64)
    at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm(JvmBackendFacade.kt:52)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.generateModule(JvmIrCodegenFactory.kt:36)
    at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.doGenerateFiles(KotlinCodegenFacade.java:47)
    at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:39)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:641)
...
Caused by: java.lang.IllegalStateException: Unhandled special name in mangledNameFor: <get-unixMillisLong>
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor(InlineClassAbi.kt:72)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements.buildReplacement(MemoizedInlineClassReplacements.kt:197)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements.createStaticReplacement(MemoizedInlineClassReplacements.kt:172)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements.access$createStaticReplacement(MemoizedInlineClassReplacements.kt:41)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements$getReplacementFunction$1.invoke(MemoizedInlineClassReplacements.kt:55)
    at org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements$getReplacementFunction$1.invoke(MemoizedInlineClassReplacements.kt:41)
...   
    at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.downlevel(CompilerPhase.kt:24)
    at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper.runBody(CompilerPhase.kt:127)
    at org.jetbrains.kotlin.backend.common.phaser.AbstractNamedPhaseWrapper.invoke(CompilerPhase.kt:105)
    at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:42)
    at org.jetbrains.kotlin.backend.jvm.JvmLower.lower(JvmLower.kt:288)
    at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm(JvmBackendFacade.kt:91)
    ... 37 more


e: java.lang.IllegalStateException: Backend Internal error: Exception during code generation

Execution failed for task ':feature:session:compileDebugKotlin'.
> A failure occurred while executing org.jetbrains.kotlin.compilerRunner.GradleKotlinCompilerWork
   > Internal compiler error. See log for more details

諦めて、モジュールにComposeを切り出す

一応ビルド成功。
変更はこちらにあります。
https://github.com/DroidKaigi/conference-app-2020/compare/5ea4077..ae364d6
image.png

まとめ

Compose、まだまだ色々大変ですが、やっていきましょう :muscle:




以下は調査ログです。

以下少しだけCompose導入で戦った記録 (prebuiltの取得の仕方とか、ローカルAndroidXデプロイの仕方などは参考になるかも)

Dep.kt
    object Compose {
        val composeReleaseVersion = "dev06"
        val composeVersion = "0.1.0-$composeReleaseVersion"
        val composeCompilerExtensionVersion = "0.1.0-$composeReleaseVersion"
        val compose = "androidx.compose:compose-runtime:$composeVersion"
    }
build.gradle
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = Dep.Compose.composeCompilerExtensionVersion
    }
build.gradle
dependencies {
...
    implementation(Dep.Compose.compose)

エラー。

e: java.lang.NoSuchMethodError: org.jetbrains.kotlin.codegen.state.GenerationState$Builder.isIrBackend(Z)Lorg/jetbrains/kotlin/codegen/state/GenerationState$Builder;

https://stackoverflow.com/a/59684701/4339442
Kotlinのバージョンがだめらしい。 :thinking:

Dep.kt
    object Kotlin {
        val version = "1.3.70"
        val stdlibCommon = "org.jetbrains.kotlin:kotlin-stdlib-common:$version"
        val stdlibJvm = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$version"

→ 同じエラー。

Jetpack Composeの自力ビルド + ローカルパブリッシュ

リリースされていないバージョンを試してみる。
今snapshotビルドは動かなくなってしまったみたいなので、自分でビルドしてローカルにデプロイする。
最新のAndroidXのライブラリをローカルのmavenリポジトリにpublishして使う
https://qiita.com/takahirom/items/d0859c8ac125f026cd72

cd frameworks/support/ui # frameworks/supportでないので注意
./gradlew publishMavenPublicationToMavenLocal

deployされたことを確認。

ls ~/.m2/repository/androidx/compose/compose-runtime/                                                                                                                                        
compose-runtime/0.1.0-dev07/ compose-runtime/maven-metadata-local.xml

MavenLocalを追加

build.gradle
    repositories {
        mavenLocal()

2度目のエラー。
DrawerLayoutの依存するinterfaceがないらしい。

e: Supertypes of the following classes cannot be resolved. Please make sure you have the required dependencies in the classpath:
    class androidx.drawerlayout.widget.DrawerLayout, unresolved supertypes: androidx.customview.widget.Openable

MavenLocalの位置がよくなかったので、一番下に移動

build.gradle
    repositories {
        ...
        mavenLocal()
    }

振り出しに戻る

e: java.lang.NoSuchMethodError: org.jetbrains.kotlin.codegen.state.GenerationState$Builder.isIrBackend(Z)Lorg/jetbrains/kotlin/codegen/state/GenerationState$Builder;

AndroidXをKotlin 1.3.70で動かす

/buildSrc/build_dependencies.gradle
if (isUiProject) {
    build_versions.kotlin = "1.3.70"

これだとprebuildに色々ないと言われて、ビルドできない。またmavenリポジトリを追加しまくってもmavenリポジトリにない謎のリポジトリがあってできなかった。

そこでこれでprebuiltの取得をやってみたら、prebuiltの取得に成功したが、一部リポジトリは成功しなかった。

cd frameworks/support
./development/importMaven/import_maven_artifacts.py --name=org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.70

以下のブランチをfetchすることで依存関係を取得できた

https://android-review.googlesource.com/c/platform/prebuilts/androidx/external/+/1230140

git fetch "https://android.googlesource.com/platform/prebuilts/androidx/external" refs/changes/40/1230140/3 && git checkout FETCH_HEAD

ビルドしたところ普通にコンパイルエラーめっちゃ出て心が折れました。

> Task :compose:compose-compiler-hosted:compileKotlin FAILED
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt: (34, 1): Class 'ComposeIrGenerationExtension' is not abstract and does not implement abstract member public abstract fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext, backendContext: BackendContext?): Unit defined in org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposeIrGenerationExtension.kt: (35, 5): 'generate' overrides nothing
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/ComposePlugin.kt: (47, 5): 'processOption' overrides nothing
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt: (281, 44): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/AbstractComposeLowering.kt: (292, 14): None of the following functions can be called with the arguments supplied:
public constructor IrFunctionReferenceImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
public constructor IrFunctionReferenceImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt: (141, 38): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt: (149, 38): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt: (159, 41): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableCallTransformer.kt: (185, 45): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (146, 17): Type mismatch: inferred type is ClassConstructorDescriptor but Int was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (149, 17): Type mismatch: inferred type is Int but IrStatementOrigin? was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (150, 17): Too many arguments for public constructor IrConstructorCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol, typeArgumentsCount: Int, constructorTypeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (235, 16): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposableTypeRemapper.kt: (245, 13): Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
private final fun IrMemberAccessExpression.copyRemappedTypeArgumentsFrom(other: IrMemberAccessExpression): Unit defined in androidx.compose.plugins.kotlin.compiler.lower.DeepCopyIrTreeWithSymbolsPreservingMetadata
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (185, 46): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (268, 63): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (292, 33): Unresolved reference: descriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (344, 25): Type mismatch: inferred type is FunctionDescriptor but Int was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposeObservePatcher.kt: (438, 16): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt: (239, 40): Unresolved reference: descriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerLambdaMemoization.kt: (352, 21): Unresolved reference: descriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (25, 56): Unresolved reference: WrappedFunctionDescriptorWithContainerSource
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (26, 56): Unresolved reference: WrappedPropertyGetterDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (27, 56): Unresolved reference: WrappedPropertySetterDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (28, 56): Unresolved reference: WrappedSimpleFunctionDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (247, 16): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (258, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (261, 17): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (264, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (265, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (266, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (268, 17): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (270, 13): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (366, 44): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (383, 65): Unresolved reference: WrappedSimpleFunctionDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (386, 17): Unresolved reference: WrappedPropertyGetterDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (391, 17): Unresolved reference: WrappedPropertySetterDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (396, 17): Unresolved reference: WrappedFunctionDescriptorWithContainerSource
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (398, 17): Unresolved reference: WrappedSimpleFunctionDescriptor
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (410, 16): None of the following functions can be called with the arguments supplied:
public constructor IrFunctionImpl(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: FunctionDescriptor, returnType: IrType) defined in org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
public constructor IrFunctionImpl(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, symbol: IrSimpleFunctionSymbol, returnType: IrType, visibility: Visibility = ..., modality: Modality = ...) defined in org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
public constructor IrFunctionImpl(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, symbol: IrSimpleFunctionSymbol, name: Name, visibility: Visibility, modality: Modality, returnType: IrType, isInline: Boolean, isExternal: Boolean, isTailrec: Boolean, isSuspend: Boolean, isOperator: Boolean, isExpect: Boolean, isFakeOverride: Boolean) defined in org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (423, 18): Cannot infer a type for this parameter. Please specify it explicitly.
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (468, 13): Type mismatch: inferred type is ClassConstructorDescriptor but Int was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/compiler/lower/ComposerParamTransformer.kt: (469, 19): The integer literal does not conform to the expected type IrStatementOrigin?
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (440, 21): Unresolved reference: putValueArgument
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (492, 49): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (499, 49): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (536, 41): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (539, 41): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (574, 17): Unresolved reference: putValueArgument
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (583, 9): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (591, 9): Unresolved reference: dispatchReceiver
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (700, 41): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (749, 41): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (824, 41): Type mismatch: inferred type is JvmBackendContext but IrGeneratorContext was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (836, 9): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (842, 9): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (843, 9): Unresolved reference: it
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (859, 9): None of the following functions can be called with the arguments supplied:
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, typeArgumentsCount: Int, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
public constructor IrCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = ..., superQualifierSymbol: IrClassSymbol? = ...) defined in org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (878, 13): Type mismatch: inferred type is ClassConstructorDescriptor but Int was expected
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (879, 13): An argument is already passed for this parameter
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (901, 5): None of the following functions can be called with the arguments supplied:
public constructor IrDelegatingConstructorCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol) defined in org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
public constructor IrDelegatingConstructorCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol, typeArgumentsCount: Int) defined in org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
public constructor IrDelegatingConstructorCallImpl(startOffset: Int, endOffset: Int, type: IrType, symbol: IrConstructorSymbol, typeArgumentsCount: Int, valueArgumentsCount: Int) defined in org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
e: /Users/takahirom/git/aosp-androidx/frameworks/support/compose/compose-compiler-hosted/src/main/java/androidx/compose/plugins/kotlin/frames/FrameIrTransformer.kt: (988, 1): Class 'FrameRecordClassDescriptor' is not abstract and does not implement abstract member public abstract fun getDefaultFunctionTypeForSamInterface(): SimpleType? defined in org.jetbrains.kotlin.descriptors.ClassDescriptor

FAILURE: Build failed with an exception.


  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Androidアプリのサンプルプロジェクト体験

目次

  • Androidアプリ体験に必要なもの
  • Android Studio IDEのインストール
  • Android Studioの追加パッケージのインストール
  • サンプルプロジェクトの作成

Androidアプリ体験に必要なもの

当サンプルは実際のアンドロイドスマホで試す為、必要なものとして以下となります。

  • Android Studio IDE
  • アンドロイドスマホ
  • USBケーブル

Android Studio IDEのインストール

インストールガイドは以下のリンクにて、ご参照ください。
https://qiita.com/nayylin/items/d0a02aab68a3170f5f26

Android Studioの追加パッケージのインストール

  • まずは、Android Studioを開き、「Configure」をクリックし、「SDK Manager」を選択する。 0018.JPG 0019.JPG

1.USB Driverのパッケージインストール

  • アプリはスマートフォンと接続して試すため、USB Driverツールのインストールを行う。
    SDK Toolsタグから「Google USB Driver」を選択し「Apply」をクリックする。 0027.JPG
  • 「OK」をクリックする。 0028.JPG
  • インストールポップアップが表示され、完了後「Finish」をクリックする。 0029.JPG
  • 最後は「OK」をクリックする。 0030.JPG

2.適用なアンドロイドバージョンのインストール

  • SDK Platformsタグから適用なアンドロイドバージョンを選択し「Apply」をクリックする。 0020.JPG
  • 「OK」をクリックする。 0021.JPG
  • ライセンス契約のポップアップが表示されたら、「Accept」をクリックする。 0023.JPG
  • インストールポップアップが表示され、完了後「Finish」をクリックする。 0025.JPG
  • 最後は「OK」をクリックする。 0026.JPG

サンプルプロジェクトの作成

  • まずはAndroid Studioを開き、「Start a new Android Studio project」をクリックする。
    0031.JPG

  • アプリのタイプはまず「Empty Acivity」を選択する。
    0037.JPG

  • プロジェクトの設定を行い、完了後「Finish」をクリックする。
    0038.JPG

  • 最初の時点で足りないコンポーネントがダウンロードされ、IDEが起動される。
    0039.JPG

  • 最初のMainActivity.javaに定義されている「Hello World!」の内容がアプリを実行すると表示される内容となる。このままアプリの実行を行う。
    0041.JPG

  • アンドロイドスマホで接続してアプリを開くため、まずはスマホとPCをケーブルで接続し、スマホの「USB Debugging」モードをオンにする。
    接続後、Runメニューから「Run 'app'」をクリックする。
    0045.JPG

  • アプリを実行後プロジェクトがビルドされる。
    0046.JPG

  • ビルドが完了後スマホの画面にて、ソースで定義された「Hello World!」が表示される。
    0047.JPG
    (スマホの画面)
    a.jpg
    これでアンドロイドのサンプルプロジェクト体験が完了です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

KotlinでもPythonみたいに文字列操作したい!

kotlinの文字列操作も便利だけどやっぱりPythonみたいに文字列操作したいなぁ

というわけで、kotlinでもPythonと同等の文字列操作ができるようになるライブラリを作りました。

ktPyString

https://github.com/ChanTsune/ktPyString

Stringに対して拡張関数を定義することで、kotlinでもpythonみたいな文字列操作ができるようにしています。

導入

Gradle

build.gradle
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'dev.tsune:ktPyString:0.0.0'
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.core:core-ktx:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

Maven

<dependency>
  <groupId>dev.tsune</groupId>
  <artifactId>ktPyString</artifactId>
  <version>0.0.0</version>
  <type>pom</type>
</dependency>

依存ライブラリに追加します。

文字列操作

スライス

val str = "0123456789"
str[0,5]
// 01234
str[0,8,2]
// 0246
str[null,null,-1]
// 9876543210

Pythonista御用達のスライス操作です。

一度慣れると他の言語でもやりたくなるやつです。

ちなみに同じ動作をPythonで書くと以下のようになります。

str = "0123456789"
str[0:5]
# 01234
str[0:8:2]
# 0246
str[::-1]
# 9876543210

文字列検索

// 先頭からの検索  
"123412312312345".find("123") // 0

// 開始位置を指定して検索
"123412312312345".find("123",start:2) // 4

// 終了位置を指定して検索
"123412312312345".find("123",end:1) // -1

// 末尾からの検索
"123412312312345".rfind("123") // 10

末尾からの検索も同様に開始位置と終了位置を指定して検索できます。

文字列結合

val array = ["abc","def","ghi"]
"".join(array) // "abcdefghi"
"-".join(array) // "abc-def-ghi"
"++".join(array) // "abc++def++ghi"

文字列分割

行ごとの分割
"abc\nabc".splitlines() // ["abc", "abc"]
"abc\r\nabc\n".splitlines() // ["abc", "abc"]

// 改行文字を残して分割
"abc\nabc\r".splitlines(true) // ["abc\n", "abc\r"]
"abc\r\nabc\n".splitlines(true) // ["abc\r\n", "abc\n"]

トリミング

// 右端のみ
"rstrip sample   ".rstrip() // "rstrip sample"
"rstrip sample   ".rstrip("sample ") // "rstri"
"  rstrip sample".rstrip() // "  rstrip sample"

// 左端のみ
"  lstrip sample".lstrip() // "lstrip sample"
"  lstrip sample".lstrip(" ls") // "trip sample"
"lstrip sample".lstrip() // "lstrip sample"

// 両端
"   spacious   ".strip() // "spacious"
"www.example.com".strip("cmowz.") // "example"

出現回数カウント

"abc abc abc".count("abc") // 3

// 開始位置の指定
"abc abc abc".count("abc", start:2) // 2

// 終了位置の指定
"abc abc abc".count("abc", end:1) // 0

ゼロ埋め

"abc".zfill(1) // "abc"
"abc".zfill(5) // "00abc"

// 符号付きの場合
"+12".zfill(5) // "+0012"
"-3".zfill(5) // "-0003"
"+12".zfill(2) // "+12"

符号付きの場合は符号の後ろにゼロが入ります。

さいごに

全部書いていると長くなってしまうので、紹介はこの辺りで。

このほかにも、Pythonのstr型で利用できるメソッドは言語機能的に実現不可能または、実現が難しいもの以外ほとんどサポートしています。

Pythonからプログラミングを始めたという人なら、慣れ親しんだPythonの文字列操作ができるようになるので比較的便利ではないでしょうか?

このメソッド実装できるよ、とかこっちの実装の方がパフォーマンスいいんじゃない?

kotlinだったらこう書くと綺麗だよ等ありましたら教えてください。

プルリクお待ちしております。

もしあれば、バグ報告とかも嬉しいです。

余談ですが、Swift版のライブラリも過去に作っているので、iOSとAndroidで文字列操作周りの処理をほとんどコピペで動かすこともできるかも知れません。(Swiftとkotlin の文法が割と似ているので)
https://qiita.com/ChanTsune/items/bd611a4c778c0fb338e6

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Android]Firebase Performance Monitoringを導入する

タイトル通りFirebase Performance Monitoringを実装するだけの記事。

前提

Firebaseの導入は完了している事。
まだの場合はFirebaseの導入についての公式の記事を参照。

実装

プロジェクトレベルのbuild.gradleに以下を書き足す。

buildscript {
    :
    dependencies {
        :
        classpath 'com.google.firebase:perf-plugin:1.3.1'
    }
}

アプリレベルのbuild.gradleに以下を書き足す。

:
dependencies {
    :
    implementation 'com.google.firebase:firebase-perf:19.0.5'
}

既にprotobufを利用している場合、二重インポートでエラーになるという既知の問題があるので、以下のようにして回避する。

:
dependencies {
    :
    implementation ('com.google.firebase:firebase-perf:19.0.5',{
        exclude group: 'com.google.protobuf'
    })
}

確認

導入したアプリを立ち上げて適当に触ってみる。
しばらくすると、Firebase Performance Monitoringの画面で「検出しました。反映されるまで24時間ほどかかります。お待ちください。」といった表示が出る。
更に丸一日経過すると、画面に数値が反映される。

以上のように、基本的には導入するのみでいい感じに計測してくれるが、自分でカスタム計測を仕込むこともできる

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Android]in-app updates APIの検証方法

本記事では表題の通り、in-app updates APIのテスト方法のみ説明する。
テスト方法がよく分からず試行錯誤した結果なので、もっと良い方法があるかも知れない。

実装方法については以下の記事がとても良いので参照されたい。
Android in-app Updates API 解説と雑感 - Qiita
なお当該記事のAn update has just been downloaded.はサンプルプログラムのままになっており、うっかりそのまま使っちゃうと「あぁ〜」となるので、いい感じに変更されると良い。

手順

準備

in-app updates API対応バージョンのapkまたはaabを用意する。
バージョンコード/バージョン名はリリース済みのものより上である必要がある。

テスターの登録

Playコンソールにログインする。
対象のアプリをクリックする。
リリース管理→アプリのリリースに遷移する。
「内部テスト版」の「管理」をクリックする。

「テスターの管理」の右側のキャレットをクリックし、展開する。

「新しいリストを作成」をクリック。

リスト名は任意で問題ない。
メールアドレスにテストしたいユーザーのメールアドレスを入力する。
入力が終わったら「作成」。

テストしたいユーザーでログインしたブラウザで、「テスターの管理」セクションにあったオプトインURLを踏む。
すると以下のような画面が表示されるので、「プログラムに参加する」。

以上でテスターの登録は完了。
反映には1日ほどかかった。

1度目のアプリのアップロード

1度目でin-app updates APIを仕込んだバージョンをアップロードし、
2度目でアップデートの挙動を確認するため、少なくとも2度必要。

先程の「内部テスト版」画面に遷移する。
「テスターの管理」で先程作成したリストにチェックが付いている事を確認する。
付いていなかったらチェックする。

右上から「リリースを作成」する。
ここでin-app updatesの処理を含めたapkまたはaabをアップロードする。
このバージョンには念の為にLogCatへのログ出力を含んだバージョンにしておく事をおすすめする。
万が一エラーで死んでいた場合にアップデートが機能しているかの確認がしづらいからだ。
後は通常のリリース手順なので割愛する。

Playストアからテスターユーザーでダウンロード

テスターユーザーでログインした状態で、Playストアで反映されるのを待つ。
反映されたらアップデートする。
アプリを立ち上げるかはアプリによって任意に実施すると良い。
一度テスターの状態が反映されると、次のアップデートからは即時に反映される。

Playストアの自動更新をOFFにする

アップデートし終わったら、アプリ内アップデートをテストするために自動更新をOFFにしておく。
Playストアのアプリ詳細ページから右上のハンバーガーメニュー「…」をタップし、「自動更新の有効化」のチェックをはずす。

2度目のアプリのアップロード

バージョン番号だけ上げたバージョンでも良いので、新しいapkまたaabを準備し、1度目のアプリのアップロードの手順と同様の手順で内部テスト版として公開する。
この時点ではログ出力は削除しておいても良いかも知れないが、状況によって判断する。

Playストアでアップデートがある事を確認

テスターユーザーでPlayストアでアップデートが公開されている事を確認する。
おそらく即座に反映されているはずだ。
Playストアでアップデートはしない

in-app updatesが発動するかのテスト

1つ前のバージョンのアプリを何度か開いて、アップデートが来ていないか確認する。
in-app updatesは記事執筆時点ではPlayストアとそれなりのタイムラグがあるので、3時間ほど待つ事もある。
アップデートが届いている場合、Flexibleバージョンを実装している場合は以下のようなダイアログが表示される。

動作確認が取れれば、内部テストから昇格して本番公開するなどする。
動作確認がNGであれば、2度目のアプリのアップロードを繰り返す。

事後処理

テストが完了したら、Playストアの自動更新をONにする。

所感

残念ながら今のところ非常に手間がかかる。
もうちょっとなんとかならないか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Android Activity タスクとスタック

アクティビティのタスクとスタックについてまとめます。間違っていたらご指摘のほどよろしくお願いいたします。

タスク

タスクは複数のアクティビティのまとまりのことです。公式ドキュメント1によると、

タスクは、ユーザーが新しいタスクを開始したとき、またはホームボタンを使用してホーム画面に移動したときに、「バックグラウンド」に移動できるまとまったユニットです。

です。端末のバックキーの反対側にある □ ボタンを押したら出てくる[最近]画面で、タスクの一覧を確認することができます。

アクティビティAがアクティビティBを起動すると、基本的には、それらのアクティビティはひとつのタスクに所属します。(後述しますが、別のタスクで起動することもできます。)
activities_2.png
注意したいのが、タスクは一つのアプリ内のアクティビティをまとめたものとは限らないということです。アプリが異なっても、同じタスクに所属する場合はあります。(むしろデフォルトの起動モードではそうなります)
activities_3.png

起動モード

アクティビティは起動モードという属性を設定できます。起動モードによって、どのタスクで起動するのかが変わります。

standard

1つのタスクに複数のインスタンスを生成でき、複数のタスクに跨って生成できます。デフォルトの起動モードです。
activities_launch_mode1.png

singleTop

1つのタスクに複数のインスタンスを生成できますが、タスクの一番上に既にある場合は、重ねてインスタンスを作成できません。複数のタスクに跨って生成できます。
activities_launch_mode2.png

singleTask

複数のタスクに跨って存在することはできません。端末内で同じアクティビティのインスタンスを持つタスクは1つだけになります。
activities_launch_mode3.png

singleInstane

複数のタスクに跨って存在することはできません。端末内で同じアクティビティのインスタンスを持つタスクは1つだけになり、さらに、そのタスク内には他のアクティビティは存在することができません。1タスク内に1つのアクティビティだけある状態になります。
activities_launch_mode4.png
singleTaskとsingleInstanceは、常に自身のタスクで(なければ新しく作成して)、アクティビティを起動したい場合にのみ使用します。

いろいろなアプリから呼び出されてもいい画面だけど、タスクはひとつにしたい、そういうときに使います。例えばブラウザアプリのアクティビティがsingleTaskになっています。いろいろなアプリからブラウザは呼び出されますが、常に自身のタスクで開きます。
activities_singletask_example.png

タスクの確認方法

起動中のタスクはコマンドで確認できます。

$ adb shell dumpsys activity activities

これでもいいですが、アクティビティの詳細情報も出力されて見にくいので、

$ adb shell dumpsys activity activities | sed -En -e '/Stack #/p' -e '/Running activities/,/Run #0/p'

とすると、タスク(とスタック)とタスクに属するアクティビティだけが出力され、見やすくなります。

タスクの状態は[最近]画面でもある程度わかるのですが、必ずしもタスク毎に分かれて表示されるわけではないので、起動したアクティビティが所属してるタスクを正確に把握したい場合は、コマンドで確認するといいと思います。

試しにstandardのアクティビティから別のstandardのアクティビティを起動した時のタスク状態をみてましょう。
(API level 28 のエミュレータで試しました)

  Stack #106: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{b418524 #99 A=jp.favolabo.activitystart U=0 StackId=106 sz=2}
        Run #1: ActivityRecord{a2296cf u0 jp.favolabo.activitystart/.StandardTwoActivity t99}
        Run #0: ActivityRecord{fec21ab u0 jp.favolabo.activitystart/.StandardOneActivity t99}
  Stack #0: type=home mode=fullscreen
    Running activities (most recent first):
      TaskRecord{ff86f1 #5 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{ef5787f u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t5}

StandardOneActivityStandardTwoActivityを起動したんですね。NexusLauncherActivityというのはホーム画面のアクティビティになります。

IntentにフラグをつけてActivityを起動

FLAG_ACTIVITY_NEW_TASKというフラグがあります。実は、アクティビティの起動モードをsingleTaskにすると、このフラグが設定されて起動されています。コードで書くと以下のようになります。

Activity.kt
val intent = Intent(this, StandardActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)

なので動的にstandardのアクティビティをsingleTaskのように起動したい場合があれば、上記のように設定すればよいかと思います。

ちなみにですが、さきほどのタスクを確認するコマンドで、アクティビティの詳細情報まで出力して

  • standardのアクティビティにFLAG_ACTIVITY_NEW_TASKをつけて起動した場合
  • singleTaskのアクティビティを普通に起動した場合

を見比べてみると、

standardのアクティビティに`FLAG_ACTIVITY_NEW_TASK`をつけて起動した場合
Intent { flg=0x10000000 cmp=jp.favolabo.activitystart/.StandardActivity }
singleTaskのアクティビティを普通に起動した場合
Intent { flg=0x10000000 cmp=jp.favolabo.activitystart/.SingleTaskActivity }

とIntentの情報があり、flgが同じ(=FLAG_ACTIVITY_NEW_TASK)であることがわかります。

taskAffinity

singleTaskのアクティビティを起動するときに、どのタスクで起動すべきかを決めるための属性として、taskAffinity(親和性)というものがあります。

ためしに、同じアプリでsingleTaskのアクティビティをstandardのアクティビティから起動してみます。すると、同じタスク上で起動します。

これはなぜかというと、taskAffinityが同じアクティビティは、同じタスク内に起動しようとするからです。
taskAffinityはデフォルトではパッケージ名になります。たとえば com.hoge.fuga.app というパッケージ名だと、そのアプリ内のアクティビティのtaskAffinityも com.hoge.fuga.app になります。
activities_taskaffinity.png

必ず別タスクでsingleTaskのアクティビティを起動したい場合は、taskAffinityを明示的に指定します。

AndroidManifest.xml
<activity android:name=".SingleTaskActivity"
    android:launchMode="singleTask"
    android:taskAffinity="app.hoge.fuga2"/>

どのタスクでアクティビティが起動するか、こちら2 の解説記事でわかりやすく、起動モードごとにアニメーション付きで説明されていますので、是非見てみてください。

スタック

アクティビティを起動すると、後入れ先出しのいれもの(スタック)に積まれます。バックボタンを押すと、現在表示中のアクティビティから順に取り出されて、ホーム画面が表示されるまで、一つ前のアクティビティに戻っていきます。

例えばsingleTaskアクティビティであるブラウザを呼び出した場合は、以下のようなスタックになります。

  Stack #120: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{45197fa #113 A=com.android.chrome U=0 StackId=120 sz=1}
        Run #0: ActivityRecord{976c635 u0 com.android.chrome/org.chromium.chrome.browser.ChromeTabbedActivity t113}
  Stack #119: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{86811ab #112 A=jp.favolabo.activitystart U=0 StackId=119 sz=1}
        Run #0: ActivityRecord{847e274 u0 jp.favolabo.activitystart/.StandardActivity t112}
  Stack #0: type=home mode=fullscreen
    Running activities (most recent first):
      TaskRecord{ff86f1 #5 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{ef5787f u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t5}

ブラウザでバックボタンを押していくと、
ブラウザ(ChromeTabbedActivity) → StandardActivity → ホーム画面(NexusLauncherActivity
の順で取り出されていきます。
activities_pop1.png

ここで、試しにブラウザが表示されたら、ホームボタンを押して、呼び出し元のアクティビティ(StandardActivity)をアイコンからタップして起動してみましょう。するとスタックは以下のように変わりました。

  Stack #119: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{86811ab #112 A=jp.favolabo.activitystart U=0 StackId=119 sz=1}
        Run #0: ActivityRecord{847e274 u0 jp.favolabo.activitystart/.StandardActivity t112}
  Stack #0: type=home mode=fullscreen
    Running activities (most recent first):
      TaskRecord{ff86f1 #5 I=com.google.android.apps.nexuslauncher/.NexusLauncherActivity U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{ef5787f u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t5}
  Stack #120: type=standard mode=fullscreen
    Running activities (most recent first):
      TaskRecord{45197fa #113 A=com.android.chrome U=0 StackId=120 sz=1}
        Run #0: ActivityRecord{976c635 u0 com.android.chrome/org.chromium.chrome.browser.ChromeTabbedActivity t113}

スタックの一番上がStandardActivityになっていて、次にホーム画面(NexusLauncherActivity)になっていますね。なので、当たり前ですが、バックボタンを押すと、ホーム画面に戻ります。
activities_pop2.png

参考

親和性と新しいタスク
アクティビティのリファレンス

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

android 足し算ができない!

3/9 kotlinを勉強し始めてドットインストールのkotlin入門を履修終了
  (foreachからあんまり理解してない)

3/12 androidアプリ開発のテキストに沿ってアプリ開発の勉強開始。

テキストで学んだことを使って簡単なアプリ開発を使用と思い
摂取したカロリーをひたすら計算していくアプリを作ってみる。

しかし、うまくいかない・・・!
EditTextに数字を入力して追加を押すと、下のTextViewに追加した数字が表示され、
もう一度EditTextに数字を入力して追加を押すと、下のTextViewに表示された数字と足されて表示される仕組みが作りたかったが
なぜか追加ボタンを押すとイミュレーターがアプリが落ちる。。。
forを使うのか?とかも考えたけどその構文が分からず・・・

解決方法分かる方いたら教えてください。。。

qiita.rb
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val btClick = findViewById<Button>(R.id.btClick)
        val listener = CalListener()
        btClick.setOnClickListener(listener)
    }

    private inner class CalListener: View.OnClickListener{
        @SuppressLint("SetTextI18n")
        override fun onClick(view: View) {

                val input = findViewById<EditText>(R.id.etKcal)
                val output = findViewById<TextView>(R.id.tvSumKcal)
                var inputInt = input.text.toString().toInt()
                var outputInt = output.text.toString().toInt()

                var sum :Int
                sum  = inputInt+outputInt
                output.text = sum.toString() + "Kcal"
        }
    }
}

image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Android StudioでAPIレベルを下げる

はじめに

最近とあるプロジェクトに参加しAndroidアプリ開発をしていたのですが,渡されたタブレットで実行しようとしたら,APIが古いよと怒られてしました.解決するまでに色々調べて結構時間がかかったので,今回はその解決方法をメモしておきたいと思います.
今回のアプリ開発ではSonyさんのXperia Z4 Tablet SO-05Gのタブレットを使用しました.

どんなエラーが出たのか?

Installation did not succeed.
The application could not be installed: INSTALL_FAILED_OLDER_SDK
The application's minSdkVersion is newer than the device API level.

原因としては,デバイスのAPIよりプロジェクトのAPIのほうが新しいからだそう.シンプルにプロジェクトのAPIをデバイスのAPIに合わせて下げれば解決できます.

ちなみに実行時にはSony SO-05G(minSdk(API 23) > deviceSdk(API 21))というエラーがデバイス選択欄に書かれていました.

では解決方法を記していきます.

解決方法

  1. Android Studioの上部タブFileからProject Structureを選択
    pj_structure.png

  2. Modulesの上部タブDefault Configを選択

  3. Min SDK Versionから指定したいversionを選択
    min_sdk.png
    ※ここで注意※
    選択したいAPIがインストールされていない場合は,プルダウンメニューに表示されません.そのためまずは,選択したいAPIのSDKをインストールしなければなりません.次にSDKのインストール方法を記します.

SDKのインストール方法

  1. Android Studioの上部タブToolsからSDK Managerを選択
    tools.png

  2. Android SDKSDK PlatformsからインストールしたいSDKをチェックし,インストール
    sdk_manager.png

これでMin SDK VersionにインストールしたSDKのAPIレベルが表示されるので,選択することが可能になります.

最後に

以上がAPIレベルの下げ方になります.ぱっと見簡単そうに見えるけど,解決するまでに結構時間を食っちゃいました.同じところで躓いている人がいたら参考にしてみてください.環境設定が得意になりたい.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitHub Actionsで「No version of NDK matched the requested version 20.0.5594570. Versions available locally: 21.0.6113669」というエラーが出た時に…

CIでエラー

GitHub ActionsでAndroidアプリのビルドをしようとしたら「 No version of NDK matched the requested version 20.0.5594570. Versions available locally: 21.0.6113669 」というエラーが出てCIが失敗するようになってしまいました。

対策

app/build.gradle に下記の通り ndkVersion を指定してあげることで、エラーが出ずにビルドが通るようになりました。

android {
・・・略・・・

    ndkVersion "21.0.6113669"
}

参考

https://stackoverflow.com/questions/60404457/android-no-version-of-ndk-matched-the-requested-version

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Android/iOSストア情報まとめ(2020.03)

はじめに

アプリを新規公開する際に必要な情報をまとめました。
ストア情報はデザイナーや非エンジニアが決めることが多いため、そのような方たちが読めるようにまとめます。また、ストア情報の他にも、決めるべき項目について記載しました。

※オプショナルな情報については薄い文字で記載しています。

アプリ情報

Android iOS 備考
正式名称 ~50文字 ~23文字 SEO対策しすぎるとリジェクトされる可能性があります
短縮名称 ~12文字程度 ~13文字 アプリアイコンの下に表示される名前。
機種などにより表示できる文字数は変わります
サブタイトル なし ~30文字 iOS11以降で表示されます
更新情報 ~500文字 ~4000文字 初回リリース時も必要となります
ID Package id Bundle id Androidの場合、ストアURLに含まれます。
一度決めると変更はできません。例えばGoogleMapの場合はcom.google.android.apps.mapsとなっています

忘れがちなのが更新情報です。初回リリースですが、こちらの文言も必要となりますのでご注意ください。
また、プライマリー言語の設定と、各項目の翻訳も必要となります。

更新情報について
AndroidのGoogleフォトのスクリーンショットです。下記のように最新ニュースとして更新情報が表示されます。
スクリーンショット 2020-03-15 22.58.12.png

IDについて
AndroidのPackageIdはURLに表示されます。下記はGoogleMapの例です。
image.png
そのため、あまり適当なIDを付与しないようにします。一度リリースすると変更もできなくなります。
一方、iOSの場合URLに表示されるのはAppleから自動で割り振られるID(数字)のため、一般ユーザが目にすることはありません。が、管理上、Androidのpackage idに似せた方がよいと思います。

説明文

Android iOS 備考
詳しい説明 ~4000文字 ~4000文字
簡単な説明 ~80文字 ~170文字 iOSではプロモーション用テキスト
キーワード なし ~100文字 SEO対策
  • プロモーションテキストについて
    • iOS11以降。審査なしで現在のアプリ機能について知らせることができるようです。

ストア画像(Androidのみ)

サイズ 形式 用途
フィーチャーグラフィック 横1,024x縦500 JPG or 24bit PNG(アルファなし) ストアのアプリタブでフィーチャーされる際に使用。
必須
1.png
プロモーション画像 横180x縦120 JPG or 24bit PNG(アルファなし) ストアのゲームタブでフィーチャーされる際に使用。
オプショナル。
2スクリーンショット 2020-03-15 23.38.23.png

URL、連絡先情報

Android iOS 備考
プラポリURL オプショナル 必須
サポートURL なし オプショナル
ウェブサイト(Android)/ マーケティングURL(iOS) オプショナル オプショナル
Copyright なし 必須
電話 オプショナル なし ストアに表示されます
メール 必須 なし ストアに表示されます

アプリアイコン

OSごとに大きく異なるため、別々に記載します。

Android

ストア用画像

  • 512x512
  • 32bit PNG

Android8.0未満

解像度 アイコンサイズ
xxxhdpi 192x192
xxhdpi 144x144
xhdpi 96x96
hdpi 72x72
mdpi 48x48

AdaptiveIcon(Android8.0以上)

参考:AdaptiveIconとは

解像度 サイズ
xxxhdpi 432x432
xxhdpi 324x324
xhdpi 216x216
  • foregroundとbackgroundの2枚を用意します(サイズは同じ)
  • foregroundは直径66がsafe zoneなので、モチーフはそこに収まるようにします
  • OS8以上なので、ある程度高解像度の画像だけで十分

iOS

サイズ 用途
20x20 ipad notification用(@1x)
29x29 iPad設定画面用(@1x)
iPhone設定画面用(@1x)
40x40 ipad notification用(@2x)
notification用(@2x)
iPad Spotlight用(@1x)
58x58 iPad設定画面用(@2x)
iPhone設定画面用(@2x)
60x60 notification用(@3x)
76x76 iPadAppIcon(@1x)
80x80 iPad Spotlight用(@2x)
Spotlight用(@2x)
87x87 設定画面用(@3x)
152x152 iPadAppIcon(@2x)
120x120 Spotlight用(@3x)
AppIcon(@2x)
167x167 iPadProAppIcon(@2x)
180x180 AppIcon(@3x)
1024x1024 ストア用

スクリーンショット

スマートフォンの場合のみ記載します。必要に応じてタブレット、Wear、TVなども設定可能です。
また、各言語でローカライズされた画像を用意しましょう。

Android iOS
サイズ 1 辺の最小の長さ: 320px
1 辺の最大の長さ: 3840px
アス比は1:2以下(縦長すぎ/横長すぎるのはエラー)
後述
形式 JPG/PNG(アルファなし) JPG/PNG(アルファなし)
枚数 2枚(最大8枚) 各サイズ最低1枚、最大10枚

iOSの場合は以下のサイズで揃える必要があります。

サイズ 枚数 該当端末
6.5インチ 1242 x 2688 最低1枚、最大10枚 iPhone 11 Pro Max, iPhone 11, iPhone XS Max, iPhone XR
5.5インチ 1242 x 2208 最低1枚、最大10枚 iPhone 6s Plus、iPhone 7 Plus、iPhone 8 Plus
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Android/iOSストア情報まとめ(2020年03月更新)

はじめに

アプリを新規公開する際に必要な情報をまとめました。
ストア情報はデザイナーや非エンジニアが決めることが多いため、そのような方たちが読めるようにまとめます。また、ストア情報の他にも、決めるべき項目について記載しました。
とはいえ、本記事では基本的に必要最低限に近いレベルのことしか記載していませんので、実際には様々なカスタマイズ情報を掲載してアプリのグロースをしてみてください。

※オプショナルな情報については薄い文字で記載しています。

アプリ情報

Android iOS 備考
正式名称 ~50文字 ~23文字 SEO対策しすぎるとリジェクトされる可能性があります
短縮名称 ~12文字程度 ~13文字 アプリアイコンの下に表示される名前。
機種などにより表示できる文字数は変わります
サブタイトル なし ~30文字 iOS11以降で表示されます
更新情報 ~500文字 ~4000文字 初回リリース時も必要となります
ID Package id Bundle id Androidの場合、ストアURLに含まれます。
一度決めると変更はできません。例えばGoogleMapの場合はcom.google.android.apps.mapsとなっています

忘れがちなのが更新情報です。初回リリースですが、こちらの文言も必要となりますのでご注意ください。
また、プライマリー言語の設定と、各項目の翻訳も必要となります。

更新情報について

下記のように最新ニュース新機能として更新情報が表示されます。
Android iOS
スクリーンショット 2020-03-15 22.58.12.png image.png

IDについて
AndroidのPackageIdはURLに表示されます。下記はGoogleMapの例です。
image.png
そのため、あまり適当なIDを付与しないようにします。一度リリースすると変更もできなくなります。
一方、iOSの場合URLに表示されるのはAppleから自動で割り振られるID(数字)のため、一般ユーザが目にすることはありません。が、管理上、Androidのpackage idに似せた方がよいと思います。
ちなみにiOSのストアURLはこのようになります。
image.png

説明文

Android iOS 備考
詳しい説明 ~4000文字 ~4000文字
簡単な説明 ~80文字 ~170文字 iOSではプロモーション用テキスト
キーワード なし ~100文字 SEO対策
  • プロモーションテキストについて
    • iOS11以降。審査なしで現在のアプリ機能について知らせることができるようです。

ストア画像(Androidのみ)

サイズ 形式 用途
フィーチャーグラフィック 横1,024x縦500 JPG or 24bit PNG(アルファなし) ストアでフィーチャーされる際に使用。
必須スクリーンショット 2020-03-15 23.20.05.png
プロモーション画像 横180x縦120 JPG or 24bit PNG(アルファなし) 古い端末のストアでフィーチャーされる際に使用されます。今となっては用意しなくてもよいと思います

フィーチャーグラフィックはかつてストアのヘッダー画像として使われていましたが、ストアの仕様変更により、フィーチャー時にのみ使われるようになりました。

URL、連絡先情報

Android iOS 備考
プラポリURL オプショナル 必須
サポートURL なし オプショナル
ウェブサイト(Android)/ マーケティングURL(iOS) オプショナル オプショナル
Copyright なし 必須
電話 オプショナル なし ストアに表示されます
メール 必須 なし ストアに表示されます

URL、連絡先情報の表示場所
Android iOS
スクリーンショット 2020-03-15 22.59.09.png Screen Shot 2020-03-16 at 0.13.16.png

アプリアイコン

OSごとに大きく異なるため、別々に記載します。

Android

Androidはストア用に高解像度が1枚、アプリに組み込む画像が解像度ごとに必要です。また、OS8以降とその前でアイコンの仕様が異なります。

ストア用画像

  • 512x512
  • 32bit PNG

Android8.0未満

解像度 アイコンサイズ
xxxhdpi 192x192
xxhdpi 144x144
xhdpi 96x96
hdpi 72x72
mdpi 48x48

AdaptiveIcon(Android8.0以上)

参考:AdaptiveIconとは

解像度 サイズ
xxxhdpi 432x432
xxhdpi 324x324
xhdpi 216x216
  • foregroundとbackgroundの2枚を用意します(サイズは同じ)
  • foregroundは直径66がsafe zoneなので、モチーフはそこに収まるようにします
  • OS8以上なので、ある程度高解像度の画像だけで十分

iOS

サイズ 用途
20x20 ipad notification用(@1x)
29x29 iPad設定画面用(@1x)
iPhone設定画面用(@1x)
40x40 ipad notification用(@2x)
notification用(@2x)
iPad Spotlight用(@1x)
58x58 iPad設定画面用(@2x)
iPhone設定画面用(@2x)
60x60 notification用(@3x)
76x76 iPadAppIcon(@1x)
80x80 iPad Spotlight用(@2x)
Spotlight用(@2x)
87x87 設定画面用(@3x)
152x152 iPadAppIcon(@2x)
120x120 Spotlight用(@3x)
AppIcon(@2x)
167x167 iPadProAppIcon(@2x)
180x180 AppIcon(@3x)
1024x1024 ストア用

スクリーンショット

スマートフォンの場合のみ記載します。必要に応じてタブレット、Wear、TVなども設定可能です。
また、各言語でローカライズされた画像を用意しましょう。

Android iOS
サイズ 1 辺の最小の長さ: 320px
1 辺の最大の長さ: 3840px
アス比は1:2以下(縦長すぎ/横長すぎるのはエラー)
後述
形式 JPG/PNG(アルファなし) JPG/PNG(アルファなし)
枚数 2枚(最大8枚) 各サイズ最低1枚、最大10枚

iOSの場合は以下のサイズで揃える必要があります。

サイズ 枚数 該当端末
6.5インチ 1242 x 2688 最低1枚、最大10枚 iPhone 11 Pro Max, iPhone 11, iPhone XS Max, iPhone XR
5.5インチ 1242 x 2208 最低1枚、最大10枚 iPhone 6s Plus、iPhone 7 Plus、iPhone 8 Plus
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む