diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java index 69fdab7d0..b103d1f95 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java @@ -7,6 +7,7 @@ import android.os.Build; import android.os.Bundle; import android.support.v4.app.NavUtils; import android.view.MenuItem; +import android.view.View; import android.webkit.JavascriptInterface; import android.webkit.ValueCallback; import android.webkit.WebView; @@ -45,11 +46,64 @@ public class ExternalPebbleJSActivity extends GBActivity { throw new IllegalArgumentException("Must provide a device when invoking this activity"); } - setContentView(R.layout.activity_external_pebble_js); + myWebView = WebViewSingleton.getorInitWebView(this, mGBDevice, appUuid); + myWebView.setWillNotDraw(false); + myWebView.addJavascriptInterface(new ActivityJSInterface(ExternalPebbleJSActivity.this), "GBActivity"); + FrameLayout fl = (FrameLayout) findViewById(R.id.webview_placeholder); + fl.addView(myWebView); - WebViewSingleton.getorInitWebView(this, mGBDevice, appUuid); + + myWebView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // chromium, enable hardware acceleration + v.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } else { + // older android version, disable hardware acceleration + v.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + + + String queryString = ""; + if (confUri != null) { + //getting back with configuration data + try { + appUuid = UUID.fromString(confUri.getHost()); + queryString = confUri.getEncodedQuery(); + } catch (IllegalArgumentException e) { + GB.toast("returned uri: " + confUri.toString(), Toast.LENGTH_LONG, GB.ERROR); + } + ((WebView) v).loadUrl("file:///android_asset/app_config/configure.html?" + queryString); + } else { + //show configuration + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + myWebView.evaluateJavascript("Pebble.evaluate('showConfiguration');", new ValueCallback() { + @Override + public void onReceiveValue(String s) { + LOG.debug("Callback from showConfiguration", s); + } + }); + } else { + ((WebView) v).loadUrl("javascript:Pebble.evaluate('showConfiguration');"); + } + } + + + } + + @Override + public void onViewDetachedFromWindow(View v) { + myWebView.removeJavascriptInterface("GBActivity"); + myWebView.setWillNotDraw(true); + FrameLayout fl = (FrameLayout) findViewById(R.id.webview_placeholder); + fl.removeAllViews(); + } + }); } @@ -60,57 +114,6 @@ public class ExternalPebbleJSActivity extends GBActivity { confUri = incoming.getData(); } - @Override - protected void onResume() { - super.onResume(); - String queryString = ""; - - myWebView = WebViewSingleton.getorInitWebView(this, mGBDevice, appUuid); - myWebView.addJavascriptInterface(new ActivityJSInterface(this), "GBActivity"); - - - FrameLayout fl = (FrameLayout) findViewById(R.id.webview_placeholder); - if (myWebView != null) - fl.addView(myWebView); - - //needed to display clay dialogs - myWebView.getSettings().setUseWideViewPort(true); - myWebView.requestFocus(); - - - if (confUri != null) { - //getting back with configuration data - try { - appUuid = UUID.fromString(confUri.getHost()); - queryString = confUri.getEncodedQuery(); - } catch (IllegalArgumentException e) { - GB.toast("returned uri: " + confUri.toString(), Toast.LENGTH_LONG, GB.ERROR); - } - myWebView.loadUrl("file:///android_asset/app_config/configure.html?" + queryString); - } else { - //show configuration - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - myWebView.evaluateJavascript("Pebble.evaluate('showConfiguration');", new ValueCallback() { - @Override - public void onReceiveValue(String s) { - LOG.debug("Callback from showConfiguration", s); - } - }); - } else { - myWebView.loadUrl("javascript:Pebble.evaluate('showConfiguration');"); - } - } - - } - - @Override - protected void onPause() { - - FrameLayout fl = (FrameLayout) findViewById(R.id.webview_placeholder); - fl.removeAllViews(); - super.onPause(); - } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/appmanager/AbstractAppManagerFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/appmanager/AbstractAppManagerFragment.java index 3e68b2dfa..07b3679f6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/appmanager/AbstractAppManagerFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/appmanager/AbstractAppManagerFragment.java @@ -39,6 +39,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.service.devices.pebble.PebbleProtocol; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils; +import nodomain.freeyourgadget.gadgetbridge.util.WebViewSingleton; public abstract class AbstractAppManagerFragment extends Fragment { @@ -323,6 +324,8 @@ public abstract class AbstractAppManagerFragment extends Fragment { view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); popupMenu.show(); + //TODO: replace with local broadcast on app start + WebViewSingleton.getorInitWebView(getActivity(), mGBDevice, selectedApp.getUUID()); return true; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java index 3b56e17fa..bc3fd2026 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java @@ -570,6 +570,7 @@ class PebbleIoThread extends GBDeviceIoThread { case START: LOG.info("got GBDeviceEventAppManagement START event for uuid: " + appMgmt.uuid); WebViewSingleton.getorInitWebView(getContext(), gbDevice, appMgmt.uuid); + //TODO: the method call above will not work the first time as we need an activity. Either we find a way to have one here, or replace it with a local broadcast break; default: break; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/WebViewSingleton.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/WebViewSingleton.java index 9c6b0ccad..d988633ca 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/WebViewSingleton.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/WebViewSingleton.java @@ -1,12 +1,10 @@ package nodomain.freeyourgadget.gadgetbridge.util; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.MutableContextWrapper; import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; import android.webkit.ConsoleMessage; import android.webkit.JavascriptInterface; import android.webkit.WebChromeClient; @@ -35,7 +33,7 @@ import java.util.UUID; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; -public class WebViewSingleton { +public class WebViewSingleton extends Activity { private static final Logger LOG = LoggerFactory.getLogger(WebViewSingleton.class); @@ -46,56 +44,52 @@ public class WebViewSingleton { private WebViewSingleton() { } - public static WebView getorInitWebView(final Context context, final GBDevice device, final UUID uuid) { - final MutableContextWrapper _contextWrapper = new MutableContextWrapper(context); - if (contextWrapper != null) { - contextWrapper.setBaseContext(context); - } else { - contextWrapper = _contextWrapper; - } - - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - if (instance == null) { - instance = new WebView(_contextWrapper); - instance.clearCache(true); - instance.setWebViewClient(new GBWebClient()); - instance.setWebChromeClient(new GBChromeClient()); - instance.setWebContentsDebuggingEnabled(true); - WebSettings webSettings = instance.getSettings(); - webSettings.setJavaScriptEnabled(true); - //needed to access the DOM - webSettings.setDomStorageEnabled(true); - //needed for localstorage - webSettings.setDatabaseEnabled(true); - } - - if (jsInterface == null || (jsInterface != null && (!device.equals(jsInterface.device) || !uuid.equals(jsInterface.mUuid)))) { - instance.removeJavascriptInterface("GBjs"); - jsInterface = new JSInterface(device, uuid); - instance.addJavascriptInterface(jsInterface, "GBjs"); - instance.loadUrl("file:///android_asset/app_config/configure.html"); - } else { - LOG.debug("Not reloading the webview " + jsInterface.mUuid.toString()); - } + public static WebView getorInitWebView(Context context, GBDevice device, UUID uuid) { + if (context instanceof Activity) { + final MutableContextWrapper _contextWrapper = new MutableContextWrapper(context); + if (contextWrapper != null) { + contextWrapper.setBaseContext(context); + } else { + contextWrapper = _contextWrapper; + } + } + //here we are sure that contextWrapper is either null or an activity, hence we run on the main thread + if (contextWrapper != null) { + if (instance == null) { + instance = new WebView(contextWrapper); + instance.setWillNotDraw(true); + instance.clearCache(true); + instance.setWebViewClient(new GBWebClient()); + instance.setWebChromeClient(new GBChromeClient()); + instance.setWebContentsDebuggingEnabled(true); + WebSettings webSettings = instance.getSettings(); + webSettings.setJavaScriptEnabled(true); + //needed to access the DOM + webSettings.setDomStorageEnabled(true); + //needed for localstorage + webSettings.setDatabaseEnabled(true); } - }); + if (jsInterface == null || (jsInterface != null && (!device.equals(jsInterface.device) || !uuid.equals(jsInterface.mUuid)))) { + instance.removeJavascriptInterface("GBjs"); + jsInterface = new JSInterface(device, uuid); + instance.addJavascriptInterface(jsInterface, "GBjs"); + instance.loadUrl("file:///android_asset/app_config/configure.html"); + } else { + LOG.debug("Not reloading the webview " + jsInterface.mUuid.toString()); + } + } else { + LOG.debug("WEBV: not using the passed context, as it is not an activity"); + } return instance; } public static void disposeWebView() { - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - if (instance != null) { - instance.destroy(); - instance = null; - } - } - }); + if (instance != null) { + instance.destroy(); + instance = null; + } } private static class GBChromeClient extends WebChromeClient { @@ -155,7 +149,7 @@ public class WebViewSingleton { @JavascriptInterface public void gbLog(String msg) { - Log.d("WEBVIEW", msg); + LOG.debug("WEBVIEW", msg); } @JavascriptInterface @@ -196,7 +190,7 @@ public class WebViewSingleton { } } - LOG.info(out.toString()); + LOG.info("WEBV:" + out.toString()); GBApplication.deviceService().onAppConfiguration(this.mUuid, out.toString()); } catch (JSONException e) {