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

ShapeableImageViewで真ん丸や角丸の画像を手軽に作ってみる

真ん丸や角丸の画像を作る方法としてPiccasoなどのライブラリを使う方法1や、手軽な方法としてCardViewを用いたやり方2などがありますが、Material Components 1.2.0に追加されたShapeableImageViewを使ったやり方を紹介してみます。

下のような画像を手軽に作成できます。

top.png

準備

Material Components 1.2.0を追加しておきます。

dependencies {
    implementation "com.google.android.material:material:1.2.0"
}

使い方

使い方としては、styleを定義してShapeableImageViewapp:shapeAppearanceOverlay属性に指定してやるだけでOKです。以下で詳しく見ていきます。

真ん丸

styles.xmlに以下を追加。
cornerFamilyroundedcornerSizeに50%を指定してあります。

<style name="circleImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">50%</item>
</style>

あとはレイアウトファイルにShapeableImageViewを配置してapp:shapeAppearanceOverlay属性に上記のスタイルを指定してやります。

<com.google.android.material.imageview.ShapeableImageView
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:adjustViewBounds="true"
    android:src="@drawable/ic_droid"
    app:shapeAppearanceOverlay="@style/circleImageView" />

circle.png

角丸

cornerSizeを調整してやれば角丸にできます。
今回は24%にしてみました。

<style name="roundedCornersImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">24%</item>
</style>

cornerRounded.png

ひし形

cornerFamilycutを指定し、cornerSizeを50%にすればひし形にできます。

<style name="diamondImageView" parent="">
    <item name="cornerFamily">cut</item>
    <item name="cornerSize">50%</item>
</style>

diamond.png

部分的に適応

四隅の一部のみを変えることも可能です。
例えば左上をround、右下をcutにするには以下のように指定してやります。
指定できる属性名についてはhttps://material.io/develop/android/theming/shapeに載ってます。

<style name="mixImageView" parent="">
    <item name="cornerFamilyTopLeft">rounded</item>
    <item name="cornerFamilyBottomRight">cut</item>
    <item name="cornerSizeTopLeft">28%</item>
    <item name="cornerSizeBottomRight">24%</item>
</style>

mix.png

手軽に真ん丸や角丸などの画像を作成できました!
以上です。

参考にしたサイト

How to use the ShapeableImageView

Material Components: ShapeableImageViewで丸く切り抜かれた画像を表示する

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

【Android/Kotlin】インターネット接続の確認とNetworkInfo非推奨の解消

開発環境

  • macOS 10.15.5
  • Android Studio 4.0
  • Kotlin 1.3.72

やりたいこと

サーバーとの通信の前に端末がインターネットに接続されているかどうかを確認したい。

NetworkInfoを使う方法

デベロッパーガイドの接続ステータスの特定と監視(2020/08/09アクセス)によると、ConnectivityManagerを使用すれば、インターネットに接続されているか、接続されている場合はどのようなタイプかを確認できるそうです。

ということで、ボタンが押されると接続状況が確認され、接続のタイプを表示する簡単な実装を行いました。
(マニフェストファイルにパーミッションを追加するのを忘れないようにしましょう)

AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
MainActivity.kt
        val text = findViewById<TextView>(R.id.textView)
        val button = findViewById<Button>(R.id.button)

        button.setOnClickListener {
            val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val activeNetwork: NetworkInfo? = cm.activeNetworkInfo
            val isConnected: Boolean = activeNetwork?.isConnectedOrConnecting == true
            val connectionType = activeNetwork?.type

            if (isConnected) {
                text.text = when (connectionType) {
                    ConnectivityManager.TYPE_WIFI -> "Wifiに接続しています"
                    ConnectivityManager.TYPE_MOBILE -> "モバイル通信に接続しています"
                    else -> "その他のネットワークに接続しています"
                }
            } else {
                text.text = "インターネットに接続していません"
            }
        }

