Wednesday, October 31, 2012

What's New in PhoneGap Android 2.2.0

Well we've tagged Apache Cordova 2.2.0 release candidate 2 which means that Cordova 2.2.0 will be out soon in source release form which will be followed quickly by the binary PhoneGap 2.2.0 release. Shaz wrote up a post on what's new in iOS so I was asked (shamed) to do this on for Android. So without further ado here's what you should expect on Android:

1. FileTransfer API changes

  • Added support for the onprogress event to get progress events for a FileTransfer operation
  • Added the abort function to cancel a FileTransfer operation

See the API doc.

2. Graduated the Globalization plugin to core

This plugin was previously in the phonegap-plugins repo (BB WebWorks 5, iOS, Android). The globalization object obtains information and performs operations specific to the user’s locale and timezone.

See the API doc.

3. Splashscreen API

The Splashscreen API is now formally documented for iOS and Android.

4. Android JavaScript to Java bridge improvements
  • The callback server is gone.
  • Uses events to specify when a result it ready.
  • Up to 25 times faster.
Read issue CB-638 for more information.

5. Partial support for video tag

We've been able to shim in support for the video tag. See my earlier blog post for more details.

6. Hardware acceleration is enabled by default

When you run bin/create to make a new PhoneGap Android project then android:hardwareAccelerated is set to true by default on the main activity.

See Android docs for an explanation of hardware acceleration.

7. useBrowserHistory now defaults to true

We've deprecated the current way that history is handled in Android apps in favour of the default way it is handled in the web view. To go back a page you should be using history.back(). Because of this change iframe's now work properly.

If you need to enable the old way to handle history you can set useBrowserHistory to false in config.xml.

8. Introduce CordovaPlugin class

CordovaPlugin will be replacing the Plugin class for extending PhoneGap functionality. It adds a new execute method public boolean execute(String action, String rawArgs, CallbackContext callbackContext) to enable developers passing large amounts of data to the native side provide their own JSON parser. It also cuts down on boiler-plate, makes multi-threading easier, and adds an application-wide thread-pool to CordovaInterface. Adds an onReset method that is called when top level navigation changes. This is where you should stop any long running processes like a file transfer that are no longer needed on the new page.

9. Various bug fixes
  • Back and Menu button events now fire if the cursor is inside a text view.
  • Fixed a path where the whitelist was not being checked in DroidGap.
  • FileTransfer.download now supports the trustAllHosts option to allow downloading from servers with self signed certificates.
  • Removed trailing space from contact.name.formatted.
  • Properly set contact's IM type.
  • navigator.language is now set properly when the language is switched in Android settings.

56 comments:

Unknown said...

IMPORTANT:

Before Cordova 2.2.0, the Connection object existed at: navigator.network.connection.
To match the spec, this was changed to navigator.connection in 2.2.0.

this resulted in an error with my script which was the same as the example at http://docs.phonegap.com/en/2.2.0/cordova_connection_connection.md.html#Connection

for me navigator.connection.type is 0 since I upgraded.

seems like I dont have a decent way to check connection right now. any help on this will be appreciated.

Simon MacDonald said...

@H.C.L. Bazić

You can still use navigator.network.connection.type as it is being set properly even though it is deprecated. It won't be removed for about 6 months. I'll bring this to Andrews attention though. Thanks for the update.

Unknown said...

Is there a fix for the webview freezing after being dormant for long periods of time in this release? It seems to be a big issue in Android 4.0.1 with cordova 2.1.0 currently.

Simon MacDonald said...

@Adam

Certainly there was a fix for this on the ASUS Transformer but looking at JIRA it seems you have a separate issue. We'll handle the discussion over on JIRA.

Unknown said...

Wonderful Improvements here.

Is there a fix to the orientation change for android 4.x devices.
The activity seems to be reloading on devices > android 4.x ,despite handling orientation changes in manifest and overriding methods in main activity,and my app totally gets refreshed.There seems no native way for me to control it.

Thanks for any help.

Simon MacDonald said...

@Prasad Wagh

I can't reproduce that problem. You should provide sample code/project that demonstrates it and we'll look at it.

