البدء بـ الإصدار
الإصدار 11.8.0 من "خدمات Google Play"، يجب نقل تطبيقات Wear OS نهائيًا
من GoogleApiClient
الفئة واستخدام كائنات العميل المستندة إلى الفئة
GoogleApi
بدلاً من ذلك.
يؤدي استخدام
GoogleApi
إلى تسهيل إعداد العمليات غير المتزامنة.
على سبيل المثال، كما هو موضح في مقدمة عن
واجهة برمجة تطبيقات "مهام Google"، يمكنك الحصول على كائن Task
بدلاً من
الكائن
PendingResult
.
تتضمن هذه الصفحة ما يلي:
- جدول مكونات الاستبدال
- مثال على تحديث تطبيق حالي لاستخدام Tasks API
ملاحظة: لا ينطبق هذا التحديث على تطبيقات Wear OS في الصين التي تستخدم بشكل عام الإصدار 10.2.0 من "خدمات Google Play"
ملاحظة: تتوفّر واجهة برمجة التطبيقات هذه حاليًا على هواتف Android فقط. وساعات Wear OS المقترنة بهواتف Android. لساعات Wear OS المقترنة بنظام iOS الهواتف، يمكن للتطبيقات الاستعلام عن واجهات برمجة التطبيقات الأخرى التي تستند إلى السحابة الإلكترونية في حالة توفر الاتصال بالإنترنت.
استبدالات المكوّنات التي تم إيقافها نهائيًا
عند استخدام الصفوف التي تُوسّع فئة
GoogleApi
، مثل
DataClient
و
MessageClient
، تديرها "حزمة SDK لخدمات Google Play"
عمليات الربط "بخدمات Google Play" نيابةً عنك.
ولا تحتاج التطبيقات التي تستخدم الفئات البديلة أدناه إلى إنشاء
إدارة GoogleApiClient
الأخرى. راجع أيضًا الوصول
Google APIs و
مرجعية لفئة الأجهزة القابلة للارتداء.
يتضمن الجدول التالي مكونات تم إيقافها نهائيًا و البدائل:
مكوِّن تم إيقافه | المكوِّن البديل |
CapabilityApi
|
CapabilityClient
|
Channel
|
ChannelClient.Channel
|
ChannelApi
|
ChannelClient
|
DataApi
|
DataClient
|
MessageApi
|
MessageClient
|
NodeApi
|
NodeClient
|
يُرجى أيضًا مراعاة ما يلي:
- لتلقّي الإشعارات بشأن التغييرات في القنوات، يتم استبدال
Channel.ChannelListener
بالعنوانChannelClient.ChannelCallback
. - لإعداد سلسلة المحادثات لعمليات معاودة الاتصال بالمستمع، يتم استبدال
GoogleApiClient.Builder.setHandler
بـ طريقةsetLooper
منWearableOptions.Builder
مثال على نقل بيانات تطبيق Wear
كمثال على الترحيل، توضح مقتطفات الرمز الواردة أدناه كيف يمكن بيانات Wear تم إنشاء نموذج الطبقة الذي يستخدم Data Layer API تم تحديثه في الإصدار 11.8.0 "خدمات Google Play" إذا كان التطبيق يحتوي على وحدة هاتف، قد تكون التحديثات مشابهة لتلك الخاصة بوحدة Wear.
تعديل الاعتمادية على "خدمات Google Play"
بما أنّ تطبيقك قد يعتمد على إصدار سابق من "خدمات Google Play"،
قم بتعديل التبعية التالية في ملف build.gradle
الخاص
وحدة Wear:
dependencies { ... compile 'com.google.android.gms:play-services-wearable:11.8.0' }
تحديث عبارات الاستيراد لتطبيقك
يمكنك استيراد الصفوف اللازمة، بما في ذلك الصفوف في Tasks API.
على سبيل المثال، كانت تعرف سابقًا طبقة بيانات Wear
تضمنت العينة عبارة الاستيراد التالية في
ملف MainActivity.java
. عبارة import
هذه
يجب إزالته:
Kotlin
... import com.google.android.gms.common.api.GoogleApiClient ...
Java
... import com.google.android.gms.common.api.GoogleApiClient; ...
في Wear
نموذج طبقة البيانات، وعبارات import
مثل ما سبق
على سبيل المثال، ما يلي (الثاني مخصص
التعامل مع استثناءات المهام):
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; ...
تنفيذ واجهات العميل الجديدة
إزالة أي استخدام لـ GoogleApiClient
والواجهات المرتبطة بها (ConnectionCallbacks
،
OnConnectionFailedListener
وما إلى ذلك) واستبدال الآخر
عمليات التنفيذ للمستمعين مع إصداراتهم الجديدة. الطرق الفعلية
لها نفس الأسماء كما في السابق، لذا فإن التغيير الرئيسي
مشابه للمثال أدناه.
النشاط الرئيسي لعينة طبقة بيانات Wear (كما هو موضح في الاختلاف
في
GitHub) على سبيل المثال،
الواجهة "CapabilityApi.CapabilityListener
". ولكن الآن،
النشاط الرئيسي ينفذه
CapabilityClient.OnCapabilityChangedListener
في ما يلي مقارنة بين تعريفات الفئات.
في ما يلي مقتطف قبل استخدام الإصدار 11.8.0 من Google Play التالية:
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
في ما يلي مقتطف بعد استخدام الإصدار 11.8.0 من Google Play التالية:
Kotlin
class MainActivity : Activity(), DataClient.OnDataChangedListener, MessageClient.OnMessageReceivedListener, CapabilityClient.OnCapabilityChangedListener
Java
public class MainActivity extends Activity implements DataClient.OnDataChangedListener, MessageClient.OnMessageReceivedListener, CapabilityClient.OnCapabilityChangedListener
إزالة المستمعين وإضافتها
يتم تخزين كائنات العميل الجديد مؤقتًا ومشاركتها بين
GoogleApi
مثيل، لذا من غير الضروري الاحتفاظ بالعضو
المتغيرات العملاء غير مكلفين الإنشاء ولن يفقدوا
المستمعين.
في ما يلي مقتطف من طبقة بيانات Wear OS المعدَّلة النموذج:
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); }
طلب معلومات باستخدام واجهة برمجة تطبيقات "مهام Google"
قد تحتاج إلى طلب معلومات من خارج المستمعين يعدّلون المحتوى.
تطبيقك عند حدوث تغيير في البيانات. في هذه الحالات، يمكنك تقديم طلب باستخدام
عميل مثل
DataClient
، مع Tasks API
فئة نتيجة (أي Task<ResultType>
).
على سبيل المثال، كما هو موضّح في طبقة بيانات Wear نموذج، يمكنك استخدام Tasks API إيجاد العُقد المتصلة بأي إمكانيات معيّنة:
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(); }
للحصول على رمز إضافي يستخدم واجهات برمجة تطبيقات "المهام القابلة للارتداء" و"مهام Google"، يُرجى الاطّلاع على طبقة بيانات Wear عينة. وكمثال على استخدام المهام الصعبة خارج سلسلة واجهة المستخدم أو في إحدى الخدمات، يتوفّر خيار آخر. فيما يلي مثال على طريقة حظر الوصول إلى مهمة والحصول على النتيجة بشكل متزامن:
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); } }