在 Cordova 與 InAppBrowser 之間分享資料
Cordova 是一個 Hybrid App 可以使用 InAppBrowser 去打開一個網頁,但是他們之間要怎麼共享資料?
Cordova 架構
Cordova 有很多 Plugin 可以安裝,其中一個就是 InAppBrowser,可以開啟遠端的網頁,但是透過這網頁是無法直接使用其他 Plugin 的功能,像是 Camera、Push Notification,需要先讓 Cordova 和 InAppBrowser 之間可以互相溝通分享資料。
了解 InAppBrowser
再開始之前,讓我們來了解一下 InAppBrowser ,InAppBrowser 允許在 App 內打開的網頁,而不用離開 App,如果不是用 InAppBrowser打開的網頁,則將會用默認的瀏覽器打開。
打開網頁非常簡單,安裝 InAppBrowser 之後只要只用 window.open
。1
var win = window.open("http://google.com", "_blank", "location=yes");
InAppBrowser 不支援 postMessage,但有4個事件可以使用:
- loadstart – 當 InAppBrowser 開始加載 URL 時觸發事件。
- loadstop – 當 InAppBrowser 完成加載 URL 時觸發事件。
- loaderror – 當 InAppBrowser 在加載 URL 時遇到錯誤時觸發事件。
- exit – InAppBrowser 窗口關閉時觸發事件。
executeScript
InAppBrowser 有一個 executeScript function,可以在 InAppBrowser 上直接執行 Javascript,並且可以取得結果1
2
3
4
5
6
7
8let win = window.open("http://google.com", "_blank", "location=yes");
win.addEventListener("loadstop", () => {
//code goes here
win.executeScript({ code: "localStorage.setItem('name', 'Test')" });
win.executeScript({ code: "localStorage.getItem('name')" }, ([val]) => {
console.log(val);
});
});
Cordova 傳遞資料給 InAppBrowser1
2let myName = 'John';
win.executeScript({ code: `localStorage.setItem('name', '${myName}')` });
InAppBrowser 傳遞資料給 Cordova
由於 InAppBrowser 內沒有任何方法可以直接送資料給 Cordova,但可以透過創一個定期執行的函數,此函數將從 InAppBrowser 的 LocalStorage 中獲取資料。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15let name;
let nameInterval;
let win = window.open("http://google.com", "_blank", "location=yes");
win.addEventListener("loadstop", () => {
nameInterval = setInterval(() => {
win.executeScript({ code: "localStorage.getItem('name')" }, ([val]) => {
name = val;
});
}, 100);
});
win.addEventListener("exit", () => {
clearInterval(nameInterval);
});
這樣在 InAppBrowser 內就能透過 LocalStorage 傳資料給 Cordova
後記
為方便使用,可以將這方法實作成一個 EventBus 去處理兩方之間大量資料的溝通。
以下為範例用法,而非實際功能實作。
Cordova → InAppBrowser
Cordova端1
bus.emit('show-alert', 'Hello World.');
InAppBrowser端1
bus.on('show-alert', (text) => alert(text));
InAppBrowser → Cordova
搭配 PushNotification
的plugin: cordova-plugin-fcm-with-dependecy-updated
Cordova端1
2
3bus.on('fcb-subscribe-topic', (topic) => {
FCM.subscribeToTopic(topic)
});
InAppBrowser端1
bus.emit('fcb-subscribe-topic', 'vip');