Salud y Bienestar said...

I would like to know if the issue "Return from camera not reliable on Android" was resolved?

https://groups.google.com/forum/?fromgroups=#!topic/phonegap/GFwv2OticKw

thanks.

brian said...

Is there anything new that needs to be done to take advantage of the android bridge improvements? Looking through the code it seems like it uses the new options by default by I am still experiencing annoying freezes on ICS.

Simon MacDonald said...

@brian

No, you shouldn't need to do anything. I know that Andrew/Joe and I are trying to figure out the freezes on ICS over on the mailing list. We need a good reproduction scenario to figure this out though.

Simon MacDonald said...

@LUIS SOTO

No, we haven't completely solved it. I made improvements in 1.9.0/2.0.0 but we are still working on a complete fix for this annoying Android issue.

Unknown said...

Hello Simon,
Does this release solve the problems with android ics url parameter?

Simon MacDonald said...

@Ademola Olayioye

Joe has indicated that it has been fixed. Have you tried the latest release? If it is still a problem let us know as soon as possible.

Unknown said...

Thank you for your response.
The latest release has indeed solved the problem.

Michelangelo Giacomelli said...

hello, good job.
I would like some information on hardware acceleration.
It means that the canvas will be accelerated? you can start thinking about games?
perhaps using canvas and easel.js ...

Simon MacDonald said...

@michelangelo giacomelli

Actually if you are relying on a canvas element in the web view you will probably want to turn off hw acceleration. It is still kinda buggy. But I'd say test it out for yourself.

dajver said...

how to download files with https protocol in android ? I'm try to use it, but keep getting an error.

My download code:

var fileTransfer = new FileTransfer();
fileTransfer.download(
task_url,
fileListDir + fileName,
function(entry) {
mylog("download complete: " + entry.fullPath);
},
function(error) {
mylog("download error source " + error.source);
mylog("download error target " + error.target);
mylog("upload error code" + error.code);
});
My log

11-19 13:56:13.339: E/FileTransfer(17969): {"target":"/mnt/sdcard/task1/Picture_4.jpg","source":"https://91.228.199.95/ksiywFac63f2hs/fotos.gleb/Picture_4.jpg","code":3} 11-19 13:56:13.339: E/FileTransfer(17969): javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:477) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:328) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.setupSecureSocket(HttpConnection.java:185) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:433) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeConnection(HttpsURLConnectionImpl.java:378) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:205) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:152) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.cordova.FileTransfer.download(FileTransfer.java:486) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.cordova.FileTransfer.execute(FileTransfer.java:88) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.cordova.api.PluginManager$1.run(PluginManager.java:231) 11-19 13:56:13.339: E/FileTransfer(17969): at java.lang.Thread.run(Thread.java:1019) 11-19 13:56:13.339: E/FileTransfer(17969): Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:161) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:664) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:474) 11-19 13:56:13.339: E/FileTransfer(17969): ... 10 more 11-19 13:56:13.339: E/FileTransfer(17969): Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. 11-19 13:56:13.339: E/FileTransfer(17969): at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:207) 11-19 13:56:13.339: E/FileTransfer(17969): at java.security.cert.CertPathValidator.validate(CertPathValidator.java:197) 11-19 13:56:13.339: E/FileTransfer(17969): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:156) 11-19 13:56:13.339: E/FileTransfer(17969): ... 13 more

Simon MacDonald said...

@Gleb Kravchenko

Looks like you are trying to download from a service with a self signed certificate. You need to enable debug mode to download:

var fileTransfer = new FileTransfer();
fileTransfer.download(
task_url,
fileListDir + fileName,
function(entry) {
mylog("download complete: " + entry.fullPath);
},
function(error) {
mylog("download error source " + error.source);
mylog("download error target " + error.target);
mylog("upload error code" + error.code);
},
true);

dajver said...

Thanks!!! U saved me!

Unknown said...

