الميزات الجديدة في Web In Play

منذ أن تم تقديم ميزة النشاط على الويب الموثوق به في العام الماضي، يواصل فريق Chrome العمل على المنتج، ما يسهِّل استخدامه مع "التفاف الفقاعات"، ويضيف ميزات جديدة، مثل عملية دمج "الفوترة القادمة في Google Play" وتفعيله للعمل على المزيد من الأنظمة الأساسية، مثل ChromeOS. ستلخص هذه المقالة آخر الأخبار والقادمة لنشاط الويب الموثوق به.

الميزتان الجديدتان "التفاف الفقاعات" و"النشاط على الويب الموثوق به"

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

عملية الإعداد المبسّطة

في السابق، كان استخدام Bubblewrap يتطلب إعداد Java Development Kit يدويًا وحزمة تطوير البرامج (SDK) لـ Android، وكلاهما معرَّض للخطأ. تقدم الأداة الآن تنزيل التبعيات الخارجية تلقائيًا عند تشغيلها لأول مرة.

إذا كنت تفضّل إجراء ذلك، ما زال بإمكانك اختيار استخدام تثبيت حالي للملحقات إذا كنت تفضّل ذلك، وسيساعد الأمر doctor الجديد في العثور على المشاكل واقتراح إصلاحات للإعدادات، ويمكن تعديلها الآن من سطر الأوامر باستخدام الأمر updateConfig.

المعالج المحسَّن

عند إنشاء مشروع باستخدام init، تحتاج الأداة إلى معلومات لإنشاء تطبيق Android. وتستخرج الأداة القيم من بيان تطبيق الويب وتوفّر الإعدادات التلقائية حيثما أمكن.

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

الشاشة: إتاحة ملء الشاشة والاتجاه

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

عند اكتشاف خيار "ملء الشاشة" في بيان تطبيق الويب، يتم إعداد تطبيق Android لتشغيله أيضًا في وضع ملء الشاشة، أو الوضع الغامر، وفقًا لبنود محدّدة في Android.

يحدِّد حقل orientation من بيان تطبيق الويب ما إذا كان يجب بدء تشغيل التطبيق في الوضع العمودي أو الوضع الأفقي أو الاتجاه الذي يستخدمه الجهاز حاليًا. تقرأ Bubblewrap الآن حقل بيان تطبيق الويب وتستخدمه كإعداد تلقائي عند إنشاء تطبيق Android.

ويمكنك تخصيص كلا الإعدادَين كجزء من مسار bubblewrap init.

ناتج حزم التطبيقات

حِزم التطبيقات هي تنسيق لنشر التطبيقات يفوّض عملية إنشاء حزمة APK النهائية وتسجيل الدخول إلى Play. ومن الناحية العملية، يتيح هذا عرض الملفات الأصغر للمستخدمين عند تنزيل التطبيق من المتجر.

أصبح تطبيق Bubblewrap الآن ضمن حزمة App Bundle في ملف باسم app-release-bundle.aab. عليك تفضيل هذا التنسيق عند نشر التطبيقات على "متجر Play" لأنه سيكون مطلوبًا من المتجر ابتداءً من النصف الثاني من عام 2021.

تفويض رصد الموقع الجغرافي

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

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

برامج ثنائية محسّنة

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

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

كيفية تحديث تطبيق حالي

يتألف التطبيق الذي يتم إنشاؤه باستخدام Bubblewrap من تطبيق ويب وبرنامج تضمين خفيف في Android يفتح تطبيق الويب التقدّمي (PWA). وعلى الرغم من فتح تطبيق الويب التقدّمي (PWA) داخل "النشاط على الويب الموثوق به" خلال دورات التحديث نفسها مثل أي تطبيق ويب، يجب تحديث برنامج تضمين البرنامج الأصلي.

يجب تحديث تطبيقك لضمان أنه يستخدم أحدث إصدار من برنامج تضمين، مع أحدث إصلاح الأخطاء والميزات. عند تثبيت أحدث إصدار من Bubblewrap، سيطبق الأمر update أحدث إصدار من برنامج تضمين على مشروع حالي:

npm update -g @bubblewrap/cli
bubblewrap update
bubblewrap build

