20190524のKotlinに関する記事は3件です。

AWS Cloud9 で サーバサイドKotlin の開発環境を構築する

こんにちは。らすてぃです。
昨年あたりから、SpringBoot + KotlinIntelliJ IDEAで弄っていたのですが
事情により、その開発環境を クラウドIDE(AWS Cloud9) で用意することにしました。

最終的に到達したいことはもろもろあるのですが、少しずつ進んでいきたいと思います。

できるようになること

  • AWS Cloud9 上で
    • Kotlinの開発ができる
    • githubのリモートリポジトリにpushできる
    • docker-composeが利用できる

事前にやっておくこと

  • AWS Cloud9 の準備
    • アカウント作成とかIAM作成とかそのあたり

Kotlin の環境を作る

EC2のOSはUbuntuを選択。なので、aptで構築していきます。

以下の記事がとても参考になりました。
https://qiita.com/kako351/items/3360cbac578aa7e35c9b

Javaのインストール

1. リポジトリ追加

$ sudo add-apt-repository ppa:openjdk-r/ppa

2. アップデート

$ sudo apt-get update

3. Javaのパッケージ確認

$ sudo apt-cache search openjdk-.+-jdk$
openjdk-11-jdk - OpenJDK Development Kit (JDK)
openjdk-8-jdk - OpenJDK Development Kit (JDK)

4. Java11をインストール

$ sudo apt-get install openjdk-11-jdk

5. Java11に設定

$ sudo update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                            Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-11-openjdk-amd64/bin/java      1111      auto mode
  1            /usr/lib/jvm/java-11-openjdk-amd64/bin/java      1111      manual mode
  2            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      manual mode

Press <enter> to keep the current choice[*], or type selection number:

選択肢を聞かれるので、 java11 を選択します。 (この場合は1)

6. バージョン確認

$ java -version
openjdk version "11.0.3" 2019-04-16
OpenJDK Runtime Environment (build 11.0.3+7-Ubuntu-1ubuntu218.04.1)
OpenJDK 64-Bit Server VM (build 11.0.3+7-Ubuntu-1ubuntu218.04.1, mixed mode, sharing)

Kotlinのインストール

公式サイトを見ながらインストールします。

https://kotlinlang.org/docs/tutorials/command-line.html

1. SDKMAN!のインストール

$ curl -s https://get.sdkman.io | bash
$ source "/home/ubuntu/.sdkman/bin/sdkman-init.sh"

2. Kotlinのインストール

$ sdk install kotlin

ちなみにバージョンを指定したい場合は、次のように利用可能なバージョンを確認・指定する

$ sdk list kotlin
================================================================================
Available Kotlin Versions
================================================================================
     1.3.31              1.2.31              1.1.2-5             1.0.0          
     1.3.30              1.2.30              1.1.2-2                            
     1.3.21              1.2.21              1.1.2                              
     1.3.20              1.2.20              1.1.1                              
     1.3.11              1.2.10              1.1                                
     1.3.10              1.2.0               1.0.7                              
     1.3.0               1.1.61              1.0.6                              
     1.2.71              1.1.60              1.0.5-2                            
     1.2.70              1.1.51              1.0.5                              
     1.2.61              1.1.50              1.0.4                              
     1.2.60              1.1.4-3             1.0.3                              
     1.2.51              1.1.4-2             1.0.2                              
     1.2.50              1.1.4               1.0.1-2                            
     1.2.41              1.1.3-2             1.0.1-1                            
     1.2.40              1.1.3               1.0.1                              

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================
$ sdk install kotlin 1.3.31

3. バージョン確認

$ kotlinc -version
info: kotlinc-jvm 1.3.31 (JRE 11.0.3+7-Ubuntu-1ubuntu218.04.1)

4. Hello, World!

hello.kt
fun main(args: Array<String>) {
    println("Hello, World!")
}
$ kotlinc hello.kt -include-runtime -d hello.jar
$ java -jar hello.jar
Hello, World!

Gradleのインストール

これも公式サイトを見ながらインストールします。

https://gradle.org/install/

SDKMAN!が使えるようになっているので、それを使います。

$ sdk install gradle

githubの設定をする

鍵の作成

$ ssh-keygen -t rsa -b 4096 -f id_rsa_cloud9 -C your_email@example.com

公開鍵の設定

  1. github.com の Settings から SSH and GPG keys にある New SSH key をクリック
  2. Title に識別できる文字列を入力し、Key に先程作成した公開鍵の内容をペーストする
  3. Add SSH key をクリック

