Implementation
Future<void> injectJavaScript() async {
debugPrint(
'Appbridge: _injectJavaScript called. Attempting to inject JavaScript.');
const jsCode = '''
window.AppBridge = {
core: {
getVersion: (params) => _callNative('core.getVersion', params),
getEnv: (params) => _callNative('core.getEnv', params),
ready: (params) => _callNative('core.ready', params),
has: (path) => _callNative('core.has', {path: path}),
getCapabilities: (params) => _callNative('core.getCapabilities', params),
setVpn: (params) => _callNative('core.setVpn', params),
addShortcuts: (params) => _callNative('core.addShortcuts', params),
appIcon: (params) => _callNative('core.appIcon', params),
},
events: {
on: (event, handler) => {
return _callNative('events.on', {event: event, handler: handler.toString()})
.then(res => {
if (res.data && res.data.off) {
return eval('(' + res.data.off + ')');
}
return { off: () => console.warn('Unsubscribe function not provided by native.') };
});
},
once: (event, handler) => {
return _callNative('events.once', {event: event, handler: handler.toString()})
.then(res => {
if (res.data && res.data.off) {
return eval('(' + res.data.off + ')');
}
return { off: () => console.warn('Unsubscribe function not provided by native.') };
});
},
emit: (event, payload) => _callNative('events.emit', {event: event, payload: payload}),
off: (event, callbackId) => _callNative('events.off', {event: event, callbackId: callbackId}),
},
app: {
getStatus: (params) => _callNative('app.getStatus', params),
openSettings: (section) => _callNative('app.openSettings', {section: section}),
exit: (params) => _callNative('app.exit', params),
minimize: (params) => _callNative('app.minimize', params),
update: {
check: (params) => _callNative('app.update.check', params),
apply: (params) => _callNative('app.update.apply', params),
}
},
nav: {
open: (params) => _callNative('nav.open', params),
close: (params) => _callNative('nav.close', params),
replace: (params) => _callNative('nav.replace', params),
setTitle: (params) => _callNative('nav.setTitle', params),
setBars: (params) => _callNative('nav.setBars', params),
},
ui: {
toast: (params) => _callNative('ui.toast', params),
alert: (params) => _callNative('ui.alert', params),
confirm: (params) => _callNative('ui.confirm', params),
actionSheet: (params) => _callNative('ui.actionSheet', params),
loading: (params) => _callNative('ui.loading', params),
haptics: (params) => _callNative('ui.haptics', params),
safeArea: (params) => _callNative('ui.safeArea', params),
},
storage: {
get: (params) => _callNative('storage.get', params),
set: (params) => _callNative('storage.set', params),
remove: (params) => _callNative('storage.remove', params),
clear: (params) => _callNative('storage.clear', params),
},
permission: {
check: (params) => _callNative('permission.check', params),
request: (params) => _callNative('permission.request', params),
ensure: (name) => _callNative('permission.ensure', {name: name}),
},
device: {
getIds: (params) => _callNative('device.getIds', params),
getInfo: (params) => _callNative('device.getInfo', params),
getBattery: (params) => _callNative('device.getBattery', params),
getStorageInfo: (params) => _callNative('device.getStorageInfo', params),
getMemoryInfo: (params) => _callNative('device.getMemoryInfo', params),
getCpuInfo: (params) => _callNative('device.getCpuInfo', params),
},
share: {
open: (params) => _callNative('share.open', params),
copyLink: (params) => _callNative('share.copyLink', params),
},
clipboard: {
get: (params) => _callNative('clipboard.get', params),
set: (params) => _callNative('clipboard.set', params),
},
notifications: {
checkPermission: (params) => _callNative('notifications.check', params),
showLocal: (params) => _callNative('notifications.showLocal', params),
},
auth: {
getToken: (params) => _callNative('auth.getToken', params),
refreshToken: (params) => _callNative('auth.refreshToken', params),
},
payment: {
pay: (params) => _callNative('payment.pay', params),
},
download: {
start: (params) => _callNative('download.start', params),
pause: (params) => _callNative('download.pause', params),
resume: (params) => _callNative('download.resume', params),
cancel: (params) => _callNative('download.cancel', params),
status: (params) => _callNative('download.status', params),
list: (params) => _callNative('download.list', params),
m3u8: (params) => _callNative('download.m3u8', params),
getDefaultDir: (params) => _callNative('download.getDefaultDir', params),
setDefaultDir: (params) => _callNative('download.setDefaultDir', params),
getFilePath: (params) => _callNative('download.getFilePath', params),
},
apk: {
download: (params) => _callNative('apk.download', params),
install: (params) => _callNative('apk.install', params),
open: (params) => _callNative('apk.open', params),
isInstalled: (params) => _callNative('apk.isInstalled', params),
},
cache: {
getSize: (params) => _callNative('cache.getSize', params),
clear: (params) => _callNative('cache.clear', params),
},
appstore: {
open: (params) => _callNative('appstore.open', params),
search: (params) => _callNative('appstore.search', params),
},
testflight: {
open: (params) => _callNative('testflight.open', params),
},
deeplink: {
open: (params) => _callNative('deeplink.open', params),
parse: (params) => _callNative('deeplink.parse', params),
},
liveActivity: {
start: (params) => _callNative('liveActivity.start', params),
update: (params) => _callNative('liveActivity.update', params),
stop: (params) => _callNative('liveActivity.stop', params),
},
video: {
open: (params) => _callNative('video.open', params),
},
novel: {
open: (params) => _callNative('novel.open', params),
},
comics: {
open: (params) => _callNative('comics.open', params),
},
live: {
start: (params) => _callNative('live.start', params),
stop: (params) => _callNative('live.stop', params),
play: (params) => _callNative('live.play', params),
pause: (params) => _callNative('live.pause', params),
},
post: {
open: (params) => _callNative('post.open', params),
},
// Add this new function
triggerInitSDK: () => {
if (typeof AppBridge !== 'undefined' && typeof AppBridge.core !== 'undefined' && typeof AppBridge.core.ready !== 'undefined') {
initSDK(); // Call the initSDK function defined in demo.html
} else {
console.warn('AppBridge not fully ready to trigger initSDK.');
}
}
};
function _callNative(method, params) {
console.log('Calling Native Method:', method);
console.log('AppBridge JS: Attempting to call native handler "AppBridge" with method:', method, 'and params:', params);
return new Promise((resolve, reject) => {
const messageId = Date.now() + '_' + Math.random();
window.addEventListener('message', function handler(event) {
if (event.data.type === 'bridge_response' && event.data.messageId === messageId) {
window.removeEventListener('message', handler);
console.log('AppBridge JS: Received bridge_response for messageId:', messageId, 'response:', event.data.response);
if (event.data.response.code === 0) {
resolve(event.data.response);
} else {
reject(event.data.response);
}
}
});
window.flutter_inappwebview.callHandler('AppBridge', {
method: method,
params: params || {},
messageId: messageId
});
console.log('AppBridge JS: Dispatched callHandler for messageId:', messageId);
});
}
// Listen for flutterInAppWebViewPlatformReady before calling initSDK()
window.addEventListener('flutterInAppWebViewPlatformReady', function(event) {
console.log('AppBridge JS: flutterInAppWebViewPlatformReady event received. Calling initSDK().');
initSDK();
});
''';
await _webViewController!.evaluateJavascript(source: jsCode);
debugPrint('Appbridge: JavaScript injection complete.');
}