هناك سبب آخر لتحديث هذه التطبيقات هو ضمان تطبيق التغييرات التي تم إجراؤها على بيان الويب على التطبيق. استخدِم الأمر merge الجديد لإجراء ذلك:

bubblewrap merge
bubblewrap update
bubblewrap build

تحديثات على معايير الجودة

أدخل Chrome 86 تغييرات على معايير جودة النشاط على الويب الموثوق بها، والتي تم توضيحها بالتفصيل في التغييرات على معايير الجودة لتطبيقات الويب التقدّمية (PWA) باستخدام نشاط الويب الموثوق به.

تلخيص سريع، يجب عليك التأكّد من تعامل التطبيقات مع السيناريوهات التالية لمنع تعطُّلها:

  • عدم إثبات صحة روابط الأصول الرقمية عند إطلاق التطبيق
  • تعذّر عرض HTTP 200 لطلب مورد شبكة بلا اتصال بالإنترنت
  • عرض خطأ HTTP 404 أو 5xx في التطبيق.

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

self.addEventListener('fetch', event => {
  event.respondWith((async () => {
    try {
      return await fetchAndHandleError(event.request);
    } catch {
      // Failed to load from the network. User is offline or the response
      // has a status code that triggers the Quality Criteria.
      // Try loading from cache.
      const cachedResponse = await caches.match(event.request);
      if (cachedResponse) {
        return cachedResponse;
      }
      // Response was not found on the cache. Send the error / offline
      // page. OFFLINE_PAGE should be pre-cached when the service worker
      // is activated.
      return await caches.match(OFFLINE_PAGE);
    }
  })());
});

async function fetchAndHandleError(request) {
  const cache = await caches.open(RUNTIME_CACHE);
  const response = await fetch(request);

  // Throw an error if the response returns one of the status
  // that trigger the Quality Criteria.
  if (response.status === 404 ||
      response.status >= 500 && response.status < 600) {
    throw new Error(`Server responded with status: ${response.status}`);
  }

  // Cache the response if the request is successful.
  cache.put(request, response.clone());
  return response;
}

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

export class FallbackOnErrorPlugin {
  constructor(offlineFallbackUrl, notFoundFallbackUrl, serverErrorFallbackUrl) {
    this.notFoundFallbackUrl = notFoundFallbackUrl;
    this.offlineFallbackUrl = offlineFallbackUrl;
    this.serverErrorFallbackUrl = serverErrorFallbackUrl;
  }

  checkTrustedWebActivityCrash(response) {
    if (response.status === 404 || response.status >= 500 && response.status <= 600) {
      const type = response.status === 404 ? 'E_NOT_FOUND' : 'E_SERVER_ERROR';
      const error = new Error(`Invalid response status (${response.status})`);
      error.type = type;
      throw error;
    }
  }

  // This is called whenever there's a network response,
  // but we want special behavior for 404 and 5**.
  fetchDidSucceed({response}) {
    // Cause a crash if this is a Trusted Web Activity crash.
    this.checkTrustedWebActivityCrash(response);

    // If it's a good response, it can be used as-is.
    return response;
  }

  // This callback is new in Workbox v6, and is triggered whenever
  // an error (including a NetworkError) is thrown when a handler runs.
  handlerDidError(details) {
    let fallbackURL;
    switch (details.error.details.error.type) {
      case 'E_NOT_FOUND': fallbackURL = this.notFoundFallbackUrl; break;
      case 'E_SERVER_ERROR': fallbackURL = this.serverErrorFallbackUrl; break;
      default: fallbackURL = this.offlineFallbackUrl;
    }

    return caches.match(fallbackURL, {
      // Use ignoreSearch as a shortcut to work with precached URLs
      // that have _WB_REVISION parameters.
      ignoreSearch: true,
    });
  }
}

الفوترة في Google Play

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

سيتم إطلاق Chrome 88 من خلال مرحلة التجربة والتقييم على Android التي تتيح دمج أنشطة الويب الموثوق بها وPayment Request API وDigital Goods API لتنفيذ عمليات الشراء من خلال خدمة "الفوترة في Google Play". نتوقع أن تكون مرحلة التجربة والتقييم هذه متاحة أيضًا لنظام التشغيل ChromeOS على الإصدار 89.

