mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-03 17:02:13 +01:00
Move some methods to clarify responsibilities and simplify some things
This commit is contained in:
parent
e159a5dde3
commit
9ee1aa87e8
@ -17,7 +17,6 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@ -90,7 +89,7 @@ public class ExternalPebbleJSActivity extends AbstractGBActivity {
|
|||||||
}
|
}
|
||||||
myWebView.setWillNotDraw(false);
|
myWebView.setWillNotDraw(false);
|
||||||
myWebView.removeJavascriptInterface("GBActivity");
|
myWebView.removeJavascriptInterface("GBActivity");
|
||||||
myWebView.addJavascriptInterface(new ActivityJSInterface(ExternalPebbleJSActivity.this), "GBActivity");
|
myWebView.addJavascriptInterface(new ActivityJSInterface(), "GBActivity");
|
||||||
FrameLayout fl = (FrameLayout) findViewById(R.id.webview_placeholder);
|
FrameLayout fl = (FrameLayout) findViewById(R.id.webview_placeholder);
|
||||||
fl.addView(myWebView);
|
fl.addView(myWebView);
|
||||||
|
|
||||||
@ -122,7 +121,7 @@ public class ExternalPebbleJSActivity extends AbstractGBActivity {
|
|||||||
|
|
||||||
JSInterface gbJSInterface = new JSInterface(currentDevice, currentUUID);
|
JSInterface gbJSInterface = new JSInterface(currentDevice, currentUUID);
|
||||||
myWebView.addJavascriptInterface(gbJSInterface, "GBjs");
|
myWebView.addJavascriptInterface(gbJSInterface, "GBjs");
|
||||||
myWebView.addJavascriptInterface(new ActivityJSInterface(ExternalPebbleJSActivity.this), "GBActivity");
|
myWebView.addJavascriptInterface(new ActivityJSInterface(), "GBActivity");
|
||||||
|
|
||||||
myWebView.loadUrl("file:///android_asset/app_config/configure.html");
|
myWebView.loadUrl("file:///android_asset/app_config/configure.html");
|
||||||
|
|
||||||
@ -163,16 +162,9 @@ public class ExternalPebbleJSActivity extends AbstractGBActivity {
|
|||||||
|
|
||||||
private class ActivityJSInterface {
|
private class ActivityJSInterface {
|
||||||
|
|
||||||
Context mContext;
|
|
||||||
|
|
||||||
ActivityJSInterface(Context c) {
|
|
||||||
mContext = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JavascriptInterface
|
@JavascriptInterface
|
||||||
public void closeActivity() {
|
public void closeActivity() {
|
||||||
NavUtils.navigateUpFromSameTask((ExternalPebbleJSActivity) mContext);
|
NavUtils.navigateUpFromSameTask(ExternalPebbleJSActivity.this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,4 +27,14 @@ public class GBDeviceEventAppMessage extends GBDeviceEvent {
|
|||||||
public UUID appUUID;
|
public UUID appUUID;
|
||||||
public int id;
|
public int id;
|
||||||
public String message;
|
public String message;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "GBDeviceEventAppMessage{" +
|
||||||
|
"type=" + type +
|
||||||
|
", appUUID=" + appUUID +
|
||||||
|
", message='" + message + '\'' +
|
||||||
|
", id=" + id +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ import android.content.Intent;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
import android.webkit.ValueCallback;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -59,7 +61,6 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.ble.PebbleLESupport;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.ble.PebbleLESupport;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
|
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
|
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||||
@ -100,12 +101,45 @@ class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
private int mBytesWritten = -1;
|
private int mBytesWritten = -1;
|
||||||
|
|
||||||
private void sendAppMessageJS(GBDeviceEventAppMessage appMessage) {
|
private void sendAppMessageJS(GBDeviceEventAppMessage appMessage) {
|
||||||
WebViewSingleton.appMessage(appMessage);
|
sendAppMessage(appMessage);
|
||||||
if (appMessage.type == GBDeviceEventAppMessage.TYPE_APPMESSAGE) {
|
if (appMessage.type == GBDeviceEventAppMessage.TYPE_APPMESSAGE) {
|
||||||
write(mPebbleProtocol.encodeApplicationMessageAck(appMessage.appUUID, (byte) appMessage.id));
|
write(mPebbleProtocol.encodeApplicationMessageAck(appMessage.appUUID, (byte) appMessage.id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void sendAppMessage(GBDeviceEventAppMessage message) {
|
||||||
|
final String jsEvent;
|
||||||
|
try {
|
||||||
|
WebViewSingleton.checkAppRunning(message.appUUID);
|
||||||
|
} catch (IllegalStateException ex) {
|
||||||
|
LOG.warn("Unable to send app message: " + message, ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle ACK and NACK types with ids
|
||||||
|
if (message.type != GBDeviceEventAppMessage.TYPE_APPMESSAGE) {
|
||||||
|
jsEvent = (GBDeviceEventAppMessage.TYPE_NACK == GBDeviceEventAppMessage.TYPE_APPMESSAGE) ? "NACK" + message.id : "ACK" + message.id;
|
||||||
|
LOG.debug("WEBVIEW received ACK/NACK:" + message.message + " for uuid: " + message.appUUID + " ID: " + message.id);
|
||||||
|
} else {
|
||||||
|
jsEvent = "appmessage";
|
||||||
|
}
|
||||||
|
|
||||||
|
final String appMessage = PebbleUtils.parseIncomingAppMessage(message.message, message.appUUID);
|
||||||
|
LOG.debug("to WEBVIEW: event: " + jsEvent + " message: " + appMessage);
|
||||||
|
WebViewSingleton.invokeWebview(new WebViewSingleton.WebViewRunnable() {
|
||||||
|
@Override
|
||||||
|
public void invoke(WebView webView) {
|
||||||
|
webView.evaluateJavascript("Pebble.evaluate('" + jsEvent + "',[" + appMessage + "]);", new ValueCallback<String>() {
|
||||||
|
@Override
|
||||||
|
public void onReceiveValue(String s) {
|
||||||
|
//TODO: the message should be acked here instead of in PebbleIoThread
|
||||||
|
LOG.debug("Callback from appmessage: " + s);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
PebbleIoThread(PebbleSupport pebbleSupport, GBDevice gbDevice, GBDeviceProtocol gbDeviceProtocol, BluetoothAdapter btAdapter, Context context) {
|
PebbleIoThread(PebbleSupport pebbleSupport, GBDevice gbDevice, GBDeviceProtocol gbDeviceProtocol, BluetoothAdapter btAdapter, Context context) {
|
||||||
super(gbDevice, context);
|
super(gbDevice, context);
|
||||||
mPebbleProtocol = (PebbleProtocol) gbDeviceProtocol;
|
mPebbleProtocol = (PebbleProtocol) gbDeviceProtocol;
|
||||||
|
@ -42,7 +42,6 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.WebViewSingleton;
|
|
||||||
|
|
||||||
public class JSInterface {
|
public class JSInterface {
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ public class JSInterface {
|
|||||||
public String sendAppMessage(String msg, String needsTransactionMsg) {
|
public String sendAppMessage(String msg, String needsTransactionMsg) {
|
||||||
boolean needsTransaction = "true".equals(needsTransactionMsg);
|
boolean needsTransaction = "true".equals(needsTransactionMsg);
|
||||||
LOG.debug("from WEBVIEW: " + msg + " needs a transaction: " + needsTransaction);
|
LOG.debug("from WEBVIEW: " + msg + " needs a transaction: " + needsTransaction);
|
||||||
JSONObject knownKeys = WebViewSingleton.getAppConfigurationKeys(this.mUuid);
|
JSONObject knownKeys = PebbleUtils.getAppConfigurationKeys(this.mUuid);
|
||||||
if (knownKeys == null) {
|
if (knownKeys == null) {
|
||||||
LOG.warn("No app configuration keys for: " + mUuid);
|
LOG.warn("No app configuration keys for: " + mUuid);
|
||||||
return null;
|
return null;
|
||||||
|
@ -17,11 +17,22 @@
|
|||||||
package nodomain.freeyourgadget.gadgetbridge.util;
|
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class PebbleUtils {
|
public class PebbleUtils {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(PebbleUtils.class);
|
||||||
|
|
||||||
public static String getPlatformName(String hwRev) {
|
public static String getPlatformName(String hwRev) {
|
||||||
String platformName;
|
String platformName;
|
||||||
if (hwRev.startsWith("snowy")) {
|
if (hwRev.startsWith("snowy")) {
|
||||||
@ -102,4 +113,65 @@ public class PebbleUtils {
|
|||||||
public static File getPbwCacheDir() throws IOException {
|
public static File getPbwCacheDir() throws IOException {
|
||||||
return new File(FileUtils.getExternalFilesDir(), "pbw-cache");
|
return new File(FileUtils.getExternalFilesDir(), "pbw-cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JSONObject getAppConfigurationKeys(UUID uuid) {
|
||||||
|
try {
|
||||||
|
File destDir = getPbwCacheDir();
|
||||||
|
File configurationFile = new File(destDir, uuid.toString() + ".json");
|
||||||
|
if (configurationFile.exists()) {
|
||||||
|
String jsonString = FileUtils.getStringFromFile(configurationFile);
|
||||||
|
JSONObject json = new JSONObject(jsonString);
|
||||||
|
return json.getJSONObject("appKeys");
|
||||||
|
}
|
||||||
|
} catch (IOException | JSONException e) {
|
||||||
|
LOG.warn("Unable to parse configuration JSON file", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String parseIncomingAppMessage(String msg, UUID uuid) {
|
||||||
|
JSONObject jsAppMessage = new JSONObject();
|
||||||
|
|
||||||
|
JSONObject knownKeys = PebbleUtils.getAppConfigurationKeys(uuid);
|
||||||
|
SparseArray<String> appKeysMap = new SparseArray<>();
|
||||||
|
|
||||||
|
if (knownKeys == null || msg == null) {
|
||||||
|
return "{}";
|
||||||
|
}
|
||||||
|
|
||||||
|
String inKey, outKey;
|
||||||
|
//knownKeys contains "name"->"index", we need to reverse that
|
||||||
|
for (Iterator<String> key = knownKeys.keys(); key.hasNext(); ) {
|
||||||
|
inKey = key.next();
|
||||||
|
appKeysMap.put(knownKeys.optInt(inKey), inKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONArray incoming = new JSONArray(msg);
|
||||||
|
JSONObject outgoing = new JSONObject();
|
||||||
|
for (int i = 0; i < incoming.length(); i++) {
|
||||||
|
JSONObject in = incoming.getJSONObject(i);
|
||||||
|
outKey = null;
|
||||||
|
Object outValue = null;
|
||||||
|
for (Iterator<String> key = in.keys(); key.hasNext(); ) {
|
||||||
|
inKey = key.next();
|
||||||
|
switch (inKey) {
|
||||||
|
case "key":
|
||||||
|
outKey = appKeysMap.get(in.optInt(inKey));
|
||||||
|
break;
|
||||||
|
case "value":
|
||||||
|
outValue = in.get(inKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (outKey != null && outValue != null) {
|
||||||
|
outgoing.put(outKey, outValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jsAppMessage.put("payload", outgoing);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.warn("Unable to parse incoming app message", e);
|
||||||
|
}
|
||||||
|
return jsAppMessage.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,29 +31,20 @@ import android.os.Looper;
|
|||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.util.SparseArray;
|
|
||||||
import android.webkit.ValueCallback;
|
|
||||||
import android.webkit.WebResourceResponse;
|
import android.webkit.WebResourceResponse;
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventAppMessage;
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.webview.GBChromeClient;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.webview.GBChromeClient;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.webview.GBWebClient;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.webview.GBWebClient;
|
||||||
@ -149,6 +140,20 @@ public class WebViewSingleton {
|
|||||||
return webViewSingleton.instance;
|
return webViewSingleton.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the webview is up and the given app is running.
|
||||||
|
* @param uuid the uuid of the application expected to be running
|
||||||
|
* @throws IllegalStateException when the webview is not active or the app is not running
|
||||||
|
*/
|
||||||
|
public static void checkAppRunning(@NonNull UUID uuid) {
|
||||||
|
if (webViewSingleton.instance == null) {
|
||||||
|
throw new IllegalStateException("webViewSingleton.instance is null!");
|
||||||
|
}
|
||||||
|
if (!uuid.equals(currentRunningUUID)) {
|
||||||
|
throw new IllegalStateException("Expected app " + uuid + " is not running, but " + currentRunningUUID + " is.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void runJavascriptInterface(@NonNull GBDevice device, @NonNull UUID uuid) {
|
public static void runJavascriptInterface(@NonNull GBDevice device, @NonNull UUID uuid) {
|
||||||
if (uuid.equals(currentRunningUUID)) {
|
if (uuid.equals(currentRunningUUID)) {
|
||||||
LOG.debug("WEBVIEW uuid not changed keeping the old context");
|
LOG.debug("WEBVIEW uuid not changed keeping the old context");
|
||||||
@ -156,13 +161,13 @@ public class WebViewSingleton {
|
|||||||
final JSInterface jsInterface = new JSInterface(device, uuid);
|
final JSInterface jsInterface = new JSInterface(device, uuid);
|
||||||
LOG.debug("WEBVIEW uuid changed, restarting");
|
LOG.debug("WEBVIEW uuid changed, restarting");
|
||||||
currentRunningUUID = uuid;
|
currentRunningUUID = uuid;
|
||||||
new Handler(webViewSingleton.mainLooper).post(new Runnable() {
|
invokeWebview(new WebViewRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void invoke(WebView webView) {
|
||||||
webViewSingleton.instance.onResume();
|
webView.onResume();
|
||||||
webViewSingleton.instance.removeJavascriptInterface("GBjs");
|
webView.removeJavascriptInterface("GBjs");
|
||||||
webViewSingleton.instance.addJavascriptInterface(jsInterface, "GBjs");
|
webView.addJavascriptInterface(jsInterface, "GBjs");
|
||||||
webViewSingleton.instance.loadUrl("file:///android_asset/app_config/configure.html?rand=" + Math.random() * 500);
|
webView.loadUrl("file:///android_asset/app_config/configure.html?rand=" + Math.random() * 500);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!internetHelperBound) {
|
if (!internetHelperBound) {
|
||||||
@ -174,51 +179,12 @@ public class WebViewSingleton {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void appMessage(GBDeviceEventAppMessage message) {
|
|
||||||
|
|
||||||
final String jsEvent;
|
|
||||||
if (webViewSingleton.instance == null) {
|
|
||||||
LOG.warn("WEBVIEW is not initialized, cannot send appMessages to it");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!message.appUUID.equals(currentRunningUUID)) {
|
|
||||||
LOG.info("WEBVIEW ignoring message for app that is not currently running: " + message.appUUID + " message: " + message.message + " type: " + message.type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: handle ACK and NACK types with ids
|
|
||||||
if (message.type != GBDeviceEventAppMessage.TYPE_APPMESSAGE) {
|
|
||||||
jsEvent = (GBDeviceEventAppMessage.TYPE_NACK == GBDeviceEventAppMessage.TYPE_APPMESSAGE) ? "NACK" + message.id : "ACK" + message.id;
|
|
||||||
LOG.debug("WEBVIEW received ACK/NACK:" + message.message + " for uuid: " + message.appUUID + " ID: " + message.id);
|
|
||||||
} else {
|
|
||||||
jsEvent = "appmessage";
|
|
||||||
}
|
|
||||||
|
|
||||||
final String appMessage = parseIncomingAppMessage(message.message, message.appUUID);
|
|
||||||
LOG.debug("to WEBVIEW: event: " + jsEvent + " message: " + appMessage);
|
|
||||||
new Handler(webViewSingleton.mainLooper).post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
webViewSingleton.instance.evaluateJavascript("Pebble.evaluate('" + jsEvent + "',[" + appMessage + "]);", new ValueCallback<String>() {
|
|
||||||
@Override
|
|
||||||
public void onReceiveValue(String s) {
|
|
||||||
//TODO: the message should be acked here instead of in PebbleIoThread
|
|
||||||
LOG.debug("Callback from appmessage: " + s);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void stopJavascriptInterface() {
|
public static void stopJavascriptInterface() {
|
||||||
new Handler(webViewSingleton.mainLooper).post(new Runnable() {
|
invokeWebview(new WebViewRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void invoke(WebView webView) {
|
||||||
if (webViewSingleton.instance != null) {
|
webView.removeJavascriptInterface("GBjs");
|
||||||
webViewSingleton.instance.removeJavascriptInterface("GBjs");
|
webView.loadUrl("about:blank");
|
||||||
webViewSingleton.instance.loadUrl("about:blank");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -230,86 +196,47 @@ public class WebViewSingleton {
|
|||||||
internetHelperBound = false;
|
internetHelperBound = false;
|
||||||
}
|
}
|
||||||
currentRunningUUID = null;
|
currentRunningUUID = null;
|
||||||
new Handler(webViewSingleton.mainLooper).post(new Runnable() {
|
invokeWebview(new WebViewRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void invoke(WebView webView) {
|
||||||
if (webViewSingleton.instance != null) {
|
webView.removeJavascriptInterface("GBjs");
|
||||||
webViewSingleton.instance.removeJavascriptInterface("GBjs");
|
// webView.setWebChromeClient(null);
|
||||||
// webViewSingleton.instance.setWebChromeClient(null);
|
// webView.setWebViewClient(null);
|
||||||
// webViewSingleton.instance.setWebViewClient(null);
|
webView.clearHistory();
|
||||||
webViewSingleton.instance.clearHistory();
|
webView.clearCache(true);
|
||||||
webViewSingleton.instance.clearCache(true);
|
webView.loadUrl("about:blank");
|
||||||
webViewSingleton.instance.loadUrl("about:blank");
|
// webView.freeMemory();
|
||||||
// webViewSingleton.instance.freeMemory();
|
webView.pauseTimers();
|
||||||
webViewSingleton.instance.pauseTimers();
|
|
||||||
// instance.destroy();
|
// instance.destroy();
|
||||||
// instance = null;
|
// instance = null;
|
||||||
// contextWrapper = null;
|
// contextWrapper = null;
|
||||||
// jsInterface = null;
|
// jsInterface = null;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JSONObject getAppConfigurationKeys(UUID uuid) {
|
public static void invokeWebview(final WebViewRunnable runnable) {
|
||||||
try {
|
if (webViewSingleton.instance == null || webViewSingleton.mainLooper == null) {
|
||||||
File destDir = PebbleUtils.getPbwCacheDir();
|
LOG.warn("Webview already disposed, ignoring runnable");
|
||||||
File configurationFile = new File(destDir, uuid.toString() + ".json");
|
return;
|
||||||
if (configurationFile.exists()) {
|
|
||||||
String jsonString = FileUtils.getStringFromFile(configurationFile);
|
|
||||||
JSONObject json = new JSONObject(jsonString);
|
|
||||||
return json.getJSONObject("appKeys");
|
|
||||||
}
|
|
||||||
} catch (IOException | JSONException e) {
|
|
||||||
LOG.warn("Unable to parse configuration JSON file", e);
|
|
||||||
}
|
}
|
||||||
return null;
|
new Handler(webViewSingleton.mainLooper).post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (webViewSingleton.instance == null) {
|
||||||
|
LOG.warn("Webview already disposed, cannot invoke runnable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runnable.invoke(webViewSingleton.instance);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String parseIncomingAppMessage(String msg, UUID uuid) {
|
public interface WebViewRunnable {
|
||||||
JSONObject jsAppMessage = new JSONObject();
|
/**
|
||||||
|
* Called in the main thread with a non-null webView instance
|
||||||
JSONObject knownKeys = getAppConfigurationKeys(uuid);
|
* @param webView the webview, never null
|
||||||
SparseArray<String> appKeysMap = new SparseArray<>();
|
*/
|
||||||
|
void invoke(WebView webView);
|
||||||
if (knownKeys == null || msg == null) {
|
|
||||||
return "{}";
|
|
||||||
}
|
|
||||||
|
|
||||||
String inKey, outKey;
|
|
||||||
//knownKeys contains "name"->"index", we need to reverse that
|
|
||||||
for (Iterator<String> key = knownKeys.keys(); key.hasNext(); ) {
|
|
||||||
inKey = key.next();
|
|
||||||
appKeysMap.put(knownKeys.optInt(inKey), inKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
JSONArray incoming = new JSONArray(msg);
|
|
||||||
JSONObject outgoing = new JSONObject();
|
|
||||||
for (int i = 0; i < incoming.length(); i++) {
|
|
||||||
JSONObject in = incoming.getJSONObject(i);
|
|
||||||
outKey = null;
|
|
||||||
Object outValue = null;
|
|
||||||
for (Iterator<String> key = in.keys(); key.hasNext(); ) {
|
|
||||||
inKey = key.next();
|
|
||||||
switch (inKey) {
|
|
||||||
case "key":
|
|
||||||
outKey = appKeysMap.get(in.optInt(inKey));
|
|
||||||
break;
|
|
||||||
case "value":
|
|
||||||
outValue = in.get(inKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (outKey != null && outValue != null) {
|
|
||||||
outgoing.put(outKey, outValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jsAppMessage.put("payload", outgoing);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.warn("Unable to parse incoming app message", e);
|
|
||||||
}
|
|
||||||
return jsAppMessage.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user