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

firebaseのエラー"Unhandled Exception: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null, null)"の解決策

firebaseを使ったgoogle認証

flutterでfirebaseauthを使ったgoogle認証を実装しようとしたら、
android環境で以下のようなエラーがでた。

E/flutter ( 4434): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] 
Unhandled Exception:PlatformException(sign_in_failed,com.google.android.gms.common.api.ApiException: 10: , null, null)

色々ググってみたら、fingerprintを登録すればいいと書いてあるので、
https://developers.google.com/android/guides/client-auth
の言う通りに下記を実行したけどうまくいかない、、、

keytool -list -v \
-alias androiddebugkey -keystore ~/.android/debug.keystore

最終的な解決策

①android>gradle下にあるgradlewを右クリックして「Open in Terminal」を実行

gradlew.png

②新しくターミナルが立ち上がるので下記を実行

./gradlew signingReport

そうするとSHA1とSHA256でのキーが表示される。
それらをfirebaseの設定の「フィンガープリントを追加」で追記する。
fingerprint.png

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

1行編集で自分のプロジェクトでDaggerのAnnotation ProcessingをAndroid Studioでデバッグする

Daggerが内部でどんなモデルを作ってどんな処理をしているんだ。。ってなったり、エラーになって、中身のコードを読みにいって、この変数に何が入っているんだろう。。ってなったりすることが稀にあるのでメモしておきます。

appモジュールなどでcompileOnlyでkaptで使うコンパイラの依存関係を追加して、Android Studioが使っていデバッグしたいコードを見られるようにします。プロジェクトでの編集はこれだけです。デバッグでの利用が終わったら消してください。

dependencies {
    // compileOnlyで追加する
    compileOnly 'com.google.dagger:dagger-compiler:2.30.1'
    // hiltなら以下など
    compileOnly "com.google.dagger:hilt-android-compiler:2.29.1-alpha"
}

デバッグしたいコードをcommand + option + oなど(macでのFind simbolのショートカット)でブレークポイントつけたいクラス、処理を探してブレークポイントをつけます。

image.png

configurationを開いて、EditConfigrations...をクリックします。
image.png
+ボタンから、Remoteを追加します
image.png
Use module classpathを先程compileOnlyを追加したモジュールで追加します。
image.png

次にターミナルなどからデバッグしたいプロジェクトで実行したいモジュールやバリアントにして次のGradleビルドを動かします。(Kotlinなのでkaptになっていますが、Javaの方はそのタスクを指定してあげてください。)

./gradlew --no-daemon clean app:kaptDebugKotlin -Dorg.gradle.debug=true -Dkotlin.daemon.jvm.options="-Xdebug,-Xrunjdwp:transport=dt_socket\,address=5005\,server=y\,suspend=n"

このGradleビルドは最初の段階で実行されずに止まります。
image.png

Android Studio上でRemoteのConfigurationが設定されているのを確認して、デバッグのアイコンを押します。
image.png
するとビルドが動き出して、止まってほしいところでデバッガーの実行を止めてデバッグすることができます。

image.png

これは自分のプロジェクトである必要はなく、どのプロジェクトでもcompileOnlyを追加すれば確認できます。
またこれはDaggerに限定されず、さまざまな処理に応用できそうです。

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

ChromeCustomTabsでできること~ダークテーマ対応~

今更の話題ですが、CustomTabsIntentにダークテーマ用メソッドが増えていることに気づき、どういうことができるのかを今一度整理してみようと思います。

ダークテーマ対応のメソッドについては、androidx.browser:browser:1.2.0で追加されています。
https://developer.android.com/jetpack/androidx/releases/browser#1.2.0

検証用のアプリはこちら、また、CustomTabsのインターフェースを実装した、というか、それ以外の機能の無いブラウザーのソースコードはこちら。いずれもMIT Licenseで公開していますのでご参考まで。

また、CustomTabsの機能の中には説明が全く無い、もしくは、あってもコメント程度で、どうやって使うのか分からないメソッドや、どういう意味があるのか分からないコールバックといったものが結構あります。将来の拡張のためなのか、Chromiumのソースコードを調べても未実装だったというものもあります(調べたのが結構前なので今どうなっているか分かりませんが)。その辺は詳細不明と書いていますのでご容赦ください。

基本的使い方

詳細は省略しますが、基本的な使い方を抑えておきます。

サービスのバインド

プロセス間通信による機能を使う場合、サービスのバインドを行います。
単にCustomTabsのUIを使いたいだけの場合、これは必須ではありません。

