جوجل اللعب الفوري. إعادة بيع مدى الحياة

عندما تشارك في برنامج الوصول المبكر ، فأنت لا تعلم مقدمًا ما الذي سيحدث في النهاية. بالطبع ، تأمل أن تنطلق التكنولوجيا ، وأن يتقدم تطبيقك بالسوق وسيحصل على جزء من العلاقات العامة على Google I / O. وهذا دافع جيد لقراءة أكواد المصدر بدلاً من الوثائق في المرحلة الأولية ، والتي ، علاوة على ذلك ، يجب تنزيلها من الأرشيف السري.

في AppsConf ، أظهر Yevgeny Saturov ما يمكن أن تؤديه المشاركة في الوصول المبكر كمثال على تطوير تطبيق باستخدام التشغيل الفوري ، مع شرح جميع ميزات تطبيق Google Play Instant على طول الطريق. عند فك تشفير تقريره ، سنكتشف من أين جاءت حزم تطبيقات Android ، وما علاقة Dynamic Delivery به ، والتعرف على المكونات الإضافية Gradle الجديدة ، ومعرفة كيفية التعامل مع المفاجآت التي أعدها مطورو SDK لنا.


نبذة عن المتحدث: يعمل Evgeny Saturov ( saturovv ) في Surf ، وهي شركة متخصصة في تطوير نظامي Android و iOS المخصصين ، ومؤخراً ، تم تطويرها على Flutter. يوجين رفرفة هو متحمس ومؤسس FlutterDevPodcast.

رحلة قصيرة في التاريخ



قبل عامين ، جاء إلينا رجل رائع في Surf وقال: "لدينا تقنية لا يعرفها إلا القليل من الناس. ولديك عملاء وحالات مثيرة للاهتمام. دعونا ، سنقدم لك تقنيتنا ، ستقوم بدمجها في مكان ما ، وستحصل على تعايش رائع. سنقوم بترويج ذلك على Google I / O وسيكون الجميع على ما يرام. "

في الواقع ، فإن العمل مع برنامج الوصول المبكر هو خنزير في كزة . عليك أن تتعامل مع الكود الخام ، والذي ، بالطبع ، لا يعمل دائمًا كما هو موصوف وموصف. في حالتنا:

  • تم تسليم جميع القطع الأثرية في شكل أرشيف ZIP ، والذي كان لا بد من تنزيله كل بضعة أيام من وحدة تخزين فائقة السرية ويتم تحديثه على جهاز محلي يدويًا فقط.
  • يمكنك العمل فقط في "الكناري".
  • لا توجد أي مستندات تقريبًا ، وهي محرّر مستندات Google غير الموزعة والمنتشرة فقط ، وغالبًا ما تشبه تدفق أفكار المطورين.
  • بطبيعة الحال ، لن يكون النشر في الطعام أمرًا مستحيلًا - لا يمكن تحقيق ذلك إلا بعد ظهور التكنولوجيا في الإصدار العام. وهذا يعني أن النشر بأكمله موجود فقط في مسار ألفا.
  • من المحتمل أنه بعد إصدار عام ، سيتضح أنه تمت إعادة كتابة SDK بالكامل دون دعم التوافق مع الإصدارات السابقة. تحصل على واجهات وواجهات برمجة تطبيقات مختلفة تمامًا - تحتاج إلى إعادة كل شيء مرة أخرى.

هذا ملخص موجز لكيفية مشاركتنا في برنامج الوصول المبكر.

أصبح كل هذا ممكنًا بفضل شريكنا العادي - شركة Labyrinth - أكبر متجر للكتب والقرطاسية على الإنترنت في روسيا. انضموا إلى المشروع ، ولا حتى التأكد من وجود أي فائدة في النهاية. وحقيقة أن Surf ، في عام 2017 ، كاستوديو ، كانت جزءًا من برنامج Google Certified Agency Program. لسوء الحظ ، تم إغلاق البرنامج هذا العام.

تطبيقات أندرويد الفورية


في عام 2017 ، حتى يتم تشغيل التطبيق دون تثبيت ، يجب نشره في وحدات بشكل صحيح.



لدينا إضافات Gradle جديدة تقوم بإنشاء القطع الأثرية المقابلة:

  • وحدة التطبيقات الفورية - مكون إضافي للتطبيق أنشأ أرشيف ZIP مع ملف APK ، واحد لكل وحدة من ميزات التطبيق ؛
  • وحدة التطبيقات القابلة للتثبيت - تم إنشاؤها APK.

لقد ظهر تسلسل هرمي ثنائي المستوى من وحدات الميزات. يمكن أن يكون هناك دائمًا وحدة واحدة فقط للميزات الأساسية وتحتوي على جميع الكود الأساسي المتاح لجميع الميزات والموارد والتبعيات وما إلى ذلك. احتوت وحدة ميزة المستوى الأعلى على تنفيذ شاشات محددة.

