読者です 読者をやめる 読者になる 読者になる

EDIT MODE

モバイルアプリ開発に関することを書いています

Kotlin/Pluginもくもく会を開催しました

先日、Kotlin や IntelliJ Plugin をテーマにもくもく会を開催しました。

もくもく会の様子

当日は、簡単な自己紹介をした後、1名飛び込みで LT をしていただいたりしました。

その後、Kotlin グループと Plugin グループとで何となく分かれ、開発を始めたのですが、 飲み物とピザをサムライズム山本さんが用意して下さってので、飲んだり食べたりしながら楽しくもくもく出来ました!

ちょっと写真が無くて申し訳ないのですが、サムライズムさんはプロジェクターやマイク、電源、WiFiと何でも揃っているので最高でした。

僕は Plugin グループでもくもくしてたのですが、意見交換とかも出来て楽しかったです。 Kotlin グループも Kotlin エヴァンジェリスト?のたろうさんも来て下っていたし、ちょこちょこ会話も聞こえてきて楽しそうでした。

同じ目的でもくもくするのって、やっぱりいいですね。

会を終えて思ったこと

過去2回やった Plugin 勉強会でも思ったのですが、少人数開催とはいえ初対面の方や開発中に声かけづらいとかもあり、コミュニケーション取るの難しいなと思っていました。

そのため今回は、参加者のみなさんに簡単な自己紹介をお願いして、コミュニケーションしやすくなればいいなと思ったのですが、 もしかしたらあまりプラスに働かなかったかもしれません。

他に何か良い方法は無いかなと考えたところ、slack のグループがあったらいいのかもと思いました。

Kotlin を始め、メジャーなテーマでは既に slack の公開グループがいくつかありますが、Plugin 開発は無さそうでした。 今後も勉強会やもくもく会でコミュニケーションが円滑になったり、継続して情報交換が出来るようになればいいなと思い、Plugin 開発をテーマとした slack グループを作成しました。

だいぶニッチかもしれませんが、興味ある方は誰でも参加可能ですので、もしよろしければ以下のリンクから参加申請してみてください。

IntelliJ Plugin Developer への参加申請リンク

勉強会 or もくもく会の方も、都合が悪く参加出来なかった方もいらしたので、ぜひまた次回開催できればいいなと思っています。

Rx Ja Night 2016 #1 に参加しました

最高のイベントでした。 RxJavaがメインではありましたが、他のReactiveXでも適用できる内容だったと思います。

主催の @fushiroyamaさん 、発表者のみなさま、会場を提供してくださったVOYAGE GROUPさま、ありがとうございました!!

15分セッション

1. 実際のアプリ開発で使った Rx を紹介 ( bl_lia さん)

2. ReactiveX のドキュメントにある図の見方の解説 ( yanzm さん)

3. RxJava + Vert.x + jOOλ で Microservice 的な何かを作ってみた(業務的に)( chimerast さん)

4. Tapping Retry ( hydrakecat さん)

10分LT

1. Subject 入門 ( fushiroyama さん)

2. iOS の Reactive 系ライブラリ ( wm3 さん)

3. TestSubscriver ( yuyakaido さん)

上記以外で参考になったこと

みんな新しい Operator を試すときにどうやってるのかなーと思ったのを聞いてみたところ、RxJava だと IntelliJ で Java のプロジェクトを作って、その中でミニマムな実装で動きを確認するという話しを聞きました。

他にも RxSwift だと playground で試せるっぽい話も。

まとめ

個人的に今日心に焼き付けたいことTOP3です

  • marble diagram で operator をしっかり理解しよう
  • テスト書こう
  • retryWhen 便利っぽいので使いこなせるようにしよう

DroidKaigi2016にスタッフ&スピーカーとして参加したのでKPTしました

DroidKaigiの運営では、2015のときもそして今回もイベント終了後に全員でKPTによる振り返りを行っています。 それにあやかって、僕個人に対してもKPTをしてみようと思いました。

Keep

  1. 発表のシミュレーションを繰り返し行う
  2. 事前にイベント会場を下見する

1については、今回初めて50分という持ち時間に挑戦しました。これまでは30分が最長だったため、資料を作っていても時間配分のイメージが全く湧きませんでした。細かい内容は今までの経験上、当日ちょっと変わる可能性もあったので、大まかにですが全体を流すように発表のシミュレーションをするようにしました。

