چیزهای جدید برای Web In Play

از زمانی که Trusted Web Activity در سال گذشته معرفی شد، تیم Chrome همچنان به کار روی محصول ادامه می‌دهد، استفاده از آن را با Bubblewrap آسان‌تر می‌کند، ویژگی‌های جدیدی مانند ادغام Google Play Billing آینده را اضافه می‌کند و آن را قادر می‌سازد بر روی پلتفرم‌های بیشتری مانند ChromeOS کار کند. این مقاله آخرین و به‌روزرسانی‌های آتی را برای «فعالیت وب معتمد» خلاصه می‌کند.

ویژگی های جدید Bubblewrap و Trusted Web Activity

Bubblewrap به شما کمک می کند تا برنامه هایی ایجاد کنید که PWA های شما را در داخل یک فعالیت وب مورد اعتماد راه اندازی کنند، بدون نیاز به دانش ابزارهای خاص پلت فرم.

جریان راه اندازی ساده شده

قبلاً، استفاده از Bubblewrap به تنظیم دستی کیت توسعه جاوا و Android SDK نیاز داشت که هر دو مستعد خطا هستند. این ابزار اکنون دانلود خودکار وابستگی های خارجی را هنگام اجرا برای اولین بار ارائه می دهد.

اگر ترجیح می‌دهید، همچنان می‌توانید از نصب موجود وابستگی‌ها استفاده کنید، و دستور doctor جدید به یافتن مشکلات کمک می‌کند و اصلاحاتی را برای پیکربندی توصیه می‌کند، که اکنون می‌تواند با استفاده از دستور updateConfig از خط فرمان به‌روزرسانی شود.

جادوگر بهبود یافته

هنگام ایجاد یک پروژه با init ، Bubblewrap برای تولید برنامه اندروید به اطلاعات نیاز دارد. این ابزار مقادیر را از Web App Manifest استخراج می کند و در صورت امکان پیش فرض ها را ارائه می دهد.

شما می توانید این مقادیر را هنگام ایجاد یک پروژه جدید تغییر دهید، اما قبلاً معنای هر فیلد مشخص نبود. گفتگوهای مقداردهی اولیه با توضیحات و اعتبارسنجی بهتر برای هر فیلد ورودی بازسازی شدند.

نمایش: تمام صفحه و پشتیبانی جهت گیری

در برخی موارد، ممکن است بخواهید برنامه شما تا حد امکان از صفحه نمایش استفاده کند و هنگام ساختن PWA، این کار با تنظیم فیلد display از مانیفست برنامه وب روی fullscreen اجرا می شود.

هنگامی که Bubblewrap گزینه تمام صفحه را در مانیفست برنامه وب تشخیص می‌دهد، برنامه اندروید را طوری پیکربندی می‌کند که در حالت تمام صفحه یا حالت غوطه‌ور در شرایط خاص Android نیز راه‌اندازی شود.

فیلد orientation از مانیفست برنامه وب مشخص می‌کند که آیا برنامه باید در حالت عمودی، حالت افقی یا در جهتی که دستگاه در حال حاضر از آن استفاده می‌کند شروع شود. Bubblewrap اکنون قسمت Web App Manifest را می خواند و هنگام ایجاد برنامه اندروید از آن به عنوان پیش فرض استفاده می کند.

می‌توانید هر دو پیکربندی bubblewrap init سفارشی کنید.

خروجی AppBundles

App Bundles قالبی برای انتشار برنامه‌هایی است که تولید و امضای نهایی APK را به Play واگذار می‌کند. در عمل، این امکان را فراهم می کند تا فایل های کوچکتر هنگام دانلود برنامه از فروشگاه به کاربران ارائه شود.

Bubblewrap اکنون برنامه را به عنوان App Bundle در فایلی به نام app-release-bundle.aab بسته بندی می کند. هنگام انتشار برنامه‌ها در Play Store باید این قالب را ترجیح دهید زیرا از نیمه دوم سال 2021 فروشگاه به آن نیاز دارد.

هیأت موقعیت جغرافیایی