Hi,Simon. Is there win8 doesn't support Cordova Opendatabase method?
I use Cordova 2.2.0 in visual studio express for windows 8 with my project code, when I run, I got error: "javascript runtime error: boject dosen't support property or method openDatabase". So I am wondering the Win8 doesn't support the database in Cordova 2.2.0? Thanks

Simon MacDonald said...

@Wei Zhang

You should ask that question on the Google Group or talk to @purplecabbage. I haven't touched the WIndows Phone stuff at all.

Unknown said...

How can apply that(https://issues.apache.org/jira/browse/CB-1829) fix to the 2.2.0 release? As is phonegap is unusable...

Simon MacDonald said...

@Luigi Picaro

You'd have to download the source code for cordova android with the 2.2.0 tag. Then you need to open the NetworkManager.java file and remove the onPause method and re-compile.

unimity said...

If the cursor is inside a text view and clicked on the back button the app exits in cordova 2.2. Is this an issue in cordova 2.2?

Simon MacDonald said...

@unimity

That bug should be fixed. I just tried it in 2.3.0rc1 and I can't reproduce it but then again I believed it was fixed for 2.2.0. What are the particulars of the reproduction scenario?

unimity said...

Hi,
The scenario is keep the cursor in a text view and click on the back button the app exits. But if the cursor is in a textarea and clicked on back button, it works fine.

unimity said...

To avoid back button issue when the cursor is placed in text view , we included the below code.
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//if(appView.canGoBack()){
// this.sendJavascript("javascript:BackButton()");
// return true;
//}
this.sendJavascript("javascript:BackButton()");
return true;
}
return super.onKeyDown(keyCode, event);
}

It works in android 2.2, android 2.3 but in android 4.1 back button is not working when included the above code

Simon MacDonald said...

@unimity

Weird, I can't reproduce in 2.3.0rc1 but I'll take a closer look at it before we cut rc2.

Unknown said...

I'm posting here because there does not seem to be an obvious way of reporting bugs of that kind, not because I want an answer to something (Cordova bug reporting is not so obvious either); to this:
"While with an Eclipse local build, the app version in the Android Applications sub-screen is correct, it reports a different, unrelated, and WRONG version with the official PG Build package; for instance our app is actually at "0.9.8" but it shows "1.1" !
Yes, widget attributes in config.xml ARE:
versionCode = "1"
version = "0.9.8",
they answered this: "This tracker is for Cordova, not for the Adobe PhoneGap Build service. Please contact them with your issue." So be it. A.R.

Simon MacDonald said...

@Al Reno

The bug tracker for Apache Cordova/PhoneGap is:

https://issues.apache.org/jira/browse/CB

Unknown said...

I don't think you understand my last post at all: I DID report the bug at https://issues.apache.org/jira/browse/CB-1975
They closed it immedialely with the said comment ("This tracker is for Cordova, not for the Adobe PhoneGap Build service. Please contact them with your issue.")
The ball is is YOUR camp Simon, weither you like it or not! YOU report it to your brilliant Build dudes at Adobe becaue THEY don't have the heart to have a bug reporting system, that's not my problem anymore! A.R.

Simon MacDonald said...

@Al Reno

Crap sorry Al. I sent you to the wrong place. If it is a PhoneGap Build problem you need to go to:

http://community.phonegap.com/nitobi

Also, I do not work for Adobe and I have nothing to do with the PhoneGap Build service.

Akorede Ismael Olusola Enitan Jimoh said...

Hi Simon,

Please I am creating a fileUpload with the code below:


File Transfer Example


// Wait for Cordova to load
//
document.addEventListener("deviceready", onDeviceReady, false);

// Cordova is ready
//
function onDeviceReady() {

// Retrieve image file location from specified source
navigator.camera.getPicture(uploadPhoto,
function(message) { alert('get picture failed'); },
{ quality: 50,
destinationType: navigator.camera.DestinationType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY }
);

}

function uploadPhoto(imageURI) {
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType="image/jpeg";

var params = {};
params.value1 = "test";
params.value2 = "param";

options.params = params;

var ft = new FileTransfer();
ft.onprogress = function(progressEvent) {
if (progressEvent.lengthComputable) {
loadingStatus.setPercentage(progressEvent.loaded / progressEvent.total);
} else {
loadingStatus.increment();
}
};
ft.upload(imageURI, encodeURI("http://some.server.com/upload.php"), win, fail, options);
}