لكنها كانت طويلة ومكلفة لعدة أسباب:

  • هيكل وحدات جامدة في حد ذاته هو وجود قيود كبيرة. من الصعب أن نتخيل أن أي شركة كبيرة ستحول تطبيقها النامي الذي يعمل بشكل جيد إلى كومة من وحدات التدخين على مر السنين فقط لدعم تقنية جديدة لا تزال غير معروفة ما إذا كانت ستقلع أم لا.
  • تقييد صارم على حجم التجميع ، أي ، يجب ألا تتجاوز ميزة واحدة 4 ميغابايت. هذا الحد صغير موضوعيًا ، وأحيانًا لا يمكن بلوغه تمامًا ، على سبيل المثال ، بسبب التبعيات الشديدة أو شيء من هذا القبيل.
  • تأكد من استخدام AppLinks ، لأن هذه هي الطريقة الوحيدة للدخول إلى التطبيق الفوري. نقر المستخدم على الرابط من البريد والمراسلة ونتائج البحث ووصل إلى شاشتك من خلال اعتراض الرابط.
  • وأخيرا ، هناك عدد كبير من القيود التقنية. في البداية كان من المستحيل استخدام NDK. لا يمكنك إرسال إشعارات الدفع وتلقي البيانات الحساسة وتغيير إعدادات الجهاز وبدء عمليات الخلفية. لا يمكن استخدام الخدمات وأجهزة استقبال البث وموفري المحتوى. النشاط فقط.

المهمة الرئيسية للتطبيق الفوري هي مجرد عرض لواجهة المستخدم وليس أكثر. كانت إعادة بيع المباني مؤلمة للغاية ، وبالتالي لا تزال هذه القصة غير موجودة على الإطلاق تقريبًا في الإنتاج.

لكن في الإنصاف ، أعطى تطبيق التطبيق الفوري في Labyrinth زيادة بنسبة 5 ٪ في المشتريات من خلال عميل الهاتف المحمول.

2019. Google Play Instant


لقد مر عامان ، في ساحة 2019 - لا تزال التطبيقات الفورية موجودة ، ولكن ليس كتقنية مستقلة. ما زال هذا نادرًا جدًا في الإنتاج ، ولم أكن أبحث عنه عن قصد ، لكنني أعرف بعض الأمثلة فقط: Sports.ru ، Vimeo. من غير المرجح أن تعتمد Google على هذه النتيجة عندما أعلنت عن هذه التقنية.

الآن يسمى التطبيق الفوري بشكل مختلف - Google Play Instant. ساعد تغيير الاسم في التخلص من الوثائق غير ذات الصلة. إذا رأيت تطبيق Android Instant ، فمن الواضح أن هذا لم يعد ذا صلة.

بالإضافة إلى الاسم ، فقد تغير كل شيء آخر ، بما في ذلك هيكل وحدات. أصبحت المطالب أكثر ولاءً . تدمج التكنولوجيا بطريقة مختلفة تمامًا في المشروع ولا تتطلب إعادة هيكلة مؤلمة ، وهو أمر جيد بالتأكيد.
لكن الأمر الأقل وضوحًا والأكثر أهمية في رأيي هو أن هذه التكنولوجيا ، التي بقيت مناسبة ونادرة للغاية ، أصبحت منشئ مجموعة كاملة من التقنيات ، التي أصبحت الآن جزءًا منها.
في البداية ، وضعت Google التطبيق الفوري كتقنية تجذب الأشخاص إلى الأعمال التجارية ، وليس التطبيقات. كان هناك مبدأ توجيهي في التصميم يمنع تطبيقات الهبوط باستخدام زر واحد "تنزيل التطبيق الكامل". ولكن تم حل مشكلة أساسية أخرى ، وأعتقد أن هذا قد حدث بالصدفة.

في شباط (فبراير) من هذا العام ، فإن جهاز Samsung Galaxy S10 + المميز مع ذاكرة تبلغ سعتها 1 تيرابايت قد رأى النور. مجرد التفكير في الأمر - تيرابايت واحد! لماذا تحتاج كثيرا؟

وفقًا لإحصاءات Google الرسمية ، زاد متوسط ​​حجم ملفات APK على مدار الـ 7 سنوات الماضية 5.5 مرة.



بناء حجم يهم حقا ، وتبين البحوث على هذه الإحصاءات:

  • كل 6 ميجابايت إضافية من التجميع تقلل التحويل في التثبيت بنسبة 1٪ ؛
  • يتحقق 70٪ من المستخدمين من حجم التطبيق قبل التنزيل ؛
  • يهتم 50٪ من المستخدمين بحجم المساحة التي سيشغلها التطبيق على الجهاز بعد التثبيت.

هذا الأمر أكثر أهمية إذا كان جمهورك المستهدف أشخاصًا من كبار السن ، أو ليس لديهم دخل مرتفع للغاية ، أو كانت هذه أسواق ناشئة.

يصعب تجاهل هذا الأخير ، لأنه في عام 2018 كانت الهند هي التي أظهرت زيادة لا تصدق في المنشآت.



يرجى ملاحظة أن هناك عددًا قليلًا جدًا من أنظمة التشغيل iOS ، وأن العدد الإجمالي لعمليات تثبيت تطبيقات Android يتجاوز ذلك في الولايات المتحدة الأمريكية والبرازيل وإندونيسيا مجتمعين.

أصبح من الواضح الآن المشكلة التي يمكن حلها باستخدام Google Play Instant. يمكنك الذهاب إلى شروط غير مفهومة.

حزمة تطبيقات Android


حزمة تطبيقات Android - تنسيق جديد لنشر التطبيقات على Google Play. في الداخل ، لا يختلف كل شيء تمامًا عن ملف APK: كل ملفات dex نفسها ، البيان ، الموارد ، الأصول ، إلخ. إلخ ولكن هناك أيضًا بيانات التعريف ، والتي لا تصل إلى جهاز المستخدم.



يتم تمثيل البيانات التعريفية بثلاثة ملفات: resources.pb ، stocks.pb ، native.pb. في الواقع ، هذه هي جداول مراسلات الموارد الموجودة في إعدادات التجميع والتكوين للأجهزة.