object CustomTabsHelper : CustomTabsServiceConnection() {
    fun bind(context: Context, packageName: String) {
        CustomTabsClient.bindCustomTabsService(
            context.applicationContext,
            packageName,
            this
        )
    }

    override fun onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) {
        client.warmup(0)
        session = client.newSession(null)
    }
}

ブラウザーの起動

上記、サービスのバインドを行い、sessionを取得している場合は、それをBuilderに渡すことで、バインドしているブラウザーアプリを起動することができます。

CustomTabsIntent.Builder(session)
    // 様々なオプション設定
    .build()
    .launchUrl(context, url)

sessionがない場合も、起動したいブラウザーのパッケージ名を直接指定することで、CustomTabsの呼び出しをすることができます。

val customTabsIntent = CustomTabsIntent.Builder()
    // 様々なオプション設定
    .build()
customTabsIntent.intent.setPackage(browserPackageName)
customTabsIntent.launchUrl(context, url)

UIのカスタマイズ

CustomTabsIntent.Builderに対して様々な設定を行うことで表示されるUIのカスタマイズを行うことができます。

メソッド 意味
setToolbarColor(color) ツールバーの背景色を指定することができます。ステータスバーも同じ色に設定されます。フォアグラウンドの色は自動的に選ばれ、白に対するコントラストが3以上あれば白、そうでなければ黒が選ばれます。
setSecondaryToolbarColor(color) addToolbarItemを設定したときに現れるボトムバーの背景色を指定します。指定しない場合はtoolbarColorと同じ色が設定されます。ただし、addToolbarItemはDeprecatedです。
setNavigationBarColor(color) ナビゲーションバーの色を指定します。
showTitle(showTitle) サイト名(title)を表示するかどうかを設定します。
enableUrlBarHiding() ツールバーをスクロールに合わせて動かすように指定します。設定しなくても動いている気がしますが。
setCloseButtonIcon(icon) デフォルトでは×ボタンが表示されますが、別のアイコンを表示させることができます。渡すことができるのはBitmapです。Intentで渡すことになるためサイズに注意。
addDefaultShareMenuItem() メニューに共有機能を追加します。
addMenuItem(label, pendingInten) メニューに独自項目を追加します。第二引数にはメニューが選択されたときに送信してほしいIntentをPendingIntentとして渡します。送信されるIntentのdataには選択されたときに表示しているページのURLが格納されています。
setStartAnimations(context, enterResId, exitResId) ブラウザを起動するときのアニメーションを指定します
setExitAnimations(context, enterResId, exitResId) ブラウザを終了するときのアニメーションを指定します
setActionButton(icon, description, pendingIntent, shouldTint) ツールバーにボタンを追加します。shouldTintをtrueにすると、フォアグラウンドカラーでtintが設定されます。descriptionはアクセシビリティのためのもので直接表示はされません。タップ時に送信してほしいIntentをPendingIntentとして渡します。送信されるIntentのdataには選択されたときに表示しているページのURLが格納されています。
addToolbarItem(id, icon, description, pendingIntent) ボトムバーにアイコンを表示させます。Deprecatedのため新規では利用しない方が良いでしょう。
setSecondaryToolbarViews(remoteViews, clickableIDs, pendingIntent) addToolbarItemの代わりにボトムバーを設定する新しいメソッドです。UIはRemoteViewsで指定することができるので自由度が高くなっています。クリック時の反応についてはRemoteViews#setOnClickPendingIntent()を使うのではなく、第二引数でクリック可能なViewのIDを指定し、そのときに送信して欲しいIntentをPendingIntentとして渡します。クリックされたViewのIDがCustomTabsIntent.EXTRA_REMOTEVIEWS_CLICKED_IDをkeyとするExtraにint値で格納されます。送信されるIntentのdataには選択されたときに表示しているページのURLが格納されています。
setColorScheme(colorScheme) ダークテーマの指定を行います、CustomTabsIntent# COLOR_SCHEME_SYSTEM / COLOR_SCHEME_LIGHT / COLOR_SCHEME_DARK が指定でき、順にシステムに従う、ライトテーマ、ダークテーマです。COLOR_SCHEME_SYSTEM は当然OS側がダークテーマに対応していないと切り替わりません。COLOR_SCHEME_LIGHT / COLOR_SCHEME_DARKはブラウザーが対応していればOSが対応していなくてもWebページのレンダリングも含めて切り替わります。
setColorSchemeParams(colorScheme, params) toolbarColor / secondaryToolbarColor / navigationBarColor を colorSchemeに応じて変更したい場合に指定します。setColorSchemeでCOLOR_SCHEME_SYSTEM を指定した場合に、システムテーマがライトかダークかで色を変えたい場合ですね。第二引数はCustomTabColorSchemeParamsというクラスでBuilderを使ってそれぞれの色を設定します。この機能はブラウザー側が対応していない可能性もあるので、デフォルトの色をsetToolbarColor等で設定した上で、COLOR_SCHEME_DARKなどテーマで上書きしたい色を設定するように指定することが推奨されています。

