diff --git a/framework/src/org/apache/cordova/AndroidChromeClient.java b/framework/src/org/apache/cordova/AndroidChromeClient.java index 7296ceb3..2852a203 100755 --- a/framework/src/org/apache/cordova/AndroidChromeClient.java +++ b/framework/src/org/apache/cordova/AndroidChromeClient.java @@ -18,31 +18,24 @@ */ package org.apache.cordova; -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.LOG; - import android.annotation.TargetApi; import android.app.Activity; -import android.app.AlertDialog; import android.content.ActivityNotFoundException; -import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.util.Log; import android.view.Gravity; -import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.webkit.ConsoleMessage; +import android.webkit.GeolocationPermissions.Callback; import android.webkit.JsPromptResult; import android.webkit.JsResult; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebStorage; import android.webkit.WebView; -import android.webkit.GeolocationPermissions.Callback; -import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.RelativeLayout; @@ -52,11 +45,6 @@ import android.widget.RelativeLayout; * The kind of callbacks that happen here are on the chrome outside the document, * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related * to but different than CordovaWebViewClient. - * - * @see WebChromeClient - * @see WebView guide - * @see CordovaWebViewClient - * @see CordovaWebView */ public class AndroidChromeClient extends WebChromeClient { @@ -69,104 +57,46 @@ public class AndroidChromeClient extends WebChromeClient { // the video progress view private View mVideoProgressView; - //Keep track of last AlertDialog showed - private AlertDialog lastHandledDialog; + private CordovaDialogsHelper dialogsHelper; - public AndroidChromeClient(CordovaInterface ctx, AndroidWebView app) { + public AndroidChromeClient(CordovaInterface ctx, AndroidWebView webView) { this.cordova = ctx; - this.appView = app; + this.appView = webView; + dialogsHelper = new CordovaDialogsHelper(webView.getContext()); } /** * Tell the client to display a javascript alert dialog. - * - * @param view - * @param url - * @param message - * @param result - * @see Other implementation in the Dialogs plugin. */ @Override public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { - AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity()); - dlg.setMessage(message); - dlg.setTitle("Alert"); - //Don't let alerts break the back button - dlg.setCancelable(true); - dlg.setPositiveButton(android.R.string.ok, - new AlertDialog.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - result.confirm(); - } - }); - dlg.setOnCancelListener( - new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - result.cancel(); - } - }); - dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { - //DO NOTHING - public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) - { + dialogsHelper.showAlert(message, new CordovaDialogsHelper.Result() { + @Override public void gotResult(boolean success, String value) { + if (success) { result.confirm(); - return false; + } else { + result.cancel(); } - else - return true; } }); - lastHandledDialog = dlg.show(); return true; } /** * Tell the client to display a confirm dialog to the user. - * - * @param view - * @param url - * @param message - * @param result - * @see Other implementation in the Dialogs plugin. */ @Override public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) { - AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity()); - dlg.setMessage(message); - dlg.setTitle("Confirm"); - dlg.setCancelable(true); - dlg.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - result.confirm(); - } - }); - dlg.setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - result.cancel(); - } - }); - dlg.setOnCancelListener( - new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - result.cancel(); - } - }); - dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { - //DO NOTHING - public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) - { + dialogsHelper.showConfirm(message, new CordovaDialogsHelper.Result() { + @Override + public void gotResult(boolean success, String value) { + if (success) { + result.confirm(); + } else { result.cancel(); - return false; } - else - return true; } }); - lastHandledDialog = dlg.show(); return true; } @@ -177,40 +107,24 @@ public class AndroidChromeClient extends WebChromeClient { * * Since we are hacking prompts for our own purposes, we should not be using them for * this purpose, perhaps we should hack console.log to do this instead! - * - * @see Other implementation in the Dialogs plugin. */ @Override - public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, JsPromptResult result) { + public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result) { // Unlike the @JavascriptInterface bridge, this method is always called on the UI thread. String handledRet = appView.bridge.promptOnJsPrompt(origin, message, defaultValue); if (handledRet != null) { result.confirm(handledRet); } else { - // Returning false would also show a dialog, but the default one shows the origin (ugly). - final JsPromptResult res = result; - AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity()); - dlg.setMessage(message); - final EditText input = new EditText(this.cordova.getActivity()); - if (defaultValue != null) { - input.setText(defaultValue); - } - dlg.setView(input); - dlg.setCancelable(false); - dlg.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - String usertext = input.getText().toString(); - res.confirm(usertext); - } - }); - dlg.setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - res.cancel(); - } - }); - lastHandledDialog = dlg.show(); + dialogsHelper.showPrompt(message, defaultValue, new CordovaDialogsHelper.Result() { + @Override + public void gotResult(boolean success, String value) { + if (success) { + result.confirm(value); + } else { + result.cancel(); + } + } + }); } return true; } @@ -348,9 +262,7 @@ public class AndroidChromeClient extends WebChromeClient { } public void destroyLastDialog(){ - if(lastHandledDialog != null){ - lastHandledDialog.cancel(); - } + dialogsHelper.destroyLastDialog(); } } diff --git a/framework/src/org/apache/cordova/CordovaDialogsHelper.java b/framework/src/org/apache/cordova/CordovaDialogsHelper.java new file mode 100644 index 00000000..a219c992 --- /dev/null +++ b/framework/src/org/apache/cordova/CordovaDialogsHelper.java @@ -0,0 +1,152 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +package org.apache.cordova; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.view.KeyEvent; +import android.widget.EditText; + +/** + * Helper class for WebViews to implement prompt(), alert(), confirm() dialogs. + */ +public class CordovaDialogsHelper { + private final Context context; + private AlertDialog lastHandledDialog; + + public CordovaDialogsHelper(Context context) { + this.context = context; + } + + public void showAlert(String message, final Result result) { + AlertDialog.Builder dlg = new AlertDialog.Builder(context); + dlg.setMessage(message); + dlg.setTitle("Alert"); + //Don't let alerts break the back button + dlg.setCancelable(true); + dlg.setPositiveButton(android.R.string.ok, + new AlertDialog.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + result.gotResult(true, null); + } + }); + dlg.setOnCancelListener( + new DialogInterface.OnCancelListener() { + public void onCancel(DialogInterface dialog) { + result.gotResult(false, null); + } + }); + dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { + //DO NOTHING + public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) + { + result.gotResult(true, null); + return false; + } + else + return true; + } + }); + lastHandledDialog = dlg.show(); + } + + public void showConfirm(String message, final Result result) { + AlertDialog.Builder dlg = new AlertDialog.Builder(context); + dlg.setMessage(message); + dlg.setTitle("Confirm"); + dlg.setCancelable(true); + dlg.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + result.gotResult(true, null); + } + }); + dlg.setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + result.gotResult(false, null); + } + }); + dlg.setOnCancelListener( + new DialogInterface.OnCancelListener() { + public void onCancel(DialogInterface dialog) { + result.gotResult(false, null); + } + }); + dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { + //DO NOTHING + public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) + { + result.gotResult(false, null); + return false; + } + else + return true; + } + }); + lastHandledDialog = dlg.show(); + } + + /** + * Tell the client to display a prompt dialog to the user. + * If the client returns true, WebView will assume that the client will + * handle the prompt dialog and call the appropriate JsPromptResult method. + * + * Since we are hacking prompts for our own purposes, we should not be using them for + * this purpose, perhaps we should hack console.log to do this instead! + */ + public void showPrompt(String message, String defaultValue, final Result result) { + // Returning false would also show a dialog, but the default one shows the origin (ugly). + AlertDialog.Builder dlg = new AlertDialog.Builder(context); + dlg.setMessage(message); + final EditText input = new EditText(context); + if (defaultValue != null) { + input.setText(defaultValue); + } + dlg.setView(input); + dlg.setCancelable(false); + dlg.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + String userText = input.getText().toString(); + result.gotResult(true, userText); + } + }); + dlg.setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + result.gotResult(false, null); + } + }); + lastHandledDialog = dlg.show(); + } + + public void destroyLastDialog(){ + if (lastHandledDialog != null){ + lastHandledDialog.cancel(); + } + } + + public interface Result { + public void gotResult(boolean success, String value); + } +} \ No newline at end of file