PostMessage برای TWA، PostMessage برای TWA

سید العبادی
Sayed El-Abady

از Chrome 115 Trusted Web Activities (TWA) می‌تواند با استفاده از postMessage پیام ارسال کند. این سند تنظیمات لازم برای برقراری ارتباط بین برنامه شما و وب را انجام می دهد.

در پایان این راهنما شما:

  • نحوه کار اعتبار سنجی محتوای وب و کلاینت را درک کنید.
  • نحوه راه اندازی کانال ارتباطی بین مشتری و محتوای وب را بدانید.
  • نحوه ارسال پیام و دریافت پیام از محتوای وب را بدانید.

برای پیروی از این راهنما شما نیاز دارید:

  • برای افزودن جدیدترین کتابخانه androidx.browser (min v1.6.0-alpha02) به فایل build.gradle خود.
  • Chrome نسخه 115.0.5790.13 یا بالاتر برای TWA.

متد window.postMessage() به طور ایمن ارتباط متقاطع بین اشیاء Window را فعال می کند. به عنوان مثال، بین یک صفحه و یک پاپ آپ که ایجاد کرده است، یا بین یک صفحه و یک iframe تعبیه شده در آن.

معمولاً، اسکریپت‌های صفحات مختلف فقط در صورتی مجاز به دسترسی به یکدیگر هستند که صفحاتی که از یک مبدا منشا می‌گیرند، پروتکل، شماره پورت و میزبان یکسانی را به اشتراک بگذارند (همچنین به عنوان خط‌مشی همان مبدأ شناخته می‌شود). متد window.postMessage() مکانیزم کنترل شده ای را برای برقراری ارتباط امن بین مبداهای مختلف فراهم می کند. این می تواند برای پیاده سازی برنامه های چت، ابزارهای مشارکتی و موارد دیگر مفید باشد. به عنوان مثال، یک برنامه چت می تواند از postMessage برای ارسال پیام بین کاربرانی که در وب سایت های مختلف هستند استفاده کند. استفاده از postMessage در فعالیت‌های وب مورد اعتماد (TWA) می‌تواند کمی مشکل باشد، این راهنما شما را با نحوه استفاده از postMessage در سرویس گیرنده TWA برای ارسال پیام و دریافت پیام از صفحه وب راهنمایی می‌کند.

برنامه را به اعتبارسنجی وب اضافه کنید

API postMessage به دو مبدا معتبر اجازه می دهد تا با یکدیگر ارتباط برقرار کنند، یک منبع و یک مبدا هدف. برای اینکه برنامه اندروید بتواند پیام هایی را به مبدا هدف ارسال کند، باید اعلام کند که با کدام منبع معادل است. این را می توان با پیوندهای دارایی دیجیتال (DAL) با افزودن نام بسته برنامه در فایل assetlinks.json با رابطه use_as_origin انجام داد تا به صورت زیر باشد:

[{
  "relation": ["delegate_permission/common.use_as_origin"],
  "target" : { "namespace": "android_app", "package_name": "com.example.app", "sha256_cert_fingerprints": [""] }
}]

توجه داشته باشید که راه اندازی در مبدأ مرتبط با TWA، ارائه یک مبدا برای فیلد MessageEvent.origin الزامی است، اما postMessage می تواند برای برقراری ارتباط با سایت های دیگری که شامل پیوند دارایی های دیجیتال نیستند استفاده شود. به عنوان مثال، اگر شما مالک www.example.com هستید، باید آن را از طریق DAL ثابت کنید، اما می توانید با هر وب سایت دیگری مانند www.wikipedia.org ارتباط برقرار کنید.

PostMessageService را به مانیفست خود اضافه کنید

برای دریافت ارتباط postMessage باید سرویس را راه‌اندازی کنید، این کار را با افزودن PostMessageService در مانیفست اندروید خود انجام دهید:

<service android:name="androidx.browser.customtabs.PostMessageService"
android:exported="true"/>

یک نمونه CustomTabsSession دریافت کنید

پس از افزودن سرویس به مانیفست، از کلاس CustomTabsClient برای اتصال سرویس استفاده کنید. پس از اتصال می توانید از کلاینت ارائه شده برای ایجاد یک جلسه جدید به شرح زیر استفاده کنید. CustomTabsSession کلاس اصلی برای مدیریت postMessage API است. کد زیر نشان می دهد که چگونه پس از اتصال سرویس، مشتری برای ایجاد یک جلسه جدید استفاده می شود، این جلسه برای postMessage استفاده می شود:

private CustomTabsClient mClient;
private CustomTabsSession mSession;

// We use this helper method to return the preferred package to use for
// Custom Tabs.
String packageName = CustomTabsClient.getPackageName(this, null);

