Od wersji Chrome 115 zaufane aktywności w internecie (Trusted Web Activities, TWA) mogą wysyłać wiadomości za pomocą postMessage. Ten dokument zawiera instrukcje konfiguracji umożliwiającej komunikację między aplikacją a internetem.
Po zakończeniu tego przewodnika:
- Dowiedz się, jak działa weryfikacja klienta i treści internetowych.
- Dowiedz się, jak zainicjować kanał komunikacji między klientem a webcontent.
- Dowiedz się, jak wysyłać i odbierać wiadomości do webcontent.
Aby wykonać te czynności, musisz mieć:
- Aby dodać do pliku build.gradle najnowszą bibliotekę androidx.browser (co najmniej w wersji 1.6.0-alpha02).
- Chrome w wersji 115.0.5790.13 lub nowszej w przypadku TWA.
Metoda window.postMessage()
umożliwia bezpieczną komunikację między obiektami Window w różnych domenach. Na przykład między stroną a wyskakującym oknem, które się w niej pojawiło, lub między stroną a osadzonym w niej iframe.
Zwykle skrypty na różnych stronach mogą się ze sobą komunikować tylko wtedy, gdy pochodzą z tego samego źródła, mają ten sam protokół, numer portu i hosta (co jest znane jako zasada dotycząca tego samego źródła). Metoda window.postMessage()
zapewnia kontrolowany mechanizm bezpiecznej komunikacji między różnymi źródłami. Może to być przydatne podczas wdrażania aplikacji do czatu, narzędzi do współpracy i innych. Na przykład aplikacja do czatu może używać postMessage
do wysyłania wiadomości między użytkownikami, którzy są w różnych witrynach.
Korzystanie z funkcji postMessage
w ramach zaufanej aktywności internetowej (ZAI) może być nieco kłopotliwe. W tym przewodniku znajdziesz instrukcje korzystania z funkcji postMessage w kliencie TWA do wysyłania i odbierania wiadomości ze strony internetowej.
Dodawanie aplikacji do weryfikacji internetowej
Interfejs postMessage API umożliwia komunikację między dwoma prawidłowymi źródłami: źródłem i źródłem docelowym. Aby aplikacja na Androida mogła wysyłać wiadomości do docelowego źródła, musi zadeklarować, z jakim źródłem jest ono równoważne. Można to zrobić za pomocą linków do zasobów cyfrowych (DAL), dodając nazwę pakietu aplikacji w pliku assetlinks.json
z relacją use_as_origin
. W ten sposób będzie wyglądać:
[{
"relation": ["delegate_permission/common.use_as_origin"],
"target" : { "namespace": "android_app", "package_name": "com.example.app", "sha256_cert_fingerprints": [""] }
}]
Pamiętaj, że w przypadku konfiguracji źródła powiązanego z TWA konieczne jest podanie źródła dla pola MessageEvent.origin, ale możesz użyć wartości postMessage
, aby komunikować się z innymi witrynami, które nie zawierają linku do zasobów cyfrowych. Jeśli na przykład jesteś właścicielem witryny www.example.com
, musisz udowodnić, że korzystasz z DAL, ale możesz też komunikować się z dowolnymi innymi witrynami, np. www.wikipedia.org
.
Dodawanie usługi PostMessageService do pliku manifestu
Aby otrzymywać komunikaty postMessage
, musisz skonfigurować usługę. Aby to zrobić, dodaj element PostMessageService
do pliku manifestu Androida:
<service android:name="androidx.browser.customtabs.PostMessageService"
android:exported="true"/>
Pobieranie instancji CustomTabsSession
Po dodaniu usługi do pliku manifestu użyj klasy CustomTabsClient, aby ją powiązać. Po nawiązaniu połączenia możesz użyć udostępnionego klienta do utworzenia nowej sesji w ten sposób:
CustomTabsSession to główna klasa do obsługi interfejsu postMessage API. Poniższy kod pokazuje, jak po połączeniu usługi klient jest używany do utworzenia nowej sesji, która służy do 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;
}
});
Zastanawiasz się teraz, czym jest instancja customTabsCallback
? Utworzymy go w następnej sekcji.
Tworzenie obiektu CustomTabsCallback
CustomTabsCallback to klasa wywołania zwrotnego dla CustomTabsClient, która służy do odbierania wiadomości dotyczących zdarzeń w niestandardowych kartach. Jednym z tych zdarzeń jest onPostMessage
, które jest wywoływane, gdy aplikacja otrzyma wiadomość z sieci. Dodaj do klienta wywołanie zwrotne, aby zainicjować kanał postMessage i rozpocząć komunikację, jak pokazano w poniższym kodzie.
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.
}
};
Komunikowanie się z internetu
Teraz możemy wysyłać i odbierać wiadomości z aplikacji hosta. Jak to zrobić w przeglądarce? Komunikacja musi się rozpocząć od aplikacji hosta, a strona internetowa musi uzyskać port z pierwszej wiadomości. Ten port służy do komunikacji zwrotnej. Plik JavaScript będzie wyglądał mniej więcej tak:
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);
};
});
Pełny przykładowy dokument znajdziesz tutaj.
Zdjęcie: Joanna Kosinska z Unsplash