So let's take a look at a new plugin I just created that gets you the IMEI of your Android phone. First here is the 1.4.1 version of the code:
and now the 1.5+ version:
As you can see the code is very different. Really the only changes are that PhoneGap has been replaced with cordova. There is actually a shim in place so that you can still use the PhoneGap object but that is going away for the 2.0 release so we might as well get on that train now. As well the addConstructor/addPlugin methods won't really be needed come 2.0 but lets leave them in for now.
Alright, so the JavaScript code wasn't much different so let's dive into the Java code now. First the 1.4.1 version:
and now the 1.5+ version: again not too many changes. Simply changing the imports from:
import com.phonegap.api.Plugin; import com.phonegap.api.PluginResult;to:
import org.apache.cordova.api.Plugin; import org.apache.cordova.api.PluginResult;This shouldn't be necessary for your plugin as I added code in the cordova.jar file so that every class in the org.apache.cordova.api package has a sub-class in com.phonegap.api. Once again this will be going away in the 2.0 release so we should go ahead and make the change now. Easy right?
Well kinda, but I'm being a bit disingenuous as my example does not address a key change between versions 1.4.1 and 1.5.0. In PhoneGap 1.4.1 the member variable this.ctx was of type PhonegapActivity. If you walked up PhonegapActivity's inheritance chain you'd see that android.content.Context is one of it's super classes. This was particularly useful in a number of Plugins.
In Cordova 1.5+ the member variable this.ctx is a CordavaInterface. So plugins that are passing this.ctx into methods that are expecting a Context will complain. The fix for this in your Java code is to replace:
this.ctxwith:
this.ctx.getContext()or
this.ctx.getIntent()with:
((DroidGap)this.ctx).getIntent()wherever required. These changes were predicated by refactoring of the code in order to enable Cordova to be an embeddable component. That is, at some point in the future you will be able to create an Android application that can embed the Cordova component. This will allow you to mix native and hybrid development more easily.
Update 2012/04/23: Paul Beusterien pointed out that I forgot to mention a couple of steps to get the IMEI plugin working. First add the following line to res/xml/plugins.xml:
<plugin name="imei" value="com.simonmacdonald.imei.IMEIPlugin"/>and make sure you have the proper permissions setup in your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Does it works on iPhone also? Can we get IMEI from iOS devices? what all other device information we can get (like phonenumber)?
ReplyDelete@R Ramana
ReplyDeleteNo, this plugin will not work on iOS. Android plugins are written in Java which does not run on iOS. You'd need to re-implement this in Objective-C. Check out this StackOverflow answer:
http://stackoverflow.com/questions/823181/how-to-get-imei-on-iphone
hi how to find mobile number using phonegap..in android please help me..
ReplyDelete@GreaterJun
ReplyDeleteYou would do:
TelephonyManager tMgr =(TelephonyManager)mAppContext.getSystemService(Context.TELEPHONY_SERVICE);
mPhoneNumber = tMgr.getLine1Number();
but there is no guarantee that the SIM will return the number. A lot of times you'll get null.
Hi Simon,
ReplyDeleteI am able to install condova application on my android phone to access GPS, camera etc. But i am not able to get the IMEI plugin to work.
This is what i am using:
1) Android version 2.3.3
2) Cordova 18
3) IMEI Plugin version 1.5
4) I added the plugin name to the plugin xml.
5) I added the script inclusion to index.html.
On calling the function window.plugins.imei.get it always goes into the failure function.
Please help.
Thanks
Jaskaran
@Jaskaran
ReplyDeleteDid you add read phone state permission to your manifest.xml? That is the only thing you didn't mention.
Hi Simon,
ReplyDeleteThanks for replying.
I added the below permission to the manifest:
thanks
jaskaran
@karan
ReplyDeleteSorry the XML did not come across in the comment.
Hi, Sorry about that.
ReplyDeleteI gave this permissiong(not including the angular brackets):
uses-permission android:name="android.permission.READ_PHONE_STATE"
thanks
karan
Hi Simon,
ReplyDeleteI needed some more help :-)
I needed to embedd native controls along with the html(index.html) for android.
Is there any wau to do this?
Thanks alot
karan
@karan
ReplyDeleteBy native controls do you mean the menu?
Hi Simon,
ReplyDeleteYes native controls like:
1) Menu
2) Custom menu
3) Toolbar etc
I need to do this in Android.
I really appreaciate your help and time.
Thanks
karan
@karan
ReplyDeleteYou can use the native implementation which is detailed here:
https://developer.android.com/guide/topics/ui/menus.html
and when you want to call from Java to JavaScript you do a:
this.sendJavascript(myJScode);
Hi Simon,
ReplyDeleteThis is GREAT. Thank you very much! But needed to ask something....
I have been able to make a mixed UI from the Activity Class itself. Half in native controls and half in Phonegap html. My code is :
public class Jaskaran823Activity extends DroidGap {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View header = View.inflate(getContext(), R.layout.main, null);
root.addView(header);
super.loadUrl("file:///android_asset/www/index.html");
this.sendJavascript("javascript:yourFunction('load')");
super.appView.getSettings().setJavaScriptEnabled(true);
super.appView.addJavascriptInterface(this, "MyCls");
}
}
I am now able to communicate both ways from java to javascript and vice versa.
Now can i do the same using phonegap plugins? I mean can i put the native controls in a plugin? And embedd native-UI inside the phone-gap html from within the plugins?
Something like this seems to be done for iPhone. But i need to do this in android...
Is there any exmaple of puttinh native UI from within a plugin in android?
Please help.
Thanks
Karan
@karan
ReplyDeleteI would avoid using addJavascriptInterface() as there are some problems with that code working on all versions of Android. You should switch to using a PhoneGap Plugin which works around these issues if they exist.
So use a Plugin to communicate from JavaScript to Java and return a Plugin result or alternatively you can use sendJavaScript. That is what I do when I implement a native menu.
You can check out Joe's new project which shows how to embed a CordovaWebView in an Android project:
https://github.com/infil00p/CordovaActionView
or look at Michael Brooks menu plugin:
https://github.com/mwbrooks/cordova-plugin-menu
Thanks alot Simon.
ReplyDeleteThis is super.
You have been extremely helpful...
Hi,Simon. I am migrating the phonegap plugin to cordova 2.0. Could you tell me how to modify this line:
ReplyDelete((DroidGap)this.ctx).getIntent() to cordova 2.0?
Thanks in advance.
@Wei Zhang
ReplyDeleteThat would be "cordova.getActivity().getIntent()"
Hi guyz. pls i need to apply the "getting android IMEI" stuff on my work. But this is the issue:
ReplyDeleteIt's an html/css/js code, using cordova to compile it into an android app via eclipse.
The Question:
How do I put in the codes; where exaclty and if possible can i have verbatim code?
@Yinka Adediji
ReplyDeleteWhat about the instructions don't you understand?
with cordova 2.0.0,
ReplyDeletehow is "File fp = new File(this.cordova.getActivity().getFilesDir() + "/" + filename);"
@supriya
ReplyDeleteSorry, I don't understand your question.
Hi simon
ReplyDeletein all the android twitter OAUth applications they are using On resume method get the verifier for the Authorizing the Application .
similarly for Phonegap if i use :
cordova.getActivity().startActivity(
new Intent(Intent.ACTION_VIEW, Uri.parse(requestToken
.getAuthenticationURL())));
for starting the intent . i am not getting the intent URI as a result in OnResume method of the PluginResult.
but i am getting a call to the Onresume method after the Application authentication .
Thanks and regards
Sangeeth Kumar V
@sangeeth_LVS
ReplyDeleteI believe you want to start your activity for result. You are just doing a startActivity. So I'd do:
this.cordova.startActivityForResult((Plugin)this,
new Intent(Intent.ACTION_VIEW, Uri.parse(requestToken
.getAuthenticationURL())));
and implement the onActivityResult method in your Plugin.
With Cordova 2.2 the class Plugin is deprecated, one should use CordovaPlugin from now on.
ReplyDeleteSince I have problems getting this to run I would appreciate an update to the blog showing how it's done with Cordova 2.1/2.2.
Thanks,
Juergen
@Jürgen Wahlmann
ReplyDeleteThe Plugin class will continue to work for quite some time. I do like your suggestion and I will make it a future blog post so stay tuned.
Hi, Does it work with Phonegap 3.0+?
ReplyDelete@cureorcurse
ReplyDeleteThe same Android code will work but it would need to be updated to 3.0.0 style plugin.