مهندس برمجيات
في هذه الجلسة، سنتعرّف على نظرة متعمّقة فنية لتطوّر المربّعات التي تملأ الشاشة إلى تطبيقات Wear مصغّرة ديناميكية تشغل جزءًا من الشاشة.
سنستكشف المزايا الفنية لواجهة برمجة التطبيقات الموحّدة Jetpack Glance ومحرّك Remote Compose الجديد، وسنوضّح بالتفصيل كيف يتوافقان بسلاسة مع نهج Modern Android Development.
أخيرًا، سنشارك أحدث الإرشادات حول تجربة المستخدم ونستعرض استراتيجيات نقل عملية لمساعدتك في إنشاء الجيل التالي من واجهة المستخدم السريعة.
النص
مرحبًا بالجميع.
اسمي "فرانك"، وأنا مسؤول عن تجارب "لمحة سريعة" في Wear OS.
الساعات هي أجهزة أساسية ترافق المستخدمين طوال اليوم، واليوم سنشرح لك كيفية الاستفادة من تجربة التطبيقات المصغّرة الجديدة في Wear.
سنلقي نظرة على طريقتين لتقديم أهم الميزات مباشرةً إلى معصم المستخدمين، وسنفعل ذلك باستخدام أحدث واجهات برمجة التطبيقات المصمّمة لجعل عملية إنشاء التطبيقات لنظام التشغيل Wear OS مألوفة وبديهية لمطوّري برامج Android، مثلك.
سينضم إليّ على المسرح اليوم زميلي الرائع "يوري" الذي يشاركني المكتب نفسه، وذلك لنلقي نظرة على كيفية تحقيق ذلك.
مرحبًا، أنا "يوري شيمكي".
أنا مهندس في فريق Wear OS، وينصب تركيزي الرئيسي على العمل على واجهات برمجة التطبيقات Remote Compose.
سأقدّم لكم اليوم مقدّمة سريعة عن Remote Compose، ثم سأتحدّث أيضًا عن عملية نقل البيانات من "البطاقات" إلى "تطبيقات Wear المصغّرة".
والآن، سأترككم مع "فرانك".
رائع.
شكرًا، يوري.
نعلن رسميًا عن إتاحة استخدام التطبيقات المصغّرة على الساعات الذكية ضمن منظومة Android المتكاملة والموحّدة للتطبيقات المصغّرة، وذلك من خلال تحويل "المربّعات" التي تظهر بملء الشاشة إلى تطبيقات مصغّرة على Wear.
وبما أنّ هذه التجارب يتم إنشاؤها الآن باستخدام Jetpack Glance، يمكنك ملاحظة أنّها البنية الأساسية نفسها المستخدَمة في التطبيقات المصغّرة للأجهزة الجوّالة.
ستلاحظ أنّ إنشاء التطبيقات لنظام Wear سيصبح مألوفًا أكثر بالنسبة إليك في المستقبل.
ولإتاحة هذه التجارب، نعمل على تطوير حزمة واجهة المستخدم الأساسية.
تستند تطبيقات Wear Widgets إلى Remote Compose، وهو إطار عمل جديد في Android لواجهة المستخدم عن بُعد.
هذا يعني أنّه يمكنك أخيرًا استخدام واجهة برمجة تطبيقات تعريفية تتوافق بشكل وثيق مع Jetpack Compose لإنشاء تجارب خارج التطبيق، مثل التطبيقات المصغّرة.
توفّر ميزة Remote Compose رسومات حديثة وتنسيقات متجاوبة للتطبيقات المصغّرة مع ضمان الأداء وكفاءة البطارية.
ومن خلال فصل واجهة المستخدم عن عملية التطبيق، يتم تسلسل التطبيقات المصغّرة بأمان وعرضها بسهولة على مجموعة كبيرة من أجهزة Android.
هذا يعني أنّه يمكنك توفير هذه التجارب الغنية على جميع مساحات العرض المتوافقة عن بُعد بأقل جهد ممكن.
لتسهيل عملية الانتقال من "البطاقات" إلى التطبيقات المصغّرة قدر الإمكان، نقدّم حجمَين عاديَين للحاويات: صغير وكبير.
تم تصميم هذه التطبيقات المصغّرة لتتوافق بشكل وثيق مع تنسيقات التطبيقات المصغّرة المستندة إلى شبكة 2x1 و2x2 التي اعتدت عليها من خلال إنشاء تطبيقات مصغّرة على الأجهزة الجوّالة.
واعتبارًا من Wear 7 على بعض الأجهزة المصنّعة، ستظهر الآن "تطبيقات Wear المصغّرة" في لوحة يتم الانتقال فيها عموديًا إلى جانب التطبيقات المصغّرة الأخرى.
على سبيل المثال، إليك شكل "تطبيقات Wear المصغّرة" على ساعة Samsung Galaxy Watch.
تم تصميم بنية المنصة لتتوافق مع لوحات التنقّل العمودية، حيث ستعتمد الشركات المصنّعة للأجهزة هذا النمط في المستقبل.
ولا داعي للقلق بشأن ترك أي مستخدمين أو مستخدمين حاليين.
تم تصميم واجهات برمجة التطبيقات Jetpack Glance Wear لتوفير التوافق مع الأنظمة القديمة حتى الإصدار Wear 4.
على الأجهزة القديمة التي تتيح استخدام لوحة أفقية من التطبيقات المصغّرة أو المربّعات، سيتولّى النظام ذلك نيابةً عنك.
ما عليك سوى تحديد رغبتك في إتاحة وضع ملء الشاشة في الرمز البرمجي، وسيعرض النظام التطبيق المصغّر الكبير كـ "بطاقات" تقليدية بملء الشاشة على هذه الأجهزة.
والآن، سيشرح لنا "يوري" الرمز البرمجي ليوضّح لنا كيفية نقل المربّعات الحالية إلى تطبيقات Wear المصغّرة.
شكرًا يا فريد.
إذا كنت بصدد إنشاء تطبيق مصغّر جديد لنظام Wear من الصفر، فالأمر بسيط.
ما عليك سوى تحديد GlanceWearWidgetService وإنشاء واجهة المستخدم باستخدام Remote Compose.
أما إذا كان تطبيقك يتضمّن حاليًا مربّعًا في مرحلة الإنتاج، فستحتاج إلى نقل كل من الخدمات وواجهة المستخدم والبيانات.
لضمان إجراء عملية الانتقال هذه بسلاسة قدر الإمكان، وفّرنا مسارات تضمن تجربة سلسة للمستخدمين الحاليين.
بالنسبة إلى الخدمة، يمكنك الاختيار بين استراتيجيتَين: الخدمة المزدوجة أو الخدمة الفردية.
باستخدام الخدمة المزدوجة، التي ننصح بها، ستحتفظ بخدمة TileService الحالية لأجهزة Wear OS القديمة وتضيف خدمة GlanceWearWidgetService جديدة لنظام التشغيل Wear OS 7 والإصدارات الأحدث.
في المقابل، من خلال الخدمة الواحدة، يمكنك إنشاء خدمة GlanceWearWidgetService جديدة واحدة تتعامل مع كلا البروتوكولَين، وتعمل في وضع التوافق لترجمة التطبيق المصغّر إلى بطاقة على الأجهزة القديمة.
في كلتا الحالتَين، ستتمكّن من مواصلة الوصول إلى المستخدمين.
بل يؤثر فقط في الرموز التي تحتفظ بها في المستقبل.
وقد نشرنا للتو مستندات شاملة على موقع مطوّري برامج Android الإلكتروني توضّح بالتفصيل كيفية استخدام هذين النمطين ومتى يجب استخدامهما.
يمكنك الاطّلاع على هذه المقالة لمعرفة المزيد عن الاستراتيجية الأفضل لتطبيقك.
لنتحدّث الآن عن طبقة واجهة المستخدم.
عند نقل البيانات، يتغيّر نموذجك الذهني.
في السابق، كانت المربّعات تستخدم ProtoLayout، وهي مكتبة تم إنشاؤها حصريًا لمربّعات Wear.
من ناحية أخرى، تعتمد Wear Widgets على Remote Compose.
تتشارك Remote Compose الأساس نفسه مع واجهة مستخدم Jetpack Compose، باستخدام برنامج التجميع الأساسي ووقت التشغيل نفسهما.
وقد تم تصميمه ليكون مألوفًا، ويتطابق بشكل وثيق مع مكتبات واجهة مستخدم Compose، مثل Foundation وMaterial 3.
ولكن بدلاً من المربّع أو العمود أو النص، يمكنك ببساطة استبدالها بـ RemoteBox أو RemoteColumn أو RemoteText.
ستعتاد على كتابة "remote" كثيرًا في هذه الحالة.
ولتسريع سير العمل، أضفنا مجموعة كاملة من مكوّنات Remote Compose الجاهزة للاستخدام والمصمّمة خصيصًا للأدوات.
هذا يعني أنّ تصاميم Wear Material 3 الحالية، بما في ذلك ما لديك في Figma، يمكن تكييفها بسهولة مع التطبيقات المصغّرة، ما يجعلها مألوفة لكل من المهندسين والمصممين.
لمعرفة مدى توافق هذه الأُطر، لنلقِ نظرة على مثال ملموس.
سننشئ مكوّن التطبيق الخاص بنا فوق زر التبديل في Material 3.
على اليمين، لدينا مكوّن Wear Compose العادي الذي يمكنك كتابته داخل تطبيقك، وعلى اليسار إصدار Remote Compose.
// Wear Compose
@Composable
fun HistoryEraserButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
checked: Boolean = true,
onCheckedChange: (Boolean) -> Unit = {},
)// Wear RemoteCompose
@RemoteComposable
@Composable
fun RemoteHistoryEraserButton(
onClick: Action,
modifier: RemoteModifier = RemoteModifier,
checked: RemoteBoolean = true.rb,
onCheckedChange: Action = Action.Empty,
)لاحظ مدى تشابه الأنماط.
ومع ذلك، عند كتابة رمز Remote Compose، ستستخدم التعليق التوضيحي RemoteComposable.
وعند استخدام مَعلمات مألوفة مثل المُعدِّل والقيمة المنطقية، ستجد أنواعًا مكافئة لها في Remote Compose، مثل RemoteModifier وRemoteBoolean.
وتستخدم الإجراءات بدلاً من دوال lambda.
بدلاً من تحديد الرمز البرمجي المطلوب تنفيذه داخل دالة lambda، عليك الإعلان عن إجراء مثل تشغيل intent مؤجّلة أو استدعاء خدمة أو تعديل قيمة.
لننتقل إلى نص المكوّن.
ستلاحظون أنّ المظهر متناسق أيضًا.
يمكنك تطبيق نظام ألوان Material 3 على مكوّن Remote Compose تمامًا كما تفعل في Compose العادي، ما يتيح لك مطابقة التطبيق المصغّر مع الهوية البصرية لعلامتك التجارية في تطبيقك.
// Wear Compose
val colors = MaterialTheme.colorScheme
SplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser",
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
SwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { Text("History Eraser") },
secondaryLabel = { Text("Don't touch it!") },
)// Wear RemoteCompose
val colors = RemoteMaterialTheme.colorScheme
RemoteSplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser".rs,
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { RemoteText("History Eraser".rs) },
secondaryLabel = { RemoteText("Don't touch it!".rs) },
)وأخيرًا، لنطّلِع على النتيجة. واجهة المستخدم الناتجة هي بالضبط ما تتوقعه، زر إيقاف/تفعيل متحرك نظيف وسريع الاستجابة.
من الصعب معرفة الفرق.
لمساعدتك في تصميم تنسيقات التطبيقات المصغّرة وتكرارها والتحقّق منها بدون تشغيلها دائمًا على جهاز أو محاكي، أضفنا ميزة معاينة Compose للتطبيقات المصغّرة على Wear.
بما أنّ التطبيقات المصغّرة تعتمد على قيود الحاويات الخاصة بالمصنّع الأصلي للجهاز، مثل الحجم والشكل والحشو ونصف قطر الزاوية، فإنّنا نعتمد على التعليق التوضيحي العادي للمعاينة، ولكن مع موفّر مَعلمات إضافي لإدخال هذه الإعدادات.
@Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetSquirclePreview(
@PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
@Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRoundPreview(
@PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)توفّر المكتبة عمليات تنفيذ مُعدّة مسبقًا لموفّر PreviewParameter تتطابق مع أجهزة Wear OS في الواقع.
تتيح لك هذه التعليقات التوضيحية للمعاينة التحقّق بسهولة من التنسيق على أشكال مختلفة من الأجهزة.
بالإضافة إلى اختبار التنسيقات، يمكنك استخدام هذه المعاينات لإنشاء الصور الثابتة المطلوبة لأداة اختيار التطبيقات المصغّرة على الجهاز فقط.
@Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRectangularPreview(
@PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)توفّر المكتبة مَعلمة لشكل المعاينة المستطيل الذي يحاكي الحاويات المستطيلة الكاملة غير المقتصّة.
وإذا أردت معرفة كيفية عمل ذلك عمليًا، فقد حدّثنا نموذج تطبيق Horologist للوسائط ليتضمّن تطبيقًا مصغّرًا جديدًا يعرض واجهة برمجة التطبيقات هذه.
سنوضّح كيفية إضافة الإصدارَين الصغير والكبير من التطبيق المصغّر للوسائط.
يمكنك الاطّلاع على ذلك على GitHub لمقارنة رمز ProtoLayout القديم وتنفيذ Remote Compose الجديد جنبًا إلى جنب.
نحن متأكدون من أنّها ستنال إعجابك.
أخيرًا، لا يمكننا التحدّث عن هذا الموضوع بدون ذكر الذكاء الاصطناعي.
لتسريع عملية نقل البيانات، نشرنا مهارة جديدة لنقل البيانات من المربّعات إلى التطبيقات المصغّرة على GitHub.
يمكنك استخدامها مع الوكيل الذي تختاره، أو يمكنك إضافتها مباشرةً إلى "استوديو Android" باستخدام Android CLI.
android skills add wear-widgets
android skills add --allوالآن، سأترككم مع "فرانسوا" لإنهاء الجلسة.
شكرًا لك.
شكرًا، يوري.
كما ترون، فإنّ عملية تطوير المربّعات إلى تطبيقات Wear المصغّرة هي عملية بسيطة للغاية.
باختصار، من خلال الانتقال إلى Jetpack Glance Wear وRemote Compose، لا تقتصر على تحديث واجهة المستخدم، بل تنضم إلى منظومة متكاملة أكثر توحيدًا لبرامج Android المصغّرة.
يمكنك الآن إنشاء تطبيقات مصغّرة رائعة ومتوافقة مع الأنظمة القديمة باستخدام إطار عمل حديث وتوضيحي يتوافق تمامًا مع Jetpack Compose.
يمكنك البدء في نقل المربّعات اليوم من خلال الانتقال إلى دليل البدء على موقع "مطوّرو تطبيقات Android" الإلكتروني للاطّلاع على مزيد من التفاصيل.
نتطلّع إلى رؤية جميع التجارب التعبيرية السريعة التي تنشئها للساعات الذكية.
شكرًا جزيلاً على انضمامكم إلينا اليوم، ونتمنى لكم الاستمتاع ببقية المؤتمر.
شكرًا لك.
// Wear Compose
@Composable
fun HistoryEraserButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
checked: Boolean = true,
onCheckedChange: (Boolean) -> Unit = {},
)// Wear RemoteCompose
@RemoteComposable
@Composable
fun RemoteHistoryEraserButton(
onClick: Action,
modifier: RemoteModifier = RemoteModifier,
checked: RemoteBoolean = true.rb,
onCheckedChange: Action = Action.Empty,
)// Wear Compose
val colors = MaterialTheme.colorScheme
SplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser",
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
SwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { Text("History Eraser") },
secondaryLabel = { Text("Don't touch it!") },
)// Wear RemoteCompose
val colors = RemoteMaterialTheme.colorScheme
RemoteSplitSwitchButton(
checked = checked,
onCheckedChange = onCheckedChange,
toggleContentDescription = "Arm Eraser".rs,
onContainerClick = onClick,
modifier = modifier.fillMaxWidth(),
colors =
RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
checkedContainerColor = colors.errorContainer, …
),
label = { RemoteText("History Eraser".rs) },
secondaryLabel = { RemoteText("Don't touch it!".rs) },
)@Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetSquirclePreview(
@PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
@Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRoundPreview(
@PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)@Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRectangularPreview(
@PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)android skills add wear-widgets
android skills add --all