2015-07-22 36 views
-1

我一直在閱讀如何在官方網站上使用手錶和手機之間的Capability API和Message API:https://developer.android.com/training/wearables/data-layer/messages.html我毫不費力地從手錶發送消息到電話。Android Wear消息API無法正常工作

但是,我確實有麻煩,但是,使用下面顯示的方法將消息從手機發送到手錶。我不知道爲什麼,因爲它看起來像我使用相同的方法實現API(我甚至開發了一個更抽象的類來簡化API調用)。我的手機仍然無法使用功能過濾器找到手錶。

這是一個已知的問題,還是有我的執行什麼不對?

MOBILE /價值/ 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(); 
    } 

}

回答

0

我創建了一個簡單的項目,看看我是否能重現此。在我的項目中,我已經從客戶端刪除了非磨損apis,並且我能夠成功地從手機中看到「磨損」節點;我沒有發送任何消息,也沒有發送任何消息,但是確實使用了ConnectionUtils來儘可能地接近你的消息。您可能想嘗試簡化以找出問題所在: 1.從GoogleApiClient中移除所有非磨損apis,以使測試更簡單 2.確保您期望採取的路徑確實發生通過添加日誌語句 3.嘗試添加日誌消息,以查看(a)Google Api Client是否已連接到移動設備上,(b)節點偵聽器是否返回該節點。

我注意到你的代碼中有一些你可能想要研究的東西;例如你有MessageListener.NOTIFICATION_ACTIONS_PATH; Play Services中的MessageListener沒有這個常量,或者當你調用getcpability(..)。await()時,總是增加一個超時(我看不到使用阻塞版本的理由)。

+0

我會仔細看看我的項目。我無法弄清楚爲什麼我的手錶節點不會出現,所以我會簡化一些事情。 在這種情況下,'MessageListener'是我的偵聽器類,用於在後臺接收消息。 –