// Binding the service to (packageName).
CustomTabsClient.bindCustomTabsService(this, packageName, new CustomTabsServiceConnection() {
 @Override
 public void onCustomTabsServiceConnected(@NonNull ComponentName name,
     @NonNull CustomTabsClient client) {
   mClient = client;

   // Note: validateRelationship requires warmup to have been called.
   client.warmup(0L);

   mSession = mClient.newSession(customTabsCallback);
 }

 @Override
 public void onServiceDisconnected(ComponentName componentName) {
   mClient = null;
 }
});

اکنون می‌پرسید که این نمونه customTabsCallback چیست؟ ما این را در بخش بعدی ایجاد خواهیم کرد.

CustomTabsCallback را ایجاد کنید

CustomTabsCallback یک کلاس بازگشت به تماس برای CustomTabsClient است تا پیام‌هایی در مورد رویدادها در برگه‌های سفارشی خود دریافت کند. یکی از این رویدادها onPostMessage است و زمانی که برنامه پیامی از وب دریافت می‌کند، با آن تماس گرفته می‌شود. همانطور که در کد زیر نشان داده شده است، تماس برگشتی را به مشتری اضافه کنید تا کانال postMessage را برای شروع ارتباط مقداردهی کنید.

private final String TAG = "TWA/CCT-PostMessageDemo";

// The origin the TWA is equivalent to, where the Digital Asset Links file
// was created with the "use_as_origin" relationship.
private Uri SOURCE_ORIGIN = Uri.parse("https://source-origin.example.com");

// The origin the TWA will communicate with. In most cases, SOURCE_ORIGIN and
// TARGET_ORIGIN will be the same.
private Uri TARGET_ORIGIN = Uri.parse("https://target-origin.example.com");

// It stores the validation result so you can check on it before requesting
// postMessage channel, since without successful validation it is not possible
// to use postMessage.
boolean mValidated;

CustomTabsCallback customTabsCallback = new CustomTabsCallback() {

    // Listens for the validation result, you can use this for any kind of
    // logging purposes.
    @Override
    public void onRelationshipValidationResult(int relation, @NonNull Uri requestedOrigin,
        boolean result, @Nullable Bundle extras) {
        // If this fails:
        // - Have you called warmup?
        // - Have you set up Digital Asset Links correctly?
        // - Double check what browser you're using.
        Log.d(TAG, "Relationship result: " + result);
        mValidated = result;
    }

    // Listens for any navigation happens, it waits until the navigation finishes
    // then requests post message channel using
    // CustomTabsSession#requestPostMessageChannel(sourceUri, targetUri, extrasBundle)

    // The targetOrigin in requestPostMessageChannel means that you can be certain their messages are delivered only to the website you expect.
    @Override
    public void onNavigationEvent(int navigationEvent, @Nullable Bundle extras) {
        if (navigationEvent != NAVIGATION_FINISHED) {
            return;
        }

        if (!mValidated) {
            Log.d(TAG, "Not starting PostMessage as validation didn't succeed.");
        }

        // If this fails:
        // - Have you included PostMessageService in your AndroidManifest.xml ?
        boolean result = mSession.requestPostMessageChannel(SOURCE_ORIGIN, TARGET_ORIGIN, new Bundle());
        Log.d(TAG, "Requested Post Message Channel: " + result);
    }

    // This gets called when the channel we requested is ready for sending/receiving messages.
    @Override
    public void onMessageChannelReady(@Nullable Bundle extras) {
        Log.d(TAG, "Message channel ready.");

        int result = mSession.postMessage("First message", null);
        Log.d(TAG, "postMessage returned: " + result);
    }

    // Listens for upcoming messages from Web.
    @Override
    public void onPostMessage(@NonNull String message, @Nullable Bundle extras) {
        super.onPostMessage(message, extras);
        // Handle the received message.
    }
};

ارتباط از طریق وب

اکنون می توانیم از برنامه میزبان خود پیام ارسال و دریافت کنیم، چگونه از وب همین کار را انجام دهیم؟ ارتباط باید از برنامه میزبان شروع شود، سپس صفحه وب باید پورت را از اولین پیام دریافت کند. این پورت برای ارتباط برگشت استفاده می شود. فایل جاوا اسکریپت شما چیزی شبیه به مثال زیر خواهد بود:

window.addEventListener("message", function (event) {
  // We are receiveing messages from any origin, you can check of the origin by
  // using event.origin

  // get the port then use it for communication.
  var port = event.ports[0];
  if (typeof port === 'undefined') return;

  // Post message on this port.
  port.postMessage("Test")

  // Receive upcoming messages on this port.
  port.onmessage = function(event) {
    console.log("[PostMessage1] Got message" + event.data);
  };
});

شما می توانید یک نمونه کامل کامل را در اینجا پیدا کنید

عکس توسط Joanna Kosinska در Unsplash