function win(r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
}

function fail(error) {
alert("An error has occurred: Code = " + error.code);
console.log("upload error source " + error.source);
console.log("upload error target " + error.target);
}



However getting the following error: Web Console(9547): processMessage failed: Stack: ReferenceError: loadingStatus is not defined.

Please am I doing something wrong here: I am aware the link is just a sample link but the error is pointed at loadingStatus?

Thanks.

Ismael

Simon MacDonald said...

@Akorede Ismael Olusola Enitan Jimoh

It's pretty obvious from the error: " ReferenceError: loadingStatus is not defined". In a nutshell that means that object has not been created at the point you are trying to use it.

Akorede Ismael Olusola Enitan Jimoh said...

Thanks a lot Simon.

Unknown said...

Hi Simon,
Is it possible to "integrate facebook check in functionality " in phonegap ..?

Simon MacDonald said...

@Mayur Panchal

It is possible but I've never done it. I really hate Facebook. You should try Dave's plugin:

https://github.com/davejohnson/phonegap-plugin-facebook-connect/

Unknown said...

Prasad Wagh described how the app always reloads completely on orientation change - is there a fix for that?

I am having trouble with the orientation always reloading my app completely.

Thank You

Simon MacDonald said...

@Tommi Joutsiniemi

Did you apply the following config changes to your main activity?

android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale"

Unknown said...

Yes, I applied the android:configChanges into my main activity, but without screenSize, because my minimum SDk version is 7. I also had to remove hardware acceleration from the manifest for the same reason.

Still no fix, my app reloads completely when I reorient the device.

Simon MacDonald said...

@Tommi Joutsiniemi

It sounds like you are doing it wrong. You should always build with the latest SDK in this case API level 17. Then you can set a minimum SDK of 7. This will allow you to have all of those config changes I mentioned in your manifest and you app will work on Android 2.1 or greater.

Unknown said...

That is exactly how I do it. But still, this must be a problem in my setup if nobody else has this reload problem. I just have no idea where to look. I am using Sencha Touch 2.1 commercial and phonegap 2.3.0 (also tested with 2.4.0rc1). I basically have the default Sencha-generated app with PhoneGap integration.

Cheers
Tommi

Simon MacDonald said...

@Tommi Joutsiniemi

Paste up your manifest somewhere I can take a look. Don't do it in the comments as it doesn't accept xml.

Unknown said...

My AndroidManifest.xml:
https://dl.dropbox.com/u/5306505/AndroidManifest.xml

I tested my app on v2.2 emulator and reorientation works OK. On my v4.1 HTC one X device it doesn't. Do you think I should create a v4.2 emulator and find a v2.2 device to test... would that reveal something, possibly?

Simon MacDonald said...

@Tommi Joutsiniemi

You are missing "screenSize" from the config changes. I guess I wasn't clear about the API level thing. When you target 17 you can have screenSize in the manifest without impacting your ability to run on an API 7 level phone. Try adding it in and seeing if the problem goes away.

Unknown said...

ta-DAA!

screenSize did it, thank you so much!

