החל מ-Chrome 115, הפעילויות המהימנות באינטרנט (TWA) יכולות לשלוח הודעות באמצעות postMessage. במסמך הזה מוסבר איך מגדירים את התקשורת בין האפליקציה לאינטרנט.
בסוף המדריך הזה תלמדו:
- להבין איך פועל אימות הלקוח ותוכן האינטרנט.
- איך מאתחלים את ערוץ התקשורת בין הלקוח לתוכן האינטרנט.
- למדו איך לשלוח הודעות לתוכן אינטרנט ולקבל ממנו הודעות.
כדי לפעול לפי המדריך הזה, צריך:
- כדי להוסיף את הגרסה העדכנית ביותר של ספריית androidx.browser (גרסה 1.6.0-alpha02 לפחות) לקובץ build.gradle.
- Chrome מגרסה 115.0.5790.13 ואילך ל-TWA.
השיטה window.postMessage()
מאפשרת תקשורת מאובטחת בין מקורות שונים בין אובייקטים מסוג Window. לדוגמה, בין דף לבין חלון קופץ שהוא יצר, או בין דף לבין iframe שמוטמע בו.
בדרך כלל, סקריפטים בדפים שונים מורשים לגשת זה לזה רק אם הדפים מגיעים מאותו מקור, אם הם חולקים את אותו פרוטוקול, מספר יציאה ומארח (הנקרא גם מדיניות מקור זהה). השיטה window.postMessage()
מספקת מנגנון מבוקר לתקשורת מאובטחת בין מקורות שונים. האפשרות הזו יכולה להועיל להטמעת אפליקציות צ'אט, כלים לשיתוף פעולה ועוד. לדוגמה, אפליקציית צ'אט יכולה להשתמש ב-postMessage
כדי לשלוח הודעות בין משתמשים שנמצאים באתרים שונים.
השימוש ב-postMessage
בפעילויות מהימנות באינטרנט (TWA) יכול להיות קצת מסובך. במדריך הזה נסביר איך להשתמש ב-postMessage בלקוח TWA כדי לשלוח הודעות לדף האינטרנט ולקבל ממנו הודעות.
הוספת האפליקציה לאימות באינטרנט
ממשק ה-postMessage API מאפשר לשני מקורות תקינים לתקשר זה עם זה, מקור ומקור יעד. כדי שאפליקציית Android תוכל לשלוח הודעות למקור היעד, היא צריכה להצהיר לאיזה מקור מקור היא מקבילה. אפשר לעשות זאת באמצעות קישורי נכסים דיגיטליים (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 היא הכיתה המרכזית לטיפול ב-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 היא מחלקת קריאה חוזרת (callback) של 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);
};
});
דוגמה מלאה זמינה כאן
תמונה של Joanna Kosinska ב-Unsplash