Wear-Apps zu GoogleApi migrieren

Beginnend mit Version Version 11.8.0 der Google Play-Dienste nicht mehr unterstützt, sollten Wear OS-Apps migriert werden. aus GoogleApiClient und verwenden stattdessen Client-Objekte, die auf der Klasse GoogleApi basieren.

Die Verwendung von GoogleApi erleichtert die Einrichtung asynchroner Vorgänge. Wie in der Einführung zum Tasks API können Sie ein Task-Objekt anstelle eines PendingResult-Objekt.

Diese Seite enthält Folgendes:

  • Tabelle der Ersatzkomponenten
  • Beispiel für die Aktualisierung einer vorhandenen App zur Verwendung der Tasks API

Hinweis:Dieses Update gilt nicht für Wear OS-Apps für China, wo in der Regel Version 10.2.0 der Google Play-Dienste verwendet wird.

Hinweis: Diese API ist derzeit nur auf Android-Smartphones verfügbar. und Wear OS-Smartwatches, die mit Android-Smartphones gekoppelt sind. Für mit iOS gekoppelte Wear OS-Smartwatches können Apps andere cloudbasierte APIs abfragen, sofern eine Internetverbindung verfügbar ist.

Ersatz für eingestellte Komponenten

Wenn du Klassen verwendest, die die Klasse GoogleApi erweitern, z. B. DataClient und MessageClient, verwaltet das Google Play Services SDK Verbindungen zu den Google Play-Diensten.

Apps, die die Ersatzklassen unten verwenden, müssen keine GoogleApiClient verwalten Objekte. Siehe auch Zugriff Google APIs und die Referenzseite für die Wearable-Klasse

Die folgende Tabelle enthält nicht mehr unterstützte Komponenten und ihre Ersatz:

Eingestellte Komponente Ersatzkomponente
CapabilityApi CapabilityClient
Channel ChannelClient.Channel
ChannelApi ChannelClient
DataApi DataClient
MessageApi MessageClient
NodeApi NodeClient

Beachten Sie außerdem Folgendes:

Migrationsbeispiel für eine Wear-App

Als Beispiel für die Migration veranschaulichen die Code-Snippets unten, wie die Wear-Daten Ebenenbeispiel, bei dem die Data Layer API verwendet wird, wurde aktualisiert für Version 11.8.0 der Google Play-Dienste. Verfügt Ihre App über ein Telefonmodul, Updates möglicherweise denen für das Wear-Modul ähneln.

Abhängigkeit von Google Play-Diensten aktualisieren

Da deine App möglicherweise von einer früheren Version der Google Play-Dienste abhängt, die folgende Abhängigkeit in der Datei build.gradle von deines Wear-Moduls:

dependencies {
...
compile 'com.google.android.gms:play-services-wearable:11.8.0'
}

Importanweisungen Ihrer Anwendung aktualisieren

Importieren Sie die erforderlichen Klassen, einschließlich Klassen in der Tasks API.

Beispiel: ehemals Wear-Datenschicht Beispiel enthält die folgende Importanweisung in der MainActivity.java-Datei. Diese import-Anweisung sollten entfernt werden:

Kotlin

...
import com.google.android.gms.common.api.GoogleApiClient
...

Java

...
import com.google.android.gms.common.api.GoogleApiClient;
...

In der Wear Beispiel für Datenschicht, import-Anweisungen wie oben durch Folgendes ersetzt wurden (die zweite ist für Aufgabenausnahmen verarbeiten):

Kotlin

...
import com.google.android.gms.tasks.Tasks
import java.util.concurrent.ExecutionException
...

Java

...
import com.google.android.gms.tasks.Tasks;
import java.util.concurrent.ExecutionException;
...

Neue Client-Schnittstellen implementieren

Entfernen Sie jegliche Verwendung des GoogleApiClient Klasse und zugehöriger Schnittstellen (ConnectionCallbacks, OnConnectionFailedListener usw.) und ersetzen Sie die anderen Listener-Implementierungen mit ihren neuen Versionen. Die tatsächlichen Methoden zur Namen von Überschreibung haben in der Regel dieselben Namen wie zuvor. Die Hauptänderung besteht also darin, ähnlich wie im folgenden Beispiel.

Die Hauptaktivität des Wear-Datenschicht-Beispiels (wie in einem „Unterschied“ angegeben) am GitHub) beispielsweise das CapabilityApi.CapabilityListener-Schnittstelle. Aber jetzt der Hauptaktivität CapabilityClient.OnCapabilityChangedListener

Unten sehen Sie einen Vergleich der Klassendefinitionen.

