Kommunikation zwischen Wearable und Smartphone

Category: 


In den letzten Tutorials haben wir gelernt, wie man Konfigurationsaktivitäten für Watchfaces erstellt. Diesmal geht es nun darum, wie wir Einstellungen an die Uhr senden, sodass diese entsprechend reagieren kann.

Handheld UI

Der Einfachheit halber erzeugen wir keine komplizierte und wunderschöne UI, sondern platzieren bloß zwei Buttons auf der Oberfläche der Mobile App. Der eine Button soll den Stundenzeiger der Watchface blau färben und der andere soll ihn wieder rot färben.
Nachdem wir den Text der Buttons angepasst haben, müssen wir noch das onClick Event anpassen.

Für jeden Namen den wir als onClick-Handler angeben (z.B. onClickRed), müssen wir eine entsprechende Methode in der Activity angeben. Diese wird aufgerufen, wenn der Benutzer auf den jeweiligen Button klickt. In den Methoden rufen wir schließlich die (noch nicht implementierte) sendMessage Methode auf.

public void onClickRed(View view) {
        sendMessage("red");
}

public void onClickBlue(View view) {
        sendMessage("blue");
}

Nachrichten senden

Als Einstiegspunkt für die MessageApi wird ein GoogleApiClient benötigt. Dieser wird durch einen Builder erzeugt. Da wir uns nur für die Wearable API interessieren, fügen wir auch nur diese hinzu. Bei Bedarf kann man auch weitere APIs hinzufügen.

Der Pfad einer Nachricht muss mit einem Schrägstrich anfangen!

private final static String PATH = "/CONFIG";
private final static String TAG = "SAMPLE_WATCH";
private final static int CONNECTION_TIME_OUT_MS = 100;
private String nodeId;
private void sendMessage(final String msg) {
  final GoogleApiClient client =
    new GoogleApiClient.Builder(this).addApi(Wearable.API).build();

  new Thread(new Runnable() {
    @Override
    public void run() {
      client.blockingConnect(CONNECTION_TIME_OUT_MS,
        TimeUnit.MILLISECONDS);
      if(nodeId==null) {
        NodeApi.GetConnectedNodesResult result =
          Wearable.NodeApi.getConnectedNodes(client).await();
        List<Node> nodes = result.getNodes();
        if (nodes.size() > 0) {
          nodeId = nodes.get(0).getId();
        } else {
          Log.d(TAG, "no nodes");
          client.disconnect();
          return;
        }
      }

      Wearable.MessageApi.sendMessage(client, nodeId,
        PATH, msg.getBytes());
      client.disconnect();
    }
  }).start();
}

Da das ermitteln der ID, sowie das Senden der Nachricht selbst, etwas Zeit benötigt und die UI nicht blockieren soll, sollten wir das ganze als separaten Thread starten. Den Thread, bzw. genauer die Runnable-Klasse, erzeugen wir als innere Klasse.
Da wir die ID des Wearables benötigen, müssen wir diese unter Umständen erst ermitteln. Dies erledigen wir über die getConnectedNodes Methode. Falls keine Geräte angeschlossen sind, geben wir eine entsprechende Log-Meldung aus und beenden die Verbindung.
Andernfalls speichern wir ID des Gerätes und senden anschließend die Nachricht. Als letztes beenden wir die Verbindung und sind mit der Smartphone App fertig.

Nachrichten empfangen

Dem Watchface geben wir als erstes ein paar neue Variablen.

private final static String PATH = "/CONFIG";
private final static String TAG = "SAMPLE_WATCH";
private GoogleApiClient mClient;

Da die App immer bereit sein soll Nachrichten zu empfangen, müssen wir den GoogleApiClient beim Start der App verbinden und beim schließen wieder beenden.

@Override
public void onCreate(SurfaceHolder holder) {
  ...
  mClient = new GoogleApiClient.Builder(SampleWatchfaceService.this)
    .addApi(Wearable.API).build();
  mClient.connect();
  ...
}
@Override
public void onDestroy() {
  ...
  mClient.disconnect();
}

Jetzt müssen wir uns natürlich noch um das eigentliche Empfangen kümmern. Dies geschieht am einfachsten über einen Listener, welchen wir registrieren. Dieser wird vom System aufgerufen wenn eine Nachricht empfangen wird. Dabei müssen wir natürlich beachten, das wir nur unsere eigenen Nachrichten bearbeiten.
Je nachdem was wir empfangen, passen wir die Farbe des Stundenzeigers an und invalidieren die Oberfläche, sodass sie neugezeichnet wird.

public void onCreate(SurfaceHolder holder) {
  ...
  Wearable.MessageApi.addListener(mClient,
    new MessageApi.MessageListener() {
      @Override
      public void onMessageReceived(MessageEvent messageEvent) {
        if(messageEvent.getPath().equals(PATH)) {
          String data = new String(messageEvent.getData());
          if(data.equals("red"))
            mHourPaint.setARGB(255, 255, 0, 0);
          else if(data.equals("blue"))
            mHourPaint.setARGB(255, 0, 0, 255);
          invalidate();
        }
      }
    }
  );
}

Und damit sind wir nun tatsächlich in der Lage, Einstellungen auf dem Handy vorzunehmen und diese auf das Watchface zu übertragen.

Und damit sind wir auch schon am Ende dieses Tutorials. Bei Fragen oder Anregungen, hinterlasst einfach einen Kommentar.