0

Android WearのエミュレータをAndroid実機本体に接続する

Moto360へのapk書き込みが遅すぎるので、Wearはエミュレータで、本体はNexus5でやってみる事にした。


参考

Creating and Running a Wearable App | Android Developers
のSet up an Android Wear Virtual Device


Wearエミュレータの設定

Android Studioの[Tools]→[Android]→[AVD Manager]でWearのエミュレータを作る。ARMよりx86のイメージの方が速いらしい。

「About」からビルド番号を7回タップして開発者オプションを有効にし、ADB Debuggingを有効にする


この時点ではWearは親機とペアリングして無いので、Disconnectedになっている


Android実機の設定

Android実機がエミュレータと接続できるようにしておく。
AndroidStudioのTerminalで
% adb -d forward tcp:5601 tcp:5601

そして接続する。
Android実機でGoogle製のAndroid Wearアプリを起動し、普段使ってるMoto360へのペアリングを解除して、右上から「エミュレータをペア設定」で接続。


音声入力

マイクが無いのでキーボードで入力する。タイミングがすごい微妙で、
音声入力画面になる→2秒ぐらい待つ→「Didn’t catch that」と表示される→表示が消える→ここで素早く入力→enterとか押さずにしばらく待つ→するとなぜか入力できてる。

0

Android Wearからスマホ本体側にsendMessageでメッセージを送る

参考

Sending and Receiving Messages | Android Developers
これ読んであとは勘で書いたらWearable.MessageApi.sendMessageがなんとなく動いた。


Wearable.MessageApi.sendMessageの用途

Wearにはスマホ側の通知が全部表示されてそこからアクションも全部実行できるんだけど、スマホ通知からWearのActivityを起動したりはできない。スマホからWearのActivityとか呼びたい時は、sendMessageでWear内のWearableListenerServiceを実装したサービスと通信して、そこからWear内でIntent発行してもらってActivityを起こす。

Wear上のActivityからスマホに通信して何か処理してもらう時もsendMessageを使う。
WearにはWebブラウザが無いので、twitterクライアント作る時とか少なくとも認証はスマホにやってもらう必要がある。

sendMessageとは別にDataItemというWear/Handheld間の共有オブジェクトもあって、これは変更通知もくるのでこっちでやった方がいい用途もある


WearからHandheld(スマホ)へ送る場合の手順

  1. WearでGoogle API Client接続
  2. Wearable.NodeApiでHandheldのNodeIDを探す
  3. sendMessageにpath(と呼ばれてるけどタイトルみたいなもの)とdataを送信
  4. Handheld側でWearableListenerServiceを作っておけば受信できる


Wear側でGoogle API Clientを作って、接続しておく

onStartで接続してonStopで切るとかは、AndroidStudioで新規プロジェクト作成時のMobileのMainActivityをGoogle Play Service Activityにすると生成されるテンプレを参考にした。
メッセージ受診するだけのHandheld側にはGoogle API Clientを作る必要はない。


Node ID

Wearable.NodeApi.getConnectedNodesでHandheldのnodeIDを取得する。Nodeを判別できる要素はgetDisplayNameしかなくて親機を正確に判別できる気がしないし、ふつうHandheldとWearしか存在してないはずなので全員に送信するようにしてしまった。


WearからsendMessage

UIスレッドから呼べないのでAsyncTaskの中でやるとかする。

    public void sendTweetAsync(String tweet){
if(tweet == null) return;
Log.i(TAG, "send \""+tweet+"\" to handheld");
new AsyncTask<String, Void, String>() {
@Override
protected String doInBackground(String... params) {
String tweet = params[0];
byte[] bytes;
try {
bytes = tweet.getBytes("UTF-8");
}
catch(Exception ex){
Log.e(TAG, ex.getMessage());
return null;
}
for (Node node : Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await().getNodes()){
Log.v(TAG, "sending to node:" + node.getId());
Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), "/post/tweet", bytes)
.setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
@Override
public void onResult(MessageApi.SendMessageResult sendMessageResult) {
Log.v(TAG, sendMessageResult.toString());
}
});
}
return null;
}
}.execute(tweet);
}


HandheldにWearableListenerServiceを作って受信


受信側はService作ってintent filterにwearable.BIND_LISTENERを追加するとライフサイクルは適当に管理してくれる。自分でGoogle API Clientの接続管理する必要もない。
        <service android:name=".TweetService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>