接続の確認

$ ssh-agent bash
$ ssh-add ~/.ssh/id_rsa_cloud9
$ ssh -T git@github.com
Hi Your-name! You've successfully authenticated, but GitHub does not provide shell access.

Dockerを動かす環境を作る

dockerコマンドは入ってるけど、docker-composeコマンドは入ってないので、Latest releaseバージョンを確認してインストールします。

https://github.com/docker/compose/releases/

$ sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose version 1.24.0, build 0aa59064

執筆時点の最新は1.24.0です。

次にやることリスト

  • SpringBoot + Kotlin の雛形をつくり、github.com のリモートリポジトリにコミットする
  • DockerでSpringBootアプリケーションを動かす
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Android】altbeaconでBeaconからの距離(Proximity)を測りたかった話

前回 Macから無事Beaconを発射できるようになった。

Beaconの仕様を知らないまま、BeaconからAndroid端末の距離って測れるよね?と軽い気持ちで試してみようとした記録とメモを兼ねて。。。。

結論から言うと

色々調べてみると、どうやら電波強度や建物の干渉などで正確な距離は測れないみたい。

一応 BeaconManager#addRangeNotifier で受け取れるbeaconに生えてるdistance(メートル単位)があるけど
本当にメートル???ってなるくらい誤差がひどかった。

どうやったか

ググラーエンジニアなのでこのQiitaを発見。
RSSI と TxPower からビーコンとの距離および近接度(Proximity)を推定する
この記事によると

RSSI と TxPower から推定距離を計算する

自由空間では受信信号強度は距離の二乗に反比例して減衰していく(フリスの伝達公式)ので、RSSI と TxPower と距離(d)の関係は次のようになります。

RSSI = TxPower - 20 * lg(d)

(lg は底を 10 とする常用対数)

というわけで、距離 d の計算式は以下のようになります。

d = 10 ^ ((TxPower - RSSI) / 20)

なんかすごい物理法則的なアレを加味して計算しないといけないっぽかった。(語彙力)
先人の知恵を頂戴して、Kotlinで便利そうな関数を作る。

Sample.kt
fun beaconDistance(txPower: Int, rssi: Int): Double = 10.0.pow((txPower - rssi) / 20.0)

実際に観測してログに出すだけのコードはこちら

Sample.kt
    override fun onBeaconServiceConnect() {
         ~  ~

        beaconManager?.addRangeNotifier { beacons, region ->
            beacons
               .map {
                   "Distance:"+beaconDistance(it.txPower, it.rssi)
                   // it.distanceもあったけど誤差がやばい(私的見解)
               }
               .forEach { Log.d(TAG, it) }
        }
         ~  ~
    }

測ってみてどうだった?

端末持ってウロウロしてみたけど外の交通量やノイズ?や建物の作りでまあまあ誤差がでるみたい。
beacon.distance 使えないな〜、もうちょっと正確なのがいいな。
くらいの時に目安に使うのならいいかもね。

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

BiometricPromptをAndroid Mから使う

はじめに

Android PからBiometricPromptというクラスが追加されました。これはバイオメトリック(生体認証)に関連する処理を引き受けてくれるもので、これを使うと今までアプリ側で実装していたダイアログの表示をシステム側で提供してくれるようになります。また、指紋認証だけでなく、虹彩認証や顔認証にも対応しており、ユーザが選択した方式を判別し、適切なダイアログを表示してくれるという優れものです。それに伴い、従来のFingerprintManagerはAndroid API 28より非推奨になりました。こんな便利な物を使わない手がないと、早速移行してみようと思ったのですが、BiometricPromptの最低サポートがAndroid API 28からなので、Min SDKバージョンが28より低い場合は完全に移行することが出来ません?

今回はこの問題の解決方法と実装の仕方を簡単にまとめました。

解決方法

いきなり結論からです。android.hardware.biometrics.BiometricPromptではなくandroidx.biometrics.BiometricsPromptを使います。ただし、AndroidXを使うので従来のAndroid Support Libraryとは共存出来ない点に注意してください。

実装方法

まず、依存関係をGradleに追加します。

dependencies {
    ...
    implementation 'androidx.biometric:biometric:1.0.0-alpha04'
}

生体認証を使う為、Android Manifestにパーミッションを追加します。

<uses-permission android:name="android.permission.USE_BIOMETRIC" />

最後に認証ダイアログを呼び出す処理を実装します。