کاربران انتظار دارند برنامه های نصب شده بر روی دستگاه هایشان بدون توجه به فناوری، به طور مداوم رفتار کنند. هنگامی که در داخل یک فعالیت وب مورد اعتماد استفاده می شود، اکنون می توان مجوز GeoLocation را به سیستم عامل تفویض کرد و در صورت فعال بودن، کاربران همان دیالوگ های برنامه های ساخته شده با Kotlin یا Java را مشاهده می کنند و کنترل هایی را برای مدیریت مجوز در همان مکان پیدا می کنند.

این ویژگی را می‌توان از طریق Bubblewrap اضافه کرد و از آنجایی که وابستگی‌های اضافی به پروژه اندروید اضافه می‌کند، تنها زمانی باید آن را فعال کنید که برنامه وب از مجوز Geolocation استفاده می‌کند.

باینری های بهینه شده

دستگاه‌هایی با فضای ذخیره‌سازی محدود در مناطق خاصی از جهان رایج هستند و دارندگان آن دستگاه‌ها اغلب برنامه‌های کوچک‌تر را ترجیح می‌دهند. برنامه‌های کاربردی با استفاده از Trusted Web Activity، فایل‌های باینری کوچکی تولید می‌کنند که برخی از نگرانی‌های آن کاربران را از بین می‌برد.

Bubblewrap با کاهش لیست کتابخانه های مورد نیاز اندروید بهینه شده است و در نتیجه باینری هایی تولید می شود که 800k کوچکتر هستند. در عمل، این اندازه کمتر از نصف میانگین اندازه تولید شده توسط نسخه های قبلی است. برای استفاده از باینری های کوچکتر، فقط باید برنامه خود را با استفاده از آخرین نسخه Bubblewrap به روز کنید.

چگونه یک برنامه موجود را به روز کنیم

برنامه‌ای که توسط Bubblewrap تولید می‌شود، از یک برنامه وب و یک بسته‌بندی سبک وزن اندروید تشکیل شده است که PWA را باز می‌کند. حتی اگر PWA باز شده در یک فعالیت وب مورد اعتماد از چرخه های به روز رسانی مشابه هر برنامه وب پیروی می کند، بسته بندی اصلی می تواند و باید به روز شود.

باید برنامه خود را به‌روزرسانی کنید تا مطمئن شوید که از آخرین نسخه wrapper، با آخرین رفع اشکال و ویژگی‌ها استفاده می‌کند. با نصب آخرین نسخه Bubblewrap، دستور update آخرین نسخه wrapper را بر روی یک پروژه موجود اعمال می کند:

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

دلیل دیگر برای به‌روزرسانی این برنامه‌ها، اطمینان از اعمال تغییرات در Web Manifest در برنامه است. برای این کار از دستور 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 برای مدیریت این سناریوها را در نظر بگیرید:

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 Store که کالاهای دیجیتالی می فروشند، الزامی است.

Chrome 88 با نسخه آزمایشی اصلی در Android راه‌اندازی می‌شود که ادغام فعالیت‌های وب مورد اعتماد ، API درخواست پرداخت و API کالاهای دیجیتال را برای پیاده‌سازی جریان‌های خرید از طریق صورت‌حساب Google Play امکان‌پذیر می‌کند. ما انتظار داریم که این نسخه آزمایشی اولیه برای ChromeOS در نسخه 89 نیز در دسترس باشد.

مهم: Google Play Billing API اصطلاحات خاص خود را دارد و شامل مؤلفه‌های مشتری و باطن است. این بخش تنها بخش کوچکی از API را پوشش می‌دهد که مخصوص استفاده از Digital Goods API و Trusted Web Activity است. مطمئن شوید که اسناد صورت‌حساب Google Play را بخوانید و مفاهیم آن را قبل از ادغام در یک برنامه تولیدی درک کنید.

جریان اصلی

منوی Play Console

برای ارائه کالاهای دیجیتال از طریق فروشگاه Play، باید کاتالوگ خود را در Play Store پیکربندی کنید، همچنین Play Store را به عنوان یک روش پرداخت از PWA خود متصل کنید.

هنگامی که آماده پیکربندی کاتالوگ خود هستید، با پیدا کردن بخش محصولات در منوی سمت چپ در کنسول Play شروع کنید:

در اینجا گزینه ای برای مشاهده محصولات درون برنامه ای و اشتراک های موجود خود و همچنین دکمه ایجاد برای افزودن موارد جدید را خواهید یافت.

محصولات درون برنامه ای

جزئیات محصول

برای ایجاد یک محصول درون برنامه ای جدید، به شناسه محصول، نام، توضیحات و قیمت نیاز دارید. مهم است که شناسه‌های محصول معنی‌دار و به یاد ماندنی ایجاد کنید، بعداً به آن‌ها نیاز خواهید داشت و پس از ایجاد شناسه‌ها نمی‌توان آنها را تغییر داد.

هنگام ایجاد اشتراک، باید یک دوره صورتحساب را نیز مشخص کنید. شما این امکان را دارید که مزایای اشتراک خود را فهرست کنید و ویژگی هایی مانند اینکه آیا نسخه آزمایشی رایگان، قیمت مقدماتی، دوره مهلت و گزینه اشتراک مجدد دارید را اضافه کنید.

پس از ایجاد هر محصول، با فعال کردن آنها، آنها را از برنامه خود در دسترس قرار دهید.

اگر ترجیح می دهید می توانید محصولات خود را از طریق 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;
}

می‌توانید با بررسی اینکه getDigitalGoodsService() در شی window موجود است، پشتیبانی از Digital Goods API را شناسایی کنید.

سپس window.getDigitalGoodsService() با شناسه صورتحساب Google Play به عنوان پارامتر فراخوانی کنید. این یک نمونه سرویس را برای صورت‌حساب Google Play برمی‌گرداند و سایر فروشندگان می‌توانند از Digital Goods API پشتیبانی کنند و شناسه‌های مختلفی خواهند داشت.

در نهایت، getDetails() را در مرجع شیء صورتحساب Google Play که SKU مورد را به عنوان پارامتر ارسال می کند، فراخوانی کنید. این روش یک شی جزئیات حاوی قیمت و ارز موردی که می تواند به کاربر نمایش داده شود، برمی گرداند.

جریان خرید را شروع کنید

API درخواست پرداخت، جریان خرید را در وب فعال می‌کند و همچنین برای ادغام صورت‌حساب Google Play استفاده می‌شود. اگر تازه وارد API درخواست پرداخت هستید، این نحوه عملکرد API درخواست پرداخت را بررسی کنید تا بیشتر بدانید.

برای استفاده از API با صورت‌حساب Google Play، باید ابزار پرداختی را اضافه کنید که دارای روشی به نام https://play.google.com/billing است و SKU را به عنوان بخشی از داده‌های ابزار اضافه کنید:

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

سپس طبق معمول یک شیء PaymentRequest بسازید و طبق معمول از API استفاده کنید

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 اطلاعاتی درباره هویت کاربر ندارند. در نتیجه، این به شما بستگی دارد که خرید را به کاربر در باطن خود مرتبط کنید و اطمینان حاصل کنید که آنها به موارد خریداری شده دسترسی دارند. هنگامی که خرید را به یک کاربر مرتبط می کنید، به یاد داشته باشید که رمز خرید را ذخیره کنید، زیرا ممکن است برای بررسی اینکه آیا خرید لغو شده است یا بازپرداخت شده است، یا اینکه اشتراک هنوز فعال است، به آن نیاز داشته باشید. API Real Time Developer Notifications و 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 شما را در مراحل لازم برای فهرست کردن برنامه در فروشگاه Play راهنمایی می کند. در مستندات کنسول Play می‌توانید برای ایجاد فهرست برنامه ، مدیریت فایل‌های apk و سایر تنظیمات، و همچنین دستورالعمل‌هایی برای آزمایش و انتشار ایمن برنامه خود ، راهنمایی بیابید.

برای محدود کردن برنامه‌تان فقط به Chromebookها، هنگام راه‌اندازی برنامه در Bubblewrap، پرچم --chromeosonly را اضافه کنید:

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

هنگامی که برنامه خود را به صورت دستی و بدون Bubblewrap می‌سازید، یک پرچم uses-feature به مانیفست اندروید خود اضافه کنید:

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

اگر فهرست شما با یک برنامه Android به اشتراک گذاشته شده است، نسخه بسته فقط ChromeOS همیشه باید بالاتر از نسخه بسته برنامه Android باشد. می‌توانید نسخه بسته ChromeOS را روی تعداد بسیار بالاتری نسبت به نسخه Android تنظیم کنید، بنابراین لازم نیست هر دو نسخه را با هر نسخه به‌روزرسانی کنید.