シミュレーションをすることで、資料を作っているときには気づけなかった点に気づくことができ、資料にメリハリをつけられるようになったと思います。1つ注意点としては、いろんなところが気になってしまい、何度もシミュレーションと修正を繰り返し、無限に時間が吸われていったことです。

2は、スタッフとしての視点です。一応念のためくらいの軽い気持ちで、2週間ちょっと前くらいに他のスタッフと一緒に会場の下見に行ったのですが、今思うと行っておいて大正解だったなという感じです。

当日朝の集合時間が早かった(朝8時現地集合)のですが、会場までの道のりは経験済みだったため余裕を持って移動できたし、イベント中も会場となる大学内を1人で移動するのも不安はありませんでした。イベント1ヶ月前とかまでは、誘導担当でも無いし下見しなくていいかなと考えていましたが、下見は重要でした。

Problem

  1. スタッフとスピーカーの兼任はリソース配分をよく考える
  2. 備品はケチらない

1はそもそも兼任しないのがいいなという結論なのですが、それでも兼任するならどうすれば良かったのかを書こうと思います。 当たり前と言えば当たり前ですが、イベント日が近づくにつれ、スタッフ業務もどんどん忙しくなっていきます。時には予定外の作業も発生します。そのときに資料作成も佳境に入っていたのでは、睡眠時間を削るしかなくなっていきます。(実際にそうでした。)

ではどうするべきだったか。スタッフ業務の忙しさは自分ではコントロールできないので、資料作成のピークをスタッフ業務のピークと反比例するようなスケジュールを立てるべきだったと思います。今だから言えることで、実際にやるのは大変そうですが...。

2については、僕は今回のDroidKaigiで各会場で使用する電源タップの発注を担当したのですが、全体の約半数を型落ちの安価な品で購入しました。一応販売会社のレビューとかもチェックして、粗悪品を掴まないようにと気にしてはいたのですが、現実には安価な方の2個が初期不良で、別の2個がイベント中に大破するという結果でした。

もう半数の品は1個も壊れることなくイベントを終えたので、まさに「安物買いの銭失い」を地でいってしまうことになってしまいました。必要なものは、きちんと相場と同程度の金額を掛けるのが安心だと思いました。(幸い別のスタッフが1日目終了時に、電源タップを追加購入してくれたおかげでイベントに支障はでませんでした。)

Try

  1. 海外スピーカーの方に質問する

これは本当は今回のDroidKaigiで挑戦したかったのですが、完全に自分自身をコントロールできなくなって資料作成とスタッフ業務で手一杯となって、英語学習が日に日に疎かになったため、実行する勇気が出ませんでした。 ただ今回、スタッフとして海外スピーカーと接する機会があったのに、「Yes」しか言えなかった悔しい体験をしたので次こそは...。

他にもTryな項目を考えたのですが、次回スピーカーをやりたいのかスタッフをやりたいのか、まだ全然決められないので、今の時点としては1つだけにしました。

まとめ

Problemにも書きましたが、もし次のDroidKaigiがあって関わりたいのであれば、スタッフとスピーカーはどちらかにして、今回の教訓を活かしてもっとクオリティの高いアウトプットをしなければいけないなと思いました。

最後になりましたが、素晴らしいスタッフの面々と一緒にDroidKaigi2016に携われたことが、とても嬉しいです。本当にお疲れ様でした!&ありがとうございました!

f:id:androhi:20160219202842j:plain

@mgmix5さんの写真より

0 から Android アプリ開発を学びたい人へ

先日「Androidアプリ開発って、どうやって勉強したらいいですかね?」という質問を受けたので、そのときに話した内容に少し追加して、まとめてみました。

ネット上の情報だと断片的で、体系的な学習に使えそうなものが少ないですし、書籍だと何を買ったらいいか選ぶのも難しく、かつ値段も高いという悩みが多いと思います。そのあたりの敷居を下げつつ、きちんとした内容で学習できそうなものを、独断と偏見でピックアップしました。

続きを読む

"WebエンジニアのためのiOSデバッグ速習会"で学んだことのまとめ

WebエンジニアのためのiOSデバッグ速習会@Wantedly に参加してきたので、内容を忘れないようまとめました。

wantedly.connpass.com

参加者は事前に Xcode を自分の PC にインストールしておき、講師の人が説明した後に実際に手を動かして確認していく、というスタイルでした。