تسليم ديناميكي أندرويد


يعلم الجميع بوجود تطبيق للتوقيع بواسطة Google Play. ولكن ليس الجميع على استعداد لتخزين مفتاح إصدار تطبيقهم على Google Play ، لأنه لن يكون هناك عودة إلى الوراء. من المستحيل الحصول على توقيع التطبيقات من Google Play.

بعد إعطاء مفتاح الإصدار إلى Google Play ، لن تتمكن أبدًا من التوقيع على طلبك كما كان من قبل ، إلى جانبك. ولكن في مقابل ذلك ، يمكنك الاستفادة الكاملة من Android App Bundle كتنسيق. وستظهر الآن عملية توقيع التجميع مختلفة بعض الشيء.



لا يزال بإمكانك التوقيع على التجميع قبل الإصدار على Google Play ، لكنك ستوقعه باستخدام مفتاح التحميل ، وهو أمر غير فريد. يمكن استرجاعها من وحدة التحكم ، وإعادة إصدارها إذا تم اختراقها أو فقدها. أنت تعطي مفتاح الإصدار الخاص بك إلى وحدة التحكم وتودعه - ستوقع Google الآن على التجميع لك وستقسم أنه سيحافظ على أمان مفتاحك.

ومع ذلك ، إذا لم تمنح مفتاح الإصدار لـ Google Play ، فلن تتمكن من استخدام أي شيء في مشروعك سيتم مناقشته بشكل إضافي. تقوم Google بتشديد الخناق ، وحتى التطبيق الفوري ، دون التخلي عن المفتاح ، سيفشل الآن في النشر.

في الواقع ، هذا ليس مضحكا على الإطلاق ، لأن الأشخاص الذين اشتروا الترويج الفوري للتطبيق ودخلوا القصة بأكملها أعادوا تشكيل تطبيقاتهم ، لكن لسبب ما لم يتمكنوا من إعطاء مفتاحهم إلى Google Play (أو أن قسم الأمن يعارض بشكل قاطع أو لأسباب موضوعية أخرى) وجدت نفسها في موقف حيث لم يعد بإمكانهم دعم هذا القرار. تم إلقاء مئات الساعات من العمل فعليًا في سلة المهملات.

2014. Split APK Support يظهر في Android Lollipop


نظرًا لأننا نشعر بالحنين إلى اليوم ، فسوف نعود حتى في وقت مبكر إلى الماضي - في عام 2014.

ما زلت أتذكر كيف أن جهاز Android Lollipop الذي طورته NEXUS 5 ، وهو أفضل هاتف في العالم ، قد طار بتصميمه المذهل الذي بدا وكأنه مجرد قصف. ولكن كانت هناك تغييرات لم يلاحظها الكثيرون - وهذا دعم لـ Split APK.

Split APK - آلية تسمح لك بتقسيم التطبيق إلى ملفات APK صغيرة ، والتثبيت على جهاز واحد ، وجعلها تتصرف كتطبيق واحد.

تذكر هذا ، والمضي قدما.

Android Dynamic Delivery هو تنسيق توزيع تطبيق جديد على Google Play.



لقد اعتدنا على الحصول على ملف APK ، والآن تظهر حزمة تطبيقات Android ، كبديل. تعمل AAB كمولد للحاضنة في ملفات APK المبسطة جدًا. تقوم AAB بطرح كعكة APK ، والتي يمكن بعد ذلك استخدامها كتطبيق منتظم عن طريق تثبيتها بالتوازي.

دعونا نرى أي نوع من APK هو عليه.



على الأقل ، هذا هو APK الأساسي ، الذي يلعب نفس الدور كما هو الحال في التطبيق الفوري: إنه الرمز الأساسي والموارد الأساسية ومنطق العمل الذي يتم تفتيشه بين جميع الميزات.

تظهر أيضا:

  • ملفات APK ، التي تشبه بشكل مثير للريبة بادئات مُعدِّلات موارد الرسوم (الصف العلوي في المخطط).
  • عائلة أخرى من APKs تذكرنا بنيات المعالج.
  • توطين ملفات APK.

منذ حوالي عامين ، عندما لم تكن الرسومات المتجهة واسعة الانتشار ، احتوت العديد من التطبيقات في الغالب على موارد نقطية ، تم قطعها إلى كثافات بكسل مختلفة على الشاشات. التجمع يمكن أن تصبح ثقيلة جدا. قام المستخدمون بتنزيل كل هذه الموارد ، وتم تخزين معظمها على الجهاز بالوزن الزائد.

تسمح هذه الآلية الآن للمستخدم بتلقي مجموعة الموارد اللازمة لجهازه فقط. يأتي شخص إلى Google Play ، ويحدد التطبيق ، ويفهم Google Play خصائص جهاز المستخدم ، ويعطي مجموعة من ملفات APK المبسطة المطلوبة - APK واحد من كل فئة.

أنواع التسليم الديناميكي APK:

  • واحد واحد فقط قاعدة APK.
  • الحد الأقصى لتكوين APK هو ثلاثة أنواع: res * x ، الأصول * y ، lib * z. هنا: x هو عدد معدّلات الموارد المستخدمة ؛ y هو عدد أنواع البنية المستخدمة ؛ z هو عدد اللغات المحلية. على سبيل المثال ، إذا كان المشروع لا يستخدم الكود الأصلي والمكتبات الأصلية ، فلن تكون هناك فئة مرتبطة بالرمز الأصلي ، وسيبقى ملفان APK.
  • ميزة ديناميكية غير محدودة APK.