以上のようにすればインターネットの接続が確認できますが、APIレベル29でConnectivityManager.getActiveNetworkInfo()NetworkInfoが非推奨となったため、AndroidStudioでは取り消し線が引かれてしまいます。
これを解消するためにNetworkInfoクラスの代わりにConnectivityManager.getNetworkCapabilities()を使うことにします。

ConnectivityManager.getNetworkCapabilities()を使う方法

NetworkCapabilitiesはアクティブなネットワークの能力を表すクラスです。
以下のように実装できるかと思います。

MainActivity.kt
        button.setOnClickListener {
            // ConnectivityManagerの取得
            val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

            // NetworkCapabilitiesの取得
            // 引数にcm.activeNetworkを指定し、現在アクティブなデフォルトネットワークに対応するNetworkオブジェクトを渡している 
            val capabilities = cm.getNetworkCapabilities(cm.activeNetwork)

            if (capabilities != null) {
                text.text = when {
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ->
                        "Wifiに接続しています"
                    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ->
                        "モバイル通信に接続しています"
                    else -> "その他のネットワークに接続しています"
                }
            } else {
                text.text = "インターネットに接続していません"
            }
        }

*NetworkCapabilitiesはAPI21、ConnectivityManager.getActiveNetwork()API23で追加されたので、APIレベル23以上必要です

参考

を参考にさせていただきました。

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

MemuエミュレーターにXposedを入れてみた

XposedをMemuエミュレーターに入れるには

MemuエミュレーターにXposedを入れてみた。

基本的にしたのURLに方法は書いていますが
https://www.memuplay.com/blog/xposed.html

この#6 Go into terminal emulatorがどこにあるのかわからなかったのでメモします

注意:

MemuエミュレーターはデフォルトでAndroidバージョン7です(2020/8/9現在)

なので上記サイトではxposed-v85-sdk22-x86を入れていますが
xposed-v89-sdk25-x86を入れてください

環境はWindows10です

where Memu
>>> C:\Program Files (x86)\Microvirt\MEmu\MEmu.exe
cd C:\Program Files (x86)\Microvirt\MEmu
memuc.exe -i 0 execcmd cd /storage/emulated/0/Download/xposed-v85-sdk22-x86/;sh flash-script.sh

-i 0(インデックス番号)はエミュレーターを指定するものです-n (エミュ名)でも代替可
execcmdでExecします

/storage/emulated/0/Download/xposed-v85-sdk22-x86
は解凍したXposedフレームワークのPATHを
;sh flash-script.sh
で実行します

1行で書いてるのは
動かすたびに毎回入力がリセットされるからです

C:\Program Files (x86)\Microvirt\MEmu>memuc.exe -i 0 execcmd pwd
/
C:\Program Files (x86)\Microvirt\MEmu>memuc.exe -i 0 execcmd cd storage

C:\Program Files (x86)\Microvirt\MEmu>memuc.exe -i 0 execcmd pwd
/

