25
Hybrid Apps: Your own mini-Cordova Ayman Mahfouz VP of Engineering @ Webalo November 2016

Hybrid apps - Your own mini Cordova

Embed Size (px)

Citation preview

Page 1: Hybrid apps - Your own mini Cordova

Hybrid Apps: Your own mini-Cordova

Ayman MahfouzVP of Engineering @ Webalo

November 2016

Page 2: Hybrid apps - Your own mini Cordova

Agenda

- Problem- Hybrid apps- Android

- Java to JavaScript- JavaScript to Java

- iOS- Objective-C to JavaScript- JavaScript to Objective-C

- Talking Angular- Summary

Page 3: Hybrid apps - Your own mini Cordova

Problem Context - Webalo Platform

Page 4: Hybrid apps - Your own mini Cordova

Problem Context - Webalo App

Shared Java code allows for extensibility, but how to open the Webalo Client up for third party extension?

Page 5: Hybrid apps - Your own mini Cordova

Solution - Hybrid App

HTML + JavaScript

Java / Obj-C

WebView

Android App

● Java / Objective-C: Proprietary code.● JavaScript: Third-party code.

Page 6: Hybrid apps - Your own mini Cordova

AndroidJava to JavaScript

Page 7: Hybrid apps - Your own mini Cordova

Java to JavaScript

API

void evaluateJavascript(String script, ValueCallback<String> resultCallback)

webView.evaluateJavascript(“someJavaScriptFunction();”, new ValueCallback<String>() {

public void onReceiveValue(String s) { JsonReader reader = new JsonReader(new StringReader(s));

JsonToken token = JsonReader.peek() ... }});

Usage

Page 8: Hybrid apps - Your own mini Cordova

Java to JavaScript

Requirements

1. API level 19.2. WebSettings.setJavaScriptEnabled(true) // false by default3. Must be called on UI thread.

evaluateJavascript(...)

Properties

1. Asynchronous evaluation.2. Context of currently displayed page.3. Callback made on UI thread.4. Callback value is a JSON object. To pass String values use

JsonReader.setLenient(true).

Page 10: Hybrid apps - Your own mini Cordova

AndroidJavaScript to Java

Page 11: Hybrid apps - Your own mini Cordova

JavaScript to Java

Inject objects into the displayed page context:

private final class Api {

public void showMessage(String message) { Log.d(TAG, message); }}webView.addJavascriptInterface(new Api(), "MyJavaObj");

Starting API 17

void addJavascriptInterface(Object serviceApi, String name)

Usage

API

MyJavaObj.showMessage(“Hello There!”);

Java

JS

@JavascriptInterface

Page 12: Hybrid apps - Your own mini Cordova

JavaScript to Java - Notes

1. Injected objects will not appear in JavaScript until the page is next (re)loaded.

webView.loadData("", "text/html", null);

2. WebView interacts with Java object on a background thread. 3. Serialization of arguments

a. Simple types and stringsb. Serialize objects as JSON

4. Use WebChromeClient to handle callbacks

