Postbericht voor TWA

Zegt El-Abady
Sayed El-Abady

Vanaf Chrome 115 kunnen Trusted Web Activity (TWA) berichten verzenden met behulp van postMessages. In dit artikel wordt de configuratie beschreven die nodig is om te communiceren tussen uw app en internet.

Aan het einde van deze handleiding zult u: - Begrijpen hoe de client- en webcontentvalidatie werkt. - Weten hoe je het communicatiekanaal tussen klant en webcontent kunt initialiseren. - Weet hoe u berichten kunt verzenden naar en ontvangen van webcontent.

Om deze handleiding te volgen heeft u het volgende nodig:

  • Om de nieuwste androidx.browser- bibliotheek (min. v1.6.0-alpha02) toe te voegen aan uw build.gradle-bestand.
  • Chrome-versie 115.0.5790.13 of hoger voor TWA.

De methode window.postMessage() maakt veilig cross-origin-communicatie tussen Window- objecten mogelijk. Bijvoorbeeld tussen een pagina en een pop-up die deze heeft voortgebracht, of tussen een pagina en een daarin ingebed iframe.

Normaal gesproken mogen scripts op verschillende pagina's alleen toegang tot elkaar krijgen als de pagina's waarvan ze afkomstig zijn van dezelfde oorsprong zijn, hetzelfde protocol, poortnummer en dezelfde host delen (ook wel bekend als the same-origin policy ). De methode window.postMessage() biedt een gecontroleerd mechanisme om veilig te communiceren tussen verschillende bronnen. Dit kan handig zijn voor het implementeren van chattoepassingen, samenwerkingstools en andere. Een chattoepassing kan bijvoorbeeld postMessage gebruiken om berichten te verzenden tussen gebruikers die zich op verschillende websites bevinden. Het gebruik van postMessage in Trusted Web Activity (TWA) kan een beetje lastig zijn. Deze handleiding begeleidt u bij het gebruik van postMessage in de TWA-client om berichten te verzenden naar en te ontvangen van de webpagina.

Voeg de app toe aan webvalidatie

Om de postMessage te laten werken, is een geldige relatie vereist tussen een website en de Trusted Web Activity-app die deze site lanceert. Dit kan worden gedaan met Digital Asset Links (DAL) door de pakketnaam van de app toe te voegen aan uw assetlinks.json -bestand met relatie als use_as_origin , dus het zal als volgt zijn:

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

Houd er rekening mee dat bij het instellen van de oorsprong die is gekoppeld aan de TWA, het vereist is om een ​​oorsprong op te geven voor het veld MessageEvent.origin , maar postMessage kan worden gebruikt om te communiceren met andere sites die de Digital Assets Link niet bevatten. Als u bijvoorbeeld eigenaar bent www.example.com , moet u dat bewijzen via DAL, maar u kunt ook communiceren met andere websites, bijvoorbeeld www.wikipedia.org .

Voeg de PostMessageService toe aan uw manifest

Om postMessage communicatie te ontvangen, moet u de service instellen. Dit doet u door de PostMessageService toe te voegen aan uw Android-manifest:

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

Haal een CustomTabsSession-instantie op

Nadat u de service aan het manifest hebt toegevoegd, gebruikt u de klasse CustomTabsClient om de service te binden. Eenmaal verbonden kunt u de meegeleverde client als volgt gebruiken om een ​​nieuwe sessie aan te maken. CustomTabsSession is de kernklasse voor het verwerken van de postMessage API. De volgende code laat zien hoe zodra de service is verbonden, de client wordt gebruikt om een ​​nieuwe sessie te maken. Deze sessie wordt gebruikt om postMessage te plaatsen:

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;
 }
});

U vraagt ​​zich nu af wat deze customTabsCallback instantie is, toch? We zullen dit in de volgende sectie maken.

Maak aangepaste tabbladen terugbellen

CustomTabsCallback is een callback-klasse voor CustomTabsClient om berichten over gebeurtenissen op hun aangepaste tabbladen te ontvangen. Een van deze gebeurtenissen is onPostMessage en deze wordt opgeroepen wanneer de app een bericht van internet ontvangt. Voeg de callback toe aan de client om het postMessage-kanaal te initialiseren om de communicatie te starten, zoals weergegeven in de volgende code.

private final String TAG = "TWA/CCT-PostMessageDemo";
private Uri SOURCE_ORIGIN = Uri.parse("my-app-origin-uri");
private Uri TARGET_ORIGIN = Uri.parse("website-you-are-communicating-with");

// It stores the validation result so you can check on it before requesting postMessage channel, since without successful validation it is not posible 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.

 }
};

Communiceren vanaf internet

Nu kunnen we berichten verzenden en ontvangen via onze host-app. Hoe kunnen we hetzelfde doen vanaf internet? De communicatie moet beginnen vanuit de host-app, en vervolgens moet de webpagina de poort van het eerste bericht ophalen. Deze poort wordt gebruikt om terug te communiceren. Uw JavaScript-bestand ziet er ongeveer uit als in het volgende voorbeeld:

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);
  };
});

Een volledig compleet voorbeeld vindt u hier

Foto door Joanna Kosinska op Unsplash