Hier ist ein Snippet vor der Verwendung von Version 11.8.0 von Google Play Dienste:

Kotlin

class MainActivity :
        Activity(),
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        DataApi.DataListener,
        MessageApi.MessageListener,
        CapabilityApi.CapabilityListener

Java

public class MainActivity extends Activity implements
  ConnectionCallbacks,
  OnConnectionFailedListener,
  DataApi.DataListener,
  MessageApi.MessageListener,
  CapabilityApi.CapabilityListener

Hier ist ein Snippet nach Verwendung von Version 11.8.0 von Google Play Dienste:

Kotlin

class MainActivity :
        Activity(),
        DataClient.OnDataChangedListener,
        MessageClient.OnMessageReceivedListener,
        CapabilityClient.OnCapabilityChangedListener

Java

public class MainActivity extends Activity implements
  DataClient.OnDataChangedListener,
  MessageClient.OnMessageReceivedListener,
  CapabilityClient.OnCapabilityChangedListener

Listener entfernen und hinzufügen

Die neuen Clientobjekte werden im Cache gespeichert und von GoogleApi-Instanzen gemeinsam genutzt. Daher ist es nicht erforderlich, das Mitglied Variablen; sind kostengünstig in der Erstellung und verlieren ihre zu hören.

Unten sehen Sie ein Snippet aus der überarbeiteten Wear-Datenschicht. Beispiel:

Kotlin

override fun onResume() {
    super.onResume()
    Wearable.getDataClient(this).addListener(this)
    Wearable.getMessageClient(this).addListener(this)
    Wearable.getCapabilityClient(this)
            .addListener(
                    this,
                    Uri.parse("wear://"),
                    CapabilityClient.FILTER_REACHABLE
            )
}

override fun onPause() {
    super.onPause()
    Wearable.getDataClient(this).removeListener(this)
    Wearable.getMessageClient(this).removeListener(this)
    Wearable.getCapabilityClient(this).removeListener(this)
}

Java

@Override
protected void onResume() {
  super.onResume();
  Wearable.getDataClient(this).addListener(this);
  Wearable.getMessageClient(this).addListener(this);
  Wearable.getCapabilityClient(this)
  .addListener(
    this, Uri.parse("wear://"), CapabilityClient.FILTER_REACHABLE);
}

@Override
protected void onPause() {
  super.onPause();
  Wearable.getDataClient(this).removeListener(this);
  Wearable.getMessageClient(this).removeListener(this);
  Wearable.getCapabilityClient(this).removeListener(this);
}

Informationen mit der Tasks API anfordern

Möglicherweise möchten Sie Informationen außerhalb der Listener anfordern, die aktualisiert werden. wenn sich die Daten ändern. Stellen Sie in solchen Fällen eine Anfrage mit einen Client wie DataClient, in Verbindung mit der Tasks API und eine Ergebnisklasse (also Task<ResultType>).

Beispiel: Wie in der Wear-Datenschicht dargestellt“ Beispiel: Mit der Tasks API können Sie Verbundene Knoten mit bestimmten Funktionen finden:

Kotlin

private fun showNodes(vararg capabilityNames: String) {
    Wearable.getCapabilityClient(this)
            .getAllCapabilities(CapabilityClient.FILTER_REACHABLE).apply {
                addOnSuccessListener { capabilityInfoMap ->
                    val nodes: Set<Node> = capabilityInfoMap
                            .filter { capabilityNames.contains(it.key) }
                            .flatMap { it.value.nodes }
                            .toSet()
                    showDiscoveredNodes(nodes)
                }
            }
}

private fun showDiscoveredNodes(nodes: Set<Node>) {
    val nodesList: Set<String> = nodes.map { it.displayName }.toSet()
    val msg: String = if (nodesList.isEmpty()) {
        Log.d(TAG, "Connected Nodes: No connected device was found for the given capabilities")
        getString(R.string.no_device)
    } else {
        Log.d(TAG, "Connected Nodes: ${nodesList.joinToString(separator = ", ")}")
        getString(R.string.connected_nodes, nodesList)
    }
    Toast.makeText(this@MainActivity, msg, Toast.LENGTH_LONG).show()
}

Java

