Communication Between Android Java and Phonegap JavaScript

Communication between Android Java and Phonegap Javascript?

I finally made it work.

  • Create a class with methods you want to use:

    public class MyClass {
    private WebView mAppView;
    private DroidGap mGap;

    public MyClass(DroidGap gap, WebView view)
    {
    mAppView = view;
    mGap = gap;
    }

    public String getTelephoneNumber(){
    TelephonyManager tm =
    (TelephonyManager) mGap.getSystemService(Context.TELEPHONY_SERVICE);
    String number = tm.getLine1Number();
    return number;
    }
    }
  • In your main activity add a Javascript interface for this class:

    public class Main extends DroidGap
    {
    private MyClass mc;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    super.init();

    mc = new MyClass(this, appView);
    appView.addJavascriptInterface(mc, "MyCls");

    super.loadUrl(getString(R.string.url));
    }
    }
  • In Javascript call window.MyCls methods:

    <script>
    $(function(){
    $("#phone").text("My telephone number is: " +
    window.MyCls.getTelephoneNumber());
    });
    </script>

Note:

As mentioned in the comment, for Android version 4.2 and above, add @JavascriptInterface to the method which you want to access from your HTML page. Reference.

Asynchronous communication between Javascript and Phonegap Plugin

You are almost there but you need to setKeepCallback to true on your PluginResult. If you don't the subsequent results from the Java side will not have a callback on the JavaScript side. The best example of this type of coding is the Network plugin in Cordova core. Here is a link to the source:

https://git-wip-us.apache.org/repos/asf?p=cordova-plugin-network-information.git;a=blob;f=src/android/NetworkManager.java;h=e2ac500ccc885db641d5df6dab8eae23026a5828;hb=HEAD

So you should update your code to:

public boolean execute(String action, final JSONArray args,
final CallbackContext callbackId) throws JSONException {
IntentFilter wifiFilter = new IntentFilter(
WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
cordova.getActivity().registerReceiver(wifiBroadcastReceiver,
wifiFilter);
this.callbackContext = callbackId;
PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
result.setKeepCallback(true);
this.callbackContext.sendPluginResult(result);
return true;
}

public class WifiReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
PluginResult result;
if (intent.getBooleanExtra(
WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) {
Toast.makeText(cordova.getActivity(), "Wifi Connected",
Toast.LENGTH_SHORT).show();
result = new PluginResult(PluginResult.Status.OK,
"Wifi Connected");
} else {
Toast.makeText(cordova.getActivity(), "Wifi Disconnected",
Toast.LENGTH_SHORT).show();
result = new PluginResult(PluginResult.Status.ERROR,
"Wifi Disconnected");
}

result.setKeepCallback(false);
if (callbackContext != null) {
callbackContext.sendPluginResult(result);
callbackContext = null;
}
}
}
}

Javascript calls from Android using PhoneGap

Firstly, you are using a Plugin subclass. Plugin has been deprecated and has been replaced with CordovaPlugin. If you're using an old version of PhoneGap, I would recommend that you upgrade.

Secondly, your exec call is wrong. The docs for plugin development clearly state that you have to pass 5 parameters, while you're passing 3 nulls. How do you expect that to be handled?

cordova.exec(function(winParam) {}, function(error) {}, "service",
"action", ["firstArgument", "secondArgument", 42,
false]);

Here, the service, action and the array of parameters determine what will happen in your Java code. The first two determine what will happen in JavaScript under certain conditions. So, while you can use null for the first two, you have to specify the last three.

I have a working example plugin that works with PhoneGap 2.3.0. See the code below:

public class ExampleJSCommunicator extends CordovaPlugin {

public boolean execute (final String action, final JSONArray args, CallbackContext callbackContext) throws JSONException {
PluginResult.Status status = PluginResult.Status.OK;
String result = "";

cordova.getActivity ().runOnUiThread (new Runnable () {
@Override
public void run() {
try {
String displayText = "";
if (action.equals ("buttonClicked")) {
displayText = args.getString(0) + " was clicked";
}

else if (action.equals ("animationRunning")) {
displayText = args.getBoolean(0) ? "Animation started running" : "Animation stopped running";
}

TextView label = (TextView) cordova.getActivity().findViewById (R.id.textView);
label.setText (displayText + " and the Activity knows it!");
} catch (JSONException e) {
e.printStackTrace();
}
}
});

return true;
}
}

