Tweakr: Firebase と Android を使用した Wizard of Oz 型のプロトタイピングとリモート コントロール

1. はじめに

最終更新日: 2022 年 3 月 30 日

リモートでのデバッグ、設定 UI の自動生成、Wizard-of-Oz 型のプロトタイピングのためのライブラリ

アニメーションで 1 つの値を微調整してから、コンパイルして変更を確認するまでに数分かかることにうんざりしていませんか?プロトタイプを誰かに渡した後、各種オプションをオンザフライで調整して、その人にさまざまなプロトタイプを試してもらいたいと思ったことはありませんか?「1 行のソリューション」という言葉にワクワクしませんか?それならば、Tweakr の出番かもしません!

Tweakr は、コード内のフィールドやメソッドにアノテーションを付け、ローカルまたはリモートでその要素を変更するための UI を自動生成する Android ライブラリです。Firebase とウェブベースの UI を使用して、アプリ内の値や設定の変更をオンザフライで即座に実行できます。また、スマートフォンのローカルの SharedPreferences を使用して設定 UI 画面を自動生成することも可能です。

文字通り、書かなければならないコードは 1 行だけです。変更したいものに @Tweak のアノテーションを付けるだけで、残りのすべては Tweakr が処理します!

c407af6de21474.gif

作成するアプリの概要

この Codelab では、以下の機能を持つシンプルな Android アプリを作成します。

  • 画面にテキストや画像を描画する。
  • アプリのフィールドやメソッドに @Tweakr のアノテーションを付ける。
  • Firebase を使用して Tweakr ウェブ UI に接続する(ウェブ UI は構築済みですぐに使用できます)。
  • Tweakr を使用して表示を操作し、画面上で表示を動かす。

学習内容

  • Android アプリ用の Firebase を設定する方法。
  • アプリ内のフィールドとメソッドにアノテーションを付けて、Tweakr がそのフィールドやメソッドの制御用 UI を生成できるようにするための方法。

この Codelab では、Tweakr ライブラリの使用を中心に説明します。関連のない概念とコードブロックについては軽く触れるにとどめ、そのままコピーして貼り付けられるようにしています。

必要なもの

  • Android Studio がインストールされているパソコン
  • Kotlin と Android ビューに関する基本的な知識

2. Firebase プロジェクトを作成して設定する

Tweakr は、Firebase を使用して Android アプリを自動的にウェブ UI に接続する UI を作成します。まず、Android 用の Firebase プロジェクトを設定します。

Firebase プロジェクトを作成する

  1. Firebase にログインします。
  2. Firebase コンソールで [プロジェクトを追加](または [プロジェクトを作成])をクリックし、Firebase プロジェクトに Tweakr-Codelab という名前を付けます。cd5d93d8733c5730.png
  3. プロジェクト作成オプションをクリックします。プロンプトが表示されたら、Firebase の利用規約に同意します。このアプリではアナリティクスを使用しないため、Google アナリティクスの設定はスキップします。

Firebase プロジェクトの詳細については、Firebase プロジェクトについて理解するをご覧ください。

