我一直在阅读如何在手表和手机之间使用Capability API和Message API: https://developer.android.com/training/wearables/data-layer/messages.html我从手表向手机发送消息没有困难。
我确实有麻烦,然而,从手机发送消息到手表使用如下所示的方法。我不确定为什么,因为我似乎使用相同的方法实现了API(我甚至开发了一个更抽象的类来简化API调用)。我的手机使用功能过滤器似乎仍然找不到手表。
这是一个已知的问题,还是我的实现有问题?
移动/价值/wear.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="CAPABILITY_MOBILE">MOBILE</string>
<string name="CAPABILITY_ANDROID_WEAR">WEARABLE</string>
<string-array name="android_wear_capabilities">
<item>@string/CAPABILITY_MOBILE</item>
</string-array>
</resources>
穿/价值/wear.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="CAPABILITY_MOBILE">MOBILE</string>
<string name="CAPABILITY_ANDROID_WEAR">WEARABLE</string>
<string-array name="android_wear_capabilities">
<item>@string/CAPABILITY_ANDROID_WEAR</item>
</string-array>
</resources>
发送消息给Wear的方法
gapi = new GoogleApiClient.Builder(getApplicationContext())
.addApi(Drive.API)
.addApi(Games.API)
.addApi(Plus.API)
.addApiIfAvailable(Wearable.API)
.addApiIfAvailable(Fitness.HISTORY_API)
.addScope(Drive.SCOPE_FILE)
.addScope(Games.SCOPE_GAMES)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
final int action_watch = intent.getIntExtra(ACTION_WATCH, ACTION_NULL);
//For any action, open Home.class on watch
if(action_watch != ACTION_NULL) {
final ConnectionUtils.NodeManager nodeManager =
new ConnectionUtils.NodeManager(gapi, getString(R.string.CAPABILITY_ANDROID_WEAR), MessageListener.NOTIFICATION_ACTIONS_PATH);
Log.d(TAG, "Start looking for nodes");
nodeManager.setNodeListener(new ConnectionUtils.NodeListener() {
@Override
public void onNodeFound() {
nodeManager.sendMessage(action_watch+"");
Log.d(TAG, "Sending "+action_watch+" to node");
}
});
} else {
Log.d(TAG, "No watch action requested");
}
}
@Override
public void onConnectionSuspended(int i) {
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "Error occurred");
}
})
.build();
gapi.connect();
我使用一个自定义类NodeManager来自动处理能力过滤器和节点管理。
package com.felkertech.n.virtualpets.Utils;
import android.util.Log;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Result;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.CapabilityApi;
import com.google.android.gms.wearable.CapabilityInfo;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class ConnectionUtils {
public static class NodeManager {
private String transcriptionNodeId = null;
private GoogleApiClient mGoogleApiClient;
private String CAPABILITY;
private String PATH;
private NodeListener listener;
private int nodesPinged = 0;
public NodeManager(final GoogleApiClient mGoogleApiClient, String CAPABILITY, String PATH) {
this.mGoogleApiClient = mGoogleApiClient;
this.CAPABILITY = CAPABILITY;
this.PATH = PATH;
setupNode();
}
public void setNodeListener(NodeListener nodeListener) {
listener = nodeListener;
}
private void setupNode() {
new Thread(new Runnable() {
@Override
public void run() {
CapabilityApi.GetCapabilityResult result =
Wearable.CapabilityApi.getCapability(
mGoogleApiClient, CAPABILITY,
CapabilityApi.FILTER_REACHABLE).await();
updateTranscriptionCapability(result.getCapability());
CapabilityApi.CapabilityListener capabilityListener =
new CapabilityApi.CapabilityListener() {
@Override
public void onCapabilityChanged(CapabilityInfo capabilityInfo) {
updateTranscriptionCapability(capabilityInfo);
}
};
Wearable.CapabilityApi.addCapabilityListener(
mGoogleApiClient,
capabilityListener,
CAPABILITY);
}
}).start();
}
private void updateTranscriptionCapability(CapabilityInfo capabilityInfo) {
if(capabilityInfo == null)
return; //TODO Send this in update
Set<Node> connectedNodes = capabilityInfo.getNodes();
transcriptionNodeId = pickBestNodeId(connectedNodes);
if(listener != null) {
listener.onNodeFound();
if(nodesPinged == 0)
listener.onFirstNodeFound();
nodesPinged++;
}
}
private String pickBestNodeId(Set<Node> nodes) {
String bestNodeId = null;
// Find a nearby node or pick one arbitrarily
for (Node node : nodes) {
if (node.isNearby()) {
return node.getId();
}
bestNodeId = node.getId();
}
return bestNodeId;
}
public void sendMessage(String msg) {
byte[] voiceData = msg.getBytes();
if (transcriptionNodeId != null) {
Wearable.MessageApi.sendMessage(mGoogleApiClient, transcriptionNodeId,
PATH, voiceData).setResultCallback(
new ResultCallback() {
@Override
public void onResult(Result result) {
MessageApi.SendMessageResult sendMessageResult = (MessageApi.SendMessageResult) result;
if (!sendMessageResult.getStatus().isSuccess()) {
// Failed to send message
}
}
}
);
} else {
// Unable to retrieve node with transcription capability
}
}
private Collection<String> getNodes() {
HashSet<String> results = new HashSet<String>();
NodeApi.GetConnectedNodesResult nodes =
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
for (Node node : nodes.getNodes()) {
results.add(node.getId());
}
return results;
}
}
public static void sendLaunchCommand(final GoogleApiClient mGoogleApiClient) {
new Thread(new Runnable() {
@Override
public void run() {
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
for(Node node : nodes.getNodes()) {
Log.i("test", "pinging to: " + node.getDisplayName());
MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), "/messageapi/launcher", "Hello World".getBytes()).await();
if(!result.getStatus().isSuccess()){
Log.e("test", "error");
} else {
Log.i("test", "success!! sent to: " + node.getDisplayName());
}
}
}
}).start();
}
public static void sendData(GoogleApiClient mGoogleApiClient, String name, String type, Object value) {
PutDataMapRequest dataMap = PutDataMapRequest.create("/dataitem/data");
if(type.equals("boolean"))
dataMap.getDataMap().putBoolean(name, (Boolean) value);
if(type.equals("int"))
dataMap.getDataMap().putInt(name, (Integer) value);
PutDataRequest request = dataMap.asPutDataRequest();
PendingResult<DataApi.DataItemResult> pendingResult =
Wearable.DataApi.putDataItem(mGoogleApiClient, request);
pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
@Override
public void onResult(DataApi.DataItemResult dataItemResult) {
Log.d("TAG", "onResult: " + dataItemResult.getStatus().toString());
}
});
}
public interface NodeListener {
void onNodeFound();
void onFirstNodeFound();
}
}
我创建了一个简单的项目,看看我是否可以复制这个。在我的项目中,我已经从客户端删除了非穿戴api,我能够成功地从手机上看到"穿戴"节点;我没有发送任何消息,或任何花哨的东西,但确实使用你的ConnectionUtils,使其尽可能接近你的。你可能想试着简化这个来找出你的问题在哪里:1. 从GoogleApiClient中删除所有非磨损api,以简化测试2. 通过添加日志语句,确保您期望的路径确实发生了3.尝试添加日志消息,看看是否(a)谷歌Api客户端连接到移动设备上,(b)节点监听器是否返回节点。
我注意到你的代码中有一些东西你可能想看看;例如,你有MessageListener.NOTIFICATION_ACTIONS_PATH;来自Play Services的MessageListener没有这样的常量,或者当你调用getcpability(..).await()时,总是添加一个超时(我看不出使用阻塞版本开始的理由)。