Android Wear Message API无法通过电话观看

时间:2015-07-22 06:44:38

标签: android wear-os android-wear-data-api

我一直在阅读如何在官方网站上的手表和手机之间使用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 /值/ 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>

发送消息的方法

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();
    }

}

1 个答案:

答案 0 :(得分:0)

我创建了一个简单的项目,看看我是否可以重现这个。在我的项目中,我已从客户端移除了非磨损apis,我能够成功地从手机中看到“磨损”节点;我没有发送任何消息,或任何花哨的东西,但确实使用你的ConnectionUtils使它尽可能接近你。您可能希望尝试简化此操作以找出问题所在: 1.从GoogleApiClient中删除所有非磨损api,使测试更简单 2.确保通过添加日志语句确实发生了您期望获取的路径 3.尝试添加日志消息以查看(a)Google Api Client是否已在移动设备上连接,(b)节点侦听器是否返回节点。

我注意到您的代码中有一些您可能想要查看的内容;例如,你有MessageListener.NOTIFICATION_ACTIONS_PATH;来自Play服务的MessageListener没有这样的常量,或者当你调用getcpability(..)。await()时,总是添加一个超时(我看不到使用阻塞版本开始的原因)。