Firebase で Android アプリを設定する

  1. Firebase コンソールで、独自のパッケージ名を使用して新しい Android アプリを追加します(例: com.[your-domain].tweakr.sample))。パッケージ名やデバッグキーなどのフィールド。アプリ登録ボタン
  2. 手順に沿って、google-services.json ファイルをダウンロードします。
  3. google-services.json ファイルを Android アプリの app モジュール ディレクトリにコピーします(例: tweakr-codelab/app/
  4. Firebase への接続の確認をスキップします。この操作は、Android アプリで applicationId を更新した後に行います。
  5. 手順に沿って [Gradle 同期] をクリックします。

コンソールで Firebase プロダクトを有効にする

これから構築するアプリでは、ウェブアプリに使用できるいくつかの Firebase プロダクトを使用します。

  • ユーザーがアプリに簡単にログインできるようにするための Firebase Authentication と Firebase UI。
  • Tweakr がアプリとウェブ UI 間でデータを瞬時に同期するための Realtime Database。
  • データベースを保護するための Firebase セキュリティ ルール。

この中には、特別な設定が必要になるプロダクトや、Firebase コンソールを使用して有効化する必要があるプロダクトがあります。

Firebase Authentication 用に匿名ログインを有効にする

この Codelab では、ユーザーがウェブアプリにログインできるようにするために、匿名ログインを使用します。

  1. Firebase コンソールの左側のパネルにある [構築] で [Authentication] をクリックします。
  2. [Authentication] をクリックし、[開始] -> [Sign-in method] タブをクリックするか、ここをクリックして [Sign-in method] タブに直接移動します。
  3. ログイン プロバイダのリストで [匿名] をクリックし、[有効にする] スイッチをオンの位置に設定して、[保存] をクリックします。d7a9ec05ba37f407.png

Realtime Database を有効にする

Tweakr は Realtime Database を使用して、アプリとウェブ UI との間で状態を 1 秒の間に何度も同期します。

Realtime Database を有効にします。

  1. Firebase コンソールの [構築] セクションで [Realtime Database] をクリックします。
  2. [データベースを作成] をクリックします。21491f6ad60c0f3.png
  3. データベースの場所を選択します(デフォルトをそのまま使用することもできます)。この場所を後から変更することはできません。32f815f4648c3174.png
  4. [テストモードで開始する] オプションを選択します。これで、開発中にデータベースに自由に書き込めるようになります。セキュリティ ルールに関する免責条項を確認し、[次へ] をクリックします。acfcf535bff30f47.png
  1. [有効にする] をクリックします。

3. Android サンプルアプリを構築する

コードを取得する

このプロジェクトで必要となるすべてのものは Git リポジトリに用意されています。まず、コードを取得してそのコードを Android Studio で開く必要があります。

強く推奨: Android Studio を使用してリポジトリをインポートする

  1. Android Studio を開き、[Version Control] で [File] -> [New] -> [Project] を選択します。
  2. バージョン管理のオプションとして Git を選択します。
  3. URL https://github.com/google/tweakr-codelab.git を入力します。
  4. [Clone] をクリックします。

ApplicationId を更新する

Android アプリ用の一意の ApplicationId が Firebase で必要になるため、サンプルの名前を独自の ApplicationId に変更する必要があります。

  1. Tweakr_codelab.app モジュールの app/build.gradle ファイルを開きます。
  2. applicationId "com.yourdomain.tweakr.sample" の行を、Firebase の設定で指定したパッケージ名に変更します。
  3. [Sync] をクリックして変更を Gradle ファイルに同期します。

アプリを実行する

  1. [Run] をクリックして、そのままの状態でアプリをコンパイルして起動します。Android エミュレータを使用している場合は、Google Play ライブラリから Firebase で必要となる AVD イメージを作成します。

6f6d2c9539143a5a.png

アプリ上で、テキストと円を含むシンプルな画面が表示されます。

  1. テキストをクリックしてアニメーションをトリガーします。

4. 微調整をしてみましょう!

このセクションを終了すると、Tweakr ウェブサイトからアプリのビューをリモートで制御できるようになります。

Tweakr ライブラリの依存関係を追加する

  1. settings.gradle ファイルを開き、リポジトリに Jitpack を追加します。

settings.gradle

dependencyResolutionManagement {
   repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
   repositories {
       google()
       mavenCentral()
       maven { url 'https://jitpack.io' }
   }
}
  1. Tweakr_codelab.app モジュールの app/build.gradle ファイルを開き、Tweakr ライブラリの依存関係を追加します。

app/build.gradle

dependencies {

...

   // Required for local SharedPreferences or Firebase
   implementation 'com.github.google.tweakr:core:2.2.2'

   // Include this if you want Firebase support.
   implementation 'com.github.google.tweakr:firebase:2.2.2'
}
  1. [Sync Now] をクリックして Gradle の変更を同期します。

Tweakr リポジトリを初期化する

まず、SampleApplication の onCreate() メソッドで Tweakr リポジトリを初期化して、Firebase を使用することをリポジトリが把握するようにします。

  1. SampleApplication.kt ファイルを開きます。
  2. Tweakr.setRepo(TweakrFirebaseRepo()) というように書かれた行のコメント化を解除します。

これは、TweakrFirebaseRepo を使用して値をクラウドに同期するよう Tweakr に指示します。TweakrFirebaseRepo は、デフォルトの Firebase インスタンスを自動的に使用します。このインスタンスは、前のセクションで追加した google-services.json ファイルによって定義されています。

微調整を行う

アプリの一部にアノテーションを追加して、Tweakr でそれに対応するウェブ UI を作成できるようになりました。

  1. MainActivity.kt ファイルの fun animateText() 行の上に、アノテーション @Tweak を追加します。これで、このメソッドをリモートで制御することが Tweakr に伝わります。

MainActivity.kt

@Tweak
fun animateText() {
 introText.animate()
...
}
  1. onCreate() 関数の下部に、Tweakr.register(this) の行を追加します。これは、クラス内のすべてのアノテーションを解析し、その値をウェブサーバーと同期するように Tweakr に指示します。

MainActivity.kt

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

 introText = findViewById(R.id.text)
 introText.setOnClickListener { animateText() }

 Tweakr.register(this)
}
  1. アプリをもう一度実行します。

