https://github.com/grab/mobile-kit-bridge-sdk
SDK for web view bridges that offers unified method signatures for Android/iOS
https://github.com/grab/mobile-kit-bridge-sdk
Last synced: 9 months ago
JSON representation
SDK for web view bridges that offers unified method signatures for Android/iOS
- Host: GitHub
- URL: https://github.com/grab/mobile-kit-bridge-sdk
- Owner: grab
- License: mit
- Created: 2019-04-29T06:43:39.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-06-12T05:38:08.000Z (over 2 years ago)
- Last Synced: 2025-03-25T08:03:21.462Z (10 months ago)
- Language: TypeScript
- Homepage:
- Size: 683 KB
- Stars: 7
- Watchers: 5
- Forks: 5
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Disclaimer
This SDK is a generic SDK for native webviews. For Grab `SuperApp` integration, please use the [SuperApp SDK](https://github.com/grab/superapp-sdk).
# mobile-kit-bridge-sdk
SDK for mobile module bridge to offer unified method signatures for Android/iOS.
## Asynchronous returns
For example:
```javascript
const identifier = await window.WrappedLocaleKit.invoke("getLocaleIdentifier");
await window.WrappedAnalyticsModule.invoke("track", { analyticsEvent: event });
await window.WrappedMediaKit.invoke("playDRMContent", { contentURL, license });
```
All module methods will have `callback` as one of the parameters:
```java
class AnalyticsModuleBridge {
fun track(requestString: String) {
val request = Gson().fromJson(...)
val callback = request.callback
...
}
}
```
```swift
final class AnalyticsModuleBridge: WKScriptMessageHandler {
func userContentController(
_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage) {
let request = message.body as! [String : Any]
let callback = request["callback"] as! String
...
}
}
```
For the sake of standardization, **all** module methods must invoke the relevant callback after they finish, even if they run synchronously or do not have anything meaningful to return. Use the parameter `callback` to identify the correct callback to invoke:
```java
webView.evaluateJavascript("javascript:window.$callback(...)") { _ -> }
```
```swift
webView.evaluateJavascript("window.\(callback)(...)", nil)
```
The name of the callback always starts with:
```javascript
[moduleName]_[functionName]Callback
```
For e.g.:
```javascript
AnalyticsModule.track -> WrappedAnalyticsModule_trackCallback
MediaKit.playDRMContent -> WrappedMediaKit_playDRMContentCallback
```
This callback style allows us to pass errors to the partner app that they can handle in case something goes wrong.
## Value streaming
All module methods return streams, e.g.:
```javascript
/** Get stream of location updates. */
const subscription = window.WrappedLocationModule.invoke(
"observeLocationChange"
).subscribe({ next: console.log, complete: console.log });
```
Calling these methods returns `DataStream` objects that can be subscribed to with `StreamHandlers` (i.e. `onValue`, `onComplete` etc.). Once `subscribe` is called, a `Subscription` object is created to control when streaming should be terminated.
Note that `DataStream` always creates new streams whenever `subscribe` is called, so there is no need to worry about invoking it multiple times. The concept of `DataStream` is similar to that of an `Observable`, and it is easy to bridge the two:
```javascript
const playObservable = new Observable(sub => {
const subscription = window.WrappedMediaKit.invoke('observePlayDRMContent', { isStream: true, ... }).subscribe({
next: data => sub.next(data),
complete: () => sub.complete(),
});
return () => subscription.unsubscribe();
});
playObservable.pipe(filter(...), map(...)).subscribe(...);
```
`DataStream` also supports `Promise`-style chaining and `async-await`. Instead of getting values over time, this will simply deliver the first value that arrives:
```javascript
const { result, error, status_code } = await window.WrappedMediaKit.invoke('observePlayDRMContent', { isStream: true, ... });
```
Please be aware that **Promises returned by bridged methods are non-eager**, so they will only be triggered on invocation of `then`, or after an `await` in an `async` function.
## Data format
Callback results must be in the format prescribed below:
```javascript
type CallbackResult = Readonly<{
/** The result of the operation. */
result: T,
/** The error object, if any. */
error: unknown,
/** The status code. */
status_code: number
}>;
```
Make sure native code is passing data in the correct format, or else callbacks will not be invoked.