ملاحظة مهمة: تتضمّن واجهة برمجة التطبيقات Google Play Billing API مصطلحات خاصة بها وتتضمّن مكوّنات العميل والخلفية. يتناول هذا القسم جزءًا صغيرًا فقط من واجهة برمجة التطبيقات المخصص لاستخدام واجهة برمجة التطبيقات Digital Goods API و"نشاط الويب الموثوق به". احرص على قراءة مستندات خدمة "الفوترة في Google Play" وفهم مفاهيمها قبل دمجها في أحد تطبيقات الإنتاج.

التدفق الأساسي

قائمة Play Console

لتوفير سلع رقمية عبر "متجر Play"، عليك ضبط الكتالوج الخاص بك على "متجر Play"، بالإضافة إلى ربط "متجر Play" كطريقة دفع من تطبيق الويب التقدّمي (PWA).

عندما تكون مستعدًا لإعداد الكتالوج، ابدأ بالبحث عن قسم المنتجات في القائمة الجانبية اليمنى في Play Console:

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

منتجات داخل التطبيقات

تفاصيل المنتج

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

عند إنشاء الاشتراكات، عليك أيضًا تحديد مدة زمنية للفوترة. يمكنك إدراج مزايا الاشتراك وإضافة ميزات مثل توفّر فترة تجريبية مجانية وسعر تمهيدي وفترة سماح وخيار إعادة الاشتراك.

بعد إنشاء كل منتج، يمكنك جعله متاحًا في تطبيقك عن طريق تفعيله.

إذا أردت، يمكنك إضافة منتجاتك عبر Play Developers API.

بعد ضبط الكتالوج الخاص بك، تكون الخطوة التالية هي ضبط مسار الدفع من تطبيق الويب التقدّمي (PWA). ستستخدم مزيجًا من Digital Goods API وPayment Request API لتنفيذ ذلك.

استرجاع سعر المنتج باستخدام Digital Goods API

عند استخدام خدمة "الفوترة في Google Play"، يجب التأكّد من أنّ السعر المعروض للمستخدمين يتطابق مع السعر الوارد في بطاقة بيانات المتجر. قد يكون من المستحيل مزامنة هذه الأسعار يدويًا، لذلك توفّر واجهة برمجة التطبيقات Digital Goods API طريقة يمكن لتطبيق الويب من خلالها الاستعلام عن الأسعار من مقدّم الدفع الأساسي:

// The SKU for the product, as defined in the Play Store interface
async function populatePrice(sku) {
  try {
    // Check if the Digital Goods API is supported by the browser.
    if (window.getDigitalGoodsService) {
      // The Digital Goods API can be supported by other Payments provider.
      // In this case, we're retrieving the Google Play Billing provider.
      const service =
          await window.getDigitalGoodsService("https://play.google.com/billing");

      // Fetch product details using the `getDetails()` method.
      const details = await service.getDetails([sku]);

      if (details.length === 0) {
        console.log(`Could not get SKU: "${sku}".`);
        return false;
      }

      // The details will contain both the price and the currenncy.
      item = details[0];
      const value = item.price.value;
      const currency = item.price.currency;

      const formattedPrice = new Intl.NumberFormat(navigator.language, {
        style: 'currency', currency: currency }).format(value);

      // Display the price to the user.
      document.getElementById("price").innerHTML = formattedPrice;
    } else {
      console.error("Could not get price for SKU \"" + sku + "\".");
    }
  } catch (error) {
    console.log(error);
  }
  return false;
}

يمكنك اكتشاف إتاحة واجهة برمجة التطبيقات Digital Goods API من خلال التحقّق ممّا إذا كان getDigitalGoodsService() متاحًا للعنصر window.

بعد ذلك، يمكنك استدعاء window.getDigitalGoodsService() باستخدام معرّف "الفوترة في Google Play" كمَعلمة. سيؤدي هذا إلى عرض مثيل خدمة لخدمة "الفوترة في Google Play" ويمكن للمورّدين الآخرين تنفيذ الدعم لواجهة برمجة التطبيقات Digital Goods API وسيكون لديهم معرّفات مختلفة.

