Mulai layanan Google Play
versi 11.8.0, aplikasi Wear OS harus bermigrasi
dari class GoogleApiClient
dan sebagai gantinya gunakan objek klien yang didasarkan pada class
GoogleApi
.
Penggunaan
GoogleApi
memudahkan penyiapan operasi asinkron.
Misalnya, seperti yang dijelaskan dalam pengantar
Tasks API, Anda bisa mendapatkan objek Task
sebagai ganti
objek
PendingResult
.
Halaman ini menyertakan:
- Tabel komponen pengganti
- Contoh update aplikasi yang ada untuk menggunakan Tasks API
Catatan: Update ini tidak berlaku untuk aplikasi Wear OS versi China, yang umumnya menggunakan layanan Google Play versi 10.2.0.
Catatan: API ini saat ini hanya tersedia di ponsel Android dan smartwatch Wear OS yang disambungkan dengan ponsel Android. Untuk smartwatch Wear OS yang disambungkan dengan ponsel iOS, aplikasi dapat mengkueri API berbasis cloud lainnya jika konektivitas Internet tersedia.
Penggantian untuk komponen yang tidak digunakan lagi
Saat Anda menggunakan class yang memperluas class
GoogleApi
, seperti
DataClient
dan
MessageClient
, SDK layanan Google Play mengelola
koneksi ke layanan Google Play untuk Anda.
Aplikasi yang menggunakan class pengganti di bawah ini tidak perlu membuat dan
mengelola objek
GoogleApiClient
. Lihat juga Mengakses Google API dan halaman referensi untuk class Wearable.
Tabel berikut berisi komponen yang sudah tidak digunakan lagi dan penggantinya:
Komponen yang tidak digunakan lagi | Komponen pengganti |
CapabilityApi
|
CapabilityClient
|
Channel
|
ChannelClient.Channel
|
ChannelApi
|
ChannelClient
|
DataApi
|
DataClient
|
MessageApi
|
MessageClient
|
NodeApi
|
NodeClient
|
Selain itu, perhatikan hal-hal berikut:
- Untuk notifikasi tentang perubahan saluran,
Channel.ChannelListener
diganti olehChannelClient.ChannelCallback
- Guna menyetel thread untuk callback pemroses,
GoogleApiClient.Builder.setHandler
diganti oleh metodesetLooper
dariWearableOptions.Builder
Contoh migrasi untuk aplikasi Wear
Sebagai contoh migrasi, cuplikan kode di bawah ini mengilustrasikan bagaimana contoh Lapisan Data Wear, yang menggunakan Data Layer API, diupdate untuk layanan Google Play versi 11.8.0. Jika aplikasi Anda memiliki modul ponsel, update-nya mungkin serupa dengan yang ada pada modul Wear.
Mengupdate dependensi pada layanan Google Play
Karena aplikasi Anda mungkin bergantung pada versi layanan Google Play yang lebih lama,
update dependensi berikut dalam file build.gradle
dari modul Wear Anda:
dependencies { ... compile 'com.google.android.gms:play-services-wearable:11.8.0' }
Mengupdate pernyataan impor aplikasi Anda
Impor class yang diperlukan, termasuk class di Tasks API.
Misalnya, sebelumnya contoh
Lapisan Data Wear menyertakan pernyataan impor berikut dalam
file MainActivity.java
. Pernyataan import
ini harus dihapus:
Kotlin
... import com.google.android.gms.common.api.GoogleApiClient ...
Java
... import com.google.android.gms.common.api.GoogleApiClient; ...
Dalam contoh Lapisan Data Wear, pernyataan import
seperti di atas dapat diganti dengan yang berikut ini (yang kedua adalah untuk menangani pengecualian tugas):
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; ...
Mengimplementasikan antarmuka klien baru
Hapus semua penggunaan class GoogleApiClient
dan antarmuka terkait (ConnectionCallbacks
,
OnConnectionFailedListener
, dll.), lalu ganti implementasi Pemroses
lainnya dengan versi baru. Metode aktual untuk
mengganti umumnya memiliki nama yang sama seperti sebelumnya, sehingga
perubahan utama mirip dengan contoh di bawah ini.
Sebagai contoh, aktivitas utama contoh Lapisan Data Wear (seperti yang ditunjukkan dalam diff pada GitHub) telah mengimplementasikan antarmuka CapabilityApi.CapabilityListener
. Selanjutnya, aktivitas
utama mengimplementasikan
CapabilityClient.OnCapabilityChangedListener
.
Di bawah ini adalah perbandingan definisi class.
Berikut ini cuplikan sebelum penggunaan layanan Google Play versi 11.8.0:
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
Berikut ini cuplikan setelah penggunaan layanan Google Play versi 11.8.0:
Kotlin
class MainActivity : Activity(), DataClient.OnDataChangedListener, MessageClient.OnMessageReceivedListener, CapabilityClient.OnCapabilityChangedListener
Java
public class MainActivity extends Activity implements DataClient.OnDataChangedListener, MessageClient.OnMessageReceivedListener, CapabilityClient.OnCapabilityChangedListener
Menghapus dan menambahkan pemroses
Objek klien baru di-cache dan digunakan bersama oleh instance
GoogleApi
sehingga tidak perlu menyimpan variabel
anggota; pembuatan klien tidaklah mahal dan klien tidak akan kehilangan
pemrosesnya.
Di bawah ini adalah cuplikan dari revisi contoh Lapisan Data Wear:
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); }
Meminta informasi dengan Tasks API
Anda mungkin ingin meminta informasi di luar pemroses yang mengupdate
aplikasi saat ada perubahan data. Dalam kasus semacam itu, buat permintaan menggunakan
klien seperti
DataClient
, bersama dengan Tasks API dan
class hasil (yaitu, sebagai Task<ResultType>
).
Misalnya, seperti yang ditunjukkan dalam contoh Lapisan Data Wear, Anda dapat menggunakan Tasks API untuk menemukan node yang terhubung dengan kapabilitas yang diberikan:
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(); }
Untuk kode tambahan yang menggunakan Wearable dan Tasks API, lihat contoh Lapisan Data Wear. Dan sebagai contoh menggunakan tugas berat dari UI thread atau dalam layanan, tersedia opsi lain. Berikut adalah contoh cara memblokir pada tugas dan mendapatkan hasil secara sinkron:
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); } }