サービスの機能

あまりクローズアップされることはないですが、結構需要な機能があります。

CustomTabsClient

メソッド 機能
warmup(flag) ブラウザーアプリに起動の準備をリクエストします。起動前の初期化までを先に行わせておくことで、起動が速くなります。long型引数がありますが、「Reserved for future use.」とのことなので適当に0とかを入れておけば良いです。
newSession(callback) ブラウザーアプリとの間でセッションを作成します。引数のcallbackはNullableなので必要なければnullで問題無いです。Callbackを渡せば様々なイベントを受け取ることができるようになります。
extraCommand(command, args) 「Can be used as a channel between the Custom Tabs client and the provider to do something that is not part of the API yet.」らしいです。ブラウザーとアプリの提供元で連携すれば何かに使えるのでしょうか。詳細不明

コールバックについては別途説明します。それ以外で特に詳細を説明できそうなものもないので次に行きます。

CustomTabsSession

メソッド 機能
mayLaunchUrl(url, extras, otherLikelyBundles) これから要求する可能性のあるURLを伝えます。先読みを行うなどで読み込みを高速化させることができます。
requestPostMessageChannel(postMessageOrigin) 「Sends a request to create a two way postMessage channel between the client and the browser.」らしいです。詳細不明
postMessage(message, extras) 前述のメソッドで作ったチャンネルを使ってメッセージを送信する、同様に詳細不明
validateRelationship(relation, origin, extras) Digital Asset Linksを使って呼び出し元アプリとoriginの間の関係性の検証をリクエストする。多分AppLinksの検証をリクエストするってことでしょうけど、よく分かりません。
receiveFile(uri, purpose, extras) Intentでは渡せないような、大きなファイルを渡すらしいですが、詳細不明
setActionButton(icon, description)
setSecondaryToolbarViews(removeViews, clickableIDs, pendingIntent)
setToolbarItem(id, icon, description)
後述のUI設定と同じメソッドの一部が用意されており、動的にUIを変更することができるようです。具体的なユースケースが分からず試していないです。

ってことで不明だらけで、分かっているのはmayLaunchUrlぐらいでしょうか?

mayLaunchUrlの第一引数はUriで、開く可能性の一番高いURLを渡します。第二引数はreserveなのでnullを渡しておきましょう。第三引数に第一引数以外に伝えたいURLを渡しますが、型がListです。このBundleはkeyをCustomTabsService.KEY_URLとして、UriをParcenableとして格納したBundleです。正直なぜUriのリストにしなかったのかと疑問ですが、以下のように詰め替えして渡します。

session.mayLaunchUrl(
    Uri.parse(url),
    null,
    listOf(...)
        .map { Uri.parse(it) }
        .map { Bundle().also { it.putParcelable(CustomTabsService.KEY_URL, it) } }
)

CustomTabsCallback

CustomTabsClient#newSession() に渡すコールバックです。様々なイベントを受け取ることができます。

メソッド 機能
onNavigationEvent(navitationEvent, extras) ブラウザーで発生したイベントが通知されます。定義されているイベントについては後述。extrasにはkey:timestampUptimeMillisでイベント発生のタイムスタンプとおぼしき値が入っています。
extraCallback(callbackName, args) 任意のコールバック、CustomTabsSession#warmup()の結果、onWarmupCompleted(引数null)、メニューからブラウザーで開く、をしたときにonOpenInBrowser(引数:timestampUptimeMillis)が呼び出されました。
extraCallbackWithResult(callbackName, args) 結果を返す任意のコールバック呼び出しですが、詳細不明
onMessageChannelReady(extras, extras) CustomTabsSession#requestPostMessageChannel()の結果コールされるのだと思いますが、詳細不明
onPostMessage(message, extras) CustomTabsSession#postMessage()関連だとは思いますが、詳細不明
onRelationshipValidationResult(relation, requestedOrigin, result, extras) CustomTabsSession#validateRelationship()の結果呼び出されるらしいですが、詳細不明

onNavigationEventのイベントとしては以下が定義されています。

