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

11. 【Android/Kotlin】Toast

はじめに

DreamHanksのMOONです。

前回はライブラリを追加する方法について説明しました。
10. 【Android/Kotlin】ライブラリを追加

今回はToastという通知メッセージについて説明していきます。

Toastとは

Toastはみんなさんが考えているトーストパンの意味と同じです。
トースト機器でトーストが完成すると飛び出るようなものだという意味で、
通知メッセージが画面に現れることを意味します。

今回はこのテキストを入力し、Toastメッセージにテキストを表示していきます。

Toast追加

・Activityを作成

ToastActivity.kt
package com.example.practiceapplication

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.*

class ToastActivity : AppCompatActivity() {

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

        val text_et = findViewById<EditText>(R.id.text_et)              //EditText(入力エリア)
        val toast_btn = findViewById<Button>(R.id.toast_btn)            //追加ンボタン

        //ボタンのクリックイベントを設定
        toast_btn.setOnClickListener {
            //入力したテキストに対するToastメッセージを生成
            Toast.makeText(applicationContext, text_et.text.toString(), Toast.LENGTH_SHORT).show()
        }

    }

}

ボタンクリックイベント内にToastを生成するためのコードを追加します。

・レイアウトのxmlファイルを作成
1.PNG

activiy_toast.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ToastActivity"
    android:gravity="center">

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/text_et"
        android:inputType="text"
        android:hint="テキストを入力してください。"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/toast_btn"
        android:text="ボタン"/>

</LinearLayout>

アプリ起動

こんにちはというテキストを入力し、ボタンをクリックした場合

DreamHanksというテキストを入力し、ボタンをクリックした場合

終わりに

今回はToastという通知メッセージについて説明しました。

次回はCircleImageViewという外部ライブラリを使用してみます。
12. 【Android/Kotlin】丸いイメージ(CircleImageView)

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

Android: YouTube Android Player API

  • Android Studio 4.0.1
  • Kotlin 1.4.0
  • YouTube Android Player API 1.2.2

YouTube Android Player APIを使って、AndroidアプリでYoutubeを再生させます。

Android Studioでプロジェクト作成

アプリの登録

Google APIsでAPIキーを作成し、Androidのプロジェクトと関連付けます。

Android Studioでプロジェクト作成

プロジェクトを作成し、パッケージ名を決めます。

アプリのフィンガープリント取得

SHA-1のフィンガープリント取得方法

  • AndroidStudioで、Gradleタブの「app/Tasks/android/signingReport」をダブルクリック
  • Runコンソールに出力される

Googleプロジェクト作成

https://console.developers.google.com/cloud-resource-manager

既存のプロジェクトを利用してもいいかもしれませんが、作成します。
リソースの管理から、プロジェクト作成

APIキー作成

https://console.developers.google.com/apis/credentials

作成したプロジェクトで
「+認証情報を作成」 → 「APIキー」 → 「閉じる」

アプリと関連付け

作成されたAPIキーを選択
APIキーの名前をAPIキー1から、適当に変更

Android アプリに使用を限定、のメニューから
「項目を追加」パッケージ名とSHA-1のフィンガープリントを設定

ライブラリのダウンロードとセットアップ

ライブラリのダウンロード

https://developers.google.com/youtube/android/player/downloads

Androidプロジェクトに登録

  • ダウンロードしたzipファイルからjarファイルをコピー
    libs/YouTubeAndroidPlayerApi.jar
    → [Project Folder]/app/libs

  • AndroidStudioで、Porject/app/libs/YouTubeAndroidPlayerApi.jarを
    右クリック「 Add As Library...」→ appを選択

アプリ実装

パーミッション設定

AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />

回転制御

AndroidManifest.xml
<activity android:name=".MainActivity"
          android:configChanges="orientation|screenSize|keyboardHidden">

レイアウトXML編集

  • Designに切り替え、Containers/をレイアウトにドロップすると、Viewクラスの選択ダイアログが表示される
  • YouTubePlayerView(com.google.android.youtube.player)を選択
  • ViewにIDを付ける(今回はyoutubeView)

※YoutubePlayerViewにボタンなどが重なっていると、再生が途中で止まってしまいました。

Activity実装

YouTubeBaseActivityを継承

MainActivity
class MainActivity : YouTubeBaseActivity() {

    val API_KEY = "[API_KEY]"

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

