Interaction between Java and Javascript in Android development: phonegap plug-in vs addjavascriptinterface

Source: Internet
Author: User

1. Preface

In "using phonegap + jquerymobile to develop Android Application Instances", we will discuss how to build a phonegap (Cordova) development environment, and how to integrate a basic Android Application Framework (and provides examples ).Code). As a result, we began to work day and night to build our first mobile phone application.

But in fact, apart from common API calling specifications (with only one self-check Manual), we still encounter various problems. So in this articleArticle). Of course, there are various reasons for the interaction between the two, but it is still necessary to give full play to the advantages of the language and provide interfaces for the other party to call.

We know that on the Android platform, Cordova implements interface containers by using the built-in WebKit kernel (in fact, this is also true on other platforms ). We also know that Cordova is a bridge framework, which aims to build a bridge between native APIs and JS and intercommunication between them. To facilitate our application expansion, Cordova also provides the plug-in mechanism (of course, we can also directly modify the Cordova openSource code). As long as you follow certain rules (Grace, in fact, this rule is very simple), you can extend the rich functional effects.

 

2. Cordova plug-in and webview. addjavascriptinterface

Grace, the topic of this article is the interaction between Java and JS (almost ran away ). As mentioned above, Cordova has a plug-in mechanism to implement Java and JS interaction in the form of plug-ins. Why do we need to mention addjavascriptinterface?

The Cordova plug-in can indeed implement interaction between the two, which is asynchronous and convenient. But for some special reasons, for example, a callback needs to be called multiple times (AHA, maybe I am too fond of it? Callback registered with plugin can only be called once ). Or do not want to write plug-ins.

In short, plug-ins do not always meet our needs everywhere (our desire is infinite), and we always have to find a solution, find a different path (I personally do not particularly agree with Cordova's hack method, but refer to its plug-in. In addition, Cordova's current status is a bit odd and the version is updated very quickly, but the document updates are not synchronized ). To be truly mature, there is still a way to go.

Addjavascriptinterface is the native API of WebKit and is a public method of webview objects. It is used to expose a Java object to JS, so that JS can directly call the Java method. Of course, to implement two-way interaction between Java and JS, we also need to use another method loadurl (same as webview object, which Cordova uses to call JS.

Of course, these two methods have advantages and disadvantages (only in practice can we understand ). The lack of Cordova plug-ins has been mentioned just now; addjavascriptinterface also has some problems. First, when the Android platform encapsulates the WebKit kernel, there are some inconsistencies between different versions. Second, loading JS directly using loadurl is a headache.

In fact, there should be better methods, such as expanding the JS engine (I prefer this method), but this method is relatively complicated and is not included in this topic for the time being.

 

3. Implementation of Cordova plug-in

The Cordova plug-in is divided into two parts (amount, Cordova itself is also divided into two parts, awkward ?), One part is implemented by Java, and the other part is implemented by Js.

1) Java Section

The Java part of the Cordova plug-in is very simple. inherit from Cordova. plugin and implement the execute method:

Public classnotifclient extends plugin {

Private Static final string tag = "icationicationclient ";

Private string callbackid = "";

Public pluginresult execute (stringaction, jsonarray ARGs, string callbackid ){

Pluginresult. Status status = pluginresult. Status. OK;

If (action. Equals ("register ")){

Try {

Register (ARGs. getstring (0), argS. getstring (1 ));

} Catch (jsonexception e ){

Status = pluginresult. Status. json_exception;

}

} Elseif (action. Equals ("watch ")){

This. callbackid = callbackid;

Pluginresult r = newpluginresult (pluginresult. Status. no_result );

R. setkeepcallback (true );

Return R;

} Else {

Status = pluginresult. Status. invalid_action;

}

Return newpluginresult (Status );

}

Public object onmessage (string ID, object data ){

Log. D (TAG, "onmessage (" + ID + ").");

If (Id. Equals ("onclientnotification ")){

If (! Callbackid. Equals ("")){

This. Success ("true", callbackid );

}

}

Return data;

}

Private void register (string username, string phone ){

Log. D (TAG, "Register (" + username + "," + phone + ").");

}

}

Well, as an example of the Cordova plug-in Java, he has completed his mission (Forgive me for deleting comments and blank lines to save space; don't worry too much, there are many examples of projects that can be learned in reference resources ).

I have to say that Cordova has done a lot of work. To reduce the workload of plug-in development, it has encapsulated a lot of JS calls (looking back at how poor loadurl is, ).

 

2) JS part