With the code above, you have your Java-side plugin capable of handling two custom "actions" - buttonClicked and animationRunning. These actions serve my purposes, but you could name them otherwise.

Now, you still need to register your plugin, so that Cordova will know about it. This is done in the xml/config.xml file. Under plugins, you have to add the following:

<plugin name="ExampleJSCommunicator" value="com.example.phonegap.ExampleJSCommunicator"/>

Then you can pass data (or "actions") from JavaScript as follows. Note that the parameters (which.id and animationRunning are passed in an array):

cordova.exec (null, null, "ExampleJSCommunicator", "buttonClicked", [which.id]);  // my first action
cordova.exec (null, null, "ExampleJSCommunicator", "animationRunning", [animationRunning]); // my second action

These two exec calls will trigger the execute method in the ExampleJSCommunicator class and will get handled in the respective if blocks. It doesn't matter where you call exec, as long as you declare your JavaScript code after you include the cordova.js file. My JavaScript is contained within a separate main.js file and it works just fine:

<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="main.js"></script>

Javascript-to-Java Communication in an Android Phonegap app

You can pass a javascript variable to the java while using the plugins as below.

cordova.exec(null, null, "service", "action", ["firstArgument", "secondArgument", 42]);

Here the first and second parameter to the exec method are the sucess and failure calllback.
service and action are the native class and method names respectively.
And the last parameter ["firstArgument", "secondArgument", 42] are the javascript variables which you can pass to the native method.

For more details please go through the following link.
http://docs.phonegap.com/en/2.8.0/guide_plugin-development_index.md.html

Phonegap - HTML/JS to Container Communication

I managed to find this useful link: Dissecting PhoneGap's Architecture. Of course, if that doesn't give you the level of detail you want, you can always check out Android's Exec function

how to send data or message from java application / plugin to javascript with cordova / phonegap

You can always execute javascript from java doing this:

String js = "alert('test')";
webView.loadUrlNow("javascript:" + js);

Or you can init the plugin and keep the callback doing this

PluginResult pgRes = new PluginResult(PluginResult.Status.OK, "message");
pgRes.setKeepCallback(true);
callbackContext.sendPluginResult(pgRes);

Added example provided by Sephy

private String myCbkId;
// Store callbackId from a call to execute
@Override public boolean execute(String action, JSONArray arr, CallbackContext cbkCtx) throws JSONException {

myCbkId = cbkCtx.getCallbackId();
JSONObject data = arr.getJSONObject(0);
String ack = data.getString("data"); // You can acknowledge to the callback for instance and keep it alive
Log.d(TAG, "ack".equals(ack) ? "ack !" : "not ack !");

// These lines can be reused anywhere in your app to send data to the javascript
PluginResult result = new PluginResult(PluginResult.Status.OK, ack);
result.setKeepCallback(true);//This is the important part that allows executing the callback more than once, change to false if you want the callbacks to stop firing
this.webView.sendPluginResult(result, this.myCbkId);

return true;
}

How to call an Android Activity from PhoneGap

Any Java Native code call be called without using any plugin as following.

Follow The following Steps.

  1. Replace the following code with your existing DroidGap Activity.

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.init(); // Calling this is necessary to make this work
    appView.addJavascriptInterface(this, "MainActivity");

    /* "this" points the to the object of the current activity. "MainActivity" is used to refer "this" object in JavaScript as in Step 3. */

    super.loadUrl("file:///android_asset/www/index.html");
    }
  2. Add the custom function in current (this) activity as following.

    public void customFunctionCalled() {
    Log.e("Custom Function Called", "Custom Function Called");
    }
  3. Now call this function from your HTML/JavaScript code as following.

    <script type="text/javascript">
    function callNewActivity() {
    window.MainActivity.customFunctionCalled();
    }
    </script>

This will call customFunctionCalled() in MainActivity.

Tested Environment
Eclipse - 3.7.2
Android 2.2 Emulator
PhoneGap - 2.0.0

Please provide your comments here to improve blogs post.
http://phonegapexplorers.blogspot.in/2012/08/call-native-java-code-phonegap-android.html

How to communicate between WebView & JavaScript?

You should add javascript interface to your webView like that:

webView.addJavascriptInterface(new JavascriptInterface(this), "AndroidFunction");

You should create interface class:

public class JavascriptInterface{
Context mContext;

JavascriptInterface(Context c) {
mContext = c;
}

public void save(String action){
// save to database
}
}

On the website you should call:

AndroidFunction.save("actionName");


Related Topics



Leave a reply



Submit