イベント 意味
NAVIGATION_STARTED 読み込み開始
NAVIGATION_FINISHED 読み込み完了
NAVIGATION_FAILED 読み込み失敗
NAVIGATION_ABORTED ユーザー操作により読み込みが中断(リンククリックやリロードなど)
TAB_SHOWN タブが表示された
TAB_HIDDEN タブが非表示になった

ということでざっとまとめました。
プロセス間通信周りは不明なところが多くすみません。詳細をご存じの方がいらっしゃればコメント等で教えていただければと思います。

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

Flutter入門メモ:開発環境構築編

経緯

久々に新規でモバイルアプリでも作ろうかと思い、
一人で趣味で作るレベルだと、Swift・Kotlinでそれぞれ構築するのは掛けられる工数的に現実感が無いので、
1ソース系を試してみようかと。

1ソース系は他にも選択肢がありますが、
React Nativeはなんか好みではないのと、Apache Cordovaは嫌な思い出しかないので、
流行ってるFlutterでやれないかなと、公式を見ながら少し試してみる事にしました。
今回は開発環境までのメモ。

確認環境

  • macOS Catalina
  • Essential Essential Phone PH-1 (Android 10)

前提

  • Homebrewがインストールされている。

※今回確認を実施したMacでは、XcodeやIntelliJ、VS Codeが予めインストールされています。

手順

Flutterのインストール。

$ brew install flutter
$ flutter --version
Flutter 1.22.4 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 1aafb3a8b9 (2 weeks ago) • 2020-11-13 09:59:28 -0800
Engine • revision 2c956a31c0
Tools • Dart 2.10.4

設定の確認と解消

設定の確認をすると色々と怒られるので、一つ一つ確認。

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.4, on Mac OS X 10.15.7 19H15 darwin-x64, locale en-JP)

[!] Android toolchain - develop for Android devices (Android SDK version 27.0.3)
    ✗ Flutter requires Android SDK 29 and the Android BuildTools 28.0.3
      To update the Android SDK visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions.
    ✗ Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses
[!] Xcode - develop for iOS and macOS (Xcode 12.1)
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To install:
        sudo gem install cocoapods
[!] Android Studio (not installed)
[!] IntelliJ IDEA Ultimate Edition (version 2020.2.4)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[!] VS Code (version 1.51.1)
    ✗ Flutter extension not installed; install from
      https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[!] Connected device
    ! No devices available

! Doctor found issues in 6 categories.

Android Studio (not installed)

Android Studioのインストール。

$ brew install android-studio

設定の確認をすると下記も必要な様子。

[!] Android Studio (version 4.1)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
  1. Android Studioを起動し、Preferences->Pluginsを選択する。
  2. FlutterとDartをインストールする。

IntelliJ IDEA Ultimate Edition (version 2020.2.4)

  1. IntelliJを起動し、Preferences->Pluginsを選択する。
  2. FlutterとDartをインストールする。

VS Code (version 1.51.1)

extensionからFlutterをインストールする。

Android toolchain - develop for Android devices (Android SDK version 27.0.3)

Android SDK 29及びAndroid BuildTools 28.0.3以降のインストール。

  1. Android Studioを起動し、Configure->SDK Managerを選択する。
  2. Android SDKからAndroid 10.0を選択し、Apply。
  3. SDK ToolsからAndroid SDK build-Toolsを選択し、Apply。

ライセンスの許可を実行し、問題なければ全てyで進める。

$ flutter doctor --android-licenses

Xcode - develop for iOS and macOS (Xcode 12.1)

$ gem update --system
$ sudo gem install cocoapods

Connected device

  1. About phoneからBuild numberを連打して開発者向けオプションを開放し、
    System->Advanced->Developer optionsを選択、
    Developer optionsとUSB debuggingをオンにする。
  2. 端末をつなげる。

設定の再確認

Android Studioのpluginに関してはエラーが出たままだが、

下記によると、使用上は問題なさそう。
https://github.com/flutter/flutter/issues/67986#issuecomment-715452201

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.4, on Mac OS X 10.15.7 19H15 darwin-x64, locale en-JP)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)

[✓] Xcode - develop for iOS and macOS (Xcode 12.1)
[!] Android Studio (version 4.1)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] IntelliJ IDEA Ultimate Edition (version 2020.2.4)
[✓] VS Code (version 1.51.1)
[✓] Connected device (1 available)

! Doctor found issues in 1 category.

感想

doctorの指示に従って対応すれば良いのでだいぶ楽になりましたね。
はるか昔、Android1.6や2.1くらいの時は結構大変だった記憶があったような…。
また、環境構築時にAndroid Studio 3.1の残骸を見て、
Androidアプリの作成は何年も触ってもいないんだなという時間の流れを感じました。

参考

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