        val playerView = findViewById<YouTubePlayerView>(R.id.youtubeView)
        val listener = object: YouTubePlayer.OnInitializedListener {
            override fun onInitializationSuccess(provider: YouTubePlayer.Provider?, player: YouTubePlayer?, wasRestored: Boolean) {
                player?.loadVideo("[YoutubeのVideoID]")
            }

            override fun onInitializationFailure(provider: YouTubePlayer.Provider?, result: YouTubeInitializationResult?) {
            }
        }
        playerView.initialize(API_KEY, listener)
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dagger Hiltを踏まえたテストのプラクティス

Dagger HiltというGoogleがAndroid開発において推奨するDIライブラリ(JVM言語であれば使える)のこちらのドキュメントについてです。
https://dagger.dev/hilt/testing-philosophy
結構良いテストについて個人的に刺さる概念があったので、書いておきます。
またシンプルな部分以外のHiltの良いところが分かる気がします。


Dagger Hiltを踏まえたテストのプラクティスについて書かれている。
Dagger HiltのAPIや機能は何が良いテストを作るかの暗黙の哲学に基づいて作られている。ただ、良いテストというのが万人に受け入れられているわけではいので、Hiltチームにおいてのテストの哲学を明らかにするためのドキュメントとなる。

何をテストするのか

Hiltは外部の"ユーザーからの観点でテストする"ことを推奨する。外部のユーザーとはたくさんの意味がある。本当のユーザーも指すし、クラスやAPIの利用者も指す。
大切なところは"実装の詳細を表現してはいけない"ということ。内部の実装に依存したテスト、例えば内部のメソッドに依存したテストを書くとテストが壊れやすくなる。internalなメソッドの名前が変わっても、良いテストは何も変更する必要がない。今のテストを壊す要因はユーザーに見える変更があったときのみになる。

実際の依存関係を利用する

Hiltのテストの哲学はすべてのクラスがそれぞれテストを書くことを強制しない。実際にはそのようなルールは"ユーザーからの観点でテストする"という原則に違反する。テストは書きやすく、実行しやすくするために、必要なだけ小さくする。(高速、リソースを大量に消費しないなど)
他に違いがないのであれば、テストは以下のことを、この順番で優先する

  • 依存関係の実際のコードを利用する
  • ライブラリが提供する標準のFakeを利用する
  • 最後の手段としてMockを利用する

しかし、これにはトレードオフがある。

  • テストに置いての本物の依存関係をインスタンス化するセットアップはボイラープレートになりやすく、繰り返しになりやすい。
  • バックエンドのサーバーを立ち上げる必要があるなど、パフォーマンスのトレードオフが存在する。

Hiltは最初の問題を解決する。(詳細は以下)パフォーマンスについては問題になることはあるが、ほとんどの場合では問題にならない。I/Oで依存関係がある場合のみ問題になる可能性がある。パフォーマンスを大幅に低下させることなく、実際の依存関係を利用して便利かつ堅牢に利用できる場合は、実際の依存関係を利用する必要がある。これによってテストで大きな悪い影響がある場合は、Hiltはそのバインディングを交換する方法を提供する。

より多くの実際の依存関係を使うことの大きなアドバンテージ

