title: Android childbrowser plugin with cordova 2.3.0 giving error message
body: <p>I have successfully integrated android childbrowser plugin in cordova 1.9.0. Now i want to use same childbowser plugin in cordova 2.3.0. I have downloaded recent(Updated) child browser plugin and made some modification according to cordova 2.3.0 requirement, but still  getting one error at line no 411 i.e "The method success(PluginResult, String) is undefined for the type ChildBrowser". </p>
  
  <p>This is where i am getting error message i.e  </p>
  
  <blockquote>
    <p>this.success(result, this.browserCallbackId);</p>
  </blockquote>
  
  <p>Below is the error causing method.</p>
  
  <pre><code> private void sendUpdate(JSONObject obj, boolean keepCallback) {
          if (this.browserCallbackId != null) {
              PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
              result.setKeepCallback(keepCallback);
              **this.success(result, this.browserCallbackId);**
          }
      }
  </code></pre>
  
  <p>Any one suggest what should i do to remove error message and code to work properly.</p>
  
  <p>Below is the modified whole code</p>
  
  <pre><code>/*
  * PhoneGap is available under *either* the terms of the modified BSD license *or* the
  * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
  *
  * Copyright (c) 2005-2011, Nitobi Software Inc.
  * Copyright (c) 2010-2011, IBM Corporation
  */
  package com.nxtwhat.SuvilasCDV23;
  
  import java.io.IOException;
  import java.io.InputStream;
  
  import org.apache.cordova.api.CordovaPlugin;
  import org.apache.cordova.api.PluginResult;
  import org.json.JSONArray;
  import org.json.JSONException;
  import org.json.JSONObject;
  
  import android.app.Dialog;
  import android.content.Context;
  import android.content.DialogInterface;
  import android.content.Intent;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.net.Uri;
  import android.text.InputType;
  import android.util.Log;
  import android.util.TypedValue;
  import android.view.Gravity;
  import android.view.KeyEvent;
  import android.view.View;
  import android.view.Window;
  import android.view.WindowManager;
  import android.view.WindowManager.LayoutParams;
  import android.view.inputmethod.EditorInfo;
  import android.view.inputmethod.InputMethodManager;
  import android.webkit.WebChromeClient;
  import android.webkit.WebSettings;
  import android.webkit.WebView;
  import android.webkit.WebViewClient;
  import android.widget.EditText;
  import android.widget.ImageButton;
  import android.widget.LinearLayout;
  import android.widget.RelativeLayout;
  
  public class ChildBrowser extends CordovaPlugin  {
  
      protected static final String LOG_TAG = "ChildBrowser";
      private static int CLOSE_EVENT = 0;
      private static int LOCATION_CHANGED_EVENT = 1;
  
      private String browserCallbackId = null;
  
      private Dialog dialog;
      private WebView webview;
      private EditText edittext;
      private boolean showLocationBar = true;
  
      /**
  * Executes the request and returns PluginResult.
  *
  * @param action The action to execute.
  * @param args JSONArry of arguments for the plugin.
  * @param callbackId The callback id used when calling back into JavaScript.
  * @return A PluginResult object with a status and message.
  */
      public PluginResult execute(String action, JSONArray args, String callbackId) {
          PluginResult.Status status = PluginResult.Status.OK;
          String result = "";
  
          try {
              if (action.equals("showWebPage")) {
                  this.browserCallbackId = callbackId;
  
                  // If the ChildBrowser is already open then throw an error
                  if (dialog != null &amp;&amp; dialog.isShowing()) {
                      return new PluginResult(PluginResult.Status.ERROR, "ChildBrowser is already open");
                  }
  
                  result = this.showWebPage(args.getString(0), args.optJSONObject(1));
  
                  if (result.length() &gt; 0) {
                      status = PluginResult.Status.ERROR;
                      return new PluginResult(status, result);
                  } else {
                      PluginResult pluginResult = new PluginResult(status, result);
                      pluginResult.setKeepCallback(true);
                      return pluginResult;
                  }
              }
              else if (action.equals("close")) {
                  closeDialog();
  
                  JSONObject obj = new JSONObject();
                  obj.put("type", CLOSE_EVENT);
  
                  PluginResult pluginResult = new PluginResult(status, obj);
                  pluginResult.setKeepCallback(false);
                  return pluginResult;
              }
              else if (action.equals("openExternal")) {
                  result = this.openExternal(args.getString(0), args.optBoolean(1));
                  if (result.length() &gt; 0) {
                      status = PluginResult.Status.ERROR;
                  }
              }
              else {
                  status = PluginResult.Status.INVALID_ACTION;
              }
              return new PluginResult(status, result);
          } catch (JSONException e) {
              return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
          }
      }
  
      /**
  * Display a new browser with the specified URL.
  *
  * @param url The url to load.
  * @param usePhoneGap Load url in PhoneGap webview
  * @return "" if ok, or error message.
  */
      public String openExternal(String url, boolean usePhoneGap) {
          try {
              Intent intent = null;
              if (usePhoneGap) {
                  intent = new Intent().setClass(this.cordova.getActivity(), org.apache.cordova.DroidGap.class);
                  intent.setData(Uri.parse(url)); // This line will be removed in future.
                  intent.putExtra("url", url);
  
                  // Timeout parameter: 60 sec max - May be less if http device timeout is less.
                  intent.putExtra("loadUrlTimeoutValue", 60000);
  
                  // These parameters can be configured if you want to show the loading dialog
                  intent.putExtra("loadingDialog", "Wait,Loading web page..."); // show loading dialog
                  intent.putExtra("hideLoadingDialogOnPageLoad", true); // hide it once page has completely loaded
              }
              else {
                  intent = new Intent(Intent.ACTION_VIEW);
                  intent.setData(Uri.parse(url));
              }
              this.cordova.getActivity().startActivity(intent);
              return "";
          } catch (android.content.ActivityNotFoundException e) {
              Log.d(LOG_TAG, "ChildBrowser: Error loading url "+url+":"+ e.toString());
              return e.toString();
          }
      }
  
      /**
  * Closes the dialog
  */
      private void closeDialog() {
          if (dialog != null) {
              dialog.dismiss();
          }
      }
  
      /**
  * Checks to see if it is possible to go back one page in history, then does so.
  */
      private void goBack() {
          if (this.webview.canGoBack()) {
              this.webview.goBack();
          }
      }
  
      /**
  * Checks to see if it is possible to go forward one page in history, then does so.
  */
      private void goForward() {
          if (this.webview.canGoForward()) {
              this.webview.goForward();
          }
      }
  
      /**
  * Navigate to the new page
  *
  * @param url to load
  */
      private void navigate(String url) {
          InputMethodManager imm = (InputMethodManager)this.cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
          imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
  
          if (!url.startsWith("http") &amp;&amp; !url.startsWith("file:")) {
              this.webview.loadUrl("http://" + url);
          } else {
              this.webview.loadUrl(url);
          }
          this.webview.requestFocus();
      }
  
  
      /**
  * Should we show the location bar?
  *
  * @return boolean
  */
      private boolean getShowLocationBar() {
          return this.showLocationBar;
      }
  
      /**
  * Display a new browser with the specified URL.
  *
  * @param url The url to load.
  * @param jsonObject
  */
      public String showWebPage(final String url, JSONObject options) {
          // Determine if we should hide the location bar.
          if (options != null) {
              showLocationBar = options.optBoolean("showLocationBar", true);
          }
  
          // Create dialog in new thread
          Runnable runnable = new Runnable() {
              /**
  * Convert our DIP units to Pixels
  *
  * @return int
  */
              private int dpToPixels(int dipValue) {
                  int value = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP,
                                                              (float) dipValue,
                                                              cordova.getActivity().getResources().getDisplayMetrics()
                  );
  
                  return value;
              }
  
              public void run() {
                  // Let's create the main dialog
                  dialog = new Dialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
                  dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
                  dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                  dialog.setCancelable(true);
                  dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                          public void onDismiss(DialogInterface dialog) {
                              try {
                                  JSONObject obj = new JSONObject();
                                  obj.put("type", CLOSE_EVENT);
  
                                  sendUpdate(obj, false);
                              } catch (JSONException e) {
                                  Log.d(LOG_TAG, "Should never happen");
                              }
                          }
                  });
  
                  // Main container layout
                  LinearLayout main = new LinearLayout(cordova.getActivity());
                  main.setOrientation(LinearLayout.VERTICAL);
  
                  // Toolbar layout
                  RelativeLayout toolbar = new RelativeLayout(cordova.getActivity());
                  toolbar.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, this.dpToPixels(44)));
                  toolbar.setPadding(this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2));
                  toolbar.setHorizontalGravity(Gravity.LEFT);
                  toolbar.setVerticalGravity(Gravity.TOP);
  
                  // Action Button Container layout
                  RelativeLayout actionButtonContainer = new RelativeLayout(cordova.getActivity());
                  actionButtonContainer.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                  actionButtonContainer.setHorizontalGravity(Gravity.LEFT);
                  actionButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL);
                  actionButtonContainer.setId(1);
  
                  // Back button
                  ImageButton back = new ImageButton(cordova.getActivity());
                  RelativeLayout.LayoutParams backLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
                  backLayoutParams.addRule(RelativeLayout.ALIGN_LEFT);
                  back.setLayoutParams(backLayoutParams);
                  back.setContentDescription("Back Button");
                  back.setId(2);
                  try {
                      back.setImageBitmap(loadDrawable("www/childbrowser/icon_arrow_left.png"));
                  } catch (IOException e) {
                      Log.e(LOG_TAG, e.getMessage(), e);
                  }
                  back.setOnClickListener(new View.OnClickListener() {
                      public void onClick(View v) {
                          goBack();
                      }
                  });
  
                  // Forward button
                  ImageButton forward = new ImageButton(cordova.getActivity());
                  RelativeLayout.LayoutParams forwardLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
                  forwardLayoutParams.addRule(RelativeLayout.RIGHT_OF, 2);
                  forward.setLayoutParams(forwardLayoutParams);
                  forward.setContentDescription("Forward Button");
                  forward.setId(3);
                  try {
                      forward.setImageBitmap(loadDrawable("www/childbrowser/icon_arrow_right.png"));
                  } catch (IOException e) {
                      Log.e(LOG_TAG, e.getMessage(), e);
                  }
                  forward.setOnClickListener(new View.OnClickListener() {
                      public void onClick(View v) {
                          goForward();
                      }
                  });
  
                  // Edit Text Box
                  edittext = new EditText(cordova.getActivity());
                  RelativeLayout.LayoutParams textLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
                  textLayoutParams.addRule(RelativeLayout.RIGHT_OF, 1);
                  textLayoutParams.addRule(RelativeLayout.LEFT_OF, 5);
                  edittext.setLayoutParams(textLayoutParams);
                  edittext.setId(4);
                  edittext.setSingleLine(true);
                  edittext.setText(url);
                  edittext.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
                  edittext.setImeOptions(EditorInfo.IME_ACTION_GO);
                  edittext.setInputType(InputType.TYPE_NULL); // Will not except input... Makes the text NON-EDITABLE
                  edittext.setOnKeyListener(new View.OnKeyListener() {
                      public boolean onKey(View v, int keyCode, KeyEvent event) {
                          // If the event is a key-down event on the "enter" button
                          if ((event.getAction() == KeyEvent.ACTION_DOWN) &amp;&amp; (keyCode == KeyEvent.KEYCODE_ENTER)) {
                            navigate(edittext.getText().toString());
                            return true;
                          }
                          return false;
                      }
                  });
  
                  // Close button
                  ImageButton close = new ImageButton(cordova.getActivity());
                  RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
                  closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                  close.setLayoutParams(closeLayoutParams);
                  forward.setContentDescription("Close Button");
                  close.setId(5);
                  try {
                      close.setImageBitmap(loadDrawable("www/childbrowser/icon_close.png"));
                  } catch (IOException e) {
                      Log.e(LOG_TAG, e.getMessage(), e);
                  }
                  close.setOnClickListener(new View.OnClickListener() {
                      public void onClick(View v) {
                          closeDialog();
                      }
                  });
  
                  // WebView
                  webview = new WebView(cordova.getActivity());
                  webview.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
                  webview.setWebChromeClient(new WebChromeClient());
                  WebViewClient client = new ChildBrowserClient(edittext);
                  webview.setWebViewClient(client);
                  WebSettings settings = webview.getSettings();
                  settings.setJavaScriptEnabled(true);
                  settings.setJavaScriptCanOpenWindowsAutomatically(true);
                  settings.setBuiltInZoomControls(true);
                  settings.setPluginsEnabled(true);
                  settings.setDomStorageEnabled(true);
                  webview.loadUrl(url);
                  webview.setId(6);
                  webview.getSettings().setLoadWithOverviewMode(true);
                  webview.getSettings().setUseWideViewPort(true);
                  webview.requestFocus();
                  webview.requestFocusFromTouch();
  
                  // Add the back and forward buttons to our action button container layout
                  actionButtonContainer.addView(back);
                  actionButtonContainer.addView(forward);
  
                  // Add the views to our toolbar
                  toolbar.addView(actionButtonContainer);
                  toolbar.addView(edittext);
                  toolbar.addView(close);
  
                  // Don't add the toolbar if its been disabled
                  if (getShowLocationBar()) {
                      // Add our toolbar to our main view/layout
                      main.addView(toolbar);
                  }
  
                  // Add our webview to our main view/layout
                  main.addView(webview);
  
                  WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
                  lp.copyFrom(dialog.getWindow().getAttributes());
                  lp.width = WindowManager.LayoutParams.FILL_PARENT;
                  lp.height = WindowManager.LayoutParams.FILL_PARENT;
  
                  dialog.setContentView(main);
                  dialog.show();
                  dialog.getWindow().setAttributes(lp);
              }
  
            private Bitmap loadDrawable(String filename) throws java.io.IOException {
                InputStream input = cordova.getActivity().getAssets().open(filename);
                return BitmapFactory.decodeStream(input);
            }
          };
          this.cordova.getActivity().runOnUiThread(runnable);
          return "";
      }
  
      /**
  * Create a new plugin result and send it back to JavaScript
  *
  * @param obj a JSONObject contain event payload information
  */
      private void sendUpdate(JSONObject obj, boolean keepCallback) {
          if (this.browserCallbackId != null) {
              PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
              result.setKeepCallback(keepCallback);
              **this.success(result, this.browserCallbackId);**
          }
      }
  
      /**
  * The webview client receives notifications about appView
  */
      public class ChildBrowserClient extends WebViewClient {
          EditText edittext;
  
          /**
  * Constructor.
  *
  * @param mContext
  * @param edittext
  */
          public ChildBrowserClient(EditText mEditText) {
              this.edittext = mEditText;
          }
  
          /**
  * Notify the host application that a page has started loading.
  *
  * @param view The webview initiating the callback.
  * @param url The url of the page.
  */
          @Override
          public void onPageStarted(WebView view, String url, Bitmap favicon) {
              super.onPageStarted(view, url, favicon);
              String newloc;
              if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
                  newloc = url;
              } else {
                  newloc = "http://" + url;
              }
  
              if (!newloc.equals(edittext.getText().toString())) {
                  edittext.setText(newloc);
              }
  
              try {
                  JSONObject obj = new JSONObject();
                  obj.put("type", LOCATION_CHANGED_EVENT);
                  obj.put("location", url);
  
                  sendUpdate(obj, true);
              } catch (JSONException e) {
                  Log.d("ChildBrowser", "This should never happen");
              }
          }
      }
  }
  </code></pre>