また速習会中は、Sync を使って参加者同士がコミュニケーションを取るというのは、独特で面白かったです。

講師は @hedjirog さんでした。

やったこと

講師の方が資料を用意してくださったので、それに沿って以下のようなことをやりました。

テーマは iOS アプリのデバッグです。 使用したのは Xcode 7.1.1 です。

  1. 題材アプリ Artsy のインストール
  2. ブレークポイントを配置して任意のコードで実行を止める
  3. ビューデバッガでビュー構造からクラスなどを特定する
  4. chisel を使って LLDB コマンドでデバッグする
  5. ExceptionBreakpoint でアプリのクラッシュをデバッグする

おまけ: PonyDebugger を利用して通信内容を確認する

題材アプリ Artsy のインストール

デバッグ対象とするアプリは OSS で公開されている Artsy を使いました。 README にも書かれている通り、以下の手順でインストールできます。(結構時間かかります。)

git clone https://github.com/artsy/eigen.git
cd eigen
bundle install
make oss
bundle exec pod install
open Artsy.xcworkspace

注意点として普段 Ruby を使っていない PC だと、bundler がインストールされていないかもしれません。 そのときは、以下のコマンドでインストールされているか確認し、

gem contents bundler

見つからなければ、以下のコマンドでインストールします。

gem install bundler

パーミッションで怒られたら管理者権限で実行します。

sudo gem install bundler

Breakpoint を配置して任意のコードで実行を止める

普段何かしらの IDE を使っていれば、おなじみのデバッグ方法ですね。

Breakpoin の配置は、行番号のあたりをクリックするだけです。セットした Breakpoint は、左側の Breakpoint Navigator にリスト化されていきます。

f:id:androhi:20151127170505p:plain

さらに Xcode の場合は、セットした Breakpoint に任意のコマンド実行などを追加出来るとのこと。

これを使えば Breakpoint に到達したときに、音を鳴らすとかも簡単に出来るようです。

f:id:androhi:20151127170537p:plain

Breakpoint の削除は、Breakpoint をドラッグして離せば消えます。

ビューデバッガでビュー構造からクラスなどを特定する

ビューデバッグを開始(アプリ実行中にカルーセルみたいなボタンをクリック)すると、IDE 内にビュー構造を表したオブジェクトが立体表示出来ます。 (iOS エンジニアの人に聞いたら、割りと最近追加されたものらしいです。)

f:id:androhi:20151127170818p:plain

f:id:androhi:20151127170608p:plain

UI をクリックすると、その UI が何のクラスなのか分かります。そして、右側にはそのコンポーネントの詳細な情報が、確認出来るようになっています。

f:id:androhi:20151127170801p:plain

似たもので Reveal という、有償のビュー構造解析ツールがあるようです。(そっくりですね。こっちの方がサクサク動くらしい。)

AndroidStudio にも、この機能欲しいですね。

chisel を使って LLDB コマンドでデバッグする

chisel というデバッグツールがあるとのことです。 facebook 社が OSS として公開しています。

Chisel is a collection of LLDB commands to assist debugging iOS apps.

