
com.futureplatforms.kirin.HybridModule Maven / Gradle / Ivy
The newest version!
package com.futureplatforms.kirin;
import java.util.LinkedList;
import java.util.Queue;
import com.futureplatforms.kirin.dependencies.StaticDependencies;
import com.futureplatforms.kirin.dependencies.StaticDependencies.LogDelegate;
/**
* Deals with a screen with a webview that we need to communicate with.
*/
public abstract class HybridModule extends KirinModule
{
/**
* This queue contains the messages that should be sent to the webview for the time when
* we receive a message from it indicating it is ready.
*/
private Queue msgsForWhenWebviewIsReady;
/**
* This queue contains any messages that come from the webview before the module's onResume is called.
*/
private Queue msgsForWhenModuleIsReady;
/**
* This is set to true when the webview tells us it is ready. Once set to true, it remains true until
* the module is destroyed.
* It is set to false in the following circumstances:
* in the constructor
* when onWebviewDestroyed() is called
* when onLoad() is called after onExit() was called and there was no call to onWebviewDestroyed()
*/
private boolean webviewIsReady;
/**
* This is set to true when the module's onEntry() is called.
* It is reset to false in the constructor and onExit().
*/
private boolean moduleIsReady;
public HybridModule(final NativeSide nativeSide)
{
super(nativeSide);
this.msgsForWhenWebviewIsReady = new LinkedList();
this.msgsForWhenModuleIsReady = new LinkedList();
this.webviewIsReady = false;
this.moduleIsReady = false;
}
@Override
protected void _onLoad() {
super._onLoad();
if(this.webviewIsReady) {
// Right. This _onLoad() has been called more than once.
// We should assume that the webview has been destroyed since
this.onWebviewDestroyed();
}
}
/**
* Needs to be called from Fragment.onCreateView() on Android and viewWillAppear on iOS.
*/
public final void onEntry()
{
for(final String[] msgFromWebview : this.msgsForWhenModuleIsReady) {
onWebViewSaid(msgFromWebview[0], msgFromWebview[1]);
}
this.moduleIsReady = true;
_onEntry();
}
/**
* Called whenever onEntry() is called. Override if your module needs to know when the user has started to use it.
*/
protected void _onEntry() {}
/**
* Needs to be called from Fragment.onDestroyView() on Android and viewWillDisappear on iOS.
*/
public final void onExit()
{
this.moduleIsReady = false;
_onExit();
}
/**
* Called whenever onEntry() is called. Override if your module needs to know when the user has stopped using it.
*/
protected void _onExit() {}
/**
* This must be called from Android's Fragment.onDestroyView() or the Activity.onDestroy(), or whenever the webview is destroyed
*/
public void onWebviewDestroyed() {
this.webviewIsReady = false;
}
/**
* Called from the native side when a webview is trying to tell us something.
*
* One special message is "ready" which indicates that the webview has initialised and is capable of receiving messages from us.
*/
public final void webViewSaid(final String method, final String args)
{
if ("ready".equals(method)) {
webViewIsReady();
} else if ("log".equals(method)) {
StaticDependencies.getInstance().getLogDelegate().log("Hybrid webview LOG: " + args);
} else {
if(this.moduleIsReady) {
onWebViewSaid(method, args);
} else {
//PlatformDependencies.getInstance().getLogDelegate().log("HybridScreen.webViewSaid("+method+"/"+params+") module isn't ready yet. Queuing until it is.");
this.msgsForWhenModuleIsReady.add(new String[]{method, args});
}
}
}
/**
* Called when a message is sent from the webview to this module.
*
* @param method
* @param params
*/
protected abstract void onWebViewSaid(final String method, final String params);
private void webViewIsReady() {
//PlatformDependencies.getInstance().getLogDelegate().log("HybridScreen.webViewIsReady() Sending " + this.msgsForWhenWebviewIsReady.size() + " queued messages now.");
// We may have queued up some messages to send to the webview. Send them now it is ready.
while(!this.msgsForWhenWebviewIsReady.isEmpty()) {
final String msg = this.msgsForWhenWebviewIsReady.remove();
getNativeObject().tellWebview(msg);
}
this.webviewIsReady = true;
}
protected void tellWebview(final String javascript) {
final String encodedJavascript = encodeUTF8JsonAsAsciiJson(javascript);
LogDelegate log = StaticDependencies.getInstance().getLogDelegate();
log.log("trying to tell webview " + encodedJavascript.substring(0, Math.min(500, encodedJavascript.length())));
if(this.webviewIsReady) {
// Send immediately
getNativeObject().tellWebview(encodedJavascript);
} else {
// Queue it for for when we receive the message from the webview stating it's ready.
//PlatformDependencies.getInstance().getLogDelegate().log("HybridScreen.tellWebview() webview isn't ready yet. Queuing message until it is.");
this.msgsForWhenWebviewIsReady.add(encodedJavascript);
}
}
private static String encodeUTF8JsonAsAsciiJson( final String encodeMe ) {
final StringBuilder sb = new StringBuilder();
final int encodeMeLength = encodeMe.length();
for( int i = 0; i < encodeMeLength; i++ ) {
final char c = encodeMe.charAt(i);
if( c > 127 ) {
sb.append("\\u");
final StringBuffer hexString = new StringBuffer(Integer.toString(c, 16));
while(hexString.length() < 4) {
hexString.insert(0, '0');
}
sb.append(hexString);
}
else {
sb.append(c);
}
}
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy