มีอะไรใหม่สำหรับเว็บใน Play

นับตั้งแต่มีการเปิดตัวกิจกรรมบนเว็บที่เชื่อถือได้ไปเมื่อปีที่แล้ว ทีม Chrome ก็พัฒนาผลิตภัณฑ์อย่างต่อเนื่องเพื่อให้ใช้กับ Bubblewrap ง่ายขึ้น เพิ่มฟีเจอร์ใหม่ๆ เช่น การผสานรวม Google Play Billing ที่กำลังจะเปิดตัว และช่วยให้ทำงานได้บนแพลตฟอร์มอื่นๆ เช่น ChromeOS บทความนี้จะสรุปข้อมูลอัปเดตล่าสุดและที่กำลังจะมีขึ้นสำหรับกิจกรรมบนเว็บและที่เชื่อถือได้

ฟีเจอร์ Bubblewrap ใหม่และกิจกรรมบนเว็บที่เชื่อถือได้

Bubblewrap ช่วยให้คุณสร้างแอปที่เรียกใช้ PWA ภายในกิจกรรมบนเว็บและเว็บที่เชื่อถือได้โดยไม่ต้องใช้ความรู้เรื่องเครื่องมือเฉพาะแพลตฟอร์ม

ขั้นตอนการตั้งค่าที่ง่ายขึ้น

ก่อนหน้านี้ การใช้ Bubblewrap จําเป็นต้องตั้งค่า Java Development Kit และ Android SDK ด้วยตัวเอง ซึ่งทั้ง 2 อย่างนี้มีโอกาสผิดพลาด เครื่องมือจะเสนอให้ดาวน์โหลดทรัพยากร Dependency ภายนอกโดยอัตโนมัติเมื่อเรียกใช้เป็นครั้งแรก

คุณยังเลือกใช้การติดตั้ง Dependency ที่มีอยู่ได้หากต้องการ และคำสั่ง doctor ใหม่จะช่วยค้นหาปัญหาและแนะนำการแก้ไขการกำหนดค่า ซึ่งตอนนี้อัปเดตจากบรรทัดคำสั่งได้โดยใช้คำสั่ง updateConfig

วิซาร์ดที่ปรับปรุงใหม่

เมื่อสร้างโปรเจ็กต์ด้วย init Bubblewrap ต้องการข้อมูลเพื่อสร้างแอป Android เครื่องมือจะแยกค่าจากไฟล์ Manifest ของเว็บแอปและเป็นค่าเริ่มต้นหากทำได้

คุณเปลี่ยนค่าเหล่านั้นได้เมื่อสร้างโปรเจ็กต์ใหม่ แต่ก่อนหน้านี้ความหมายของแต่ละช่องไม่ชัดเจน กล่องโต้ตอบการเริ่มต้นสร้างขึ้นใหม่โดยมีคำอธิบายและการตรวจสอบที่ดีขึ้นสำหรับช่องป้อนข้อมูลแต่ละช่อง

การแสดงผล: สนับสนุนแบบเต็มหน้าจอและการวางแนว

ในบางกรณีคุณอาจต้องการให้แอปพลิเคชันใช้หน้าจอให้ได้มากที่สุด และเมื่อสร้าง PWA ระบบจะดำเนินการดังกล่าวโดยการตั้งค่าช่อง display จากไฟล์ Manifest ของเว็บแอปเป็น fullscreen

เมื่อ Bubblewrap ตรวจพบตัวเลือกแบบเต็มหน้าจอในไฟล์ Manifest ของเว็บแอป จะกำหนดค่าแอปพลิเคชัน Android ให้เปิดแบบเต็มหน้าจอหรือโหมดใหญ่พิเศษในข้อกำหนดเฉพาะของ Android ด้วย

ช่อง orientation จากไฟล์ Manifest ของเว็บแอปจะกำหนดว่าจะให้แอปพลิเคชันเริ่มต้นในโหมดแนวตั้ง โหมดแนวนอน หรือในการวางแนวที่อุปกรณ์ใช้อยู่ ตอนนี้ Bubblewrap จะอ่านช่องไฟล์ Manifest ของเว็บแอปและใช้เป็นค่าเริ่มต้นเมื่อสร้างแอป Android

คุณปรับแต่งการกำหนดค่าทั้ง 2 แบบให้เป็นส่วนหนึ่งของขั้นตอน bubblewrap init ได้

เอาต์พุต AppBundles

App Bundle คือรูปแบบการเผยแพร่สำหรับแอปที่มอบสิทธิ์การสร้าง APK สุดท้ายและการลงนามไปยัง Play ในทางปฏิบัติ วิธีนี้จะช่วยให้สามารถให้บริการไฟล์ขนาดเล็กแก่ผู้ใช้เมื่อดาวน์โหลดแอปจาก Store

ตอนนี้ Bubblewrap ทำแพ็กเกจแอปพลิเคชันเป็น App Bundle ในไฟล์ที่ชื่อว่า app-release-bundle.aab คุณควรเลือกใช้รูปแบบนี้เมื่อเผยแพร่แอปไปยัง Play Store เนื่องจากร้านค้าจะกำหนดให้ต้องมีตั้งแต่ช่วงครึ่งหลังของปี 2021

การมอบสิทธิ์ตำแหน่งทางภูมิศาสตร์

ผู้ใช้คาดหวังให้แอปพลิเคชันที่ติดตั้งในอุปกรณ์ของตนทำงานอย่างสอดคล้องกันไม่ว่าจะใช้เทคโนโลยีใดก็ตาม เมื่อใช้ภายในกิจกรรมบนเว็บและเว็บที่เชื่อถือได้ ระบบจะมอบสิทธิ์GeoLocationให้กับระบบปฏิบัติการได้ และเมื่อเปิดใช้ ผู้ใช้จะเห็นกล่องโต้ตอบเหมือนกับแอปที่สร้างด้วย Kotlin หรือ Java และเห็นการควบคุมเพื่อจัดการสิทธิ์ได้ในที่เดียว

คุณสามารถเพิ่มฟีเจอร์นี้ได้ผ่านทาง Bubblewrap และเนื่องจากจะเพิ่มทรัพยากร Dependency เพิ่มเติมลงในโปรเจ็กต์ Android คุณจึงควรเปิดใช้เฉพาะเมื่อเว็บแอปใช้สิทธิ์เข้าถึงตำแหน่งทางภูมิศาสตร์อยู่

ไบนารีที่เพิ่มประสิทธิภาพ

อุปกรณ์ที่มีพื้นที่เก็บข้อมูลจำกัดพบได้ทั่วไปในบางพื้นที่ของโลก และเจ้าของอุปกรณ์เหล่านั้นมักชอบแอปพลิเคชันขนาดเล็กมากกว่า แอปพลิเคชันที่ใช้กิจกรรมบนเว็บและเว็บที่เชื่อถือได้จะสร้างไบนารีขนาดเล็ก ซึ่งช่วยขจัดความกังวลบางอย่างออกจากผู้ใช้เหล่านั้นได้

Bubblewrap ได้รับการเพิ่มประสิทธิภาพโดยลดรายการไลบรารี Android ที่จำเป็น ทำให้ไบนารีที่สร้างขึ้นมีขนาดเล็กลง 800 K ในทางปฏิบัติ ขนาดดังกล่าวน้อยกว่าครึ่งหนึ่งของขนาดเฉลี่ย ที่เวอร์ชันก่อนหน้าสร้างขึ้น หากต้องการใช้ประโยชน์จากไบนารีขนาดเล็ก คุณเพียงอัปเดตแอปโดยใช้ Bubblewrap เวอร์ชันล่าสุด

วิธีอัปเดตแอปที่มีอยู่