أخيرًا، استدعِ getDetails() في المرجع إلى عنصر "الفوترة في Google Play" من خلال تمرير رمز التخزين التعريفي للعنصر كمَعلمة. ستعرض الطريقة عنصر تفاصيل يحتوي على كل من السعر والعملة للعنصر الذي يمكن عرضه للمستخدم.

بدء مسار الشراء

تتيح Payment Request API تدفق عمليات الشراء على الويب، كما تُستخدم أيضًا في دمج Google Play الفوترة. اطّلِع على How Payment Request API هذه لمعرفة المزيد من المعلومات إذا كنت مستخدمًا جديدًا لـ Payment Request API.

لاستخدام واجهة برمجة التطبيقات مع خدمة "الفوترة في Google Play"، يجب إضافة وسيلة دفع لديها وسيلة متوافقة تُسمى https://play.google.com/billing وإضافة رمز التخزين التعريفي (SKU) كجزء من بيانات الأداة:

const supportedInstruments = [{
  supportedMethods: "https://play.google.com/billing",
  data: {
    sku: sku
  }
}];

بعد ذلك، يمكنك إنشاء عنصر PaymentRequest كالمعتاد واستخدام واجهة برمجة التطبيقات كالمعتاد

const request = new PaymentRequest(supportedInstruments, details);

الإقرار بعملية الشراء

بعد اكتمال المعاملة، عليك استخدام Digital Goods API لتأكيد تسديد الدفعة. سيحتوي كائن الاستجابة من PaymentRequest على رمز مميّز ستستخدمه للإقرار بالمعاملة:

const response = await request.show();
const token = response.details.token;
const service =
          await window.getDigitalGoodsService("https://play.google.com/billing");
await service.acknowledge(token, 'onetime');

لا تتوفّر لدى "واجهة برمجة التطبيقات Digital Goods API" و"واجهة برمجة التطبيقات Payment Request API" معلومات عن هوية المستخدم. ونتيجة لذلك، فإن الأمر متروك لك لربط عملية الشراء بالمستخدم في الخلفية والتأكد من إمكانية وصوله إلى العناصر التي تم شراؤها. عند ربط عملية الشراء بمستخدم، تذكر حفظ الرمز المميز للشراء، حيث قد تحتاج إليه للتحقق مما إذا تم إلغاء عملية الشراء أو استرداد أموالها، أو ما إذا كان الاشتراك لا يزال نشطًا. يمكنك الاطّلاع على واجهة برمجة التطبيقات في الوقت الفعلي الخاصة بإشعارات المطوّر في الوقت الفعلي وواجهة برمجة التطبيقات Google Play Developer API لتوفير نقاط نهاية للتعامل مع هذه الحالات في الخلفية.

البحث عن أذونات الوصول الحالية

قد يكون المستخدم قد حصّل قيمة رمز ترويجي أو قد يكون لديه اشتراك حالي في منتجك. للتحقّق من أنّ المستخدم لديه الأذونات المناسبة، يمكنك طلب الأمر listPurchases() في خدمة السلع الرقمية. سيؤدي هذا الإجراء إلى إرجاع جميع عمليات الشراء التي أجراها عميلك في تطبيقك. ويمكنك أيضًا الإقرار بأي عمليات شراء تمت بدون الموافقة عليها لضمان أنّ المستخدم يحصِّل قيمة استحقاقاته بشكل صحيح.

const purchases = await itemService.listPurchases();
for (p of purchases) {
  if (!p.acknowledged) {
    await itemService.acknowledge(p.purchaseToken, 'onetime');
  }
}

التحميل إلى "متجر Play" على نظام التشغيل ChromeOS

تتوفر "أنشطة الويب الموثوق بها" أيضًا بدءًا من إصدار Chrome 85 في "متجر Play" على نظام التشغيل ChromeOS. عملية إدراج تطبيقك في المتجر هي نفسها في نظام التشغيل ChromeOS وعملية Android.

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

لتقييد التطبيق على أجهزة Chromebook فقط، أضِف العلامة --chromeosonly عند إعداد التطبيق في Bubblewrap:

bubblewrap init --manifest="https://example.com/manifest.json" --chromeosonly

عند إنشاء تطبيقك يدويًا بدون Bubblewrap، يمكنك إضافة علامة uses-feature إلى بيان Android الخاص بك:

<uses-feature  android:name="org.chromium.arc" android:required="true"/>

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