سيتم مناقشة APK الديناميكي بمزيد من التفاصيل أدناه. لكن أولاً ، سنقول وداعًا لـ Split Block.

وداعا سبليت


يمكنك القول أنه في وقت سابق كان بإمكانك فعل شيء مشابه ، حيث تولد مجموعة من ملفات APK يدويًا مع مجموعة الموارد الصحيحة فقط ، ثم تم نشرها يدويًا في Google Play.

android { splits { density { enable true exclude "ldpi", "xxhdpi", "xxxhdpi" compatibleScreens 'small', 'normal', 'large', 'xlarge' } } } 

هذا المشروع في حد ذاته أمر مشكوك فيه إلى حد ما ، والآن يتم تجاهل كل هذا بكل بساطة. إذا قمت بإنشاء حزمة تطبيقات Android ، فستظهر كتلة Bundle ، والتي تتيح لك تعطيل تقسيم المشروع يدويًا إلى إحدى الفئات.

 android { bundle { language { enableSplit = false } density { enableSplit = true } abi { enableSplit = true } } } 

يمكنك تحديد أن التطبيق يدعم ، على سبيل المثال ، اللغة الروسية أو الإنجليزية فقط ، وتخطي هذه الخطوة أثناء التجميع.

الأكثر اهتمامًا ، ربما ، يفكرون الآن في ما يجب فعله مع preLollipops. فقط في Android 5 ظهر الدعم لـ Split APK. نحن بحاجة إلى الخروج بطريقة ما من هذا الموقف ، لأن Min SDK لا يزال بعيدًا عن 21.

بالنسبة إلى preLollipops ، يكون الموقف خرقاء تمامًا ، لكن ممكن فقط. يجمع Google Play ملفات APK متعددة لـ preLollipops ، والتي تشمل جميع أنواع مجموعات ملفات APK للتهيئة. هناك APK واحد فقط ، ولكن هناك الكثير من الخيارات.

حزمة تطبيقات Android تغير حياتنا


و مهم جدا أولاً ، قد يكون من الأسهل بكثير إنشاء مشروع ، خاصة إذا كنت تستخدم لإنشاء Split APK يدويًا. ولكن وفقا لملاحظاتي لا يوجد الكثير من هؤلاء الناس.

ثانياً ، لم تعد تخاطر بفقدان مفتاح التسوية أو الإخلال به. لن تكون هناك مأساة كبيرة ، إذا فقدت مفتاح التحميل الخاص بك ، يمكنك تذكره وإعادة إصداره.

لن نوجه أصابع الاتهام - في الجزء العلوي من تطبيق Google Play الروسي ، توجد تطبيقات لها مفاتيح إطلاق لفترة طويلة على w3bsit3-dns.com ، ويتم توقيع جميع التجميعات المخصصة باستخدام مفتاح إصدار ، ولا يوجد شيء يمكن القيام به في هذا خلال السنوات الخمس القادمة. يبقى الانتظار حتى يتم الانتقال إلى Signing V3 ، والتي ظهرت بـ 28 واجهة برمجة تطبيقات فقط.
الميزة بلا شك في حزمة تطبيقات Android: يتوقف المستخدمون عن إنفاق حركة المرور ومساحة القرص على الموارد التي لا يحتاجون إليها. هذا يعزز إلى حد كبير الاحتفاظ بالتطبيق.
ولكن إذا كان لديك كل الرسومات الموجودة في المتجه ، وموقعين محليين ، وليس هناك مكتبات أصلية ، فستكون الفائدة مجهرية.

وحدة الميزة الديناميكية


وحدة الميزات الديناميكية هي وحدة وظيفية لا يتم توفيرها عند تثبيت التطبيق ، ولكن يتم تنزيلها من Google Play وتثبيتها فقط عند الطلب.

هذه الوحدات هي على قدم المساواة مع APK الأساسية.



من المهم أن تحتوي كل وحدة من وحدات الميزات نفسها أيضًا على مجموعة من إعدادات Split APKs. وفقًا لذلك ، قد يزيد العدد الإجمالي لملفات APK عن القياس. ولكن هذا ليس مصدر قلق على الإطلاق ، فإن Google Play تفعل ذلك.

تطبيقات وحدات الميزة الديناميكية:


الميزات التي تستخدمها نسبة مئوية صغيرة جدًا من الجمهور ، ولكنها مع ذلك مهمة لمنتجك. على سبيل المثال ، هذا تطبيق ترفيه محتوى ، ويستهلك 95٪ من مستخدميه المحتوى. ولكن هناك نسبة صغيرة جدًا من المحررين الذين ينشئون المحتوى. بالنسبة إليهم ، هناك محرر فيديو رائع يزن كثيرًا ، ويعمل رائعًا بشكل لا يصدق. بعد ذلك ، لا معنى لوزن التجميع للجميع والجميع ، يمكنك وضع هذه الميزة في "وحدة الميزات الديناميكية" ، وتوفيرها فقط لأولئك الذين يحتاجون إليها ، وتنزيلها لاحقًا.

الميزات الثقيلة التي لا تتعلق سيناريو استخدام التطبيق الرئيسي. على سبيل المثال ، الملاحة AR في خدمة خريطة. أي ميزة AR هي الأكثر لوضعها في وحدة الميزات الديناميكية.

