From 9ab8dea4f90792397b72d9775e8b352815f61f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zsolt=20Boldizsa=CC=81r?= Date: Sun, 20 May 2018 00:35:05 +0300 Subject: [PATCH 1/2] Avoid holding strong reference to activity and only show dialog if host activity is not finished yet. --- src/android/RemoteInjectionPlugin.java | 69 ++++++++++---------------- 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/src/android/RemoteInjectionPlugin.java b/src/android/RemoteInjectionPlugin.java index 68537d0..cf50e20 100644 --- a/src/android/RemoteInjectionPlugin.java +++ b/src/android/RemoteInjectionPlugin.java @@ -2,7 +2,6 @@ import android.app.Activity; import android.app.AlertDialog; -import android.content.DialogInterface; import android.content.res.AssetManager; import android.util.Base64; @@ -17,6 +16,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.lang.ref.WeakReference; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; @@ -31,16 +31,16 @@ public class RemoteInjectionPlugin extends CordovaPlugin { // List of files to inject before injecting Cordova. private final ArrayList preInjectionFileNames = new ArrayList(); - private int promptInterval; // Delay before prompting user to retry in seconds private RequestLifecycle lifecycle; protected void pluginInitialize() { String pref = webView.getPreferences().getString("CRIInjectFirstFiles", ""); - for (String path: pref.split(",")) { + for (String path : pref.split(",")) { preInjectionFileNames.add(path.trim()); } - promptInterval = webView.getPreferences().getInteger("CRIPageLoadPromptInterval", 10); + // Delay before prompting user to retry in seconds + int promptInterval = webView.getPreferences().getInteger("CRIPageLoadPromptInterval", 1); final Activity activity = super.cordova.getActivity(); final CordovaWebViewEngine engine = super.webView.getEngine(); @@ -114,7 +114,7 @@ private boolean isRemote(String url) { private void injectCordova() { List jsPaths = new ArrayList(); - for (String path: preInjectionFileNames) { + for (String path : preInjectionFileNames) { jsPaths.add(path); } @@ -134,7 +134,7 @@ private void injectCordova() { // (https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs). The script tag // is appended to the DOM and executed via a javascript URL (e.g. javascript:doJsStuff()). StringBuilder jsToInject = new StringBuilder(); - for (String path: jsPaths) { + for (String path : jsPaths) { jsToInject.append(readFile(cordova.getActivity().getResources().getAssets(), path)); } String jsUrl = "javascript:var script = document.createElement('script');"; @@ -178,14 +178,14 @@ private String readFile(AssetManager assets, String filePath) { * Searches the provided path for javascript files recursively. * * @param assets - * @param path start path + * @param path start path * @return found JS files */ - private List jsPathsToInject(AssetManager assets, String path){ + private List jsPathsToInject(AssetManager assets, String path) { List jsPaths = new ArrayList(); try { - for (String filePath: assets.list(path)) { + for (String filePath : assets.list(path)) { String fullPath = path + File.separator + filePath; if (fullPath.endsWith(".js")) { @@ -205,13 +205,13 @@ private List jsPathsToInject(AssetManager assets, String path){ } private static class RequestLifecycle { - private final Activity activity; + private final WeakReference activityRef; private final CordovaWebViewEngine engine; private UserPromptTask task; private final int promptInterval; RequestLifecycle(Activity activity, CordovaWebViewEngine engine, int promptInterval) { - this.activity = activity; + this.activityRef = new WeakReference<>(activity); this.engine = engine; this.promptInterval = promptInterval; } @@ -240,8 +240,8 @@ private synchronized void startTask(final String url) { task.cancel(); } - if (promptInterval > 0 ) { - task = new UserPromptTask(this, activity, engine, url); + if (promptInterval > 0 && activityRef.get() != null && !activityRef.get().isFinishing()) { + task = new UserPromptTask(this, activityRef.get(), engine, url); new Timer().schedule(task, promptInterval * 1000); } } @@ -252,7 +252,7 @@ private synchronized void startTask(final String url) { */ static class UserPromptTask extends TimerTask { private final RequestLifecycle lifecycle; - private final Activity activity; + private final WeakReference activityRef; private final CordovaWebViewEngine engine; final String url; @@ -260,7 +260,7 @@ static class UserPromptTask extends TimerTask { UserPromptTask(RequestLifecycle lifecycle, Activity activity, CordovaWebViewEngine engine, String url) { this.lifecycle = lifecycle; - this.activity = activity; + this.activityRef = new WeakReference<>(activity); this.engine = engine; this.url = url; } @@ -282,35 +282,18 @@ private void cleanup() { @Override public void run() { - if (lifecycle.isLoading()) { + if (lifecycle.isLoading() && activityRef.get() != null && !activityRef.get().isFinishing()) { // Prompts the user giving them the choice to wait on the current request or retry. - lifecycle.activity.runOnUiThread(new Runnable() { - @Override - public void run() { - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setMessage("The server is taking longer than expected to respond.") - .setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - UserPromptTask.this.cleanup(); - } - }) - .setPositiveButton("Retry", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - // Obviously only works for GETs but good enough. - engine.loadUrl(engine.getUrl(), false); - } - }) - .setNegativeButton("Wait", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - lifecycle.startTask(url); - } - }); - AlertDialog dialog = UserPromptTask.this.alertDialog = builder.create(); - dialog.show(); - } + activityRef.get().runOnUiThread(() -> { + AlertDialog.Builder builder = new AlertDialog.Builder(activityRef.get()); + builder.setMessage("The server is taking longer than expected to respond.") + .setPositiveButton("Retry", (dialog, id) -> { + // Obviously only works for GETs but good enough. + engine.loadUrl(engine.getUrl(), false); + }) + .setNegativeButton("Wait", (dialog, id) -> lifecycle.startTask(url)); + alertDialog = builder.create(); + alertDialog.show(); }); } else { lifecycle.stopTask(); From 0d19eb276ecda43e2adffdc002fa3c0cc353b5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zsolt=20Boldizsa=CC=81r?= Date: Thu, 2 Aug 2018 13:13:34 +0300 Subject: [PATCH 2/2] Set promptInterval back to its default value. --- src/android/RemoteInjectionPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/android/RemoteInjectionPlugin.java b/src/android/RemoteInjectionPlugin.java index cf50e20..c8f9d06 100644 --- a/src/android/RemoteInjectionPlugin.java +++ b/src/android/RemoteInjectionPlugin.java @@ -40,7 +40,7 @@ protected void pluginInitialize() { preInjectionFileNames.add(path.trim()); } // Delay before prompting user to retry in seconds - int promptInterval = webView.getPreferences().getInteger("CRIPageLoadPromptInterval", 1); + int promptInterval = webView.getPreferences().getInteger("CRIPageLoadPromptInterval", 10); final Activity activity = super.cordova.getActivity(); final CordovaWebViewEngine engine = super.webView.getEngine();