Из Chrome 115 Trusted Web Activity (TWA) может отправлять сообщения с помощью postMessage. В этом документе описывается настройка, необходимая для связи между вашим приложением и Интернетом.
К концу этого руководства вы:
- Поймите, как работает проверка клиента и веб-контента.
- Знать, как инициализировать канал связи между клиентом и веб-контентом.
- Знайте, как отправлять сообщения и получать сообщения из веб-контента.
Чтобы следовать этому руководству, вам понадобится:
- Чтобы добавить последнюю версию библиотеки androidx.browser (минимум 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 позволяет двум допустимым источникам взаимодействовать друг с другом: источнику и целевому источнику. Чтобы приложение Android могло отправлять сообщения в целевой источник, ему необходимо объявить, какому исходному источнику оно эквивалентно. Это можно сделать с помощью Digital Asset Links (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
в манифест Android:
<service android:name="androidx.browser.customtabs.PostMessageService" android:exported="true"/>
Получите экземпляр CustomTabsSession.
После добавления службы в манифест используйте класс CustomTabsClient для привязки службы. После подключения вы можете использовать предоставленный клиент для создания нового сеанса следующим образом. CustomTabsSession — это основной класс для обработки API postMessage. Следующий код показывает, как после подключения службы клиент используется для создания нового сеанса, этот сеанс используется для 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
, верно? Мы создадим это в следующем разделе.
Создать обратный вызов CustomTabs
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. } };
Общение через Интернет
Теперь мы можем отправлять и получать сообщения из нашего хост-приложения. Как нам сделать то же самое через Интернет? Связь должна начинаться с хост-приложения, затем веб-страница должна получить порт из первого сообщения. Этот порт используется для обратной связи. Ваш файл JavaScript будет выглядеть примерно так:
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); }; });
Полный образец вы можете найти здесь.
Фото Джоанны Косинской на Unsplash