الميزات التي يجب أن تكون متاحة للمستخدمين دون تثبيت التطبيق نفسه (على سبيل المثال ، اختيار منتج في الكتالوج ووضع طلب). صحيح ، هذا شيء يذكرنا بشكل مثير للريبة بكل شيء.
أصبح تطبيق Android Instant Apps الآن هو وحدة الميزات الديناميكية الممكّنة الفوري.
وبالتالي ، اتضح أن هناك نوعان من وحدات الميزات الديناميكية:

  • وحدات الميزات الديناميكية العامة هي وحدات وظيفية يتم تنزيلها وتثبيتها على جهاز منفصل عن التطبيق الرئيسي. انهم يعيشون هناك طالما يعيش التطبيق نفسه. حتى تقوم بحذفها ، ستكون وحدة الميزات الديناميكية.
  • الوحدات الديناميكية للميزات الديناميكية القابلة للتمكين الفوري - وحدات الوظائف المتاحة للتشغيل دون تثبيت على الجهاز. هذه الوحدة تعيش لفترة محدودة.

يمكن تمييز النوع الثاني من التطبيقات على Google Play بوجود زر "تجربة". عند النقر فوقه ، يتم استبدال عنوان URL الافتراضي ويمكنك أن ترى كيف يبدو التطبيق على الأقل كمثال لميزة رئيسية واحدة.

يمكن العثور على هذا في كثير من الأحيان في القسم مع الألعاب. هذا ملائم وأكثر قابلية للتطبيق من التطبيقات ، لأنه يمكنك تنزيل جزء صغير من اللعبة كعرض توضيحي ومعرفة ما يدور حوله ، هل يستحق قضاء وقتك في المرور ووقته.

هيكل وحدات


لقد قلت بالفعل أن الهيكل المعياري قد تم تبسيطه. لنرى كيف.

في البداية ، كان لدينا هيكل وحشي إلى حد ما. من بين أشياء أخرى ، كان يحتوي على وحدات فارغة ، على سبيل المثال ، كانت وحدة التطبيقات الفورية فارغة دائمًا ، ولم يكن بها أي كود ، ولا موارد ، ولكن ملف build.gradle فقط وكان هذا هو الحال.

فكر المطورون ، فلماذا ينتجون وحدات إضافية فقط من أجل جمع القطع الأثرية من نوع معين. ورأوا ذلك ، وتم نقل الوظيفة إلى وحدة التطبيقات.

ولكن بعد ذلك ذهبوا إلى أبعد من ذلك وفكروا - لماذا نحتاج إلى Base Feature Module؟ هناك بعض المشكلات منه ، لأننا نقوم بتهيئة كل شيء هناك ، ومعرف التطبيق الخاص به مختلف. تأتي العكازات من هنا ، على سبيل المثال ، نقل معرف التطبيق من وحدة التطبيقات إلى وحدة الميزة الأساسية ، واستبداله كمعرف تطبيق حقيقي للتطبيق بحيث يتعقب كل شيء في Crashlytics ، إلخ.

نتيجة لذلك ، اتضح مثل هذا.



لقد تركوا وحدة التطبيقات ، المرفقة بها وحدات الميزات - وهذا كل شيء!

لا تنقل مشاعري عندما اكتشفت ذلك. قال الشباب من المسرح الكبير أن لديهم تقنية رائعة: "لنقطع جميع التطبيقات إلى هذا الهيكل!" ولكن هذا لا يعمل لمدة 5 دقائق ، ولكن العمل مع عواقب وخيمة.

في عام 2017 ، لم يكن وجود تطبيق مترابط من العار. كانت المتاهة هكذا ، ثم لم تصل إلى الإصدار العام ، لكنها كانت في مرحلة تجريبية. في الوقت الذي شاركنا فيه في برنامج الوصول المبكر ، كان هناك بالفعل حوالي 90 شاشة هناك. لقد أمضينا شهرين إضافيين في إعادة البناء والاختبار والتأكد من أن كل شيء يعمل حقًا.

وبعد ذلك يقولون: "نحن أذكياء للغاية ، ويمكن القيام بذلك أسهل بكثير . "

لكن العودة إلى النثر.

التكوين المهد


لدعم التكوين الجديد ، نحتاج أولاً إلى سرد جميع وحدات الميزات الديناميكية في ملف build.gradle لوحدة التطبيق في كتلة Android:

 //  build.gradle app- android { dynamicFeatures = [":dynamic_feature", M:dynamic_feature2M] } 

بعد ذلك ، في ملف build.gradle لكل وحدة من الميزات الديناميكية ، اكتب التبعية على وحدة التطبيق:

 //  build.gradle  dynamic feature- dependencies { implementation project(':app') } 

من حيث المبدأ ، لا شيء معقد. ولكن هناك أيضا تكوين من المظاهر.

التكوين واضح


في بيان وحدة التطبيق ، يمكننا ضبط العلامة الحقيقية للإشارة إلى وجود ميزة تمكين فوري واحد على الأقل في هذا التطبيق:

 //   app- <dist:module dist:instant="true|false" /> 

إذا لم تكن هذه العلامة موجودة ، فلن يكون من الممكن تضمينها في المسار المقابل على Google Play.

بالإضافة إلى ذلك ، هناك أيضًا تكوين واضح لكل وحدة من الميزات الديناميكية بشكل فردي ، حيث توجد المزيد من الإعدادات:

 //    dynamic feature- <dist:module dist:instant="true|false" // Instant-Enabled  dist:onDemand="false|true" // ,         dist:title="@string/feature_modulejnstall_name"> //   <dist:fusing dist:include="true |false" /> //,      APK  preLollipop </dist:module> 