問題がなければ、Tweakr がバックグラウンドで初期化され、Tweak が Firebase サーバーと同期されます。次のセクションでは、ここまでに作成した魔法のような動作を確認していきます。

5. ウェブ UI で値を調整する

アプリで微調整できる値の設定が完了したので、Tweakr ウェブ UI を開いて、インターネット経由でリモートでその値を制御できるようになりました。アプリの値の微調整を開始する最も簡単な方法は、Tweakr の構築済みウェブサイト、Easyserver を使用する方法です。このウェブサイトは GitHub でホストされており、Firebase データベースに接続して値を同期し、Android アプリからウェブ UI を生成します。

Firebase でウェブアプリを設定する

まず、Firebase でウェブアプリを設定し、Easyserver にそのウェブアプリへのアクセス権を付与する必要があります。

  1. Firebase コンソールで [プロジェクトの概要] をクリックします。
  2. [アプリを追加] をクリックし、[ウェブ] を選択します。82b936ff2bbbbbac.png
  3. ニックネームを入力し、[登録] をクリックします。
  4. [Firebase SDK の追加] のステップで、const firebaseConfig 以降をすべてコピーします。次のステップで、Tweakr Easyserver にコピーした内容を貼り付けます。c4f2e17447f8442c.png

Easyserver を起動する

  1. https://google.github.io/tweakr/easyserver/ に移動し、手順に沿って Easyserver による Firebase へのアクセスを許可します。
  2. 前の手順でコピーした firebaseConfig コードを貼り付けます。

e8a19d25f923a76f.png

正しく貼り付けられている場合は、一意のログインリンクと [Let's get Tweakin'] ボタンが表示されます。

  1. [Let's get Tweakin'] をクリックします。

先ほどアノテーションを付けた関数にちなんだ名前の animateText() ボタンが表示されます。

7e916285f11317d4.png

ボタンを押す

Android アプリを開いた状態で、Tweakr ウェブ UI の [animateText()] ボタンをクリックして、スマートフォンの画面を確認します。

f238f06c1cf5583e.gif

魔法のようですね。テキストのアニメーションが実行されます。どうしてこうなるのでしょうか?

これはパラメータを持たないメソッドの話ですが、メソッドがパラメータを取得する場合はどうなるのかと、疑問に思ったことでしょう。次のセクションで確認しましょう。

6. パラメータを持つメソッド

Tweakr は、パラメータが 1 つのメソッドでも動作します(2 つ以上のパラメータを持つメソッドはまだサポートされていません)。やってみましょう。

  1. MainActivity クラスで、TextView のテキストを変更する新しいメソッドを追加します。

MainActivity.kt

class MainActivity : Activity() {
...

 @Tweak
 fun setMessage(text: String) {
   introText.text = text
 }

...
  1. 必ず新しいメソッドに @Tweak アノテーションを追加してください。
  2. アプリを再度実行します。Tweakr Easyserver ウェブサイトが自動的に更新されてメソッドを呼び出すためのテキスト フィールドが表示されるのを確認します。
  3. テキスト フィールドに何かしらの入力を行うと、アプリのアップデートがリアルタイムで表示されます!

322a56390bd5fe31.gif

メソッドをリモートで制御できることも素晴らしいですが、Tweakr の真の強みは、コード内のフィールドの値を変更できることです。次のセクションで、さらに面白いものを見てみましょう。

7. (省略可)フィールド値を調整する

Android Studio で CircleView.kt ファイルを開きます。上部に、円のサイズと位置を調整するためのフィールドがあるようです。微調整してみましょう!

アノテーションを追加する

