CamTwistを使ってAndroidEmulatorのカメラソースをPC画面にする

バーコード読み取り機能を作る場合などにいちいち実機でバーコードをスキャンするのが面倒臭かったのでなんとかPCに表示した画像をエミュレータのカメラソースにできないか調べてみました

CamTwist

CamTwistニコニコ生放送やTwitchなどで配信する時に、Webカメラの映像ではなく、PC画面を映像のソースとして配信するためのソフトです。エミュレータではWebカメラや内臓カメラをソースとして使えますが、同じようにCamTwistの映像も使うことができます

以下の方法はCamTwist以外にも同じ機能をもったソフトであれば有効だと思います

設定方法

CamTwist

CamTwistをダウンロードページからダウンロードしてインストールします

CamTwistの設定は、以下のようにします

  • Desktop (範囲は任意)
  • Rotation Translation(任意)
  • Zoom(任意)

f:id:scache:20170927010204p:plain:w400

エミュレータで表示した時に画像が回転した状態で表示されていたらRotationを設定してみてください

AVD

  1. エミュレータの設定画面からShow Advanced Settingsを押す
  2. Cameraの設定をwebcam0にする
  3. 設定を保存

f:id:scache:20170927010812p:plain:w400

f:id:scache:20170927014603p:plain:w200

以上で設定は終了です

エミュレータ起動

エミュレータでカメラアプリを起動して確認してみます

以下のようにCamTwistで指定した範囲の映像が表示されていればOKです

f:id:scache:20170927012641p:plain:w300

おまけ webcam0について

Macではもともと内臓カメラがついている端末がほとんどだと思いますが、エミュレータの設定では内臓カメラやCamTwistなどの映像ソースが複数ある場合でもwebcam0しか選択することができません(AndroidStudioのエミュレータ設定ではカメラがあろうがなかろうがNone, Emulated, Webcam0の3つのみ選択できるようになっているようです)。

そのため、環境によっては内臓カメラの映像が自動的に選択されてしまうかもしれません。

emulatorコマンド Commonly used optionsを見た限りではemulatorコマンドからエミュレータを起動する際にどの映像ソースを使うかを選択できそうですが、カメラ一覧を取得してもwebcam0しか表示されず任意の映像ソースを選択する方法はわかりませんでした。

FCMを使ってAndroid端末へ通知を送るスクリプト

Firebase Cloud Messaging(FCM)を使ってAndroid端末へ通知を送るスクリプトを作りました(iOSは非対応です)
スクリプト内で送られているデータはcurlを使う場合を参照してください

作成したスクリプト

ソースコードhttps://github.com/sckm/fcm-send にあがっています

インストー

あらかじめgoがインストールされている必要があります

$ go get github.com/sckm/fcm-send

使い方

以下のように、はじめにjsonのdataキーで送りたい内容をファイルに書いておきます

{
    "message": "Hello World!",
    "title": "example title"
}

その後、以下のコマンドを実行することで通知が送られます

$ token='registration token'
$ server_key='your server key'
$ fcm-send -t $token -s $server_key -p data.json

curlを使う場合

作成したスクリプトは以下のcurlコマンドと同等のリクエストを送っています

token='registration token'
server_key='your server key'
msg='{"message":"Hello World!", "title": "example title"}'

curl \
    --header "Authorization: key=${server_key}" \
    --header Content-Type:"application/json" \
    https://fcm.googleapis.com/fcm/send \
    -d "{ 
        \"to\" : \"${token}\", 
        \"data\": $msg
    }"

FirebaseCrashReportingにmappingファイルをあげるスクリプトを作った

FirebaseCrashReportingにAndroidマッピングファイルをあげる際に相対パスが使えなかったり、google-services.jsonがapp直下にない時にAppIdなどを指定するのが面倒くさかったのでgolangスクリプトを作ってみました

ソースコードhttps://github.com/sckm/fcr-upload-mapping

動作環境

インストー

go get github.com/sckm/fcr-upload-mapping

使い方

cd [Androidプロジェクトのルートパス]
fcr-upload-mapping \
    -a [サービスアカウントキーファイルのパス] \
    -c [アプリバージョンコード] \
    -p [パッケージ名] \
    -m [マッピングファイルのパス] \
    -s [google-services.jsonのパス]

google-services.jsonがapp直下にある場合は省略可能です

その他

今はgradlewがあるディレクトリでしか動かないようになっていたり、引数の説明が足りないので修正したい
Golangに慣れていないのでコードが汚い・・・

RxJava2のSingle.zipのエラー処理ではまった話

問題

RxJavaでたまにonErrorReturnItemなどでエラー処理をしていてもたまにエラーがすり抜けてきてアプリが落ちてしまうことがあった
問題となっていそうな部分を簡単に表すと以下のようになっていた

Single.zip(
  Single
  Single
)
.onErrorReturnItem

対処方法