أول onDemand بعض الشيء ، لأن onDemand هو الميزة الأساسية المعتادة ، onDemand هي نفس الميزة onDemand للتثبيت.

العنوان - الاسم التقني للوحدة ، وفقًا لذلك ، بعد أن تم ترميزها في تطبيقنا ، سنضخ هذه الوحدة من Google Play.

معلمة include هي معلمة preLollipops. إذا قمت بتعيينها على "خطأ" ، فلن يرى المستخدمون preLollipops هذه الميزة ولن يتمكنوا من استخدامها.

تكوين مشاريع Gradle


كانت حياة المكون الإضافي Instantapp والمكون الإضافي للميزات قصيرة جدًا ولكنها نابضة بالحياة. استمروا أقل من عامين. منذ مارس من هذا العام ، لم تعد معتمدة.

يوجد الآن وحدة نمطية ديناميكية واحدة فقط نستخدمها:
 apply plugin: 'com.android.dynamic-feature' 

تكوين المشروع في وحدة التطبيق فقط


نقطة مهمة: كل الإعدادات المتعلقة بالتوقيع (توقيع التكوين) ، التجميع (تكوين ProGuard) ، versionCode و versionName يجب القيام بها فقط في وحدة التطبيق build.gradle.
خلاف ذلك ، سيتم تجاهلها. تجنب تحديد أي من كتل التكوين هذه في ملفات build.gradle لوحدات الميزات الديناميكية.

جوجل تلعب لحظة


الآن لدينا ما يلي.

تم تبسيط متطلبات الهيكل المعياري إلى الحد الأقصى هذه أخبار جيدة حقًا لأولئك الذين لم يشاركوا بعد. الآن يمكنك أن تجرب ، حتى لو كان لديك تطبيق له هيكله الخاص. هذا لن يؤثر عليك على الإطلاق ، يمكنك فقط إرفاق الوحدة في الأعلى ، وسيعمل كل شيء بشكل جيد.

أصبحت القيود المفروضة على حجم التجمع أكثر ولاء. إذا كان قبل ذلك كان 4 ميغابايت ، الآن:

  • وحدات الميزة الديناميكية غير محدودة في الحجم ؛
  • يمكن أن تستغرق وحدات الميزات الديناميكية التي يتم تمكينها حاليًا ما يصل إلى 10 ميغابايت.

ولكن الآن هناك مقياس تدريجي.



إذا الميزة الخاصة بك:

  • أكثر من 10 ميغابايت ، ثم آسف ؛
  • من 4 إلى 10 ميغابايت - يمكن الوصول إليها بواسطة الزر "تجربة" من Google Play وهذا كل شيء ؛
  • أقل من 4 ميغابايت - تتوفر جميع وسائل جذب المستخدمين إلى وحدة تمكين البحث الفوري (بدء التشغيل من الإعلانات أو الارتباط أو الرسائل أو ما إلى ذلك).

ظهرت آلية لتحميل الوحدات - Play Core API. قلة من الناس يعرفون أن التطبيق الفوري كان يتم تثبيته من خلال Chrome.

 @Override public boolean maybeLaunchInstantApp(Tab tab, String url, String referrerUrl, boolean isIncomingRedirect) { if (tab == null || tab.getWebContents() == null) return false; InstantAppsHandler handler = InstantAppsHandler.getInstance(); Intent intent = tab.getTabRedirectHandler() != null ? tab.getTabRedirectHandler().getInitialIntent() : null; if (isIncomingRedirect && intent != null && intent.getAction() == Intent.ACTION_VIEW) { Intent resolvedIntent = new Intent(intent); resolvedIntent.setData(Uri.parse(url)); return handler.handleIncomingIntent(getAvailableContext(), resolvedIntent, ChromeLauncherActivity.isCustomTabIntent(resolvedIntent)); } else { ... } return false; } 

هذا جزء حقيقي من التعليمات البرمجية من Chrome لنظام Android ، والذي اعترض رابط تطبيقك الفوري ، وذهب إلى Google Play واستبدل تطبيقات فورية من هناك. إذا تم الكشف عن التطبيق الفوري ، فقد فتح النشاط بطريقة أو بأخرى ، حيث تم تشغيل التطبيق الفوري.

وبالتالي كانت هناك مشاكل كبيرة مع المتداول هذه الميزة. مع Samsung ، هذه قصة مختلفة تمامًا ، وأظن أن متصفحها المدمج لديه امتيازات أكثر قليلاً من Chrome. لم يعمل التطبيق الفوري هناك حتى آخر مرة.

Play Core Library يتيح لك نسيان مشاكل التسليم. يمكنك فقط توصيله كحزمة:

 implementation 'com.google.android.play:core:1.4.0' 

وقم بتنزيل وحدات الميزات التي تحتاجها من Google Play.

تحتوي المكتبة على بناء جملة وظيفي إلى حد ما يسمح لك بتنزيل الوحدات النمطية واحدة تلو الأخرى:

 val splitInstallManager = SplitInstallManagerFactory.create(context) 

أو على الفور حزمة من عدة:

 val request = SplitInstallRequest .newBuilder() .addModule("feature1") .addModule("feature2") .build() 

شنق المستمع:

 splitInstallManager .startInstall(request) .addOnSuccessListener { sessionId -> ... } .addOnFailureListener { exception -> ... } 