  1. centerX, centerY フィールドと radius フィールドの上に @Tweak アノテーションを追加します。
  2. また、オブジェクトの初期化時に Tweakr.register() を呼び出す必要があるため、init() メソッドも追加します。最終的に、コードは次のようになります。

CircleView.kt

/** A View that draws a circle **/
class CircleView @JvmOverloads constructor(
 context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

 @Tweak
 var centerX = 180f

 @Tweak
 var centerY = 180f

 @Tweak
 var radius = 50f

 init {
  Tweakr.register(this)
 }

...

これで Tweakr でフィールドを変更できるようになりましたが、まだ完了ではありません。これは、描画キャンバスに直接描画を行うカスタムビューであるため、Tweakr がフィールドの値を変更しても、ビューが自動的に新しい値で再描画することはありません。Tweakr で変更が同期されるたびに、再描画するようにビューに指示する必要があります。

  1. フィールドの値がリモートで変更されるたびに通知が届くように、Tweakr にリスナーを追加します。

メモリリークを回避するには、ビューがリスナーを使用していないときに、attachedToWindow イベントを使用してリスナーを削除する必要もあります。

Tweakr の値の変更をリッスンする

onAttachedToWindow() メソッドを Tweakr.addListener(this) の呼び出しでオーバーライドしてから、onDetachedFromWindow() のリスナーを削除します。

CircleView.kt

/** A View that draws a circle **/
class CircleView @JvmOverloads constructor(
 context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr), TweakrRepo.OnChangeListener
 {

...

  override fun onAttachedToWindow() {
   super.onAttachedToWindow()

   // Register onFieldChanged() to redraw when any value changes.
   Tweakr.addListener(this)
  }

  override fun onDetachedFromWindow() {
   Tweakr.removeListener(this)

   super.onDetachedFromWindow()
  }

  override fun onFieldChanged(name: String?, value: Any?) {
   // This is called whenever a field's value is changed in Tweakr's UI.
   // We could be granular here and check the name to match only the fields
   // we care about, but for this demo it's simple enough to just redraw
   // whenever *any* value changes.
   invalidate()
  }

...

this をリスナーとして設定しているため、クラスが TweakrRepo.OnChangeListener インターフェースを拡張 / 実装していることを確認する必要もあります。)

試してみる

これで、実際に試せるようになりました。アプリを実行し、Tweakr Easyserver ウェブサイトが微調整する新しいフィールドで自動的に更新されることを確認します。

80e03628ec47917c.gif

8. おわりに

おつかれさまです。これで、Tweakr を使用する最初のアプリを構築できました。

メソッドとフィールドに @Tweak アノテーションを付ける方法、そのフィールドを含むオブジェクトで Tweakr.register() を呼び出す方法、より高度な使用法で Tweakr の変更イベントをリッスンして、ビューを手動で再描画できるようにする方法を学びました。

アニメーション値のオンザフライでの変更、UX 調査時やユーザー調査時の wizard-of-oz 型プロトタイプのリモートでの制御など、プロトタイピング ワークフローを高速化できるいくつかのスキルを活用できるようになったはずです。Google がチームで行っている一般的な用途は、モーション プロトタイプ APK をモーション デザイナーと共有して、彼らに Tweakr ウェブ UI のリンクを送信し、アニメーションの値を好きなように微調整してもらうというやり方です。(モーション デザイナーは、アニメーションの値を正確にすることが好きなようですね!)

また Google のチームは、マイクロインタラクション、ジェスチャー、ハプティックスのプロトタイプを作成して、Tweakr リンクをチームと共有し、切り替え可能な、デザインのさまざまな設定やオプションを確認できるようにしています。その後に共有ドキュメントを作成し、ユーザーが好きな Tweakr 値を入力できるようにしています。この方法は、デザインを本番環境に実装する前にコンセンサスを得るのに役立っています。

次のステップ

その他のヒント

  • Wizard-of-oz 型のリモート コントロール: アプリの画面名の列挙型を取得するメソッドをアクティビティで作成します。Tweakr がこのメソッドを呼び出す際、画面名に対応する新しいフラグメントを読み込みます。これにより、Tweakr ウェブ UI で目的の画面をクリックするだけで、スマートフォンでアプリを表示しているすべてのユーザーに新しいフラグメントが表示されるようになります。ユーザー調査に最適です!
  • 複数のユーザー: Tweakr ウェブ UI はデフォルトで、アプリを使用するすべてのユーザーに同時に変更を同期します。ただし、複数のユーザーが同時にアクセスする場合は、各ユーザーが各自のセッションを持つことが必要な場合があります。この場合、UI で行った調整はそのユーザーのスマートフォンのみに影響し、他のユーザーには影響しません。getUserKey(). を使用した複数のセッションの作成方法については、TweakrFirebaseRepoMultiuser のドキュメントをご覧ください。
  • ローカルの PreferenceScreen: Tweakr では、必ず Firebase を使用しなければならないという訳ではありません。Android の設定 UI を自動生成することもできるため、スマートフォンでローカルに設定を変更できます。サンプルコードドキュメントをご覧ください。