Vanaf Chrome 115 kunnen Trusted Web Activity (TWA) berichten verzenden met postMessage. In dit document wordt de configuratie beschreven die nodig is om te communiceren tussen uw app en internet.
Aan het einde van deze handleiding zult u:
- Begrijp hoe de validatie van client- en webinhoud werkt.
- Weet hoe u 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 bekend als hetzelfde oorsprongsbeleid ). 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
Met de postMessage API kunnen twee geldige oorsprongen met elkaar communiceren: een bron- en een doeloorsprong. Om ervoor te zorgen dat de Android-applicatie berichten naar de doeloorsprong kan verzenden, moet deze aangeven met welke bronoorsprong deze gelijkwaardig is. Dit kan worden gedaan met Digital Asset Links (DAL) door de pakketnaam van de app toe te voegen aan uw assetlinks.json
-bestand met de relatie als use_as_origin
, zodat deze er als volgt uitziet:
[{
"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 de 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";
// 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.
}
};
Communiceren vanaf internet
Nu kunnen we berichten verzenden en ontvangen via onze host-app. Hoe doen we hetzelfde 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