2016-07-31 21 views
1

Ich baue ein Zifferblatt für Android tragen. Das Zifferblatt wird gelegentlich den Handheld nach Informationen fragen, die dazu verwendet werden, das Zifferblatt zu aktualisieren. Unglücklicherweise treten onDataChanged und onMessageReceived nur dann auf, wenn das Zifferblatt zum ersten Mal geladen wird, und nie wieder (ich kann zu einem anderen Zifferblatt wechseln und wieder funktionieren.)onDataChanged nur einmal aufgerufen?

Der Großteil des Boilerplate ist den Beispielen I entnommen denken. So in der Uhr Gesicht Ich habe

@Override 
    public void onCreate() { 
     Log.d(TAG, "onCreate - Creating service..."); 
     super.onCreate(); 
     initGoogleApiClient(); 
    } 

    private void initGoogleApiClient() { 
     mApiClient = new GoogleApiClient.Builder(mContext) 
       .addApi(Wearable.API) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .build(); 
     Log.d(TAG, "Calling connect on mApiClient..."); 

     mApiClient.connect(); 
    } 

@Override 
    public void onMessageReceived(MessageEvent messageEvent) { 
     Log.d(TAG, "onMessageReceived: " + messageEvent.getPath() + " " + messageEvent.getData()); 

     switch (messageEvent.getPath()) { 
      case "case 1": 
        Log.d(TAG,"some data was sent to us..."); 
       if (!mApiClient.isConnected()) 
        mApiClient.connect(); 
       break; 
     } 
    } 

    @Override 
    public void onConnected(@Nullable Bundle bundle) { 
     Log.d(TAG,"onConnected - adding Listeners"); 
     Wearable.DataApi.addListener(mApiClient, this); 
     Wearable.MessageApi.addListener(mApiClient, this); 
    } 

    @Override 
    public void onConnectionSuspended(int i) { 
     Log.d(TAG,"onConnection suspended"); 
    } 

    @Override 
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 
     Log.e(TAG,"onConnection failed"); 
    } 

    @Override 
    public void onDataChanged(DataEventBuffer dataEventBuffer) { 
     Log.d(TAG, "onDataChanged"); 
     for (DataEvent event : dataEventBuffer) { 
      if (event.getType() == DataEvent.TYPE_CHANGED && event.getDataItem().getUri().getPath().equals("/image")) { 
       Log.d(TAG, "Matched TYPE_CHANGED and /image"); 
       DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem()); 
       Asset photoAsset = dataMapItem.getDataMap().getAsset("photo"); 
       loadBitmapFromAsset(photoAsset); 
      } 
     } 
    } 

auf dem Handheld zeigt die Protokollierung, dass die Daten an das tragbare auf die gleiche Art und Weise gesendet wird sowohl in der ersten Instanz, nachdem die Uhr Gesicht geladen (wo es funktioniert) und auf nachfolgende Anfragen. Der Unterschied zu nachfolgenden Anforderungen besteht darin, dass keine Protokollierung im oben genannten Code erfolgt und nichts ausgelöst wird.

Einige Hand Code dafür, wie die Daten gesendet werden:

private void SendBitmap(final Bitmap bitmap) { 
//snip - stuff to resize the bitmap 
Log.d(TAG, "Resized image to " + cropped.getWidth() + "x" + cropped.getHeight()); 

final Bitmap croppedBitmap = cropped; 

new Thread(new Runnable() { 
    @Override 
    public void run() { 

     if (!nodeConnected || !mGoogleApiClient.isConnected()) 
     { 
      Log.d(TAG,"No node connected. Attempting connection for 5 seconds..."); 
      mGoogleApiClient.blockingConnect(5, TimeUnit.SECONDS); 
     } 
     if (!nodeConnected) 
     { 
      Log.e(TAG, "Failed to connect to mGoogleApiClient within 5 seconds"); 
      return; 
     } 

     if (mGoogleApiClient.isConnected()) { 
      Log.d(TAG, "Client is connected..."); 
      Asset asset = createAssetFromBitmap(croppedBitmap); 
      PutDataMapRequest putDataMapRequest = PutDataMapRequest.create("/image").setUrgent(); 
      putDataMapRequest.getDataMap().clear(); //clear down current stuff 
      putDataMapRequest.getDataMap().putAsset("photo", asset); 
      putDataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis()); 
      PutDataRequest request = putDataMapRequest.asPutDataRequest().setUrgent(); 

      PendingResult<DataApi.DataItemResult> pendingResult = 
        Wearable.DataApi.putDataItem(mGoogleApiClient, request); 

      Log.d(TAG,"DataItem is put"); 

      pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>() { 
       @Override 
       public void onResult(DataApi.DataItemResult dataItemResult) { 
        Log.d(TAG, "Sending task data: " + dataItemResult.getStatus().isSuccess()); 
       } 
      }); 
     } 
     else { 
      Log.w(TAG,"Client is NOT connected..."); 
     } 
    } 
}).start(); 


//send a message to trigger connection? 
SendToDataLayerThread photoTrigger = new SendToDataLayerThread("case 1", "Photo sent...".getBytes()); 
photoTrigger.run(); 
Log.d(TAG, "Photo sent to the Google API"); 
} 

private static Asset createAssetFromBitmap(Bitmap bitmap) { 
final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteStream); 
return Asset.createFromBytes(byteStream.toByteArray()); 
} 

public class SendToDataLayerThread extends Thread { 
    String path; 
    byte[] message; 

    // Constructor to send a message to the data layer 
    SendToDataLayerThread(String p, byte[] msg) { 
     path = p; 
     message = msg; 
    } 