I have a simple app which was generated with the latest ST ("sencha generate"), and merged to a newly generated PhoneGap project ("create" in PhoneGap). (BTW, the magic was to have www and android folders side by side at app's root, and then make a symbolic link from android/assets/www point to that www - that way it should be relatively easy to use that same www folder on a possible future iPhone version of the app.)

Anyway, here's how I probably managed to get confused: I had 2.2 as the target SDK at some point (initially, after I generated the skeleton), and I had to edit the manifest to make my app work. Then when I changed the target SDK to v4.2 I undid those changes but apparently forgot to bring back screenSize.

I hope I didn't blame PhoneGap at any point, it works perfectly...

Thank You again

Cheers
Tommi

Simon MacDonald said...

@Tommi Joutsiniemi

No worries, just happy it is working for you.

Gabriele said...

Hi, I appreciate very much the improvements made on html5 video tag support.
I spent the last couple of days (and nights) facing problems related to the integration of a video in an Android PhoneGap Application i'm developing. My base platform is Android 4.0.3 and 4.0.4.
After finding the correct encoding (webm video) I realized that the video playback result is actually very different from one device to another. In my Asus Transformer (as well as on Samsung Galaxy Note) the video is rendered inline in the phonegap webview (the video is inside the page and has the correct size, set to 320x180 pixels, just for example). The, very excited by this incredible result, I tested my app on another device (Zenithink ZPad C91 tablet) and the video is shown fullscreen... :'(
Checking the LogCat I fount this:
MediaPlayer error(-38, 0)
setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder

I googled a little bit but I can't figure out what is wrong. Maybe you can give me a clue or can suggest how to fix this problem.

Do you plan to work on phonegap and video tag support?

Thankyou very much

Best Regards

Simon MacDonald said...

@Gabriele

Welcome to Android fragmentation. If you want a consistent, unfortunately fullscreen, appearance you could use my VideoPlayer plugin.

Gabriele said...

Thank you Simon! It is comforting to know that I was not wrong.. Even if my problem is still there! :)
I'll try your VideoPlayer plugin for sure: I read many beatiful comments about it and i'm looking forward to try it! I really hope it will help me with my app! I'll let you know.
Thank you very much!

Anonymous said...

i am uploading 000000001.db file to server by using file transfer api of phonegap but it gives me error
file not found error code=1
can anyone help me out how to get rid of this fucking things.

Simon MacDonald said...

@Mohsin Qureshi

Show some code.

Anonymous said...

how can i send you my code whats your email?
function uploadPicture() {
alert('uploading file');
// Get URI of picture to upload
var img = document.getElementById('camera_image');
// var imageURI = img.src;

//"/data/data/com.suave.nexttrainer/app_database/file_0/0000000001.db";

var imageURI = "/data/data/com.suave.nexttrainer/app_database/file_0/0000000001.db";


alert(imageURI);
/* if (!imageURI || (img.style.display == "none")) {
document.getElementById('camera_status').innerHTML = "Take picture or select picture from library first.";
return;
}*/

// Verify server has been entered
server = document.getElementById('serverUrl').value;
alert('server');
if (server) {

// Specify transfer options
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType="image/jpeg";
options.chunkedMode = false;

// Transfer picture/file to server
var ft = new FileTransfer();
alert('ft');
ft.upload(imageURI, server, function(r) {
document.getElementById('camera_status').innerHTML = "Upload successful: "+r.bytesSent+" bytes uploaded.";
}, function(error) {
document.getElementById('camera_status').innerHTML = "Upload failed: Code = "+error.code;
}, options);
}

Simon MacDonald said...

@Mohsin Qureshi

Two things:

1) try using

"var imageURI = "file:///data/data/com.suave.nexttrainer/app_database/file_0/0000000001.db";

2) Is com.suave.netxtrainer your app package? Because only that app can read from that directory.

Anonymous said...

i do like that but in my log cat it shows this .
its the path of sever on which i have to upload the database file "http://nextrainer.com/nexdbbackup/upload.php"


02-20 01:50:51.194: E/FileTransfer(1624): {"target":"http:\/\/nextrainer.com\/nexdbbackup\/upload.php","source":"file:\/\/\/data\/data\/com.suave.nexttrainer\/app_database\/file_0\/0000000001.db","code":1}
02-20 01:50:51.194: E/FileTransfer(1624): java.io.FileNotFoundException: /data/data/com.suave.nexttrainer/app_database/file_0/0000000001.db: open failed: ENOENT (No such file or directory)

Simon MacDonald said...

@Mohsin Qureshi

Are you sure that "/data/data/com.suave.nexttrainer/app_database/file_0/0000000001.db" actually exists? If you run "adb shell" then cd to "/data/data/com.suave.nexttrainer/app_database/file_0" do you see the file? You'll have to do that on the emulator if you don't have a rooted phone.

Simon MacDonald said...
This comment has been removed by the author.