RxJavaのissuesを調べてみると同じ問題があった
Rx2: Multiple errors in zip'ed observables throw exception

ここに書いてある対処方法は、

  • RxJavaPlugins.setErrorHandler()でエラーハンドラーを設定する(issueのコメントではsetOnErrorになっているが名前が変更になった?)
  • zipの中のSingleでonErrorReturnonErrorResumeNextなどを呼び出す

いっけん良さそうに見えるので原因がわかりづらくてはまってしまった
実際にはどうしてそうなってしまうのかまだわかっていないのでRxJavaの実装を読んでいきたい

文字列リソースに複数の値を渡す

基本的な方法

複数の値を渡す際には%1$s%2$sなどを設定する。
1や2で何番目の引数を使うかを指定する

<string name="string_res1">1番目%1$s 2番目%2$s"</string>
getString(R.string.string_res1, "A", "B")

結果: 1番目A 2番目B

渡した値の一部を使わない場合

引数で複数の値を渡すが文字列リソースで使わない場合の挙動

<string name="string_res2">2番目のみ%2$s"</string>
getString(R.string.string_res2, "A", "B")

結果: 2番目のみB

特に問題なく文字列が取得できる

必要以上に値を渡した場合

1番目の引数のみ使う文字列リソースに2つの値を渡した場合

<string name="string_res3">1番目%1$s"</string>
getString(R.string.string_res3, "A", "B")

結果: 1番目A

実行時には問題なく文字列が取得できる
ただしlintでの警告がでる
values-ja/strings.xmlを作成して日本語の場合に2つの値を使うようにしても警告がでた

DataBindingでincludeしたレイアウトに値を渡す メモ

AndroidのDataBindingでincludeしたレイアウトに値を渡す時に少し悩んだのでメモ

参考: Data Binding Library

変数の渡し方法

includeされるファイルが以下のような時

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:bind="http://schemas.android.com/apk/res-auto">
   <data>
       <variable name="user1" type="com.example.User"/>
   </data>
   <merge>
       <include layout="@layout/name"
           bind:user="@{user1}"/>
       <include layout="@layout/contact"
           bind:user="@{user1}"/>
   </merge>
</layout>

includeする側のレイアウトではbind:hoge属性を使って変数を渡すことができる
hogeの部分にはlayoutで指定したファイル内の変数名を指定する(今回の場合はuser1)

<data>
    <variable name="user2" type="com.example.User"/>
</data>
<LinearLayout ...>
    <include layout="@layout/name"
        bind:user1="@{user2}"/
</LinearLayout>

参考にした公式サイトの情報ではbind:user="@{user}"となっていてすこしわかりづらいですね・・・

リソースファイルの値を渡す方法

もし、includeするlayoutにリソースファイルの値を渡したい時の例

例: Stringの値を受け取ることができるレイアウトファイル
"@{@string/app_name}"のように指定すると良い

<data>
    <variable name="title" type="String"/>
</data>
 <include
     layout="@layout/layout_text"
     bind:title="@{@string/app_name}"
     />

Backgroundに設定した画像を拡大させない方法

AndroidのViewのbackgroundに画像を設定した場合にViewのサイズに合わせて画像も拡大されます
通常は特に問題ないのですがどうしても画像を拡大させたくない場合がある時の対処方法を紹介します

今回は24x24dpの以下のような画像を使いました (AndroidStudioのImageAssetで作りました)

ic_weekend.png

画像サイズを維持するDrawableを作成する

以下のようなDrawableファイルを使うことで画像サイズを維持するDrawableを作成することが可能になります

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center"
    android:src="@drawable/ic_weekend"/>

最低限必要なのはsrcのみで表示したい画像を設定します
gravityを設定することで表示位置を変更できます

実際の表示

以下のようなレイアウトを設定して表示を確認してみます
48x48dpと12x12dpの2通り

<View
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:background="@drawable/ic_weekend"
    />

<View
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:background="@drawable/no_scale_ic_weekend"
    />
    
<View
    android:layout_width="12dp"
    android:layout_height="12dp"
    android:background="@drawable/ic_weekend"
    />

<View
    android:layout_width="12dp"
    android:layout_height="12dp"
    android:background="@drawable/no_scale_ic_weekend"
    />

Screen Shot 2016-12-19 at 11.57.01 PM.png

2,4番目が今回作った、サイズを維持するdrawableを表示した場合です
1番目は拡大されて表示していますが2番目では期待通り24x24dpの表示になっています

おまけですが12x12dpの場合も見てみました
ただの画像を表示した場合はサイズに合わせて縮小されていますが、今回つくってDrawableでは一部分のみしか表示されていませんでした

まとめ

固定画像のサイズをViewのBackgroundに設定する際にはbitmap要素のDrawableファイルを作成すると良いようです

画像サイズより大きいViewのbackgroundに画像を表示する場合は問題ないですが、
小さいViewに設定する際には一部分のみしか表示されないので注意する必要があります