Od wersji
11.8.0 usług Google Play, aplikacje na Wear OS powinny zostać przeniesione
od GoogleApiClient
i używaj obiektów klienta opartych na klasie
GoogleApi
.
Użycie usługi
GoogleApi
ułatwia konfigurowanie operacji asynchronicznych.
Na przykład jak opisano we wprowadzeniu do
Tasks API możesz uzyskać obiekt Task
zamiast
PendingResult
obiekt.
Na tej stronie znajdują się:
- Tabela komponentów zamiennych
- Przykład aktualizowania istniejącej aplikacji w celu użycia interfejsu Tasks API
Uwaga: ta aktualizacja nie dotyczy aplikacji na Wear OS na Chiny, które zwykle korzystają z Usług Google Play w wersji 10.2.0.
Uwaga: ten interfejs API jest obecnie dostępny tylko na telefonach z Androidem. i zegarki z Wear OS sparowane z telefonami z Androidem. Zegarki z Wear OS sparowane z iOS aplikacje mogą wysyłać zapytania do innych interfejsów API działających w chmurze, jeśli dostępne jest połączenie z internetem.
Zastępowanie wycofanych komponentów
Gdy używasz klas, które rozszerzają klasę
GoogleApi
, np.
DataClient
i
MessageClient
, zarządza pakiet SDK Usług Google Play
połączeń z Usługami Google Play.
W aplikacjach korzystających z klas zastępczych nie trzeba tworzyć
zarządzaj: GoogleApiClient
obiektów. Patrz też Uzyskiwanie dostępu
interfejsów API Google oraz
stronie referencyjnej klasy urządzenia do noszenia.
Poniższa tabela zawiera wycofane komponenty i ich zamienniki:
Wycofany komponent | Komponent zastępczy |
CapabilityApi
|
CapabilityClient
|
Channel
|
ChannelClient.Channel
|
ChannelApi
|
ChannelClient
|
DataApi
|
DataClient
|
MessageApi
|
MessageClient
|
NodeApi
|
NodeClient
|
Pamiętaj też o tych kwestiach:
- W przypadku powiadomień o zmianach na kanałach atrybut
Channel.ChannelListener
jest zastępowany przezChannelClient.ChannelCallback
- Aby ustawić wątek pod kątem wywołań zwrotnych detektora, parametr
GoogleApiClient.Builder.setHandler
jest zastępowany przezsetLooper
metodaWearableOptions.Builder
Przykład migracji aplikacji na Wear
Fragmenty kodu poniżej pokazują przykład migracji Dane dotyczące Wear Próbka warstwy, która korzysta z interfejsu API warstwy danych, została zaktualizowana dla wersji 11.8.0 Usług Google Play. Jeśli aplikacja ma moduł telefonu, mogą być podobne do aktualizacji modułu Wear.
Zaktualizuj zależność w Usługach Google Play
Twoja aplikacja może zależeć od wcześniejszej wersji Usług Google Play,
zaktualizuj tę zależność w pliku build.gradle
modułowi Wear:
dependencies { ... compile 'com.google.android.gms:play-services-wearable:11.8.0' }
Zaktualizuj instrukcje importowania aplikacji
Zaimportuj niezbędne zajęcia, w tym je w interfejsie Tasks API.
Na przykład: dawniej Wear Data Wear
przykład umieścił tę deklarację na temat importu w
MainActivity.java
. Ta instrukcja import
należy usunąć:
Kotlin
... import com.google.android.gms.common.api.GoogleApiClient ...
Java
... import com.google.android.gms.common.api.GoogleApiClient; ...
W kategorii Wear
Przykład warstwy danych, instrukcje import
takie jak powyżej
zostały zastąpione na przykład następującym (drugi dotyczy
obsługi wyjątków dotyczących zadań):
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; ...
Wdrażanie nowych interfejsów klienta.
Usuń użycie GoogleApiClient
i powiązane interfejsy (ConnectionCallbacks
,
OnConnectionFailedListener
itp.) i zastąpić drugi
Implementacje detektorów w nowych wersjach. Rzeczywiste metody
zwykle mają takie same nazwy jak wcześniej, więc główna zmiana to
podobnie jak w przykładzie poniżej.
Główna aktywność próbki warstwy danych Wear (wskazana w różnicach)
w dniu
GitHub) wdrożyliśmy na przykład
interfejsu CapabilityApi.CapabilityListener
. Teraz jednak
implementacje głównych działań
CapabilityClient.OnCapabilityChangedListener
Poniżej znajdziesz porównanie definicji klas.
Oto fragment kodu, który znajduje się przed użyciem wersji 11.8.0 Google Play usługi:
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
Oto fragment kodu używany po użyciu wersji 11.8.0 Google Play usługi:
Kotlin
class MainActivity : Activity(), DataClient.OnDataChangedListener, MessageClient.OnMessageReceivedListener, CapabilityClient.OnCapabilityChangedListener
Java
public class MainActivity extends Activity implements DataClient.OnDataChangedListener, MessageClient.OnMessageReceivedListener, CapabilityClient.OnCapabilityChangedListener
Usuń i dodaj detektory
Nowe obiekty klienta są przechowywane w pamięci podręcznej i współdzielone między instancjami
GoogleApi
, dlatego nie ma potrzeby utrzymywania elementu
zmienne; są niedrogie i nie stracą
słuchaczom.
Poniżej znajdziesz fragment zmienionej warstwy danych dotyczących Wear przykład:
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); }
Wysyłanie próśb o informacje za pomocą interfejsu Tasks API
Możesz też poprosić o informacje spoza listy detektorów, którzy aktualizują się
do Twojej aplikacji, gdy nastąpi zmiana danych. W takich przypadkach użyj funkcji
klienta, takiego jak
DataClient
, w połączeniu z interfejsem Tasks API oraz
klasę wyniku (czyli Task<ResultType>
).
Na przykład jak widać w warstwie danych z Wear przykładowej, możesz użyć interfejsu Tasks API, aby znajdź połączone węzły o dowolnych możliwościach:
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(); }
Dodatkowy kod, który korzysta z interfejsów API do noszenia i Listy zadań, znajdziesz w Warstwa danych Wear przykład. To przykład wykorzystania ciężkich zadań poza wątki interfejsu użytkownika. lub w usłudze, pojawia się inna opcja. Oto przykład Jak zablokować zadanie i generować wyniki synchronicznie:
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); } }