إظهار هذا في واجهة المستخدم والرد على حقيقة أن الوحدة قد تم تثبيتها.

تعتبر مكتبة Play Core بداية جيدة:

  • أخيرًا ، يمكنك التوقف عن الأمل في مواجهة Google Chrome.
  • يمكنك إثبات تحميل الوحدات النمطية على واجهة المستخدم بالطريقة التي تريدها.
  • من الممكن تحميل وحدات الميزات على دفعات.
  • هناك طريقة لمعالجة الأخطاء التي تحدث عند تنزيل وحدة الميزات وتثبيتها بمرونة.
  • لا تحتاج حتى إلى إعادة تشغيل التطبيق بعد تثبيت الميزة ، لأنه يوجد SplitCompat.install() - يمكنك الاتصال به ويمكنك الوصول على الفور إلى الفئات من الميزة المثبتة حديثًا مباشرة.

لكنني سأخدعك إذا قلت إن مكتبة Play Core لن تجعلك تعاني:

  • الرمز مبهم ولا يتم توثيقه بأي شكل من الأشكال.
  • الأحداث من جميع جلسات التحميل النشطة تأتي إلى واحدة SplitInstallStateUpdatedListener - تحتاج إلى فرزها يدويا. من الضروري حفظ معرف الجلسة في مكان ما مسبقًا ، مما يؤدي في النهاية إلى رمز غير جميل.
  • الخرقاء ، إدارة الدولة الزائدة ومعالجة الأخطاء: 9 حالات ممكنة ، 10 أخطاء محتملة. يمكن تفسير مجموعات من هذه الأخطاء والحالات بشكل مختلف ، ويتم إرجاع جميع الحالات والأخطاء كما int.
  • لا توجد إمكانية لإجراء اختبار عادي لتنزيل وتثبيت الميزات على جهاز محلي - وهذا ببساطة مستحيل.

الخيار الوحيد هو تضمين التصميم الخاص بك على Google Play في قناة الاختبار الداخلية وتجربة ما حدث. إذا وجدت نوعًا من الأخطاء ، فابدأ العملية بأكملها مرة أخرى ، وانشر التحديثات وحاول المزيد. إذا كنت تريد التحقق من كيفية عمله دون إنشاء ، فستحصل على الخطأ "-2" ويمكنك فقط تخمين معنى ذلك. هذه هي المشكلة الأكثر شيوعًا في المستودع مع العينات الرسمية من الميزات الديناميكية من Google.

لا توجد ممارسة جيدة للتنقل بين الوحدات النمطية للميزة. في الأمثلة الرسمية ، التي توضح كيفية حدوث التفاعل بين الوحدات النمطية للميزات ، تقترح أن يتم حل الموقف بكل بساطة: قم بتشغيل التبعية من وحدة إلى أخرى. كل اتجاه له اعتماده الخاص ، لماذا أعود؟



ولكن بعد ذلك تضيع كل فوائد الانقسام إلى وحدات. لقد تحولنا إلى وحدات قبل وقت طويل من الحاجة إلى حل هذه المشاكل. وقد فعلوا ذلك جزئيًا لأنه يبسط العمل باستخدام قاعدة الكود للمطورين عديمي الخبرة الذين ، بسبب قلة الخبرة ، يمكنهم استخدام نشاط التوقيع مع نشاط أساسي - ثم يبحثون عنه لمراجعة الكود.

إذا قمت بتوصيل جميع الوحدات مع التبعيات لأعلى ولأسفل ، فإن Google فقط هي التي ستستفيد من ذلك ، والتي لن تضطر إلى التفكير في أي شيء حول الملاحة.

لقد فكرنا لفترة طويلة في كيفية القيام بذلك ، وفي النهاية توصلنا إلى حل لا يزال يجعلني أرتعش. يطلق عليه Class.forName - إنشاء مثيل ClassPath باستخدام ClassPath الكامل ، والذي ينقطع عن طريق إعادة تسمية فئة أي حزمة من مسارها ، إلخ.

 abstract class ActivityCrossFeatureRoute { override fun prepareIntent(context: Context): Intent? { try { return Intent(context, Class.forName(targetClassPath())) } catch (e: ClassNotFoundException) { Logger.e("Activity with the following classpath was not found in the current " + "application: ${targetClassPath()}. If this activity is the part of Dynamic Feature, " + "please check if this Dynamic Feature is downloaded and installed on the device" + "successfully.") } return null } } 

شعرت بالخزي من إخبار أي شخص بهذا الأمر حتى دخلت مستودع التطبيق Plaid ورأيت أنهما قد قاما بحل مشكلة التنقل بنفس الطريقة ونصحت الجميع بالقيام بذلك على Stack Overflow.

تعد Plaid واحدة من أروع حالات العرض ، حيث تحاول Google جميع أحدث اتجاهاتها ، والرسوم المتحركة الرائعة ، وحيل التصميم ، وأحدث مكونات واجهة المستخدم ، وعلى وجه الخصوص ، الوحدات.

الكثير ، حقا الكثير من الأخطاء ، والهندسة ، والخشونة. لن تضطر إلى البحث عن الأخطاء لفترة طويلة.

  • لا يمكن الوصول إلى الموارد من وحدة التطبيق إلا على طول المسار الكامل.