val executor = Executors.newSingleThreadExecutor()

val biometricPrompt = BiometricPrompt(this, executor,
    object : BiometricPrompt.AuthenticationCallback() {
        override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
            super.onAuthenticationError(errorCode, errString)
            Log.d("Biometric", "Error")
        }

        override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
            super.onAuthenticationSucceeded(result)
            Log.d("Biometric", "Succeeded")
        }

        override fun onAuthenticationFailed() {
            super.onAuthenticationFailed()
            Log.d("Biometric", "Failed")
        }
    })

val promptInfo = BiometricPrompt.PromptInfo.Builder()
    .setTitle("Title")
    .setSubtitle("Sub title")
    .setDescription("Description")
    .setNegativeButtonText("Cancel")
    .build()

biometricPrompt.authenticate(promptInfo)

これだけで、認証ダイアログを表示できます。

i ii iii
img_1 img_2 img_3

軽くコードの説明をします。

認証の結果を受け取るのはBiometricPromptインスタンス生成時に渡しているBiometricPrompt.AuthenticationCallbackになります。

関数名 内容
onAuthenticationError エラーが発生して操作が完了された時に呼び出される
onAuthenticationSucceeded 生体認証が成功した時に呼び出される
onAuthenticationFailed 生体認証が有効だが認識されない時に呼び出される

キャンセルボタンのイベントはonAuthenticationErrorメソッドでerrorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTONと比較することでキャッチすることができます。BIOMETRIC_ERROR定数に関しては以下のものがあります。

定数名 内容
ERROR_CANCELED 生体認証が利用できない為、操作がキャンセルされた
ERROR_HW_NOT_PRESENT 端末に生体センサが搭載されていない
ERROR_HW_UNAVAILABLE 端末が利用できない
ERROR_LOCKOUT 生体認証に5回失敗した
ERROR_LOCKOUT_PERMANENT ERROR_LOCKOUTの発生回数が多すぎる為、操作がキャンセルされた
ERROR_NEGATIVE_BUTTON ユーザがネガティブボタン(ダイアログのキャンセルボタン)を押した
ERROR_NO_BIOMETRICS ユーザの生体認証情報が登録されていない
ERROR_NO_SPACE 操作を完了するのに十分なストレージが用意されていない
ERROR_TIMEOUT 認証を実行するまでの時間が長すぎる為、タイムアウトが発生した
ERROR_UNABLE_TO_PROCESS 生体センサが画像を処理できない
ERROR_USER_CANCELED ユーザが操作をキャンセルした
ERROR_VENDOR いずれのエラーにも該当しない

ERROR_CANCELEDは具体的に端末で使用するユーザを切り替えた場合(おそらく生体認証情報がリセットされる)や端末がロックされている場合、他のアプリが生体認証を利用中の場合に発生するみたいです。ERROR_HW_UNAVAILABLEはどういったタイミングで発生するのかがわかりませんでした。ERROR_LOCKOUTが発生した場合、30秒後に再度認証可能になるみたいです(知らなかった:sweat_smile:)。ERROR_UNABLE_TO_PROCESSはおそらく虹彩認証や顔認証などのカメラを利用する場合に発生するのかと思います。

認証ダイアログのカスタマイズはBiometricPrompt.PromptInfo.Builderで行います。指定できる項目は以下の通りです。

関数名 内容
setTitle タイトルを設定(必須)
setSubtitle サブタイトルを設定(任意)
setDescription 説明を設定(任意)
setNegativeButtonText ネガティブボタンに表示されるテキストを設定(必須)

ダイアログの画像やメッセージといった細かい部分は流石に設定できないみたいですね。

また、認証ダイアログを表示する前に

private fun isBiometricEnabled(context: Context): Boolean =
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        && context.getSystemService(KeyguardManager::class.java).isKeyguardSecure
        && context.packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)

のように端末が生体認証を利用出来るか判定した方が良さそうです。

まとめ

足早にですがBiometricPromptをAndroid Mから使う方法を解説しました。本来はBuild.VERSION.SDK_INTでAndroidのバージョンを取得してFingerprintManagerとの処理を切り分けるのが行儀がいいのですが、ぶっちゃけめんどくさい効率的に出来るのであれば致し方ないのかなと。また、虹彩認証と顔認証については、次期バージョンのAndroid Q(API 29)から利用出来るみたいです。今回のデモアプリをGitHubに公開しておきますので、参考にしていただければ嬉しいです。では。

参考文献

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