webView.setWebChromeClient(new WebChromeClient() { public boolean onJsAlert(...) { // display alert in OS theme } }); }

Page 13: Hybrid apps - Your own mini Cordova

Troubleshooting

Use Chrome “Inspect” feature

chrome://inspectMust enable debugging

WebView.setWebContentsDebuggingEnabled(true);

[INFO:CONSOLE(1)] "Uncaught SyntaxError: Unexpected token ILLEGAL", source: (1)[INFO:CONSOLE(13)] "Uncaught ReferenceError: MyJavaObj is not defined"android.view.ViewRootImpl$CalledFromWrongThreadException

1. Run calls from JavaScript on UI Thread. 2. Wait till page loads WebViewClient.onPageFinished()3. Force page load using

webView.loadData("", "text/html", null);

Debugging

Common Causes

Common Errors

Page 14: Hybrid apps - Your own mini Cordova

iOSObjective-C to JavaScript

Page 15: Hybrid apps - Your own mini Cordova

Objective-C to JavaScript

WKWebView API (iOS 8+)

- (void)evaluateJavaScript : (NSString *)javaScriptString completionHandler : (void (^)(id, NSError *error))completionHandler;

[webView evaluateJavaScript : script completionHandler:^(id result, NSError *error) { if (error == nil) { if (result != nil) { NSString* resultString = [NSString stringWithFormat:@"%@", result]; ... } } else { NSLog(@"evaluateJavaScript error : %@", error.localizedDescription); } }];

Usage

Page 16: Hybrid apps - Your own mini Cordova

Objective-C to JavaScript - Pre iOS 8

UIWebView API

- (NSString *)stringByEvaluatingJavaScriptFromString : (NSString *)script;

NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];

NSString *ten = [webView stringByEvaluatingJavaScriptFromString:@"var x = 2; x * 5;"];

Usage

Page 17: Hybrid apps - Your own mini Cordova

Objective-C to JavaScript - Notes

- (void) viewDidLoad {

// Send page load request to Web View

}

- (void) webViewDidFinishLoad : (UIWebView *)webView {

// Ask Web View to evaluate JavaScript

}

Page 18: Hybrid apps - Your own mini Cordova

iOSJavaScript to Objective-C

Page 19: Hybrid apps - Your own mini Cordova

JavaScript to Objective-C

Inject an object into WK

@interface MyHandler : NSObject<WKScriptMessageHandler> { … }

- (void)userContentController : (WKUserContentController *)userContentController didReceiveScriptMessage: (WKScriptMessage *)message { NSDictionary *dict = (NSDictionary*)message.body; NSString *str = [dict objectForKey:@"strField"]; NSNumber *num = [dict objectForKey:@"numField"]; ...}

[webView.configuration.userContentController addScriptMessageHandler : myHandlerObject

name : @"handlerNameInJs"];

Usage

API

window.webkit.messageHandlers.handlerNameInJs.postMessage( { ‘strField’ : “Some string value”, ‘numField’ : 3 } );

Obj

ectiv

e-C

JS

Page 20: Hybrid apps - Your own mini Cordova

JavaScript to Objective-C - Pre iOS 8

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest : (NSURLRequest *)request navigationType : (UIWebViewNavigationType)navigationType {

NSURL* url = request.URL;

if ( ! [url.scheme isEqualToString:@"myapp"]) { return YES; }

// decode the invocation

NSString* methodName = [hostStrEncoded stringByRemovingPercentEncoding]; NSString* queryStr = [[url query] stringByRemovingPercentEncoding]; ... return NO;}

Usage - UIWebViewDelegate

Point the browser to the function you want to invoke!API

document.location.href = “myapp://methodName?param1=test&param2=3

Obj

ectiv

e-C

JS

Page 21: Hybrid apps - Your own mini Cordova

The Angular bit

Page 22: Hybrid apps - Your own mini Cordova

Angular to Native

Wrap an Angular service around the injected Object.

angular.module('MyModule').service('WrapperService', function() { this.showMessage = function(message) { MyInjectedObj.showMessage(message); };

this.someOtherMethod = function() { MyInjectedObj.someOtherMethod(); };});

Page 23: Hybrid apps - Your own mini Cordova

Java to Angular

// Get the element for the angular applicationvar app = angular.element('[ng-app]');

// Get the injector from the application var injector = app.injector();

// Get the service to be calledvar myService = injector.get("MyService");

// Invoke the servicemyService.someFunction();

What is the entry point from plain JavaScript to Angular?

Page 24: Hybrid apps - Your own mini Cordova

Appreciate what PhoneGap does for you!

Summary

● Hybrid Apps● Conversing with the Web View● Extensions

○ Other platforms○ Callbacks to JavaScript○ Code generation