แอปพลิเคชันที่สร้างโดย Bubblewrap ประกอบด้วยเว็บแอปพลิเคชันและ Wrapper ของ Android น้ำหนักเบาที่เปิด PWA แม้ว่า PWA ที่เปิดอยู่ภายในกิจกรรมบนเว็บและเว็บที่เชื่อถือได้จะเป็นไปตามรอบการอัปเดตเดียวกันกับเว็บแอป แต่ Wrapper แบบเนทีฟนั้นสามารถและควรอัปเดตได้

คุณควรอัปเดตแอปเพื่อให้แอปใช้ Wrapper เวอร์ชันล่าสุดที่มีการแก้ไขข้อบกพร่องและฟีเจอร์ล่าสุด เมื่อติดตั้ง Bubblewrap เวอร์ชันล่าสุดแล้ว คำสั่ง update จะใช้ Wrapper เวอร์ชันล่าสุดกับโปรเจ็กต์ที่มีอยู่:

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

อีกเหตุผลหนึ่งในการอัปเดตแอปพลิเคชันเหล่านั้นคือตรวจสอบว่าแอปพลิเคชันมีการเปลี่ยนแปลงไฟล์ Manifest ของเว็บ ใช้คำสั่ง merge ใหม่เพื่อดำเนินการต่อไปนี้

bubblewrap merge
bubblewrap update
bubblewrap build

การอัปเดตเกณฑ์คุณภาพ

Chrome 86 เปิดตัวการเปลี่ยนแปลงเกณฑ์คุณภาพของกิจกรรมในเว็บที่เชื่อถือได้ ซึ่งอธิบายไว้ในหัวข้อการเปลี่ยนแปลงเกณฑ์ด้านคุณภาพสำหรับ PWA ที่ใช้กิจกรรมบนเว็บและที่เชื่อถือได้ทั้งหมด

ข้อมูลสรุปสั้นๆ คือคุณควรตรวจสอบว่าแอปพลิเคชันของคุณรับมือกับสถานการณ์ต่อไปนี้เพื่อป้องกันไม่ให้เกิดข้อขัดข้อง

  • ยืนยันลิงก์เนื้อหาดิจิทัล (Digital Asset Links) เมื่อเปิดใช้งานแอปพลิเคชันไม่สำเร็จ
  • แสดงผล HTTP 200 สำหรับคำขอทรัพยากรเครือข่ายออฟไลน์ไม่สำเร็จ
  • การส่งกลับข้อผิดพลาด HTTP 404 หรือ 5xx ในแอปพลิเคชัน

นอกจากการตรวจสอบให้แน่ใจว่าแอปพลิเคชันผ่านการตรวจสอบลิงก์เนื้อหาดิจิทัล (Digital Asset Links) แล้ว คุณยังสามารถจัดการสถานการณ์ที่เหลือได้ด้วยโปรแกรมทำงานของบริการ ดังนี้

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 ทำตามแนวทางปฏิบัติแนะนำและนำต้นแบบออกเมื่อใช้ Service Worker หรือลองใช้ปลั๊กอิน 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 Billing

นอกจากอนุญาตให้แอปขายสินค้าดิจิทัลและการสมัครใช้บริการใน Play Store แล้ว Google Play Billing ยังมีเครื่องมือในการจัดการแคตตาล็อก ราคาและการสมัครใช้บริการ รายงานที่มีประโยชน์ และขั้นตอนการชำระเงินที่ขับเคลื่อนโดย Play Store ที่ผู้ใช้คุ้นเคยอยู่แล้ว และยังเป็นข้อกำหนดสำหรับแอปพลิเคชันที่เผยแพร่ใน Play Store ซึ่งขายสินค้าดิจิทัลอีกด้วย