これを活用したデバッグ方法です。(*1

chisel は Homebrew でインストールできます。

brew update
brew install chisel

chisel を使うには、設定ファイルが必要です。ホームディレクトリ下に、 .lldbinit というファイルが無ければ作成します。 .lldbinit ファイルには、以下を記述しておきます。

command script import /path/to/fblldb.py

/path/to の部分は環境によって変わります。自分の環境下でのパスを確認するには、以下で出力されます。

brew info chisel

chisel を使う手順は、アプリを実行したら || ボタンで止めて、コンソールでコマンドを実行します。 コマンドの説明は chisel の README に載ってます。

今回試したのは、以下のコマンドです。

pviews

コマンドを叩くと、以下の様なテキストベースのビュー構造を返してくれます。 (長いので途中省略しています。)

<ARWindow: 0x7fdf40c1e960; baseClass = UIWindow; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fdf40c20e30>; layer = <UIWindowLayer: 0x7fdf40c1c760>>
   | ARTopMenuViewController:0x7fdf40d17cb0 1c.[ARNavigationController 0x7fdf41890000: ] <UIView: 0x7fdf40e3af30; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fdf40cc4ae0>; layer = <CALayer: 0x7fdf40e78c70>>
   |    | <UIView: 0x7fdf40ebb230; frame = (0 621; 375 46); layer = <CALayer: 0x7fdf40ebb3a0>>
   |    |    | <ARNavigationTabButton: 0x7fdf40eaed20; baseClass = UIButton; frame = (0 0.5; 46 45.5); opaque = NO; layer = <CALayer: 0x7fdf40ea9e30>>
   ...
   |    |    |    |    | <UIImageView: 0x7fdf40c1f910; frame = (10 10; 20 20); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7fdf40c55750>>
   |    |    |    |    | XX (<UIButtonLabel: 0x7fdf40d1f100; frame = (20 10.5; 0 19); hidden = YES; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7fdf40d10790>>)
   |    | XX (<NPKeyboardLayoutGuide: 0x7fdf40ec8e90; frame = (0 667; 0 0); hidden = YES; layer = <CALayer: 0x7fdf40ec7a60>>)

f:id:androhi:20151127170939p:plain

taplog

コマンドを叩くと、シミュレーター(もしくは実機)がアクティブになります。

この状態でアプリ上のどこかをタップすると、そのイベントの開始位置で再び止まり、エディタには該当のコードを表示してくれます。

f:id:androhi:20151127170956p:plain

border

コマンドの後に、UI コンポーネントのアドレスを渡してあげると、シミュレーター(もしくは実機)の該当する UI 部分が赤枠で囲われます。

f:id:androhi:20151127171016p:plain

ExceptionBreakpoint でアプリのクラッシュをデバッグする

アプリがクラッシュしたときに、以下のように通常コンソールに出力される情報だけでは、発生元を特定するのが大変です。

f:id:androhi:20151127171042p:plain

そういうときは ExceptionBreakpoint を使うと、例外が発生した箇所で実行を止めてくれるとのことです。

使い方は、左側の Breakpoint Navigator に切り替え、アプリを実行させます。 その状態で、左下のプラスボタンから「Add Exception Breakpoint...」をクリックし、ExceptionBreakpoint を設定します。

f:id:androhi:20151127171101p:plain

実際にクラッシュを起こすと、以下のように例外が発生した場所のコードが表示され、そこで実行が止まります。

f:id:androhi:20151127171115p:plain

PonyDebuggerを利用して通信内容を確認する

Square 社が OSS で公開している PonyDebugger という、iOS 用の通信デバッグツールとのことです。

Remote network and data debugging for your native iOS app using Chrome Developer Tools

これは時間が足りず試せませんでした。 GitHub の README を見れば分かりますが、ブラウザで通信のリクエストやレスポンスが確認出来るようです。 数行アプリにもコードを書かないと行けないので、導入するときは一手間必要そうですね。

(ただ Android アプリ開発も行う人とかは特に、charles とか wireshark とかのツールで、両方ともカバーした方が便利かなと思いました。)

まとめ

  • 特定のコードでアプリを止めたい時は Breakpoint を設定する
  • Breakpoint はアクションを追加できるので必要に応じて活用する
  • UI まわりはビューデバッガを使うと便利
  • より細かいデバッグには chisel を活用すると便利
  • クラッシュ発生源の特定には ExceptionBreakpoint を使う

個人的な感想として僕は普段 Android アプリの開発がメインで、IDE は AndroidStudio を使うことが多いのですが、View まわりのデバッグXcode の方が良く出来てるなと感じました。

余談

懇親会中 wantedly 社の方にオフィスを案内してもらったのですが、とにかくお洒落すぎて素敵なオフィスでした。会議室の名前が全部ジョジョのスタンド名で、とにかくかっこいいです。

それとこちらで販売してる wantedly パーカーいいですねっていう話しになったのですが、高いだけあって物がいいらしいので気になってきました。

*1:なお chisel については、こちらのブログが詳しいようです。 yidev@恵比寿勉強会 で chisel について発表してきた (動画付き)

API level 23 未満を考慮した指紋認証 API の実装

前回、指紋認証 API のサンプルコードをざっと見てみたのですが、そのときに FingerprintManagerCompat クラスが Support Library v4 にあるのを見つけました。

androhi.hatenablog.com

このクラスを使えば Android 6.0 (API level 23 未満) も含め、スッキリと実装できるんじゃないかなと思い調べてみました。

FingerprintManager のインスタンス取得

前回のGoogleのサンプルコードでは、以下のようなコードでインスタンスを取得していました。

FingerprintManager manager = context.getSystemService(FingerprintManager.class);

ところが以下の2点で API level 23 未満では、getSystemService() 経由だと使えません。

  1. Context.getSystemService(Class<T>)API level 23から追加されたメソッド
  2. Context.getSystemService(String) だと引数のサービス名に Fingerprint は無い

そのため FingerprintManagerCompat では、別途 Context を使った方法が用意されていました。

// contextはActivityなど
FingerprintManagerCompat managerCompat = FingerprintManagerCompat.from(context);

FingerprintManagerCompat のソースコードを辿って行くと、内部で Build.VERSION.SDK_INT をチェックしていて、23 以上だと Api23FingerprintManagerCompatImpl 内部クラスを、23 未満だと LegacyFingerprintManagerCompatImpl 内部クラスを、それぞれインスタンス化していました。

指紋センサーの判定など

FingerprintManager では、端末に指紋センサーのハードウェアがあるか?や、指紋の登録があるか?などを判定するメソッドを提供しています。

まったく同じメソッドが、FingerprintManagerCompat クラスにも実装されていますが、どのような挙動になるのか確認してみました。

結論から書くと、API level 23 以上だとちゃんと FingerprintManager 経由で判定し、23 未満だと固定で false を返していました。

API level 23 未満

    private static class LegacyFingerprintManagerCompatImpl implements FingerprintManagerCompatImpl {

        public LegacyFingerprintManagerCompatImpl() {
        }

        @Override
        public boolean hasEnrolledFingerprints(Context context) {
            return false;
        }

        @Override
        public boolean isHardwareDetected(Context context) {
            return false;
        }

        ...
        }
    }