こうなります:(
ほかにいい方法があるのかもしれませんが
ちゃんと動いてるのでよし!

追記

Shell 開けました
memuc.exe -i 0 adb shell

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

KotlinのJUnitTestにおけるアサーションライブラリはKluentがとても良い感じ

JUnitのアサーションを快適に書きたい

KotlinでUnitTestを書いていて、今までさして調べずメジャーだからと言う理由でHamcrestを使ってたんですが、もともとJavaのライブラリなのでKotlinだと微妙に使いにくい部分がありました。

例えば型判定のアサーションを記述したいときは↓のように書きますが

val value = 10
assertThat(value, `is`(instanceOf(Int::class.java)))

Kotlinではisが予約語に指定されているため`で括る必要もあるのと、isinstanceOfがネストしているのも微妙に書きにくい&読みにくく、クラス指定も::class.javaまで記述する必要があって、当たり前ですがKClassで記述できないのでJavaの世界観に引きづられている印象を受けます。

また細かいところだと、isメソッド一つとってもHamcrest内だけでも3つimoport候補が出てきて、どれをimoportするんだっけ?と一瞬手が止まるのも書きにくいなぁと思っていた部分でした(ここはKotlin関係ない部分ですが)
スクリーンショット 2020-08-08 21.47.29.png

この辺はイマイチだなーと思いつつプロダクションに入らないコードだし動けばまあいいかと思っていたんですが、Kotlinに特化したアサーションライブラリを試しに使ってみたら思いの外快適に記述できて感動したので紹介します。

Kluent

スクリーンショット 2020-08-08 23.59.41.png
Docs: https://markusamshove.github.io/Kluent/
Github: https://github.com/MarkusAmshove/Kluent

KluentはKotlinに特化したJunitアサーションライブラリです。
Fluent Assertion-Library for Kotlinとあるように流れるように記述できるのが特徴です。

Hamcreststaticメソッドを軸にアサーションを実装しているのに対し、KluentはKotlinの拡張関数infix記法(中置記法)を軸にアサーションが実装されています。

アサーション比較

公式サイトへのリンク先に使い方がわかりやすく乗っているのでぱっと見で理解できるとは思いますが、1例として上記で扱った型判定のアサーションでHamcrestKluentを比較してみます。

Hamcrest
val value = 10
assertThat(value, `is`(instanceOf(Int::class.java)))
Kluent
val value = 10
value shouldBeInstanceOf Int::class

どうでしょうか、カッコもなくなりだいぶ読みやすく書きやすくなったと思います。
Hamcrestはstaticメソッドである関係上Utilクラスのように手前にassertThatメソッドを書かなくてはいけませんが、Kluentはinfix記法のおかげで「valueはint型でなければならない」という英文を違和感なく構築することができています。

もちろんinfix記法でも補完が効きます。とりあえずshould...と打てば必要なものが見つかると思います。
スクリーンショット 2020-08-08 22.11.52.png

また、infix以外にも拡張関数で定義されたアサーションもあり、nullチェックなどがそれに当たります。

Hamcrest
val value = 10
assertThat(value, `is`(notNullValue()))
Kluent
val value: Int? = 10
value.shouldNotBeNull()

そらで書く場合どちらのほうが記述しやすいかは一目瞭然ですね!
私自身Kluentの基本的な機能しかまだ使っていませんが、サイトのドキュメントを見る限り一般的にアサーションで最低限必要とされるものは揃っていると思います。

モック機能

KluentにはMocking機能があり、サイト内の解説によるとMockito-Kotlinのラッパーとしての役割も担っているそうです。

Kluent
val mock = mock(Database::class)
mock.getPerson(1)

私はMockKに慣れきっていたので使いませんでしたがMockito-Kotlinを使っている方であれば嬉しいポイントかもしれません。

Androidで使う場合

これは正直ちゃんとはわからなかった部分だったのですが、GithubのドキュメントによるとAndroidで使う場合にはartifactが異なり、以下を指定する必要があるそうです。

build.gradle
// for JVM:
testImplementation 'org.amshove.kluent:kluent:{version}'
// for Android:
testImplementation 'org.amshove.kluent:kluent-android:{version}'

この違いについてはドキュメントには記載がなかったのですが、2020/08/08現在のリポジトリ内をざっくり検索したところライブラリの機能や含まれているソースコード自体には違いはなく、JVMによる実行環境とAndroid上の実行環境の差異を吸収するためにartifactが別れているようでした。

これが正しければですが、Androidデバイス上で実行されるInstrumented Testorg.amshove.kluent:kluent-androidを使う必要がありますが、Androidのプロジェクトであってもデバイスを伴わずPC上のJVM環境で実行されるUnitTestRobolectricを使ったテストはorg.amshove.kluent:kluentで十分と思われます。

まとめ

Kluentはいいぞ!

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