Chrome 88 จะเปิดตัวพร้อมช่วงทดลองใช้จากต้นทางใน Android ซึ่งช่วยให้ผสานรวมกิจกรรมบนเว็บที่เชื่อถือได้, Payment Request API และ Digital Goods API เพื่อนําขั้นตอนการซื้อผ่าน Google Play Billing ได้ เราคาดว่าช่วงทดลองใช้จากต้นทางนี้จะพร้อมใช้งานสำหรับ ChromeOS เวอร์ชัน 89 ด้วย

สำคัญ: Google Play Billing API มีคำศัพท์ของตนเอง รวมถึงคอมโพเนนต์ไคลเอ็นต์และคอมโพเนนต์แบ็กเอนด์ ส่วนนี้จะพูดถึงเพียงส่วนเล็กๆ ของ API ที่มีไว้สําหรับการใช้ Digital Goods API และกิจกรรมบนเว็บที่เชื่อถือได้เท่านั้น โปรดอ่านเอกสารประกอบของ Google Play Billing และทำความเข้าใจแนวคิดก่อนที่จะผสานรวมเข้ากับแอปพลิเคชันเวอร์ชันที่ใช้งานจริง

ขั้นตอนพื้นฐาน

เมนู Play Console

หากต้องการให้บริการสินค้าดิจิทัลผ่าน Play Store คุณจะต้องกำหนดค่าแคตตาล็อกใน Play Store รวมถึงเชื่อมต่อ Play Store เป็นวิธีการชำระเงินจาก PWA

เมื่อพร้อมกำหนดค่าแคตตาล็อก ให้เริ่มด้วยการค้นหาส่วนผลิตภัณฑ์ในเมนูด้านซ้ายใน Play Console ดังนี้

ตรงนี้คุณจะเห็นตัวเลือกในการดูไอเทมที่ซื้อในแอปและการสมัครใช้บริการที่มีอยู่ และยังจะเห็นปุ่มสร้างสำหรับเพิ่มผลิตภัณฑ์ใหม่อีกด้วย

ผลิตภัณฑ์ที่ซื้อในแอป

รายละเอียดผลิตภัณฑ์

หากต้องการสร้างไอเทมที่ซื้อในแอปใหม่ คุณจะต้องมีรหัสผลิตภัณฑ์ ชื่อ รายละเอียด และราคา คุณต้องสร้างรหัสผลิตภัณฑ์ที่มีความหมายและจำได้ง่าย เพราะจะต้องใช้ในภายหลังและเมื่อสร้างรหัสแล้วจะเปลี่ยนแปลงไม่ได้

เมื่อสร้างการสมัครใช้บริการ คุณจะต้องระบุช่วงเวลาที่เรียกเก็บเงินด้วย คุณมีตัวเลือกในการระบุสิทธิประโยชน์ของการสมัครใช้บริการและเพิ่มฟีเจอร์ต่างๆ เช่น จะมีช่วงทดลองใช้ฟรี ราคาช่วงแนะนำ ระยะเวลาผ่อนผัน และตัวเลือกสมัครใช้บริการอีกครั้งหรือไม่

หลังจากที่สร้างผลิตภัณฑ์แต่ละรายการแล้ว ให้เปิดใช้งานผลิตภัณฑ์เหล่านั้นจากแอปโดยการเปิดใช้งาน

คุณจะเพิ่มผลิตภัณฑ์ผ่าน Play Developers API ได้หากต้องการ

เมื่อกำหนดค่าแคตตาล็อกแล้ว ขั้นตอนถัดไปคือกำหนดค่าขั้นตอนการชำระเงินจาก PWA คุณจะใช้ Digital Goods API และ Payment Request API ร่วมกันเพื่อบรรลุเป้าหมายนี้

ดึงข้อมูลราคาผลิตภัณฑ์ด้วย Digital Goods API

