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:
- Bei Benachrichtigungen über Änderungen an Kanälen wird
Channel.ChannelListener
durchChannelClient.ChannelCallback
ersetzt - Zum Festlegen des Threads für Listener-Callbacks wird
GoogleApiClient.Builder.setHandler
durch densetLooper
-Methode vonWearableOptions.Builder
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); } }