بدلاً من كتابة مثل هذا: R.string.primaryColor ، تحتاج إلى كتابة مثل هذا في كل مرة في التعليمات البرمجية: ru.appname.package.R.string.primaryColor . بطريقة مختلفة ، لن تنجح البنية ، وهنا هو الرابط لتعقب القضية الرسمي.

  • المشكلة في تشغيل JobScheduler على أجهزة O +. الحل الرسمي هو تشغيل TestJobSchedulerService يدويًا:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Intent serviceIntent = new Intent(this, TestJobSchedulerService.class); startService(serviceIntent); } 

  • خطأ في تجميد البيان عند توصيل مكتبات الطرف الثالث ، على سبيل المثال ، Firebase ، Fabric ، حزم AndroidX ، إلخ.

كلهم يستخدمون معرفات تطبيق العناصر النائبة في البيان. تم إدراج معرف التطبيق بشكل غير صحيح هناك ، وبسبب عدم تجميد البيان ، يتعذر على Android Studio العثور على النشاط الافتراضي ، وتبحث عن المشكلة لفترة طويلة حتى تجد النصيحة في متتبع المشكلة الرسمي - إعادة تعريف جميع مقدمي الخدمة وتحديد معرف التطبيق الخاص بك هناك.

 <provider android:name="com.crashlytics.android.CrashlyticsInitProvider" android:authorities="ru.app.name.crashlyticsinitprovider" tools:replace="android:authorities" /> <provider android:name="com.google.firebase.provider.FirebaseInitProvider" android:authorities="ru.app.name.firebaseinitprovider" tools:replace="android:authorities" /> <provider android:name="androidx.core.content.FileProvider" android:authorities="ru.app.name.fileprovide" tools:replace="android:authorities" /> 

  • استحالة تبعية متعددة على حزم الطرف الثالث هي واحدة من النقاط المفضلة لدي.

لنفترض أن وحدتي ميزة تحتويان على مكتبة طرف ثالث. لكن لا يمكنك إنشاء تبعية مباشرة لأنك تحصل على: org.gradle.api.GradleException: [:feature1, :feature2] all package the same library [com.lib.Name:VeryGoodLib] . الإجابة الرسمية : ماذا لو أشير في هذه الوحدات إلى إصدارات مختلفة من المكتبة.

ينصح مطورو البرامج: إضافة وحدة نمطية للميزات إلى التسلسل الهرمي ، حيث لا يوجد سوى تبعية على مكتبة تابعة لجهة خارجية ، وجعلها تعتمد على وحدتي ميزة المصدر.

  • ذاكرة التخزين المؤقت استدعاء InstantApps.isInstantApp (السياق) في attachBaseContext ().

تعطل أمثلة التعليمات البرمجية من وثائق Android Developers ، ببساطة لأنهم يقدمون attachBaseContext() للوصول إلى السياق من خلال this ، وإذا كان context==null ، فلا يمكنك حتى التحقق مما إذا كان InstantApps يعمل حاليًا أم لا.

 override fun attachBaseContext(base: Context) { super.attachBaseContext(base) if (!InstantApps.isInstantApp(this)) { SplitCompat.install(this) } } 

  • عرض ConstraintLayout عند استخدام Groups Barriers .

تخيل أنك مرت بكل شيء: تجميع التجميع ، خمنت أنه يجب أن يكون مضمنًا في قناة الاختبار على Google Play ، لم يعرض Google Play مربع حوار أحمر. بأيدي يرتجف ، تقوم بتثبيت هذا التجميع على الجهاز ، وتثبيت الميزة ، وانتقل إلى الشاشة - وترى أن التخطيط بأكمله قد تجمع في كومة في الزاوية اليسرى العليا. هذا لأنه إذا كنت تستخدم Groups Barriers ، فهناك طريقة getPackageName رائعة ، والتي تأتي لسبب ما بشكل غير صحيح. نتيجة لذلك ، كل ما تبذلونه من وجهات النظر ببساطة ليست في وضع. جميع القيود تطير ، وكل شيء يكمن بشكل عشوائي على الشاشة.

أخيرًا ، بعد التغلب على هذا ، ستجد أن ...

الميزات الديناميكية لا تزال في مرحلة تجريبية! لا يمكنك أن تتعثر في الإنتاج - لقد كنت اختبارًا مجانيًا لـ Google طوال هذا الوقت!



ولكن ليس وفقا لجوجل. إذا كنت تريد أن تصبح واحدًا ، فيمكنك ملء نموذج الفائدة ، وربما تكون محظوظًا ، وسيتم منحك حق الوصول إلى الإنتاج.
ويعتقد أن التطبيقات الفورية فقدت هذه المعركة. من غير المحتمل الإعلان عن هذا في السنوات القادمة ، ولكن زيادة نشاط المعلومات حول AMP يؤكد ذلك سراً.
الفكر أنني أردت أن أذكركم بنفسي - أكتب للناس . فكر ثلاث مرات قبل اتخاذ أي قرار ، خاصة إذا كنت تقوم بتطوير الأدوات التي سيستخدمها مطورو البرامج الآخرون. سيؤثر كل قرار وكل إجراء على شخص ما ، وربما يفسده القليل من الدم. لا أريد التسبب في انهيار لشخص ما.

روابط مفيدة



لقد صممنا برنامج Saint AppsConf ، الذي تم بالفعل 21-21 أكتوبر في سانت بطرسبرغ ، أكثر حضورا وتنوعا مما كان عليه في فصل الربيع. التحقق من ذلك!

أو الاشتراك في النشرة الإخبارية ، والبرق ، و fb - هناك نتحدث عن التقارير الفردية والاستعدادات للمؤتمر.

Source: https://habr.com/ru/post/ar462511/


All Articles