    public void run() { 
     Wearable.NodeApi.getConnectedNodes(mGoogleApiClient) 
       .setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() { 
        @Override 
        public void onResult(NodeApi.GetConnectedNodesResult nodes) { 
         for (final Node node : nodes.getNodes()) { 
          Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), path, message).setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() { 
           @Override 
           public void onResult(MessageApi.SendMessageResult sendMessageResult) { 
            if (sendMessageResult.getStatus().isSuccess()) { 
             Log.d(TAG, "Message: {" + message + "} sent to: " + node.getDisplayName()); 
            } else { 
             // Log an error 
             Log.d(TAG, "ERROR: failed to send Message"); 
            } 
           } 
          }); 
         } 
        } 
       }); 
    } 
} 

Dinge, die ich versucht habe, basierend auf anderen Beiträgen:

  • mit setUrgent()
  • zusätzlich meine Sendung Bild, Senden eines Zeitstempels, um die Daten "einzigartig"
  • Senden einer Nachricht an "aufwachen" die Verbindung auf dem tragbaren

Ich bin an diesem Punkt ziemlich ratlos. Ich bin sicher, ich vermisse etwas offensichtlich, aber ich bin mir nicht sicher, was ich als nächstes versuchen soll ...

+0

Hallo James stecken. Ich habe genau das gleiche Problem. Irgendwelche Nachrichten diesbezüglich? Ich untersuche ... Das einzige, was ich bis jetzt gefunden habe, ist, wenn Sie den URI ändern, wird der 'onDataChanged()' erneut aufgerufen. Look Likes * Ändern von Daten ohne Änderung der URI * wird nicht als "Datenänderung" betrachtet. – Benoit

+0

Ich habe es nach ein paar Änderungen funktioniert. Ich werde eine Antwort mit einigen Hinweisen in Kürze veröffentlichen! – James

Antwort

1

Ich habe es schließlich nach einer Reihe von Änderungen funktioniert. Auf der Verschleiß App endete ich mit bis:

  • in DataLayerListener.java:

    @Override 
    public void onDataChanged(DataEventBuffer dataEvents) { 
        Log.d(TAG, "onDataChanged"); 
    
        GoogleApiClient mApiClient = new GoogleApiClient.Builder(this) 
          .addApi(Wearable.API) 
          .build(); 
    
        ConnectionResult result = mApiClient.blockingConnect(250, TimeUnit.MILLISECONDS); 
        if (!result.isSuccess()) { 
         Log.e(TAG, "Failed to connect to mApiClient when receiving image..."); 
        } 
    
        for (DataEvent event : dataEvents) { 
         if (event.getType() == DataEvent.TYPE_CHANGED && event.getDataItem().getUri().getPath().equals("/myapp")) { 
          Log.d(TAG, "Matched TYPE_CHANGED and /myapp"); 
          DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem()); 
          Asset photoAsset = dataMapItem.getDataMap().getAsset("photo"); 
          InputStream assetInputStream = Wearable.DataApi.getFdForAsset(mApiClient, photoAsset).await().getInputStream(); 
    
          Bitmap background = BitmapFactory.decodeStream(assetInputStream); 
          Intent intent = new Intent("background"); 
          intent.putExtra("message", background); 
          LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent); 
         } 
        } 
    } 
    

Im Manifest:

<service 
     android:name=".MyWatchFace" 
     android:label="@string/my_watch_face_name" 
     android:permission="android.permission.BIND_WALLPAPER"> 
     <meta-data ... /> 
     <meta-data ... /> 
     <intent-filter> 
      <action android:name="com.google.android.gms.wearable.DATA_CHANGED" /> 
      <action android:name="android.service.wallpaper.WallpaperService" /> 
      <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" /> 
     </intent-filter> 
    </service> 
    <service android:name=".DataLayerListener"> 
     <intent-filter> 
      <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" /> 
      <action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" /> 
      <action android:name="com.google.android.gms.wearable.CHANNEL_EVENT" /> 
      <action android:name="com.google.android.gms.wearable.DATA_CHANGED" /> 
      <data 
       android:host="*" 
       android:path="/myapp" 
       android:pathPrefix="/myapp" 
       android:scheme="wear" /> 
     </intent-filter> 
    </service> 

Das Zifferblatt selbst BroadcastReceivers Register zu handhaben die Nachrichten, die vom DataLayerListener gesendet werden.

Ich denke, es ist die offensichtlichen Änderungen war, dass die wichtige Bit waren ... Hoffentlich, die einen Anhaltspunkt gibt, wenn Sie mit dem gleichen Problem

+0

Danke für die Post, James. Aber das hat nicht geholfen ... Schließlich habe ich entdeckt, was falsch ist: Ich kopiere/kopiere Code aus [loadBitmapFromAsset (Asset-Asset)] (https://developer.android.com/training/wearables/data-layer/assets.html#) ReceiveAsset), und diese Methode führt einen 'mGoogleApiClient.disconnect();' - in meinem Fall den Grund, warum onDataChanged() bei nachfolgenden Änderungen nicht aufgerufen wurde. Meine Vermutung ist, dass es ein Fehler ist ... – Benoit

+0

Hmm, ich habe vielleicht irgendwann ähnliches gesehen, wenn ich mich erinnere, dass ich in der Vergangenheit viel Code hinzugefügt habe, um Dinge wieder zu verbinden ... Vielleicht werde ich eines Tages ausziehen ein richtiger Arbeitsvorlagencode, damit ich beim nächsten Mal nicht alle die gleichen Probleme habe! – James

Verwandte Themen