เมื่อใช้ Google Play Billing คุณจะต้องตรวจสอบว่าราคาที่แสดงต่อผู้ใช้ตรงกับราคาจากข้อมูลผลิตภัณฑ์ใน Store การทำให้ราคาเหล่านั้นซิงค์กันเองนั้นคงเป็นไปไม่ได้ ดังนั้น 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 Billing และผู้ให้บริการอื่นๆ สามารถใช้การสนับสนุนสำหรับ Digital Goods API ได้ และจะมีตัวระบุที่แตกต่างกัน

สุดท้าย ให้เรียกใช้ getDetails() ในการอ้างอิงออบเจ็กต์การเรียกเก็บเงินของ Google Play ที่ส่ง SKU ของรายการเป็นพารามิเตอร์ เมธอดจะแสดงออบเจ็กต์รายละเอียดที่มีทั้งราคาและสกุลเงินสำหรับรายการที่แสดงแก่ผู้ใช้ได้

เริ่มขั้นตอนการซื้อ

Payment Request API ช่วยให้ใช้ขั้นตอนการซื้อบนเว็บได้และยังใช้สำหรับการผสานรวม Google Play Billing ด้วย ดูข้อมูลเพิ่มเติมได้ที่วิธีการทำงานของ API คำขอการชำระเงิน หากคุณเพิ่งเคยใช้ Payment Request API

หากต้องการใช้ API กับ Google Play Billing คุณจะต้องเพิ่มเครื่องมือการชำระเงินซึ่งมีเมท็อดที่รองรับชื่อว่า 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 ไม่รู้ข้อมูลตัวตนของผู้ใช้ ด้วยเหตุนี้ คุณจะต้องเชื่อมโยงการซื้อกับผู้ใช้ในแบ็กเอนด์และตรวจสอบว่าผู้ใช้มีสิทธิ์เข้าถึงรายการที่ซื้อหรือไม่ เมื่อเชื่อมโยงการซื้อกับผู้ใช้ อย่าลืมบันทึกโทเค็นการซื้อ เนื่องจากคุณอาจต้องใช้โทเค็นดังกล่าวเพื่อยืนยันว่าการซื้อถูกยกเลิกหรือได้รับเงินคืนแล้ว หรือยังมีการสมัครใช้บริการอยู่ โปรดดู Real Time Developer Notifications 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 Store ของ ChromeOS

กิจกรรมบนเว็บที่เชื่อถือได้มีให้ใช้งานตั้งแต่ Chrome 85 ใน Play Store ของ ChromeOS เช่นกัน ขั้นตอนการแสดงรายการแอปใน Store นั้นเหมือนกันใน ChromeOS และสำหรับ Android

เมื่อสร้าง App Bundle แล้ว Play Console จะแนะนำขั้นตอนที่จำเป็นเพื่อแสดงแอปใน Play Store ในเอกสารประกอบของ Play Console คุณสามารถดูความช่วยเหลือในการ สร้างข้อมูลแอป จัดการไฟล์ APK และการตั้งค่าอื่นๆ รวมถึงแสดงวิธีการทดสอบและเผยแพร่แอปอย่างปลอดภัย

หากต้องการจำกัดแอปพลิเคชันของคุณไปยัง Chromebook เท่านั้น ให้เพิ่มแฟล็ก --chromeosonly เมื่อเริ่มแอปพลิเคชันใน Bubblewrap ดังนี้

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

เมื่อสร้างแอปพลิเคชันด้วยตนเองโดยไม่ใช้ Bubblewrap ให้เพิ่ม Flag uses-feature ลงในไฟล์ Manifest ของ Android ดังนี้

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

หากข้อมูลของคุณแชร์กับแอป Android เวอร์ชันแพ็กเกจเฉพาะ ChromeOS จะต้องสูงกว่าเวอร์ชันแพ็กเกจแอป Android เสมอ คุณสามารถตั้งค่าเวอร์ชันแพ็กเกจ ChromeOS เป็นจำนวนที่สูงกว่าเวอร์ชัน Android เพื่อให้ไม่ต้องอัปเดตทั้ง 2 เวอร์ชันในแต่ละรุ่น