public class TweetService extends WearableListenerService {

@Override
public void onMessageReceived(MessageEvent messageEvent) {
Log.v(TAG, "onMessageReceived");
if (messageEvent.getPath().equals(MESSAGE_PATH_TWEET)) {
String msg;
try {
msg = new String(messageEvent.getData(), "UTF-8");
}
catch (Exception ex){
Log.e(TAG, ex.getMessage());
return;
}
Log.i(TAG, "receive: "+ msg);
// ここで適当に処理
}
}


Activityで受信する場合はMessageListenerを実装すればいいらしい。

0

Vibration APIでモールス信号を聞く

navigator.vibrate(ミリ秒)というのがあったので、モールス信号を再生してみた。
モールス信号ってかっこいいから覚えようとした事が何度かあったけど、まったく覚えれなかった。これなら覚えれそうな気がする。

デモ

http://shokai.github.io/web-morse-vibration/

トンを100ミリ秒振動、ツーを300ミリ秒振動として実装してる

ソースコード

https://github.com/shokai/web-morse-vibration



とりあえずモールス信号のローマ字(A-Zまで)だけ対応してる。


Vibration APIとは

ブラウザで端末をバイブレーションできる。AndroidのChromeで動いた。

Vibration API – Web developer guide | MDN
ボンバーマンとか、ゲーム用にあれば便利じゃね、とのこと

使い方

navigator.vibrate(100); // 100ミリ秒振動
navigator.vibrate([100,200,300]); // 100ミリ秒振動、200ミリ秒停止、300ミリ秒振動

navigator.vibrate(0); // 全ての振動止める

Mac版Chromeにもnavigator.vibrateあって呼び出せるけど、もちろん振動しない。ウィンドウが揺れればいいのでは

0

Android Wearで音声入力からアプリ起動する

これ
Adding Voice Capabilities | Android Developers

「Start MyRunningApp」ってやつ全然起動しなくてよくわからなかったんだけど、解決した。


AndroidManifest.xml

こう書くのが正解。「ドア 開いて」とか言えばWearMainActivityが起動する。
<activity
android:name=".WearMainActivity"
android:label="ドア" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>


日本語

Android本体の言語設定が日本語の場合はWearの音声認識も日本語として認識しようとする。
android:labelに「door」とか書くと認識できず、「boa」とか「dooors」とか日本のgoogleで検索してそれなりにヒットする固有名詞になってしまう。おとなしく日本語で「ドア」と書かないと認識できない。

他のアプリでも、「twitter 起動」や「facebook 起動」はちゃんとアプリが起動するけど、「Yo 起動」は「陽気堂」に、「Yo 開いて」は「よう平井堅」になるので「ワイオー 起動」と言う必要がある。たぶんYoとかはandroid:labelに”Yo”って書いてあるのだろう。ローマ字を日本語発音で1文字ずつ読み上げると認識される。

Hue Controlというwearのアプリはwearからhueのon/offができるけど、これも「エイチユーイー コントロール 起動」と言わないと起動できない。


トリガー

「開いて」以外にも「ドア 起動」「ドア 起動して」「ドア 起動して下さい」などでも起動する。

相性があるみたいで、「twitter 起動して」はtwitterアプリが起動するのに、「twitter 開いて」は「ひらいて」という名前の人のtwitterアカウントが開いてしまう。

0

RICOH THETAをMacに複数接続する方法

前:Web+DB Press vol.85でRICOH THETAについて書いた


THETAの数だけVM起動すれば複数接続できる。


THETAはWiFiで接続する必要があるので、USB WiFiアダプタがあるとよい。接続したいTHETAの数だけ用意する。USB WiFiを追加しないと、Macbookの内蔵のWiFiがTHETAに専有されてしまってインターネットできなくなる。

MacにTHETAを1つ接続する

MacのWiFiはインターネットに接続するのに使う。
追加のWiFiアダプタをUSB接続し、そっちをTHETAに接続する。planexのGW-USVALUE-EZが小さくていい感じなので使ってる。

「ネットワーク環境設定」の左下の歯車メニューから、「サービスの順序を設定」して内蔵WiFiを追加WiFiよりも上に持ってこないと、Macがインターネットにつながらないので注意する。


なお、THETAのIPアドレスは192.168.1.1に固定されている。ルーターのIPアドレスが192.168.1.1だったり、複数のTHETAに同時接続したりするとIPアドレスが重複してしまって接続できなくなる。

そんな時はVirtualBoxを使う

MacにTHETAを複数接続する


VirtualBoxでVMを作って、VMのネットワークアダプタの設定で割り当てを「NAT」にする。するとVMはVirtualBox内に作られた仮想ネットワークを経由してインターネットに接続する。VMのIPアドレスは192.168.56.101とかそんな感じのになる。


追加したUSB WiFiアダプタをVMに割り当てれば、

[インターネット]—[vboxnet0 (192.168.56.1)]—[VM (192.168.56.101)]—[THETA (192.168.1.1)]

のような接続で外に出る。VMではなくMac側でifconfig等で見ると「vboxnet(数字)」等の仮想アダプタが増えてるはず。

VMを複数起動してそれぞれにUSB WiFiアダプタ割り当てれば、それぞれのVMから見てTHETA(192.168.1.1)は各自に割り当てられたUSB WiFiの接続先のTHETAだけになるので、1台のMacで複数のTHETAに接続できる。

NATではなくNATネットワークにすればVM間でも通信できるはず。