API level 23 以上

    private static class Api23FingerprintManagerCompatImpl implements FingerprintManagerCompatImpl {

        public Api23FingerprintManagerCompatImpl() {
        }

        @Override
        public boolean hasEnrolledFingerprints(Context context) {
            return FingerprintManagerCompatApi23.hasEnrolledFingerprints(context);
        }

        @Override
        public boolean isHardwareDetected(Context context) {
            return FingerprintManagerCompatApi23.isHardwareDetected(context);
        }
        
        ...
public final class FingerprintManagerCompatApi23 {

    private static FingerprintManager getFingerprintManager(Context ctx) {
        return ctx.getSystemService(FingerprintManager.class);
    }

    public static boolean hasEnrolledFingerprints(Context context) {
        return getFingerprintManager(context).hasEnrolledFingerprints();
    }

    public static boolean isHardwareDetected(Context context) {
        return getFingerprintManager(context).isHardwareDetected();
    }
    
    ...

分かりやすくいいですね。

指紋認証

実際に指紋センサーから指紋を読取るときは、 FingerprintManager#authenticate(CryptoObject, CancellationSignal, int, AuthenticationCallback, Handler) メソッドを使ってましたが、これも先ほどと同じ形でした。

API level 23 以上では、FingerprintManager 経由で処理し、23 未満では何もしません。

API level 23 未満

    private static class LegacyFingerprintManagerCompatImpl
            implements FingerprintManagerCompatImpl {
        ...

        @Override
        public void authenticate(Context context, CryptoObject crypto, int flags,
                CancellationSignal cancel, AuthenticationCallback callback, Handler handler) {
            // TODO: Figure out behavior when there is no fingerprint hardware available
        }
    }

API level 23 以上

    private static class Api23FingerprintManagerCompatImpl implements FingerprintManagerCompatImpl {
        ...
        @Override
        public void authenticate(Context context, CryptoObject crypto, int flags,
                CancellationSignal cancel, AuthenticationCallback callback, Handler handler) {
            FingerprintManagerCompatApi23.authenticate(context, wrapCryptoObject(crypto), flags,
                    cancel != null ? cancel.getCancellationSignalObject() : null,
                    wrapCallback(callback), handler);
        }
public final class FingerprintManagerCompatApi23 {
    ...
    public static void authenticate(Context context, CryptoObject crypto, int flags, Object cancel,
            AuthenticationCallback callback, Handler handler) {
        getFingerprintManager(context).authenticate(wrapCryptoObject(crypto),
                (android.os.CancellationSignal) cancel, flags,
                wrapCallback(callback), handler);
    }

まとめ

当分 API level 23 以上でアプリを開発出来る状況は来ないので、開発しているアプリに指紋認証を導入したいときは、この FingerprintManagerCompat を使うのが良さそうです。

今まで割と自力で API level 判定して処理を分けていたようなところも、xxxCompat クラスがいい感じに内部で切り替えてくれるケースが増えてきた気がします。

新しい機能が出てきたら、まずは xxxCompat クラスも一緒に探すと、既存アプリへの導入が楽になりそうですね。

Android 6.0 の指紋認証 API を触ってみた感想文

10/26(月)に Android Developers Blog で、New in Android Sample: Authenticating to remote servers using the Fingerprint API という記事が公開されました。

さらに 10/19(月)にNexus5Xが発送されたにも関わらず全然触ることが出来なかったのですが...

今日やっとセットアップを終えたということもあり「思ったより指紋認証よさそう」って高まってるので、実際にサンプルコードを見て触ってみました。

指紋認証 API

先程のブログ記事によると、Android 指紋認証 API は安全に利用することが出来るよう、デバイスのセキュアなハードウェアに含まれているとのことです。

指紋認証 API の利用の仕方としては2種類の方法を、アプリケーションのニーズに合う方を選ぶのが望ましいようです。

例えば、オフラインのファイルやデータベースにアクセスするときは、パスワードと同じような Symmetric Keys を使い、ネットワークへのログインやオンライン取引のようなケースでは、公開鍵と秘密鍵で構成される Key Pair による Asymmetric Keys を使う、といった形です。

サンプルコード

Google が公開している指紋認証機能に関するサンプルコードは、AsymmetricFingerprintDialogFingerPrintDialog の2つあります。

f:id:androhi:20151028030749p:plain

AsymmetricFingerprintDialog の方は、名前の通りペアの鍵を用いてクライアント/サーバー間で認証を行うサンプルです。今回新たに追加されたサンプルは、こちらのようです。

FingerprintDialog の方は、Android 6.0 が public preview のときに公開されたサンプルで、とりあえずどうやって指紋認証をアプリに実装するかを示したものです。

両者のサンプルコードを比較してみると、違うのはサーバー側の処理のフェイクを実装している部分と、鍵の生成に KeyGenerator クラス使ってるか KeyPairGenerator クラスを使ってるかっていうあたりでした。

f:id:androhi:20151028030950p:plain f:id:androhi:20151028031002p:plain

認証フロー的な説明は、公式ブログが詳しいのでそっちを読めばいいとして、もう少し細かいとこを見てみました。

指紋認証の可否判定

サンプルコードを見てみると、2つのチェックを行っていました。1つは画面ロックに、スワイプ/パターン/PIN/パスワードのいづれかが設定されているかどうか、もう1つは端末に指紋が登録されているかどうかです。

画面ロックの有無をチェックするコード

getSystemService(KeyguardManager.class).isKeyguardSecure();

設定 > セキュリティ > 画面ロック の設定をチェックできる

指紋登録の有無をチェックするコード

getSystemService(FingerprintManager.class).hasEnrolledFingerprints();

設定 > セキュリティ > Nexus Imprint の設定をチェックできる(Nexus5Xの場合)

f:id:androhi:20151028030837p:plain

指紋の読み取り

サンプルアプリを動かしてみると、下図のような指紋センサーにタッチさせるダイアログが出るのですが、このダイアログが表示されてるときに指紋センサーが反応するようです。

f:id:androhi:20151028030912p:plain

どういう風に実装されてるか見てみました。(公式ブログにも載ってますが...)

細かい部分は割愛しますが、以下のコードで実現していました。

指紋の読み取りを開始するコード

getSystemService(FingerprintManager.class).authenticate(cryptoObject, cancellationSignal, 0, this, null);

FingerprintManager#authenticate(FingerprintManager.CryptoObject, CancellationSignal, int, FingerprintManager.AuthenticationCallback, Handler) メソッドで読み取り開始〜コールバック受け取りまで出来るようです。

一応 Support Library にも FingerprintManagerCompat クラスが用意されいて、API level 23 より前のデバイスで指紋機能なしとして振る舞ってくれるらしいです。試してません。

あとは FingerprintManager クラスには、ハードウェアとして指紋機能が有効かチェックする isHardwareDetected() というメソッドもありました。

まとめ

ざっくり見た感じでは、Asymmetoric Keys のやり方でもサンプルコードのおかげで、割とすぐに実装できそうな気がしました。

アプリのログインが指紋認証で出来るのは、すごく楽だと思うので積極的に取り入れていきたい気持ちになりました。