3月 312015
参考
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(スマホ)へ送る場合の手順
- WearでGoogle API Client接続
- Wearable.NodeApiでHandheldのNodeIDを探す
- sendMessageにpath(と呼ばれてるけどタイトルみたいなもの)とdataを送信
- 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を実装すればいいらしい。