Alas, it makes me feel awkward. When it comes to JS, I have been familiar with two methods of writing (of course, I have only been familiar with three versions: 1.0, 2.0, and 2.1. Well, in terms of the execution effect, 2.0 is compatible with 1.0 (Oh, the premise is that I made some changes, although the changes are very small, an error will still be reported when tracking the script, although it does not affect the script loading.

Let's take a look at the first method (1.0 ):

Functionnotificationclient (){}

Icationicationclient. Prototype. Register = function (username, phone ){

Phonegap.exe C (null, null, "icationicationclient", "register", [username, Phone]);

};

Icationicationclient. Prototype. Watch = function (FN ){

Phonegap.exe C (FN, null, "icationicationclient", "watch", []);

};

Phonegap. addconstructor (function (){

If (typeof navigator. icationicationclient = "undefined ")

Navigator. icationicationclient = new notificationclient ();

});

The online tutorials are all like this. In fact, an error is reported during the runtime: The phonegap object cannot be found. More seriously, the navigator. icationicationclient cannot be accessed at runtime.

Of course, if you change it to this:

// Phonegap. addconstructor (function (){

If (typeof navigator. icationicationclient = "undefined ")

Navigator. icationicationclient = new notificationclient ();

//});

ProgramIs normal, although it still reports an error.

 

OK, let's take a look at the second method (2.0 ):

Cordova. Define ("Cordova/plugin/icationicationclient", function (require, exports, module ){

VaR exec = require ('cordova/exec ');

VaR icationicationclient = function (){};

Icationicationclient. Prototype. Register = function (username, phone ){

Exec (null, null, "icationicationclient", "register", [username, Phone]);

};

Icationicationclient. Prototype. Watch = function (FN ){

Exec (FN, null, "icationicationclient", "watch", []);

};

VaR icationicationclient = newicationicationclient ();

Module. Exports = icationicationclient;

});

If (! Window. plugins ){

Window. plugins = {};

}

If (! Window. plugins. icationicationclient ){

Window. plugins. icationicationclient = Cordova. Require ("Cordova/plugin/notificationclient ");

}

Well, there is no mistake in this writing, and it can run properly and be happy.

 

3) register the plug-in

After writing the plug-in, you need to register it before it can be used in Cordova. Find the res \ XML directory under the project directory, 1.0 open the Plugins. xml file, 2.0 open the config. xml file, and add the following to the Plugins node:

<Pluginname = "icationicationclient" value = "cn. yofang. Mobile. icationicationclient"/>

 

Now, the icationicationclient plug-in can be called in Js.

1.0 usage:

Navigator. icationicationclient. Register ("azhi", "15810108888 ");

2.0 usage:

Window. plugins. icationicationclient. Register ("azhi", "15810108888 ");

 

4. webview. addjavascriptinterface implementation

Ah, I finally reached addjavascriptinterface. Every time I write about half of my documents, my hands were sore. (I also sighed when I read the documents: I finally got it ).

Addjavascriptinterface is simpler than the Cordova plug-in. First, we define a class:

Public classnotificationclient {

Private Static final string tag = "icationicationclient ";

Private context = NULL;

Private cordovawebview view = NULL;

Private string callback = "";

Public icationicationclient (contextcontext, cordovawebview view ){

This. Context = context;

This. view = view;

}

Public void register (string user, string mobile, string callback ){

Log. D (TAG, "Register (User:" + User + ", Mobile:" + mobile + ", callback:" + callback + ")");

This. Callback = callback;

Checkmessage ();

}

Public void checkmessage (){

Sharedpreferences sp = context. getsharedpreferences ("icationicationclient", 0 );

Int message = integer. valueof (sp. getint ("message", 0 ));

Log. D (TAG, "checkmessage ():" + message );

If (Message> 0 ){

Editor editor = sp. Edit ();

Editor. putint ("message", 0 );

Editor. Commit ();

Newhandler (). Post (New runnable (){

Public voidrun (){

View. sendjavascript (callback );

}

});

}

}

};

The intent of this class is very simple (well, it is similar to the notificationclient plug-in of the Cordova plug-in above, right ?) : A register method is provided for JS calls, And a callback is added to the input parameter. At the right time (check the message mark through sharedpreferences. If the value is greater than 0, it is considered the right time ), call this callback from the Java end (of course, other android native objects such as sharedpreferences and handler are used in the code, which are ignored temporarily ).

Isn't I using sendjavascript instead of loadurl? Sendjavascript is the method provided by Cordova for webview encapsulation. In fact, we changed the sentence:

View. loadurl ("javascript:" + this. Callback );

The effect is the same (of course, if you do not use Cordova, but write your own activity, you must write it ).

Okay. After writing the class, we should expose this class to JS:

Appview. getsettings (). setjavascriptenabled (true); // enable Javascript before exposing

Appview. addjavascriptinterface (newnotificationclient (this, appview), "icationicationclient ");

Well, here we use appview (the member variable of droidgap). We use Cordova, so there is no sin to use it. If the activity is implemented directly, you need to embed webview on your own and change the appview to your own webview object.

The usage in JS is as follows:

Window. icationicationclient. Register ("azhi", "15810108888", "onmessage ();");

As you can see, it is quite convenient to call in JS. You do not need to create JS class objects in advance. The objects added through addjavascriptinterface are directly attached to the window object. But the drawbacks are also obvious. Let's look at our callback, which is passed in as code (of course, it can be improved, but we will not talk about it today ).

Well, let's just make a conclusion: I hope everyone will have some gains.

 

5. Reference resources

Example of the phonegap plug-in:

Https://github.com/phonegap/phonegap-plugins/tree/master/Android

Addjavascriptinterface application example:

Http://www.codeproject.com/Articles/392603/Android-addJavaScriptInterface

WebKit API:

Https://developer.android.com/reference/android/webkit/WebView.html

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.