  • 実際の依存関係は本当の問題を補足しやすい。モックのように古いまま残されたりしない。
  • "ユーザーからの観点でテスト"と組み合わせることで、同じカバレッジでもっと少ないテストの量で書くことができる。
  • テストが壊れることが、FakeやMockの設定ミスによる問題による問題の代わりに、実際の問題を指し示す (そして、逆に言えばテストがパスすることはコードがちゃんと動くことを意味する)
  • "ユーザーからの観点でテスト"と"実際の依存関係を使う"は相性が良い。依存関係を入れ替えないため。

もし本当の依存関係が使えないのであれば、次にライブラリが提供する標準のFakeを使う。ライブラリの作者や堅牢なカバレッジで提供されることによってメンテされているのであれば、標準のFakeはMockより良い。これらの理由によりMockは最終手段となる。

HiltとDI、そしてTest

これらの基礎によって、"HiltとDI、そしてTest"に入る。"実際の依存関係を使う"についてのDagger Hiltの答えはTestでDI/Daggerを使うことである。これはもっと実際に近い、なぜならプロダクションで行われるようにオブジェクトが作られるため。これはテストがプロダクションコードより壊れにくいことを意味し、実際のオブジェクトを使いやすくする。実際、@Injectのコンストラクタがある場合は、Mockを作って入れるより、Daggerを使うほうが簡単で少ないコードにできる。

残念なことにHiltを利用しないでこのようなテストを行うことは、ボイラープレートとDaggerの設定の作業により、これまでは困難だった。しかしHiltはボイラープレートコードを生成し、FakeやMockが必要なときにテストに違った設定をセットアップできる。Hiltを使えばこの問題はDaggerでテストを作成することの妨げにならず、実際の依存関係を簡単に利用できる。

実際にどうやってHiltがTestで依存関係を置き換えるかはこちらに書いてあります。 https://qiita.com/takahirom/items/3231edf2a430569b3e9d#testing

他の解決策の欠点

ユニットテストでDaggerを使わない方法はとてもよくある方法である。これは残念なことに大きな欠点があるが、HiltなしでDaggerを利用することの難しさを考えると理解できる。
例えば、Fooクラスをテストしようとする。

class Foo @Inject constructor(bar: Bar) {
}

このケースでDaggerを使わない場合は単にコンストラクタを呼び出すだけ。一見これはとてもシンプルで理解できる、しかしFooのコンストラクタにBarを適応し始めると崩壊し始める。

テストでの直接のインスタンス化はMockを使うことを促進する

以前話した"実際の依存関係を使う"によって、本物のBarクラスをできるだけ使うべき。しかし、どのようにすれば良いだろうか?テストでFooクラスをテストで使うには、これは実際は再起になる: 自分でインスタンス化する必要があるので、Barもインスタンス化する必要があり、Barに依存関係を持っている場合、同様にそれらをインスタンス化する必要がある。深くなりすぎないようにするために、テストのスピードやパフォーマンスのためではなく、たくさんの壊れやすいボイラープレートコードはメンテナンスの問題を起こすため、FakeやMockを使い始める必要がある。これはFakeやMockを使い始めるには良い理由ではない。そして今これをすることを余儀なくされている。
以前に議論したように標準のFakeを利用する方法では、直接のインスタンス化をするメンテナンスの負荷を減らすことができる。しかし、必ずしもシンプルではない。(省略: 同様にFakeBarがClockに依存して、、などFakeも依存関係を管理しなくてはいけなくなる。)

これは通常、開発者をMockを使うことを促進する。Mockは依存関係のチェーンによる問題を解決するが、静かに古いままのこされ残されたり、実際のバグを見つけるという全体的な目的でテストを役立たなくするという重大な欠点がある。テスト作成者以外は誰もMockの動作チェックをしないため、時間が経過するとテストが有用なシナリオをテストしなくなる可能性がかなりある。

テストでの直接のインスタンス化は実装の詳細を表現する

直接のインスタンス化は"実装の詳細を表現してはいけない"というプラクティスを破る。なぜなら、その依存関係の詳細のコンストラクタを呼ぶため。Barが@Inject construcotrがついている場合、Fooが実装の詳細をリファクタしたりする場合があるので、Barに依存することを知る必要はない。
この点について説明すると、Foo(Bar, Baz)のようにFooがBarやBazといった依存関係を持っていたときに、Daggerではこのパラメーターの順番を変えても何も起こらない。しかし、直接インスタンス化していた場合はテストを変更する必要がある。同様に新しい@Injectクラスやオプショナルバインディングを追加する場合もプロダクションでは変更する必要がないが、テストでは変更が必要になる。

まとめ

Hiltは実際の依存関係を使って簡単にテストを書くために、DaggerをテストでHiltを使うデメリットを治すように設計されている。Hiltを使ったテストはこれらの哲学に従う場合、全般的に良い体験になる。

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

【Android】Android 11から始めるWireless Debugging

Wireless Debugging

Android11からadbを介したワイヤレスでのアプリのデプロイデバッグが可能になりました。
そのためUSB接続の必要がなくなりリモートで複数のデバイスにアプリにデプロイがしやすくなりました。

wireless-adb.png

設定方法

  1. AndroidStudioにSDK Platform-Toolsの最新版をインストールする(※30.0.4では確認済み)
  2. デバッグで利用する端末でDeveloper OptionsをONにする
  3. Wireless debuggingをONにする
  4. 表示されるダイアログ内の許可を選択する
  5. Pair device with pairing codeを選択する
  6. 表示されるIPアドレス、Port番号、PairCodeを覚えておく(※下記サンプル)
    wireless-adb.png

  7. terminalにて[sdk location]/platform-tools へ移動する(※sdk locationはAndroid StudioのProject Structure等で参照)

  8. 以下を実行(IP:Portは手順6で覚えた値を代入しその後PairCodeを入力)

~/Library/Android/sdk/platform-tools $ adb pair IP:Port
Enter pairing code:

以下が表示されれば成功

Successfully paired to 192.168.1.130:37099 [guid=adb-235XY]

参考資料

https://developer.android.com/about/versions/11/features#wireless-adb

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