private void showNodes(final String... capabilityNames) {
  Task<Map<String, CapabilityInfo>> capabilitiesTask =
    Wearable.getCapabilityClient(this)
            .getAllCapabilities(CapabilityClient.FILTER_REACHABLE);
  capabilitiesTask.addOnSuccessListener(new
    OnSuccessListener<Map<String, CapabilityInfo>>() {
      @Override
      public void onSuccess(Map<String, CapabilityInfo>
        capabilityInfoMap) {
          Set<Node> nodes = new HashSet<>();
          if (capabilityInfoMap.isEmpty()) {
            showDiscoveredNodes(nodes);
            return;
          }
          for (String capabilityName : capabilityNames) {
            CapabilityInfo capabilityInfo = capabilityInfoMap.get(capabilityName);
            if (capabilityInfo != null) {
              nodes.addAll(capabilityInfo.getNodes());
            }
          }
          showDiscoveredNodes(nodes);
      }
  });
}

private void showDiscoveredNodes(Set<Node> nodes) {
  List<String> nodesList = new ArrayList<>();
  for (Node node : nodes) {
    nodesList.add(node.getDisplayName());
  }
  LOGD(TAG, "Connected Nodes: " + (nodesList.isEmpty()
    ? "No connected device was found for the given capabilities"
    : TextUtils.join(",", nodesList)));
  String msg;
  if (!nodesList.isEmpty()) {
    msg = getString(R.string.connected_nodes, TextUtils.join(", ", nodesList));
  } else {
    msg = getString(R.string.no_device);
  }
  Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG).show();
}

Zusätzlichen Code, der die Wearable API und die Tasks API verwendet, finden Sie in der Wear-Datenebene Stichprobe. Und als Beispiel für die Verwendung schwerer Aufgaben außerhalb des UI-Threads oder in einem Dienst gibt es eine andere Option. Hier ist ein Beispiel für So blockieren Sie eine Aufgabe und erhalten das Ergebnis synchron:

Kotlin

override fun doInBackground(vararg params: Asset): Bitmap? {
    if (params.isNotEmpty()) {
        val asset = params[0]
        val getFdForAssetResponseTask: Task<DataClient.GetFdForAssetResponse> =
                Wearable.getDataClient(applicationContext).getFdForAsset(asset)
        return try {
            // Block on a task and get the result synchronously. This is generally done
            // when executing a task inside a separately managed background thread. Doing
            // this on the main (UI) thread can cause your application to become
            // unresponsive.
            val getFdForAssetResponse: DataClient.GetFdForAssetResponse =
                    Tasks.await(getFdForAssetResponseTask)
            getFdForAssetResponse.inputStream?.let { assetInputStream ->
                BitmapFactory.decodeStream(assetInputStream)
            } ?: run {
                Log.w(TAG, "Requested an unknown Asset.")
                null
            }

        } catch (exception: ExecutionException) {
            Log.e(TAG, "Failed retrieving asset, Task failed: $exception")
            return null
        } catch (exception: InterruptedException) {
            Log.e(TAG, "Failed retrieving asset, interrupt occurred: $exception")
            return null
        }

    } else {
        Log.e(TAG, "Asset must be non-null")
        return null
    }
}

override fun onPostExecute(bitmap: Bitmap?) {
    bitmap?.also {
        Log.d(TAG, "Setting background image on second page..")
        moveToPage(1)
        assetFragment.setBackgroundImage(it)
    }
}

Java

@Override
protected Bitmap doInBackground(Asset... params) {
  if (params.length > 0) {
    Asset asset = params[0];
    Task<DataClient.GetFdForAssetResponse> getFdForAssetResponseTask =
      Wearable.getDataClient(getApplicationContext()).getFdForAsset(asset);
    try {
      // Block on a task and get the result synchronously. This is generally done
      // when executing a task inside a separately managed background thread. Doing
      // this on the main (UI) thread can cause your application to become
      // unresponsive.
      DataClient.GetFdForAssetResponse getFdForAssetResponse =
        Tasks.await(getFdForAssetResponseTask);
      InputStream assetInputStream = getFdForAssetResponse.getInputStream();
      if (assetInputStream != null) {
        return BitmapFactory.decodeStream(assetInputStream);
      } else {
        Log.w(TAG, "Requested an unknown Asset.");
        return null;
      }

    } catch (ExecutionException exception) {
      Log.e(TAG, "Failed retrieving asset, Task failed: " + exception);
      return null;
    } catch (InterruptedException exception) {
      Log.e(TAG, "Failed retrieving asset, interrupt occurred: " + exception);
      return null;
    }
  } else {
    Log.e(TAG, "Asset must be non-null");
    return null;
  }
}

@Override
protected void onPostExecute(Bitmap bitmap) {
  if (bitmap != null) {
    LOGD(TAG, "Setting background image on second page..");
    moveToPage(1);
    assetFragment.setBackgroundImage(bitmap);
  }
}