From 45680a562e31364d8cf0c386a703531884281bcd Mon Sep 17 00:00:00 2001 From: "Juan G. Hurtado" Date: Wed, 16 May 2012 08:37:40 +0200 Subject: [PATCH 01/32] Add Android 4.0 workaround for links with params Android 4.0.x has a known bug [1] while accessing local files with params: file://file.html?param=2 This commit adds a workaround for this problem by removing the params part of the local URI before accessing the file. [1] http://code.google.com/p/android/issues/detail?id=17535 --- .../apache/cordova/CordovaWebViewClient.java | 88 +++++++++++++------ 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java index 6bddfc35..7abaff5a 100755 --- a/framework/src/org/apache/cordova/CordovaWebViewClient.java +++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java @@ -38,35 +38,35 @@ import android.webkit.WebViewClient; * This class is the WebViewClient that implements callbacks for our web view. */ public class CordovaWebViewClient extends WebViewClient { - + private static final String TAG = "Cordova"; DroidGap ctx; private boolean doClearHistory = false; /** * Constructor. - * + * * @param ctx */ public CordovaWebViewClient(DroidGap ctx) { this.ctx = ctx; } - + /** - * Give the host application a chance to take over the control when a new url + * Give the host application a chance to take over the control when a new url * is about to be loaded in the current WebView. - * + * * @param view The WebView that is initiating the callback. * @param url The url to be loaded. * @return true to override, false for default behavior */ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - + // First give any plugins the chance to handle the url themselves if ((this.ctx.pluginManager != null) && this.ctx.pluginManager.onOverrideUrlLoading(url)) { } - + // If dialing phone (tel:5551212) else if (url.startsWith(WebView.SCHEME_TEL)) { try { @@ -154,11 +154,11 @@ public class CordovaWebViewClient extends WebViewClient { } return true; } - + /** * On received http auth request. - * The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination - * + * The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination + * * @param view * the view * @param handler @@ -171,27 +171,27 @@ public class CordovaWebViewClient extends WebViewClient { @Override public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { - + // get the authentication token AuthenticationToken token = ctx.getAuthenticationToken(host,realm); - + if(token != null) { handler.proceed(token.getUserName(), token.getPassword()); } } - + @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { - // Clear history so history.back() doesn't do anything. + // Clear history so history.back() doesn't do anything. // So we can reinit() native side CallbackServer & PluginManager. - view.clearHistory(); + view.clearHistory(); this.doClearHistory = true; } - + /** * Notify the host application that a page has finished loading. - * + * * @param view The webview initiating the callback. * @param url The url of the page. */ @@ -200,8 +200,8 @@ public class CordovaWebViewClient extends WebViewClient { super.onPageFinished(view, url); /** - * Because of a timing issue we need to clear this history in onPageFinished as well as - * onPageStarted. However we only want to do this if the doClearHistory boolean is set to + * Because of a timing issue we need to clear this history in onPageFinished as well as + * onPageStarted. However we only want to do this if the doClearHistory boolean is set to * true. You see when you load a url with a # in it which is common in jQuery applications * onPageStared is not called. Clearing the history at that point would break jQuery apps. */ @@ -252,15 +252,15 @@ public class CordovaWebViewClient extends WebViewClient { this.ctx.endActivity(); } } - + /** - * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable). + * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable). * The errorCode parameter corresponds to one of the ERROR_* constants. * * @param view The WebView that is initiating the callback. * @param errorCode The error code corresponding to an ERROR_* value. * @param description A String describing the error. - * @param failingUrl The url that failed to load. + * @param failingUrl The url that failed to load. */ @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { @@ -275,9 +275,9 @@ public class CordovaWebViewClient extends WebViewClient { // Handle error this.ctx.onReceivedError(errorCode, description, failingUrl); } - + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { - + final String packageName = this.ctx.getPackageName(); final PackageManager pm = this.ctx.getPackageManager(); ApplicationInfo appInfo; @@ -289,7 +289,7 @@ public class CordovaWebViewClient extends WebViewClient { return; } else { // debug = false - super.onReceivedSslError(view, handler, error); + super.onReceivedSslError(view, handler, error); } } catch (NameNotFoundException e) { // When it doubt, lock it out! @@ -299,7 +299,7 @@ public class CordovaWebViewClient extends WebViewClient { @Override public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { - /* + /* * If you do a document.location.href the url does not get pushed on the stack * so we do a check here to see if the url should be pushed. */ @@ -307,4 +307,40 @@ public class CordovaWebViewClient extends WebViewClient { this.ctx.pushUrl(url); } } + + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + if(url.contains("?")){ + return generateWebResourceResponse(url); + } else { + return super.shouldInterceptRequest(view, url); + } + } + + private WebResourceResponse generateWebResourceResponse(String url) { + final String ANDROID_ASSET = "file:///android_asset/"; + if (url.startsWith(ANDROID_ASSET)) { + String niceUrl = url; + niceUrl = url.replaceFirst(ANDROID_ASSET, ""); + if(niceUrl.contains("?")){ + niceUrl = niceUrl.split("\\?")[0]; + } + + String mimetype = null; + if(niceUrl.endsWith(".html")){ + mimetype = "text/html"; + } + + try { + AssetManager assets = ctx.getAssets(); + Uri uri = Uri.parse(niceUrl); + InputStream stream = assets.open(uri.getPath(), AssetManager.ACCESS_STREAMING); + WebResourceResponse response = new WebResourceResponse(mimetype, "UTF-8", stream); + return response; + } catch (IOException e) { + Log.e("generateWebResourceResponse", e.getMessage(), e); + } + } + return null; + } } From 6de66b87cb84c4ad4e9c4bb0f1e053be70fabf59 Mon Sep 17 00:00:00 2001 From: "Juan G. Hurtado" Date: Wed, 16 May 2012 08:37:40 +0200 Subject: [PATCH 02/32] Add Android 4.0 workaround for links with params Android 4.0.x has a known bug [1] while accessing local files with params: file://file.html?param=2 This commit adds a workaround for this problem by removing the params part of the local URI before accessing the file. [1] http://code.google.com/p/android/issues/detail?id=17535 --- .../apache/cordova/CordovaWebViewClient.java | 88 +++++++++++++------ 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java index 6bddfc35..7abaff5a 100755 --- a/framework/src/org/apache/cordova/CordovaWebViewClient.java +++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java @@ -38,35 +38,35 @@ import android.webkit.WebViewClient; * This class is the WebViewClient that implements callbacks for our web view. */ public class CordovaWebViewClient extends WebViewClient { - + private static final String TAG = "Cordova"; DroidGap ctx; private boolean doClearHistory = false; /** * Constructor. - * + * * @param ctx */ public CordovaWebViewClient(DroidGap ctx) { this.ctx = ctx; } - + /** - * Give the host application a chance to take over the control when a new url + * Give the host application a chance to take over the control when a new url * is about to be loaded in the current WebView. - * + * * @param view The WebView that is initiating the callback. * @param url The url to be loaded. * @return true to override, false for default behavior */ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - + // First give any plugins the chance to handle the url themselves if ((this.ctx.pluginManager != null) && this.ctx.pluginManager.onOverrideUrlLoading(url)) { } - + // If dialing phone (tel:5551212) else if (url.startsWith(WebView.SCHEME_TEL)) { try { @@ -154,11 +154,11 @@ public class CordovaWebViewClient extends WebViewClient { } return true; } - + /** * On received http auth request. - * The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination - * + * The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination + * * @param view * the view * @param handler @@ -171,27 +171,27 @@ public class CordovaWebViewClient extends WebViewClient { @Override public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) { - + // get the authentication token AuthenticationToken token = ctx.getAuthenticationToken(host,realm); - + if(token != null) { handler.proceed(token.getUserName(), token.getPassword()); } } - + @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { - // Clear history so history.back() doesn't do anything. + // Clear history so history.back() doesn't do anything. // So we can reinit() native side CallbackServer & PluginManager. - view.clearHistory(); + view.clearHistory(); this.doClearHistory = true; } - + /** * Notify the host application that a page has finished loading. - * + * * @param view The webview initiating the callback. * @param url The url of the page. */ @@ -200,8 +200,8 @@ public class CordovaWebViewClient extends WebViewClient { super.onPageFinished(view, url); /** - * Because of a timing issue we need to clear this history in onPageFinished as well as - * onPageStarted. However we only want to do this if the doClearHistory boolean is set to + * Because of a timing issue we need to clear this history in onPageFinished as well as + * onPageStarted. However we only want to do this if the doClearHistory boolean is set to * true. You see when you load a url with a # in it which is common in jQuery applications * onPageStared is not called. Clearing the history at that point would break jQuery apps. */ @@ -252,15 +252,15 @@ public class CordovaWebViewClient extends WebViewClient { this.ctx.endActivity(); } } - + /** - * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable). + * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable). * The errorCode parameter corresponds to one of the ERROR_* constants. * * @param view The WebView that is initiating the callback. * @param errorCode The error code corresponding to an ERROR_* value. * @param description A String describing the error. - * @param failingUrl The url that failed to load. + * @param failingUrl The url that failed to load. */ @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { @@ -275,9 +275,9 @@ public class CordovaWebViewClient extends WebViewClient { // Handle error this.ctx.onReceivedError(errorCode, description, failingUrl); } - + public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { - + final String packageName = this.ctx.getPackageName(); final PackageManager pm = this.ctx.getPackageManager(); ApplicationInfo appInfo; @@ -289,7 +289,7 @@ public class CordovaWebViewClient extends WebViewClient { return; } else { // debug = false - super.onReceivedSslError(view, handler, error); + super.onReceivedSslError(view, handler, error); } } catch (NameNotFoundException e) { // When it doubt, lock it out! @@ -299,7 +299,7 @@ public class CordovaWebViewClient extends WebViewClient { @Override public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { - /* + /* * If you do a document.location.href the url does not get pushed on the stack * so we do a check here to see if the url should be pushed. */ @@ -307,4 +307,40 @@ public class CordovaWebViewClient extends WebViewClient { this.ctx.pushUrl(url); } } + + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + if(url.contains("?")){ + return generateWebResourceResponse(url); + } else { + return super.shouldInterceptRequest(view, url); + } + } + + private WebResourceResponse generateWebResourceResponse(String url) { + final String ANDROID_ASSET = "file:///android_asset/"; + if (url.startsWith(ANDROID_ASSET)) { + String niceUrl = url; + niceUrl = url.replaceFirst(ANDROID_ASSET, ""); + if(niceUrl.contains("?")){ + niceUrl = niceUrl.split("\\?")[0]; + } + + String mimetype = null; + if(niceUrl.endsWith(".html")){ + mimetype = "text/html"; + } + + try { + AssetManager assets = ctx.getAssets(); + Uri uri = Uri.parse(niceUrl); + InputStream stream = assets.open(uri.getPath(), AssetManager.ACCESS_STREAMING); + WebResourceResponse response = new WebResourceResponse(mimetype, "UTF-8", stream); + return response; + } catch (IOException e) { + Log.e("generateWebResourceResponse", e.getMessage(), e); + } + } + return null; + } } From 8ff48b371e6090e0af942efdd66f32be6911d4bf Mon Sep 17 00:00:00 2001 From: "Juan G. Hurtado" Date: Fri, 18 May 2012 08:45:39 +0200 Subject: [PATCH 03/32] Fix imports for changes in 45680a5 Commit 45680a5 had errors importing packages. This commit fix them. --- framework/src/org/apache/cordova/CordovaWebViewClient.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java index 7abaff5a..63ea3012 100755 --- a/framework/src/org/apache/cordova/CordovaWebViewClient.java +++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java @@ -18,12 +18,17 @@ */ package org.apache.cordova; +import java.io.IOException; +import java.io.InputStream; + import org.apache.cordova.api.LOG; +import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.AssetManager; import android.graphics.Bitmap; import android.net.Uri; import android.net.http.SslError; @@ -31,6 +36,7 @@ import android.util.Log; import android.view.View; import android.webkit.HttpAuthHandler; import android.webkit.SslErrorHandler; +import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; From c86b618aaaa2575eb47565127d7ebb7153daee82 Mon Sep 17 00:00:00 2001 From: Anis Kadri Date: Fri, 15 Jun 2012 18:35:34 -0700 Subject: [PATCH 04/32] adding bash helper scripts --- bin/templates/cordova/BOOM | 7 +++ bin/templates/cordova/appinfo.jar | Bin 0 -> 1527 bytes bin/templates/cordova/clean | 7 +++ bin/templates/cordova/cordova | 91 ++++++++++++++++++++++++++++++ bin/templates/cordova/debug | 7 +++ bin/templates/cordova/emulate | 7 +++ bin/templates/cordova/log | 7 +++ 7 files changed, 126 insertions(+) create mode 100644 bin/templates/cordova/BOOM create mode 100644 bin/templates/cordova/appinfo.jar create mode 100644 bin/templates/cordova/clean create mode 100644 bin/templates/cordova/cordova create mode 100644 bin/templates/cordova/debug create mode 100644 bin/templates/cordova/emulate create mode 100644 bin/templates/cordova/log diff --git a/bin/templates/cordova/BOOM b/bin/templates/cordova/BOOM new file mode 100644 index 00000000..37c623c4 --- /dev/null +++ b/bin/templates/cordova/BOOM @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd ) + +bash $CORDOVA_PATH/cordova BOOM diff --git a/bin/templates/cordova/appinfo.jar b/bin/templates/cordova/appinfo.jar new file mode 100644 index 0000000000000000000000000000000000000000..4116f48c30d083581fdcc7c08b91c53533cdd08a GIT binary patch literal 1527 zcmWIWW@Zs#-~hsFW#=6jkN_tG3xls~h@-BjpPT-_Qw$8u3<2Kk93T};P-Ou)HH!dM zz%~0i`gyv!28ZbRx_$ONbK1vSSMMUPx31Q?Gv_x48C)@b@U%$J%U8$K_hRWP7S0(j zC67o;Yh_r7i9A`NRq;&qb>^p{pK58(URpg@5fhKrY)~YlzEc= zN{J)ADyOvGPJ5cB+L^ENKkTS!h{zf)m3I++qIX0)o*kFtIP&byF3kygk$sVQw?i*S zo38Tp`W4;we73RQ-Qu;sCOwRhUM9~Gb7Hz#@AI~MCUe^2IBia6`gq$v*J=!`-j=e( zshIV?W`)BN7S9@KegBX@n8UPR)HnPIClul5`$n(LZ=Sl3IK_qw6e za;bgCoq4k(!asN%=C4@uptDW>V~9hhVDm)-Q;8K^D!ow&w%eO>c}=f~2JCBWbD00y z^o#iRtg5?Pzy4g7Ih)V;a*yA-;J!rT#`z`@HZ-n;()`biEpHi8-@+0QRs{AXdZ^zpyEqNdy#2OqxkHBbF~{H~15g>JX6 zGaDAJdfUL^wp+6?vXawm3hO&BWK6F+<=E=;sx&c4d*0E&u?Gfop1T5==u|$ zCDF2$?sZpxc&z({lz#Eg zZl@F3onK<#=}qSTRPj*sh_@cgJ!RjPLvkyME?BKna$D)Na(}x=W{vp8PbrDw8<%$0 z9${UUfe zRlm4<^rtM(H1+a}+neJ~>c3IYto)`Lczi?O@fsHu^Pe3ad7lM4TN=a*=7lUa@x8Hk zN$rWC?3OQl@smqqmVOnO_dsb?%xsBgN2@qz$J}1i)U5p>V*2-&sS+FOSIPuV2sdC` zxS$~Zpv8Y-L#z2N9~V^kOWHWug;o6JzT)&HEtCE5{^WwUqHRXv-wpP3d(S+rvU^96 z)cwPukq`LpF&^iEIL>C_{D_s3=2#t3W2! Vf-S(Cl?|kf83+#mX+>5L4*)4LUN8Uv literal 0 HcmV?d00001 diff --git a/bin/templates/cordova/clean b/bin/templates/cordova/clean new file mode 100644 index 00000000..daa84421 --- /dev/null +++ b/bin/templates/cordova/clean @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd ) + +bash $CORDOVA_PATH/cordova clean diff --git a/bin/templates/cordova/cordova b/bin/templates/cordova/cordova new file mode 100644 index 00000000..0f3e452c --- /dev/null +++ b/bin/templates/cordova/cordova @@ -0,0 +1,91 @@ +#!/bin/bash + +set -e + +PROJECT_PATH=$( cd "$( dirname "$0" )/.." && pwd ) + +function check_devices { + local devices=`adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}'` + if [ -z "$devices" ] ; then + echo "1" + else + echo "0" + fi +} + +function emulate { + declare -a avd_list=($(android list avd | grep "Name:" | cut -f 2 -d ":" | xargs)) + # we need to start adb-server + adb start-server 1>/dev/null + + # Do not launch an emulator if there is already one running or if a device is attached + if [ $(check_devices) == 0 ] ; then + echo "Device attached or emulator already running" + return + fi + + local avd_id="1000" #FIXME: hopefully user does not have 1000 AVDs + # User has no AVDs + if [ ${#avd_list[@]} == 0 ] + then + echo "You don't have any Android Virtual Devices. Please create at least one AVD." + echo "android" + fi + # User has only one AVD + if [ ${#avd_list[@]} == 1 ] + then + emulator -cpu-delay 0 -no-boot-anim -cache /tmp/cache -avd ${avd_list[0]} 1> /dev/null 2>&1 & + # User has more than 1 AVD + elif [ ${#avd_list[@]} -gt 1 ] + then + while [ -z ${avd_list[$avd_id]} ] + do + echo "Choose from one of the following Android Virtual Devices [0 to $((${#avd_list[@]}-1))]:" + for(( i = 0 ; i < ${#avd_list[@]} ; i++ )) + do + echo "$i) ${avd_list[$i]}" + done + echo -n "> " + read avd_id + done + emulator -cpu-delay 0 -no-boot-anim -cache /tmp/cache -avd ${avd_list[$avd_id]} 1> /dev/null 2>&1 & + fi + +} + +function clean { + ant clean +} +# has to be used independently and not in conjuction with other commands +function log { + adb logcat +} + +function debug_install { + ant debug install +} + +function debug { + ant debug +} + +function launch { + local launch_str=$(java -jar $PROJECT_PATH/cordova/appinfo.jar $PROJECT_PATH/AndroidManifest.xml) + adb shell am start -n $launch_str +} + +function BOOM { + clean + if [ $(check_devices) == 0 ] ; then + debug_install && launch + return + else + debug + echo "##################################################################" + echo "# Plug in your device or launch an emulator with cordova/emulate #" + echo "##################################################################" + fi +} + +# TODO parse arguments +(cd $PROJECT_PATH && $1) diff --git a/bin/templates/cordova/debug b/bin/templates/cordova/debug new file mode 100644 index 00000000..5d63a39f --- /dev/null +++ b/bin/templates/cordova/debug @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd ) + +bash $CORDOVA_PATH/cordova debug diff --git a/bin/templates/cordova/emulate b/bin/templates/cordova/emulate new file mode 100644 index 00000000..6c4fab2b --- /dev/null +++ b/bin/templates/cordova/emulate @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd ) + +bash $CORDOVA_PATH/cordova emulate diff --git a/bin/templates/cordova/log b/bin/templates/cordova/log new file mode 100644 index 00000000..ab3622e5 --- /dev/null +++ b/bin/templates/cordova/log @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +PROJECT_PATH=$( cd "$( dirname "$0" )/.." && pwd ) + +bash $PROJECT_PATH/cordova/cordova log From 0aec2be4dd702d4318b789d1eed5d6056cd12622 Mon Sep 17 00:00:00 2001 From: Anis Kadri Date: Fri, 15 Jun 2012 18:36:06 -0700 Subject: [PATCH 05/32] updating bash create script and node test --- bin/create | 10 ++++++++++ bin/tests/test_create_unix.js | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/bin/create b/bin/create index a6b5c8c6..d6885493 100755 --- a/bin/create +++ b/bin/create @@ -113,3 +113,13 @@ sed -i '' -e "s/__ID__/${PACKAGE}/g" $ACTIVITY_PATH cp $BUILD_PATH/bin/templates/project/AndroidManifest.xml $MANIFEST_PATH sed -i '' -e "s/__ACTIVITY__/${ACTIVITY}/g" $MANIFEST_PATH sed -i '' -e "s/__PACKAGE__/${PACKAGE}/g" $MANIFEST_PATH + +# creating cordova folder and copying emulate/debug/log/launch scripts +mkdir $PROJECT_PATH/cordova +cp $BUILD_PATH/bin/templates/cordova/appinfo.jar $PROJECT_PATH/cordova/appinfo.jar +cp $BUILD_PATH/bin/templates/cordova/cordova $PROJECT_PATH/cordova/cordova +cp $BUILD_PATH/bin/templates/cordova/debug $PROJECT_PATH/cordova/debug +cp $BUILD_PATH/bin/templates/cordova/clean $PROJECT_PATH/cordova/clean +cp $BUILD_PATH/bin/templates/cordova/log $PROJECT_PATH/cordova/log +cp $BUILD_PATH/bin/templates/cordova/emulate $PROJECT_PATH/cordova/emulate +cp $BUILD_PATH/bin/templates/cordova/BOOM $PROJECT_PATH/cordova/BOOM diff --git a/bin/tests/test_create_unix.js b/bin/tests/test_create_unix.js index 75e0697e..a9061767 100644 --- a/bin/tests/test_create_unix.js +++ b/bin/tests/test_create_unix.js @@ -80,6 +80,41 @@ create_project.on('exit', function(code) { path.exists(util.format('%s/assets/www/cordova-%s.js', project_path, version), function(exists) { assert(exists, 'cordova.js did not get added'); }); + + // make sure cordova master script was added + path.exists(util.format('%s/cordova/cordova', project_path), function(exists) { + assert(exists, 'cordova script did not get added'); + }); + + // make sure debug script was added + path.exists(util.format('%s/cordova/debug', project_path), function(exists) { + assert(exists, 'debug script did not get added'); + }); + + // make sure BOOM script was added + path.exists(util.format('%s/cordova/BOOM', project_path), function(exists) { + assert(exists, 'BOOM script did not get added'); + }); + + // make sure log script was added + path.exists(util.format('%s/cordova/log', project_path), function(exists) { + assert(exists, 'log script did not get added'); + }); + + // make sure clean script was added + path.exists(util.format('%s/cordova/clean', project_path), function(exists) { + assert(exists, 'clean script did not get added'); + }); + + // make sure emulate script was added + path.exists(util.format('%s/cordova/emulate', project_path), function(exists) { + assert(exists, 'emulate script did not get added'); + }); + + // make sure appinfo.jar script was added + path.exists(util.format('%s/cordova/appinfo.jar', project_path), function(exists) { + assert(exists, 'appinfo.jar script did not get added'); + }); // check that project compiles && creates a cordovaExample-debug.apk var compile_project = spawn('ant', ['debug'], {cwd: project_path}); From e6d801a5946c472b4acf73f0dff2ead41907f448 Mon Sep 17 00:00:00 2001 From: Anis Kadri Date: Fri, 15 Jun 2012 18:38:46 -0700 Subject: [PATCH 06/32] adding appinfo --- .../ApplicationInfo/ApplicationInfo.class | Bin 0 -> 1941 bytes .../ApplicationInfo/ApplicationInfo.java | 44 ++++++++++++++++++ .../cordova/ApplicationInfo/manifest.txt | 1 + 3 files changed, 45 insertions(+) create mode 100644 bin/templates/cordova/ApplicationInfo/ApplicationInfo.class create mode 100644 bin/templates/cordova/ApplicationInfo/ApplicationInfo.java create mode 100644 bin/templates/cordova/ApplicationInfo/manifest.txt diff --git a/bin/templates/cordova/ApplicationInfo/ApplicationInfo.class b/bin/templates/cordova/ApplicationInfo/ApplicationInfo.class new file mode 100644 index 0000000000000000000000000000000000000000..6b854f7d209a1bea4014ab9b59749ed15d2cd7dc GIT binary patch literal 1941 zcma)7TUQ%Z6#h0+2_x{e|-($CR!?zxS?`&OOg*&e1wk^ z_ynKEaXWzoX5yHY-*X9khC2%G#_@R{=CKgRqJn!WmaweiKE6<}q9TPa6?~;)Q1XI` zA<0)&4C6)|MU{4I@?$-YuOzVU*)pe}us$pB(rsoS>$QE{t=Z0Q4?3!NkUCXY`NY)oK%@jod<@etEL&hG`>40MT5?)$#ay<6(DTh^-KrSA<=89swv(3;HC)FSooe_F z4>fFJOTi-z-{Y}@CmMdhQvsz(3`Wh=V4y4zH!8mM-17G{R8Unw`8H|-1CCqMU)-wb zRi~jZ)y;-!Gc(QTgRg;x~!wS=-Asp$uE$vp!rp!)*gE4_&2}s&_#;#tPfB0sfSc90B zqpz%WNz-qUbk1O*W!0;uOSmlt%U3N|Llb2UKY_xup3m#2jxx`98a((KG7@?6RMAhQ z+X*6&m2pp|ch9M`WC4#5EVJg0yC;ya%@-@S=Noo~-87Y*2oC-%wzC2$8lQ43kU5JF z8ejikkOI-*bOds}+PTo(AIC80c(9k8U~8s-to5dw(gfSBezZX^8rA20-kfsFXJy8F zA~=1%GCJ*!ym$+H8%C|jK0QkYMc(j&<@u*GIF|EvTE5wkcYEa|XsJP~uD&nrd4X!! zX~|*Gxyc8}z`CqU;K&31a@#7ybx{4U?}ipxlK&XQ!X z3dYWcYse-`utMvu(==V54Hz?;P1CLlO!ols--t*3OZ0KyIqvttqn0}Xjf3bKhq?TP z!FIzK>AU>8OfJZyxmOS`xe$1dG!_W^pvsHJHC07~QiXfo0YZhzHp0c}TpN+qsY65s zW+EezRO}E+2s6>CRQwQqA%qX1hVTaxDXp^;`vvDx@5Fvbax**aYL+ literal 0 HcmV?d00001 diff --git a/bin/templates/cordova/ApplicationInfo/ApplicationInfo.java b/bin/templates/cordova/ApplicationInfo/ApplicationInfo.java new file mode 100644 index 00000000..9a663217 --- /dev/null +++ b/bin/templates/cordova/ApplicationInfo/ApplicationInfo.java @@ -0,0 +1,44 @@ +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import org.xml.sax.SAXException; +import java.io.IOException; + +public class ApplicationInfo { + private static void parseAndroidManifest(String path) { + // System.out.println(path); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + Document dom; + try { + DocumentBuilder db = dbf.newDocumentBuilder(); + dom = db.parse(path); + + // getting package information + Element manifest = dom.getDocumentElement(); + String pakkage = manifest.getAttribute("package"); + + // getting activity name + String activity = ((Element)dom.getElementsByTagName("activity").item(0)).getAttribute("android:name"); + System.out.println(String.format("%s/%s.%s", pakkage, pakkage, activity)); + } catch(ParserConfigurationException pce) { + pce.printStackTrace(); + } catch(SAXException se) { + se.printStackTrace(); + } catch(IOException ioe) { + ioe.printStackTrace(); + } + + } + + public static void main(String[] args) { + String path; + if(args.length > 0) { + path = args[0]; + } else { + path = System.getProperty("user.dir") + "/../AndroidManifest.xml"; + } + parseAndroidManifest(path); + } +} diff --git a/bin/templates/cordova/ApplicationInfo/manifest.txt b/bin/templates/cordova/ApplicationInfo/manifest.txt new file mode 100644 index 00000000..7d77999c --- /dev/null +++ b/bin/templates/cordova/ApplicationInfo/manifest.txt @@ -0,0 +1 @@ +Main-Class: ApplicationInfo From adf4166caaa7c48e8262e3aaa44539fbdfa9c971 Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Mon, 18 Jun 2012 16:00:42 -0700 Subject: [PATCH 07/32] Incrementing version to 1.9.0rc1 and doing some variable cleanup --- bin/templates/project/assets/www/index.html | 2 +- framework/assets/www/index.html | 2 +- .../src/org/apache/cordova/AccelListener.java | 8 ++-- framework/src/org/apache/cordova/App.java | 10 ++--- .../src/org/apache/cordova/AudioHandler.java | 4 +- .../src/org/apache/cordova/AudioPlayer.java | 6 +-- .../org/apache/cordova/BatteryListener.java | 4 +- .../org/apache/cordova/CameraLauncher.java | 38 ++++++++-------- framework/src/org/apache/cordova/Capture.java | 22 +++++----- .../org/apache/cordova/CompassListener.java | 8 ++-- .../org/apache/cordova/ContactManager.java | 2 +- .../apache/cordova/CordovaChromeClient.java | 18 ++++---- .../org/apache/cordova/CordovaWebView.java | 44 +++++++++---------- .../apache/cordova/CordovaWebViewClient.java | 30 ++++++------- framework/src/org/apache/cordova/Device.java | 16 +++---- .../src/org/apache/cordova/FileTransfer.java | 2 +- .../src/org/apache/cordova/FileUtils.java | 28 ++++++------ .../src/org/apache/cordova/GeoBroker.java | 2 +- .../org/apache/cordova/NetworkManager.java | 12 ++--- .../src/org/apache/cordova/Notification.java | 28 ++++++------ framework/src/org/apache/cordova/Storage.java | 2 +- .../src/org/apache/cordova/TempListener.java | 8 ++-- .../apache/cordova/api/CordovaInterface.java | 2 + .../src/org/apache/cordova/api/Plugin.java | 4 +- 24 files changed, 153 insertions(+), 149 deletions(-) diff --git a/bin/templates/project/assets/www/index.html b/bin/templates/project/assets/www/index.html index 8e46f620..22920c81 100644 --- a/bin/templates/project/assets/www/index.html +++ b/bin/templates/project/assets/www/index.html @@ -23,7 +23,7 @@ PhoneGap - + diff --git a/framework/assets/www/index.html b/framework/assets/www/index.html index 3791f9fd..b02bf783 100644 --- a/framework/assets/www/index.html +++ b/framework/assets/www/index.html @@ -19,7 +19,7 @@ - + diff --git a/framework/src/org/apache/cordova/AccelListener.java b/framework/src/org/apache/cordova/AccelListener.java index a7d448e0..fdba7be2 100755 --- a/framework/src/org/apache/cordova/AccelListener.java +++ b/framework/src/org/apache/cordova/AccelListener.java @@ -68,12 +68,12 @@ public class AccelListener extends Plugin implements SensorEventListener { * Sets the context of the Command. This can then be used to do things like * get file paths associated with the Activity. * - * @param ctx The context of the main Activity. + * @param cordova The context of the main Activity. */ - public void setContext(CordovaInterface ctx) { - super.setContext(ctx); - this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE); + public void setContext(CordovaInterface cordova) { + super.setContext(cordova); + this.sensorManager = (SensorManager) cordova.getActivity().getSystemService(Context.SENSOR_SERVICE); } /** diff --git a/framework/src/org/apache/cordova/App.java b/framework/src/org/apache/cordova/App.java index ed9ec779..7b3dc063 100755 --- a/framework/src/org/apache/cordova/App.java +++ b/framework/src/org/apache/cordova/App.java @@ -49,7 +49,7 @@ public class App extends Plugin { this.clearCache(); } else if (action.equals("show")) { // TODO @bc - Not in master branch. When should this be called? - ctx.getActivity().runOnUiThread(new Runnable() { + cordova.getActivity().runOnUiThread(new Runnable() { public void run() { webView.postMessage("spinner", "stop"); } @@ -162,7 +162,7 @@ public class App extends Plugin { */ @Deprecated public void cancelLoadUrl() { - this.ctx.cancelLoadUrl(); + this.cordova.cancelLoadUrl(); } /** @@ -188,7 +188,7 @@ public class App extends Plugin { */ public void overrideBackbutton(boolean override) { LOG.i("App", "WARNING: Back Button Default Behaviour will be overridden. The backbutton event will be fired!"); - this.ctx.bindBackButton(override); + this.cordova.bindBackButton(override); } /** @@ -200,7 +200,7 @@ public class App extends Plugin { */ public void overrideButton(String button, boolean override) { LOG.i("DroidGap", "WARNING: Volume Button Default Behaviour will be overridden. The volume event will be fired!"); - ((DroidGap)this.ctx).bindButton(button, override); + this.cordova.bindButton(button, override); } /** * Return whether the Android back button is overridden by the user. @@ -208,7 +208,7 @@ public class App extends Plugin { * @return boolean */ public boolean isBackbuttonOverridden() { - return this.ctx.isBackButtonBound(); + return this.cordova.isBackButtonBound(); } /** diff --git a/framework/src/org/apache/cordova/AudioHandler.java b/framework/src/org/apache/cordova/AudioHandler.java index a866d4f4..492043bf 100755 --- a/framework/src/org/apache/cordova/AudioHandler.java +++ b/framework/src/org/apache/cordova/AudioHandler.java @@ -305,7 +305,7 @@ public class AudioHandler extends Plugin { */ @SuppressWarnings("deprecation") public void setAudioOutputDevice(int output) { - AudioManager audiMgr = (AudioManager) this.ctx.getActivity().getSystemService(Context.AUDIO_SERVICE); + AudioManager audiMgr = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE); if (output == 2) { audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL); } @@ -324,7 +324,7 @@ public class AudioHandler extends Plugin { */ @SuppressWarnings("deprecation") public int getAudioOutputDevice() { - AudioManager audiMgr = (AudioManager) this.ctx.getActivity().getSystemService(Context.AUDIO_SERVICE); + AudioManager audiMgr = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE); if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_EARPIECE) { return 1; } diff --git a/framework/src/org/apache/cordova/AudioPlayer.java b/framework/src/org/apache/cordova/AudioPlayer.java index e975afaf..5df00f9c 100755 --- a/framework/src/org/apache/cordova/AudioPlayer.java +++ b/framework/src/org/apache/cordova/AudioPlayer.java @@ -88,7 +88,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3"; } else { - this.tempFile = "/data/data/" + handler.ctx.getActivity().getPackageName() + "/cache/tmprecording.mp3"; + this.tempFile = "/data/data/" + handler.cordova.getActivity().getPackageName() + "/cache/tmprecording.mp3"; } } @@ -160,7 +160,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On f.renameTo(new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + file)); } else { - f.renameTo(new File("/data/data/" + handler.ctx.getActivity().getPackageName() + "/cache/" + file)); + f.renameTo(new File("/data/data/" + handler.cordova.getActivity().getPackageName() + "/cache/" + file)); } } @@ -220,7 +220,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On else { if (file.startsWith("/android_asset/")) { String f = file.substring(15); - android.content.res.AssetFileDescriptor fd = this.handler.ctx.getActivity().getAssets().openFd(f); + android.content.res.AssetFileDescriptor fd = this.handler.cordova.getActivity().getAssets().openFd(f); this.mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength()); } else { diff --git a/framework/src/org/apache/cordova/BatteryListener.java b/framework/src/org/apache/cordova/BatteryListener.java index bca96332..eb0ea98a 100755 --- a/framework/src/org/apache/cordova/BatteryListener.java +++ b/framework/src/org/apache/cordova/BatteryListener.java @@ -73,7 +73,7 @@ public class BatteryListener extends Plugin { updateBatteryInfo(intent); } }; - ctx.getActivity().registerReceiver(this.receiver, intentFilter); + cordova.getActivity().registerReceiver(this.receiver, intentFilter); } // Don't return any result now, since status results will be sent when events come in from broadcast receiver @@ -105,7 +105,7 @@ public class BatteryListener extends Plugin { private void removeBatteryListener() { if (this.receiver != null) { try { - this.ctx.getActivity().unregisterReceiver(this.receiver); + this.cordova.getActivity().unregisterReceiver(this.receiver); this.receiver = null; } catch (Exception e) { Log.e(LOG_TAG, "Error unregistering battery receiver: " + e.getMessage(), e); diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 436c232f..1afaf8db 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -176,8 +176,8 @@ public class CameraLauncher extends Plugin { intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo)); this.imageUri = Uri.fromFile(photo); - if (this.ctx != null) { - this.ctx.startActivityForResult((Plugin) this, intent, (CAMERA + 1) * 16 + returnType + 1); + if (this.cordova != null) { + this.cordova.startActivityForResult((Plugin) this, intent, (CAMERA + 1) * 16 + returnType + 1); } // else // LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity"); @@ -192,9 +192,9 @@ public class CameraLauncher extends Plugin { private File createCaptureFile(int encodingType) { File photo = null; if (encodingType == JPEG) { - photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Pic.jpg"); + photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), "Pic.jpg"); } else if (encodingType == PNG) { - photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Pic.png"); + photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), "Pic.png"); } else { throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType); } @@ -228,8 +228,8 @@ public class CameraLauncher extends Plugin { intent.setAction(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); - if (this.ctx != null) { - this.ctx.startActivityForResult((Plugin) this, Intent.createChooser(intent, + if (this.cordova != null) { + this.cordova.startActivityForResult((Plugin) this, Intent.createChooser(intent, new String(title)), (srcType + 1) * 16 + returnType + 1); } } @@ -299,7 +299,7 @@ public class CameraLauncher extends Plugin { ExifHelper exif = new ExifHelper(); try { if (this.encodingType == JPEG) { - exif.createInFile(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/Pic.jpg"); + exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/Pic.jpg"); exif.readExifData(); } } catch (IOException e) { @@ -313,10 +313,10 @@ public class CameraLauncher extends Plugin { // Read in bitmap of captured image Bitmap bitmap; try { - bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getActivity().getContentResolver(), imageUri); + bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.cordova.getActivity().getContentResolver(), imageUri); } catch (FileNotFoundException e) { Uri uri = intent.getData(); - android.content.ContentResolver resolver = this.ctx.getActivity().getContentResolver(); + android.content.ContentResolver resolver = this.cordova.getActivity().getContentResolver(); bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri)); } @@ -336,11 +336,11 @@ public class CameraLauncher extends Plugin { values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); Uri uri = null; try { - uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException e) { LOG.d(LOG_TAG, "Can't write to external media storage."); try { - uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); + uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException ex) { LOG.d(LOG_TAG, "Can't write to internal media storage."); this.failPicture("Error capturing image - no media storage found."); @@ -349,13 +349,13 @@ public class CameraLauncher extends Plugin { } // Add compressed version of captured image to returned media store Uri - OutputStream os = this.ctx.getActivity().getContentResolver().openOutputStream(uri); + OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); os.close(); // Restore exif data to file if (this.encodingType == JPEG) { - exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx)); + exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.cordova)); exif.writeExifData(); } @@ -388,7 +388,7 @@ public class CameraLauncher extends Plugin { else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) { if (resultCode == Activity.RESULT_OK) { Uri uri = intent.getData(); - android.content.ContentResolver resolver = this.ctx.getActivity().getContentResolver(); + android.content.ContentResolver resolver = this.cordova.getActivity().getContentResolver(); // If you ask for video or all media type you will automatically get back a file URI // and there will be no attempt to resize any returned data @@ -401,7 +401,7 @@ public class CameraLauncher extends Plugin { try { Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri)); String[] cols = { MediaStore.Images.Media.ORIENTATION }; - Cursor cursor = this.ctx.getActivity().getContentResolver().query(intent.getData(), + Cursor cursor = this.cordova.getActivity().getContentResolver().query(intent.getData(), cols, null, null, null); if (cursor != null) { @@ -433,14 +433,14 @@ public class CameraLauncher extends Plugin { Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri)); bitmap = scaleBitmap(bitmap); - String fileName = DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/resize.jpg"; + String fileName = DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/resize.jpg"; OutputStream os = new FileOutputStream(fileName); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); os.close(); // Restore exif data to file if (this.encodingType == JPEG) { - exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx)); + exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.cordova)); exif.writeExifData(); } @@ -477,7 +477,7 @@ public class CameraLauncher extends Plugin { * @return a cursor */ private Cursor queryImgDB() { - return this.ctx.getActivity().getContentResolver().query( + return this.cordova.getActivity().getContentResolver().query( android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] { MediaStore.Images.Media._ID }, null, @@ -506,7 +506,7 @@ public class CameraLauncher extends Plugin { cursor.moveToLast(); int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1; Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id); - this.ctx.getActivity().getContentResolver().delete(uri, null, null); + this.cordova.getActivity().getContentResolver().delete(uri, null, null); } } diff --git a/framework/src/org/apache/cordova/Capture.java b/framework/src/org/apache/cordova/Capture.java index 6e87f1e7..a2dfafdc 100644 --- a/framework/src/org/apache/cordova/Capture.java +++ b/framework/src/org/apache/cordova/Capture.java @@ -195,7 +195,7 @@ public class Capture extends Plugin { private void captureAudio() { Intent intent = new Intent(android.provider.MediaStore.Audio.Media.RECORD_SOUND_ACTION); - this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_AUDIO); + this.cordova.startActivityForResult((Plugin) this, intent, CAPTURE_AUDIO); } /** @@ -205,11 +205,11 @@ public class Capture extends Plugin { Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); // Specify file so that large image is captured and returned - File photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Capture.jpg"); + File photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), "Capture.jpg"); intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo)); this.imageUri = Uri.fromFile(photo); - this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_IMAGE); + this.cordova.startActivityForResult((Plugin) this, intent, CAPTURE_IMAGE); } /** @@ -220,7 +220,7 @@ public class Capture extends Plugin { // Introduced in API 8 //intent.putExtra(android.provider.MediaStore.EXTRA_DURATION_LIMIT, duration); - this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_VIDEO); + this.cordova.startActivityForResult((Plugin) this, intent, CAPTURE_VIDEO); } /** @@ -258,11 +258,11 @@ public class Capture extends Plugin { try { // Create an ExifHelper to save the exif data that is lost during compression ExifHelper exif = new ExifHelper(); - exif.createInFile(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/Capture.jpg"); + exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/Capture.jpg"); exif.readExifData(); // Read in bitmap of captured image - Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getActivity().getContentResolver(), imageUri); + Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.cordova.getActivity().getContentResolver(), imageUri); // Create entry in media store for image // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) @@ -270,11 +270,11 @@ public class Capture extends Plugin { values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, IMAGE_JPEG); Uri uri = null; try { - uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException e) { LOG.d(LOG_TAG, "Can't write to external media storage."); try { - uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); + uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException ex) { LOG.d(LOG_TAG, "Can't write to internal media storage."); this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image - no media storage found.")); @@ -283,7 +283,7 @@ public class Capture extends Plugin { } // Add compressed version of captured image to returned media store Uri - OutputStream os = this.ctx.getActivity().getContentResolver().openOutputStream(uri); + OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os); os.close(); @@ -292,7 +292,7 @@ public class Capture extends Plugin { System.gc(); // Restore exif data to file - exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx)); + exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.cordova)); exif.writeExifData(); // Add image to results @@ -356,7 +356,7 @@ public class Capture extends Plugin { * @throws IOException */ private JSONObject createMediaFile(Uri data) { - File fp = new File(FileUtils.getRealPathFromURI(data, this.ctx)); + File fp = new File(FileUtils.getRealPathFromURI(data, this.cordova)); JSONObject obj = new JSONObject(); try { diff --git a/framework/src/org/apache/cordova/CompassListener.java b/framework/src/org/apache/cordova/CompassListener.java index d6e54a7e..83fcdd0a 100755 --- a/framework/src/org/apache/cordova/CompassListener.java +++ b/framework/src/org/apache/cordova/CompassListener.java @@ -67,11 +67,11 @@ public class CompassListener extends Plugin implements SensorEventListener { * Sets the context of the Command. This can then be used to do things like * get file paths associated with the Activity. * - * @param ctx The context of the main Activity. + * @param cordova The context of the main Activity. */ - public void setContext(CordovaInterface ctx) { - super.setContext(ctx); - this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE); + public void setContext(CordovaInterface cordova) { + super.setContext(cordova); + this.sensorManager = (SensorManager) cordova.getActivity().getSystemService(Context.SENSOR_SERVICE); } /** diff --git a/framework/src/org/apache/cordova/ContactManager.java b/framework/src/org/apache/cordova/ContactManager.java index b07fba0a..31b5452f 100755 --- a/framework/src/org/apache/cordova/ContactManager.java +++ b/framework/src/org/apache/cordova/ContactManager.java @@ -69,7 +69,7 @@ public class ContactManager extends Plugin { * older phones. */ if (this.contactAccessor == null) { - this.contactAccessor = new ContactAccessorSdk5(this.webView, this.ctx); + this.contactAccessor = new ContactAccessorSdk5(this.webView, this.cordova); } try { diff --git a/framework/src/org/apache/cordova/CordovaChromeClient.java b/framework/src/org/apache/cordova/CordovaChromeClient.java index a23aac4e..86b575b8 100755 --- a/framework/src/org/apache/cordova/CordovaChromeClient.java +++ b/framework/src/org/apache/cordova/CordovaChromeClient.java @@ -45,16 +45,16 @@ public class CordovaChromeClient extends WebChromeClient { private String TAG = "CordovaLog"; private long MAX_QUOTA = 100 * 1024 * 1024; - private CordovaInterface ctx; + private CordovaInterface cordova; private CordovaWebView appView; /** * Constructor. * - * @param ctx + * @param cordova */ - public CordovaChromeClient(CordovaInterface ctx) { - this.ctx = ctx; + public CordovaChromeClient(CordovaInterface cordova) { + this.cordova = cordova; } /** @@ -64,7 +64,7 @@ public class CordovaChromeClient extends WebChromeClient { * @param app */ public CordovaChromeClient(CordovaInterface ctx, CordovaWebView app) { - this.ctx = ctx; + this.cordova = ctx; this.appView = app; } @@ -87,7 +87,7 @@ public class CordovaChromeClient extends WebChromeClient { */ @Override public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { - AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx.getActivity()); + AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity()); dlg.setMessage(message); dlg.setTitle("Alert"); //Don't let alerts break the back button @@ -131,7 +131,7 @@ public class CordovaChromeClient extends WebChromeClient { */ @Override public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) { - AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx.getActivity()); + AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity()); dlg.setMessage(message); dlg.setTitle("Confirm"); dlg.setCancelable(true); @@ -243,9 +243,9 @@ public class CordovaChromeClient extends WebChromeClient { // Show dialog else { final JsPromptResult res = result; - AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx.getActivity()); + AlertDialog.Builder dlg = new AlertDialog.Builder(this.cordova.getActivity()); dlg.setMessage(message); - final EditText input = new EditText(this.ctx.getActivity()); + final EditText input = new EditText(this.cordova.getActivity()); if (defaultValue != null) { input.setText(defaultValue); } diff --git a/framework/src/org/apache/cordova/CordovaWebView.java b/framework/src/org/apache/cordova/CordovaWebView.java index 308d222f..3337be23 100755 --- a/framework/src/org/apache/cordova/CordovaWebView.java +++ b/framework/src/org/apache/cordova/CordovaWebView.java @@ -55,7 +55,7 @@ public class CordovaWebView extends WebView { public CallbackServer callbackServer; /** Actvities and other important classes **/ - private CordovaInterface mCtx; + private CordovaInterface cordova; CordovaWebViewClient viewClient; @SuppressWarnings("unused") private CordovaChromeClient chromeClient; @@ -79,7 +79,7 @@ public class CordovaWebView extends WebView { super(context); if (CordovaInterface.class.isInstance(context)) { - this.mCtx = (CordovaInterface) context; + this.cordova = (CordovaInterface) context; } else { @@ -99,14 +99,14 @@ public class CordovaWebView extends WebView { super(context, attrs); if (CordovaInterface.class.isInstance(context)) { - this.mCtx = (CordovaInterface) context; + this.cordova = (CordovaInterface) context; } else { Log.d(TAG, "Your activity must implement CordovaInterface to work"); } - this.setWebChromeClient(new CordovaChromeClient(this.mCtx, this)); - this.setWebViewClient(new CordovaWebViewClient(this.mCtx, this)); + this.setWebChromeClient(new CordovaChromeClient(this.cordova, this)); + this.setWebViewClient(new CordovaWebViewClient(this.cordova, this)); this.loadConfiguration(); this.setup(); } @@ -123,14 +123,14 @@ public class CordovaWebView extends WebView { super(context, attrs, defStyle); if (CordovaInterface.class.isInstance(context)) { - this.mCtx = (CordovaInterface) context; + this.cordova = (CordovaInterface) context; } else { Log.d(TAG, "Your activity must implement CordovaInterface to work"); } - this.setWebChromeClient(new CordovaChromeClient(this.mCtx, this)); - this.setWebViewClient(new CordovaWebViewClient(this.mCtx, this)); + this.setWebChromeClient(new CordovaChromeClient(this.cordova, this)); + this.setWebViewClient(new CordovaWebViewClient(this.cordova, this)); this.loadConfiguration(); this.setup(); } @@ -147,14 +147,14 @@ public class CordovaWebView extends WebView { super(context, attrs, defStyle, privateBrowsing); if (CordovaInterface.class.isInstance(context)) { - this.mCtx = (CordovaInterface) context; + this.cordova = (CordovaInterface) context; } else { Log.d(TAG, "Your activity must implement CordovaInterface to work"); } - this.setWebChromeClient(new CordovaChromeClient(this.mCtx)); - this.setWebViewClient(new CordovaWebViewClient(this.mCtx)); + this.setWebChromeClient(new CordovaChromeClient(this.cordova)); + this.setWebViewClient(new CordovaWebViewClient(this.cordova)); this.loadConfiguration(); this.setup(); } @@ -180,7 +180,7 @@ public class CordovaWebView extends WebView { // Enable database settings.setDatabaseEnabled(true); - String databasePath = this.mCtx.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); + String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); settings.setDatabasePath(databasePath); // Enable DOM storage @@ -191,7 +191,7 @@ public class CordovaWebView extends WebView { //Start up the plugin manager try { - this.pluginManager = new PluginManager(this, this.mCtx); + this.pluginManager = new PluginManager(this, this.cordova); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -383,13 +383,13 @@ public class CordovaWebView extends WebView { // If timeout, then stop loading and handle error if (me.loadUrlTimeout == currentLoadUrlTimeout) { - me.mCtx.getActivity().runOnUiThread(loadError); + me.cordova.getActivity().runOnUiThread(loadError); } } }; // Load url - this.mCtx.getActivity().runOnUiThread(new Runnable() { + this.cordova.getActivity().runOnUiThread(new Runnable() { public void run() { Thread thread = new Thread(timeoutCheck); thread.start(); @@ -558,7 +558,7 @@ public class CordovaWebView extends WebView { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); - mCtx.getActivity().startActivity(intent); + cordova.getActivity().startActivity(intent); } catch (android.content.ActivityNotFoundException e) { LOG.e(TAG, "Error loading url " + url, e); } @@ -570,7 +570,7 @@ public class CordovaWebView extends WebView { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); - mCtx.getActivity().startActivity(intent); + cordova.getActivity().startActivity(intent); } catch (android.content.ActivityNotFoundException e) { LOG.e(TAG, "Error loading url " + url, e); } @@ -585,7 +585,7 @@ public class CordovaWebView extends WebView { * */ private void loadConfiguration() { - int id = getResources().getIdentifier("cordova", "xml", this.mCtx.getActivity().getPackageName()); + int id = getResources().getIdentifier("cordova", "xml", this.cordova.getActivity().getPackageName()); if (id == 0) { LOG.i("CordovaLog", "cordova.xml missing. Ignoring..."); return; @@ -616,7 +616,7 @@ public class CordovaWebView extends WebView { LOG.i("CordovaLog", "Found preference for %s=%s", name, value); // Save preferences in Intent - this.mCtx.getActivity().getIntent().putExtra(name, value); + this.cordova.getActivity().getIntent().putExtra(name, value); } } try { @@ -637,8 +637,8 @@ public class CordovaWebView extends WebView { } if ("true".equals(this.getProperty("fullscreen", "false"))) { - this.mCtx.getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - this.mCtx.getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + this.cordova.getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + this.cordova.getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } } @@ -650,7 +650,7 @@ public class CordovaWebView extends WebView { * @return */ public String getProperty(String name, String defaultValue) { - Bundle bundle = this.mCtx.getActivity().getIntent().getExtras(); + Bundle bundle = this.cordova.getActivity().getIntent().getExtras(); if (bundle == null) { return defaultValue; } diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java index 3cda1b11..c9a32611 100755 --- a/framework/src/org/apache/cordova/CordovaWebViewClient.java +++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java @@ -44,7 +44,7 @@ import android.webkit.WebViewClient; public class CordovaWebViewClient extends WebViewClient { private static final String TAG = "Cordova"; - CordovaInterface ctx; + CordovaInterface cordova; CordovaWebView appView; private boolean doClearHistory = false; @@ -54,20 +54,20 @@ public class CordovaWebViewClient extends WebViewClient { /** * Constructor. * - * @param ctx + * @param cordova */ - public CordovaWebViewClient(CordovaInterface ctx) { - this.ctx = ctx; + public CordovaWebViewClient(CordovaInterface cordova) { + this.cordova = cordova; } /** * Constructor. * - * @param ctx + * @param cordova * @param view */ - public CordovaWebViewClient(CordovaInterface ctx, CordovaWebView view) { - this.ctx = ctx; + public CordovaWebViewClient(CordovaInterface cordova, CordovaWebView view) { + this.cordova = cordova; this.appView = view; } @@ -100,7 +100,7 @@ public class CordovaWebViewClient extends WebViewClient { try { Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse(url)); - this.ctx.getActivity().startActivity(intent); + this.cordova.getActivity().startActivity(intent); } catch (android.content.ActivityNotFoundException e) { LOG.e(TAG, "Error dialing " + url + ": " + e.toString()); } @@ -111,7 +111,7 @@ public class CordovaWebViewClient extends WebViewClient { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); - this.ctx.getActivity().startActivity(intent); + this.cordova.getActivity().startActivity(intent); } catch (android.content.ActivityNotFoundException e) { LOG.e(TAG, "Error showing map " + url + ": " + e.toString()); } @@ -122,7 +122,7 @@ public class CordovaWebViewClient extends WebViewClient { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); - this.ctx.getActivity().startActivity(intent); + this.cordova.getActivity().startActivity(intent); } catch (android.content.ActivityNotFoundException e) { LOG.e(TAG, "Error sending email " + url + ": " + e.toString()); } @@ -154,7 +154,7 @@ public class CordovaWebViewClient extends WebViewClient { intent.setData(Uri.parse("sms:" + address)); intent.putExtra("address", address); intent.setType("vnd.android-dir/mms-sms"); - this.ctx.getActivity().startActivity(intent); + this.cordova.getActivity().startActivity(intent); } catch (android.content.ActivityNotFoundException e) { LOG.e(TAG, "Error sending sms " + url + ":" + e.toString()); } @@ -178,7 +178,7 @@ public class CordovaWebViewClient extends WebViewClient { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); - this.ctx.getActivity().startActivity(intent); + this.cordova.getActivity().startActivity(intent); } catch (android.content.ActivityNotFoundException e) { LOG.e(TAG, "Error loading url " + url, e); } @@ -280,7 +280,7 @@ public class CordovaWebViewClient extends WebViewClient { public void run() { try { Thread.sleep(2000); - ctx.getActivity().runOnUiThread(new Runnable() { + cordova.getActivity().runOnUiThread(new Runnable() { public void run() { appView.postMessage("spinner", "stop"); } @@ -342,8 +342,8 @@ public class CordovaWebViewClient extends WebViewClient { @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { - final String packageName = this.ctx.getActivity().getPackageName(); - final PackageManager pm = this.ctx.getActivity().getPackageManager(); + final String packageName = this.cordova.getActivity().getPackageName(); + final PackageManager pm = this.cordova.getActivity().getPackageManager(); ApplicationInfo appInfo; try { appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA); diff --git a/framework/src/org/apache/cordova/Device.java b/framework/src/org/apache/cordova/Device.java index 6fd151ea..2d77f54d 100644 --- a/framework/src/org/apache/cordova/Device.java +++ b/framework/src/org/apache/cordova/Device.java @@ -38,7 +38,7 @@ import android.telephony.TelephonyManager; public class Device extends Plugin { public static final String TAG = "Device"; - public static String cordovaVersion = "1.8.0"; // Cordova version + public static String cordovaVersion = "1.9.0rc1"; // Cordova version public static String platform = "Android"; // Device OS public static String uuid; // Device UUID @@ -54,10 +54,10 @@ public class Device extends Plugin { * Sets the context of the Command. This can then be used to do things like * get file paths associated with the Activity. * - * @param ctx The context of the main Activity. + * @param cordova The context of the main Activity. */ - public void setContext(CordovaInterface ctx) { - super.setContext(ctx); + public void setContext(CordovaInterface cordova) { + super.setContext(cordova); Device.uuid = getUuid(); this.initTelephonyReceiver(); } @@ -110,7 +110,7 @@ public class Device extends Plugin { * Unregister receiver. */ public void onDestroy() { - this.ctx.getActivity().unregisterReceiver(this.telephonyReceiver); + this.cordova.getActivity().unregisterReceiver(this.telephonyReceiver); } //-------------------------------------------------------------------------- @@ -125,7 +125,7 @@ public class Device extends Plugin { private void initTelephonyReceiver() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); - //final CordovaInterface myctx = this.ctx; + //final CordovaInterface mycordova = this.cordova; this.telephonyReceiver = new BroadcastReceiver() { @Override @@ -153,7 +153,7 @@ public class Device extends Plugin { }; // Register the receiver - this.ctx.getActivity().registerReceiver(this.telephonyReceiver, intentFilter); + this.cordova.getActivity().registerReceiver(this.telephonyReceiver, intentFilter); } /** @@ -171,7 +171,7 @@ public class Device extends Plugin { * @return */ public String getUuid() { - String uuid = Settings.Secure.getString(this.ctx.getActivity().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); + String uuid = Settings.Secure.getString(this.cordova.getActivity().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); return uuid; } diff --git a/framework/src/org/apache/cordova/FileTransfer.java b/framework/src/org/apache/cordova/FileTransfer.java index 4accd55c..824ad020 100644 --- a/framework/src/org/apache/cordova/FileTransfer.java +++ b/framework/src/org/apache/cordova/FileTransfer.java @@ -524,7 +524,7 @@ public class FileTransfer extends Plugin { private InputStream getPathFromUri(String path) throws FileNotFoundException { if (path.startsWith("content:")) { Uri uri = Uri.parse(path); - return ctx.getActivity().getContentResolver().openInputStream(uri); + return cordova.getActivity().getContentResolver().openInputStream(uri); } else if (path.startsWith("file://")) { int question = path.indexOf("?"); diff --git a/framework/src/org/apache/cordova/FileUtils.java b/framework/src/org/apache/cordova/FileUtils.java index 825fabe2..32b3c05e 100755 --- a/framework/src/org/apache/cordova/FileUtils.java +++ b/framework/src/org/apache/cordova/FileUtils.java @@ -223,7 +223,7 @@ public class FileUtils extends Plugin { */ private void notifyDelete(String filePath) { String newFilePath = stripFileProtocol(filePath); - int result = this.ctx.getActivity().getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + int result = this.cordova.getActivity().getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media.DATA + " = ?", new String[] { filePath }); } @@ -246,7 +246,7 @@ public class FileUtils extends Plugin { // Handle the special case where you get an Android content:// uri. if (decoded.startsWith("content:")) { - Cursor cursor = this.ctx.getActivity().managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null); + Cursor cursor = this.cordova.getActivity().managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null); // Note: MediaStore.Images/Audio/Video.Media.DATA is always "_data" int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); @@ -728,9 +728,9 @@ public class FileUtils extends Plugin { private boolean atRootDirectory(String filePath) { filePath = stripFileProtocol(filePath); - if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + ctx.getActivity().getPackageName() + "/cache") || + if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + cordova.getActivity().getPackageName() + "/cache") || filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath()) || - filePath.equals("/data/data/" + ctx.getActivity().getPackageName())) { + filePath.equals("/data/data/" + cordova.getActivity().getPackageName())) { return true; } return false; @@ -819,16 +819,16 @@ public class FileUtils extends Plugin { fs.put("name", "temporary"); if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + - "/Android/data/" + ctx.getActivity().getPackageName() + "/cache/"); + "/Android/data/" + cordova.getActivity().getPackageName() + "/cache/"); // Create the cache dir if it doesn't exist. fp.mkdirs(); fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() + - "/Android/data/" + ctx.getActivity().getPackageName() + "/cache/")); + "/Android/data/" + cordova.getActivity().getPackageName() + "/cache/")); } else { - fp = new File("/data/data/" + ctx.getActivity().getPackageName() + "/cache/"); + fp = new File("/data/data/" + cordova.getActivity().getPackageName() + "/cache/"); // Create the cache dir if it doesn't exist. fp.mkdirs(); - fs.put("root", getEntry("/data/data/" + ctx.getActivity().getPackageName() + "/cache/")); + fs.put("root", getEntry("/data/data/" + cordova.getActivity().getPackageName() + "/cache/")); } } else if (type == PERSISTENT) { @@ -836,7 +836,7 @@ public class FileUtils extends Plugin { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { fs.put("root", getEntry(Environment.getExternalStorageDirectory())); } else { - fs.put("root", getEntry("/data/data/" + ctx.getActivity().getPackageName())); + fs.put("root", getEntry("/data/data/" + cordova.getActivity().getPackageName())); } } else { @@ -943,7 +943,7 @@ public class FileUtils extends Plugin { String contentType = null; if (filename.startsWith("content:")) { Uri fileUri = Uri.parse(filename); - contentType = this.ctx.getActivity().getContentResolver().getType(fileUri); + contentType = this.cordova.getActivity().getContentResolver().getType(fileUri); } else { contentType = getMimeType(filename); @@ -1026,7 +1026,7 @@ public class FileUtils extends Plugin { private InputStream getPathFromUri(String path) throws FileNotFoundException { if (path.startsWith("content")) { Uri uri = Uri.parse(path); - return ctx.getActivity().getContentResolver().openInputStream(uri); + return cordova.getActivity().getContentResolver().openInputStream(uri); } else { path = stripFileProtocol(path); @@ -1038,13 +1038,13 @@ public class FileUtils extends Plugin { * Queries the media store to find out what the file path is for the Uri we supply * * @param contentUri the Uri of the audio/image/video - * @param ctx) the current applicaiton context + * @param cordova) the current applicaiton context * @return the full path to the file */ @SuppressWarnings("deprecation") - protected static String getRealPathFromURI(Uri contentUri, CordovaInterface ctx) { + protected static String getRealPathFromURI(Uri contentUri, CordovaInterface cordova) { String[] proj = { _DATA }; - Cursor cursor = ctx.getActivity().managedQuery(contentUri, proj, null, null, null); + Cursor cursor = cordova.getActivity().managedQuery(contentUri, proj, null, null, null); int column_index = cursor.getColumnIndexOrThrow(_DATA); cursor.moveToFirst(); return cursor.getString(column_index); diff --git a/framework/src/org/apache/cordova/GeoBroker.java b/framework/src/org/apache/cordova/GeoBroker.java index e53358e3..499d4468 100755 --- a/framework/src/org/apache/cordova/GeoBroker.java +++ b/framework/src/org/apache/cordova/GeoBroker.java @@ -55,7 +55,7 @@ public class GeoBroker extends Plugin { */ public PluginResult execute(String action, JSONArray args, String callbackId) { if (this.locationManager == null) { - this.locationManager = (LocationManager) this.ctx.getActivity().getSystemService(Context.LOCATION_SERVICE); + this.locationManager = (LocationManager) this.cordova.getActivity().getSystemService(Context.LOCATION_SERVICE); this.networkListener = new NetworkListener(this.locationManager, this); this.gpsListener = new GPSListener(this.locationManager, this); } diff --git a/framework/src/org/apache/cordova/NetworkManager.java b/framework/src/org/apache/cordova/NetworkManager.java index 4661ddb6..37f0933e 100755 --- a/framework/src/org/apache/cordova/NetworkManager.java +++ b/framework/src/org/apache/cordova/NetworkManager.java @@ -84,11 +84,11 @@ public class NetworkManager extends Plugin { * Sets the context of the Command. This can then be used to do things like * get file paths associated with the Activity. * - * @param ctx The context of the main Activity. + * @param cordova The context of the main Activity. */ - public void setContext(CordovaInterface ctx) { - super.setContext(ctx); - this.sockMan = (ConnectivityManager) ctx.getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); + public void setContext(CordovaInterface cordova) { + super.setContext(cordova); + this.sockMan = (ConnectivityManager) cordova.getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); this.connectionCallbackId = null; // We need to listen to connectivity events to update navigator.connection @@ -102,7 +102,7 @@ public class NetworkManager extends Plugin { updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO)); } }; - ctx.getActivity().registerReceiver(this.receiver, intentFilter); + cordova.getActivity().registerReceiver(this.receiver, intentFilter); } } @@ -146,7 +146,7 @@ public class NetworkManager extends Plugin { public void onDestroy() { if (this.receiver != null) { try { - this.ctx.getActivity().unregisterReceiver(this.receiver); + this.cordova.getActivity().unregisterReceiver(this.receiver); } catch (Exception e) { Log.e(LOG_TAG, "Error unregistering network receiver: " + e.getMessage(), e); } diff --git a/framework/src/org/apache/cordova/Notification.java b/framework/src/org/apache/cordova/Notification.java index ed0b4365..7a866a8d 100755 --- a/framework/src/org/apache/cordova/Notification.java +++ b/framework/src/org/apache/cordova/Notification.java @@ -143,7 +143,7 @@ public class Notification extends Plugin { */ public void beep(long count) { Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); - Ringtone notification = RingtoneManager.getRingtone(this.ctx.getActivity().getBaseContext(), ringtone); + Ringtone notification = RingtoneManager.getRingtone(this.cordova.getActivity().getBaseContext(), ringtone); // If phone is not set to silent mode if (notification != null) { @@ -171,7 +171,7 @@ public class Notification extends Plugin { if (time == 0) { time = 500; } - Vibrator vibrator = (Vibrator) this.ctx.getActivity().getSystemService(Context.VIBRATOR_SERVICE); + Vibrator vibrator = (Vibrator) this.cordova.getActivity().getSystemService(Context.VIBRATOR_SERVICE); vibrator.vibrate(time); } @@ -184,13 +184,13 @@ public class Notification extends Plugin { */ public synchronized void alert(final String message, final String title, final String buttonLabel, final String callbackId) { - final CordovaInterface ctx = this.ctx; + final CordovaInterface cordova = this.cordova; final Notification notification = this; Runnable runnable = new Runnable() { public void run() { - AlertDialog.Builder dlg = new AlertDialog.Builder(ctx.getActivity()); + AlertDialog.Builder dlg = new AlertDialog.Builder(cordova.getActivity()); dlg.setMessage(message); dlg.setTitle(title); dlg.setCancelable(false); @@ -205,7 +205,7 @@ public class Notification extends Plugin { dlg.show(); }; }; - this.ctx.getActivity().runOnUiThread(runnable); + this.cordova.getActivity().runOnUiThread(runnable); } /** @@ -220,13 +220,13 @@ public class Notification extends Plugin { */ public synchronized void confirm(final String message, final String title, String buttonLabels, final String callbackId) { - final CordovaInterface ctx = this.ctx; + final CordovaInterface cordova = this.cordova; final Notification notification = this; final String[] fButtons = buttonLabels.split(","); Runnable runnable = new Runnable() { public void run() { - AlertDialog.Builder dlg = new AlertDialog.Builder(ctx.getActivity()); + AlertDialog.Builder dlg = new AlertDialog.Builder(cordova.getActivity()); dlg.setMessage(message); dlg.setTitle(title); dlg.setCancelable(false); @@ -269,7 +269,7 @@ public class Notification extends Plugin { dlg.show(); }; }; - this.ctx.getActivity().runOnUiThread(runnable); + this.cordova.getActivity().runOnUiThread(runnable); } /** @@ -284,10 +284,10 @@ public class Notification extends Plugin { this.spinnerDialog = null; } final Notification notification = this; - final CordovaInterface ctx = this.ctx; + final CordovaInterface cordova = this.cordova; Runnable runnable = new Runnable() { public void run() { - notification.spinnerDialog = ProgressDialog.show(ctx.getActivity(), title, message, true, true, + notification.spinnerDialog = ProgressDialog.show(cordova.getActivity(), title, message, true, true, new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) { notification.spinnerDialog = null; @@ -295,7 +295,7 @@ public class Notification extends Plugin { }); } }; - this.ctx.getActivity().runOnUiThread(runnable); + this.cordova.getActivity().runOnUiThread(runnable); } /** @@ -320,10 +320,10 @@ public class Notification extends Plugin { this.progressDialog = null; } final Notification notification = this; - final CordovaInterface ctx = this.ctx; + final CordovaInterface cordova = this.cordova; Runnable runnable = new Runnable() { public void run() { - notification.progressDialog = new ProgressDialog(ctx.getActivity()); + notification.progressDialog = new ProgressDialog(cordova.getActivity()); notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); notification.progressDialog.setTitle(title); notification.progressDialog.setMessage(message); @@ -339,7 +339,7 @@ public class Notification extends Plugin { notification.progressDialog.show(); } }; - this.ctx.getActivity().runOnUiThread(runnable); + this.cordova.getActivity().runOnUiThread(runnable); } /** diff --git a/framework/src/org/apache/cordova/Storage.java b/framework/src/org/apache/cordova/Storage.java index ef87b45a..13fd919c 100755 --- a/framework/src/org/apache/cordova/Storage.java +++ b/framework/src/org/apache/cordova/Storage.java @@ -141,7 +141,7 @@ public class Storage extends Plugin { // If no database path, generate from application package if (this.path == null) { - this.path = this.ctx.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); + this.path = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); } this.dbName = this.path + File.pathSeparator + db + ".db"; diff --git a/framework/src/org/apache/cordova/TempListener.java b/framework/src/org/apache/cordova/TempListener.java index 21c0de01..c65bc879 100755 --- a/framework/src/org/apache/cordova/TempListener.java +++ b/framework/src/org/apache/cordova/TempListener.java @@ -46,11 +46,11 @@ public class TempListener extends Plugin implements SensorEventListener { * Sets the context of the Command. This can then be used to do things like * get file paths associated with the Activity. * - * @param ctx The context of the main Activity. + * @param cordova The context of the main Activity. */ - public void setContext(CordovaInterface ctx) { - super.setContext(ctx); - this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE); + public void setContext(CordovaInterface cordova) { + super.setContext(cordova); + this.sensorManager = (SensorManager) cordova.getActivity().getSystemService(Context.SENSOR_SERVICE); } /** diff --git a/framework/src/org/apache/cordova/api/CordovaInterface.java b/framework/src/org/apache/cordova/api/CordovaInterface.java index 46b692b9..64a2743e 100755 --- a/framework/src/org/apache/cordova/api/CordovaInterface.java +++ b/framework/src/org/apache/cordova/api/CordovaInterface.java @@ -76,4 +76,6 @@ public interface CordovaInterface { * @return Object or null */ public Object onMessage(String id, Object data); + + public abstract void bindButton(String button, boolean override); } diff --git a/framework/src/org/apache/cordova/api/Plugin.java b/framework/src/org/apache/cordova/api/Plugin.java index 143655b1..1ac42f02 100755 --- a/framework/src/org/apache/cordova/api/Plugin.java +++ b/framework/src/org/apache/cordova/api/Plugin.java @@ -33,6 +33,7 @@ public abstract class Plugin implements IPlugin { public String id; public CordovaWebView webView; // WebView object public CordovaInterface ctx; // CordovaActivity object + public CordovaInterface cordova; /** * Executes the request and returns PluginResult. @@ -61,7 +62,8 @@ public abstract class Plugin implements IPlugin { * @param ctx The context of the main Activity. */ public void setContext(CordovaInterface ctx) { - this.ctx = ctx; + this.cordova = ctx; + this.ctx = cordova; } /** From 6c594b6f5f22a3718b9f59c95854ef4cdd4ad614 Mon Sep 17 00:00:00 2001 From: macdonst Date: Tue, 19 Jun 2012 11:29:00 -0400 Subject: [PATCH 08/32] Fixing merge error in FileUtils.notifyDelete --- framework/src/org/apache/cordova/FileUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/org/apache/cordova/FileUtils.java b/framework/src/org/apache/cordova/FileUtils.java index 32b3c05e..1dc6e052 100755 --- a/framework/src/org/apache/cordova/FileUtils.java +++ b/framework/src/org/apache/cordova/FileUtils.java @@ -225,7 +225,7 @@ public class FileUtils extends Plugin { String newFilePath = stripFileProtocol(filePath); int result = this.cordova.getActivity().getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media.DATA + " = ?", - new String[] { filePath }); + new String[] { newFilePath }); } /** From 32febcb892c440e44d44daa1b9c190900ad9bfb2 Mon Sep 17 00:00:00 2001 From: Anis Kadri Date: Tue, 19 Jun 2012 16:28:00 -0700 Subject: [PATCH 09/32] updating windows create.js and creating node test --- bin/create.js | 1 + bin/tests/test_create_win.js | 108 +++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 bin/tests/test_create_win.js diff --git a/bin/create.js b/bin/create.js index 46fd0064..9f704430 100644 --- a/bin/create.js +++ b/bin/create.js @@ -149,6 +149,7 @@ exec('cmd /c copy '+ROOT+'\\framework\\assets\\www\\cordova-'+VERSION+'.js '+PRO exec('cmd /c copy '+ROOT+'\\framework\\cordova-'+VERSION+'.jar '+PROJECT_PATH+'\\libs\\cordova-'+VERSION+'.jar /Y'); // copy in xml +fso.CreateFolder(PROJECT_PATH + '\\res\\xml'); exec('cmd /c copy '+ROOT+'\\framework\\res\\xml\\cordova.xml ' + PROJECT_PATH + '\\res\\xml\\cordova.xml /Y'); exec('cmd /c copy '+ROOT+'\\framework\\res\\xml\\plugins.xml ' + PROJECT_PATH + '\\res\\xml\\plugins.xml /Y'); diff --git a/bin/tests/test_create_win.js b/bin/tests/test_create_win.js new file mode 100644 index 00000000..76dd6aab --- /dev/null +++ b/bin/tests/test_create_win.js @@ -0,0 +1,108 @@ +var build_path = __dirname + '/../..' + project_path = process.env.Temp + '\\example', + package_name = 'org.apache.cordova.example', + package_as_path = 'org/apache/cordova/example', + project_name = 'cordovaExample'; + +var path = require('path'), + fs = require('fs'), + util = require('util'), + assert = require('assert'), + exec = require('child_process').exec, + spawn = require('child_process').spawn; + +var version = fs.readFileSync(build_path + '/VERSION').toString().replace('\r\n', ''); + +assert(version !== undefined); +assert(version !== ''); + +process.on('uncaughtException', function (err) { + console.log('Caught exception: ' + err); + exec('rd /s /q ' + project_path); +}); + +var create_project = spawn('cscript', + [build_path + '/bin/create.js', + project_path, + package_name, + project_name] + ); + +create_project.stderr.on('data', function (data) { + console.log('ps stderr: ' + data); +}); + +create_project.stderr.on('data', function(data) { + console.log(data.toString()); +}); + +create_project.stdout.on('data', function(data) { + console.log(data.toString()); +}); + +create_project.on('exit', function(code) { + assert.equal(code, 0, 'Project did not get created'); + + // make sure the project was created + path.exists(project_path, function(exists) { + assert(exists, 'Project path does not exist'); + }); + + // make sure the build directory was cleaned up + // path.exists(build_path + '/framework/libs', function(exists) { + // assert(!exists, 'libs directory did not get cleaned up'); + // }); + path.exists(build_path + util.format('/framework/assets/cordova-%s.js', version), function(exists) { + assert(!exists, 'javascript file did not get cleaned up'); + }); + path.exists(build_path + util.format('/framework/cordova-%s.jar', version), function(exists) { + assert(!exists, 'jar file did not get cleaned up'); + }); + + // make sure AndroidManifest.xml was added + path.exists(util.format('%s/AndroidManifest.xml', project_path), function(exists) { + assert(exists, 'AndroidManifest.xml did not get created'); + // TODO check that the activity name was properly substituted + }); + + // make sure main Activity was added + path.exists(util.format('%s/src/%s/%s.java', project_path, package_as_path, project_name), function(exists) { + assert(exists, 'Activity did not get created'); + // TODO check that package name and activity name were substitued properly + }); + + // make sure plugins.xml was added + path.exists(util.format('%s/res/xml/plugins.xml', project_path), function(exists) { + assert(exists, 'plugins.xml did not get created'); + }); + + // make sure cordova.xml was added + path.exists(util.format('%s/res/xml/cordova.xml', project_path), function(exists) { + assert(exists, 'plugins.xml did not get created'); + }); + + // make sure cordova.jar was added + path.exists(util.format('%s/libs/cordova-%s.jar', project_path, version), function(exists) { + assert(exists, 'cordova.jar did not get added'); + }); + + // make sure cordova.js was added + path.exists(util.format('%s/assets/www/cordova-%s.js', project_path, version), function(exists) { + assert(exists, 'cordova.js did not get added'); + }); + + // check that project compiles && creates a cordovaExample-debug.apk + // XXX: !@##!@# WINDOWS + exec('ant debug -f ' + project_path + "\\build.xml", function(error, stdout, stderr) { + assert(error == null, "Cordova Android Project does not compile"); + path.exists(util.format('%s/bin/%s-debug.apk', project_path, project_name), + function(exists) { + assert(exists, 'Package did not get created'); + // if project compiles properly just AXE it + exec('rd /s /q ' + project_path); + }); + }); + + +}); + From 5c7783305a6f195a184c077bc17fdbd603366f00 Mon Sep 17 00:00:00 2001 From: macdonst Date: Tue, 19 Jun 2012 20:21:13 -0400 Subject: [PATCH 10/32] CB-883: SplashScreen without show() method, only hide() --- .../src/org/apache/cordova/DroidGap.java | 72 ++++++++++--------- .../src/org/apache/cordova/SplashScreen.java | 3 +- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/framework/src/org/apache/cordova/DroidGap.java b/framework/src/org/apache/cordova/DroidGap.java index d4c142d3..a5e2a7d1 100755 --- a/framework/src/org/apache/cordova/DroidGap.java +++ b/framework/src/org/apache/cordova/DroidGap.java @@ -260,7 +260,7 @@ public class DroidGap extends Activity implements CordovaInterface { { getWindow().requestFeature(Window.FEATURE_NO_TITLE); } - + if(this.getBooleanProperty("setFullscreen", false)) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, @@ -866,7 +866,7 @@ public class DroidGap extends Activity implements CordovaInterface { } /** - * Launch an activity for which you would like a result when it finished. When this activity exits, + * Launch an activity for which you would like a result when it finished. When this activity exits, * your onActivityResult() method will be called. * * @param command The command object @@ -1088,40 +1088,46 @@ public class DroidGap extends Activity implements CordovaInterface { * Shows the splash screen over the full Activity */ @SuppressWarnings("deprecation") - protected void showSplashScreen(int time) { + protected void showSplashScreen(final int time) { + final DroidGap that = this; - // Get reference to display - Display display = getWindowManager().getDefaultDisplay(); - - // Create the layout for the dialog - LinearLayout root = new LinearLayout(this); - root.setMinimumHeight(display.getHeight()); - root.setMinimumWidth(display.getWidth()); - root.setOrientation(LinearLayout.VERTICAL); - root.setBackgroundColor(this.getIntegerProperty("backgroundColor", Color.BLACK)); - root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT, 0.0F)); - root.setBackgroundResource(this.splashscreen); - - // Create and show the dialog - splashDialog = new Dialog(this, android.R.style.Theme_Translucent_NoTitleBar); - // check to see if the splash screen should be full screen - if ((getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) - == WindowManager.LayoutParams.FLAG_FULLSCREEN) { - splashDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - splashDialog.setContentView(root); - splashDialog.setCancelable(false); - splashDialog.show(); - - // Set Runnable to remove splash screen just in case - final Handler handler = new Handler(); - handler.postDelayed(new Runnable() { + Runnable runnable = new Runnable() { public void run() { - removeSplashScreen(); + // Get reference to display + Display display = getWindowManager().getDefaultDisplay(); + + // Create the layout for the dialog + LinearLayout root = new LinearLayout(that.getActivity()); + root.setMinimumHeight(display.getHeight()); + root.setMinimumWidth(display.getWidth()); + root.setOrientation(LinearLayout.VERTICAL); + root.setBackgroundColor(that.getIntegerProperty("backgroundColor", Color.BLACK)); + root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.FILL_PARENT, 0.0F)); + root.setBackgroundResource(that.splashscreen); + + // Create and show the dialog + splashDialog = new Dialog(that, android.R.style.Theme_Translucent_NoTitleBar); + // check to see if the splash screen should be full screen + if ((getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) + == WindowManager.LayoutParams.FLAG_FULLSCREEN) { + splashDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + splashDialog.setContentView(root); + splashDialog.setCancelable(false); + splashDialog.show(); + + // Set Runnable to remove splash screen just in case + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + public void run() { + removeSplashScreen(); + } + }, time); } - }, time); + }; + this.runOnUiThread(runnable); } /** diff --git a/framework/src/org/apache/cordova/SplashScreen.java b/framework/src/org/apache/cordova/SplashScreen.java index 9fca9b25..93ab6288 100644 --- a/framework/src/org/apache/cordova/SplashScreen.java +++ b/framework/src/org/apache/cordova/SplashScreen.java @@ -31,8 +31,9 @@ public class SplashScreen extends Plugin { String result = ""; if (action.equals("hide")) { - //((DroidGap)this.ctx).removeSplashScreen(); this.webView.postMessage("splashscreen", "hide"); + } else if (action.equals("show")){ + this.webView.postMessage("splashscreen", "show"); } else { status = PluginResult.Status.INVALID_ACTION; From be83095edf4ed71bd03c9eef7880885a799e2085 Mon Sep 17 00:00:00 2001 From: Anis Kadri Date: Tue, 19 Jun 2012 16:28:00 -0700 Subject: [PATCH 11/32] updating windows create.js and creating node test --- bin/create.js | 1 + bin/tests/test_create_win.js | 108 +++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 bin/tests/test_create_win.js diff --git a/bin/create.js b/bin/create.js index 46fd0064..9f704430 100644 --- a/bin/create.js +++ b/bin/create.js @@ -149,6 +149,7 @@ exec('cmd /c copy '+ROOT+'\\framework\\assets\\www\\cordova-'+VERSION+'.js '+PRO exec('cmd /c copy '+ROOT+'\\framework\\cordova-'+VERSION+'.jar '+PROJECT_PATH+'\\libs\\cordova-'+VERSION+'.jar /Y'); // copy in xml +fso.CreateFolder(PROJECT_PATH + '\\res\\xml'); exec('cmd /c copy '+ROOT+'\\framework\\res\\xml\\cordova.xml ' + PROJECT_PATH + '\\res\\xml\\cordova.xml /Y'); exec('cmd /c copy '+ROOT+'\\framework\\res\\xml\\plugins.xml ' + PROJECT_PATH + '\\res\\xml\\plugins.xml /Y'); diff --git a/bin/tests/test_create_win.js b/bin/tests/test_create_win.js new file mode 100644 index 00000000..76dd6aab --- /dev/null +++ b/bin/tests/test_create_win.js @@ -0,0 +1,108 @@ +var build_path = __dirname + '/../..' + project_path = process.env.Temp + '\\example', + package_name = 'org.apache.cordova.example', + package_as_path = 'org/apache/cordova/example', + project_name = 'cordovaExample'; + +var path = require('path'), + fs = require('fs'), + util = require('util'), + assert = require('assert'), + exec = require('child_process').exec, + spawn = require('child_process').spawn; + +var version = fs.readFileSync(build_path + '/VERSION').toString().replace('\r\n', ''); + +assert(version !== undefined); +assert(version !== ''); + +process.on('uncaughtException', function (err) { + console.log('Caught exception: ' + err); + exec('rd /s /q ' + project_path); +}); + +var create_project = spawn('cscript', + [build_path + '/bin/create.js', + project_path, + package_name, + project_name] + ); + +create_project.stderr.on('data', function (data) { + console.log('ps stderr: ' + data); +}); + +create_project.stderr.on('data', function(data) { + console.log(data.toString()); +}); + +create_project.stdout.on('data', function(data) { + console.log(data.toString()); +}); + +create_project.on('exit', function(code) { + assert.equal(code, 0, 'Project did not get created'); + + // make sure the project was created + path.exists(project_path, function(exists) { + assert(exists, 'Project path does not exist'); + }); + + // make sure the build directory was cleaned up + // path.exists(build_path + '/framework/libs', function(exists) { + // assert(!exists, 'libs directory did not get cleaned up'); + // }); + path.exists(build_path + util.format('/framework/assets/cordova-%s.js', version), function(exists) { + assert(!exists, 'javascript file did not get cleaned up'); + }); + path.exists(build_path + util.format('/framework/cordova-%s.jar', version), function(exists) { + assert(!exists, 'jar file did not get cleaned up'); + }); + + // make sure AndroidManifest.xml was added + path.exists(util.format('%s/AndroidManifest.xml', project_path), function(exists) { + assert(exists, 'AndroidManifest.xml did not get created'); + // TODO check that the activity name was properly substituted + }); + + // make sure main Activity was added + path.exists(util.format('%s/src/%s/%s.java', project_path, package_as_path, project_name), function(exists) { + assert(exists, 'Activity did not get created'); + // TODO check that package name and activity name were substitued properly + }); + + // make sure plugins.xml was added + path.exists(util.format('%s/res/xml/plugins.xml', project_path), function(exists) { + assert(exists, 'plugins.xml did not get created'); + }); + + // make sure cordova.xml was added + path.exists(util.format('%s/res/xml/cordova.xml', project_path), function(exists) { + assert(exists, 'plugins.xml did not get created'); + }); + + // make sure cordova.jar was added + path.exists(util.format('%s/libs/cordova-%s.jar', project_path, version), function(exists) { + assert(exists, 'cordova.jar did not get added'); + }); + + // make sure cordova.js was added + path.exists(util.format('%s/assets/www/cordova-%s.js', project_path, version), function(exists) { + assert(exists, 'cordova.js did not get added'); + }); + + // check that project compiles && creates a cordovaExample-debug.apk + // XXX: !@##!@# WINDOWS + exec('ant debug -f ' + project_path + "\\build.xml", function(error, stdout, stderr) { + assert(error == null, "Cordova Android Project does not compile"); + path.exists(util.format('%s/bin/%s-debug.apk', project_path, project_name), + function(exists) { + assert(exists, 'Package did not get created'); + // if project compiles properly just AXE it + exec('rd /s /q ' + project_path); + }); + }); + + +}); + From a691e9f744a878d3f457d7c229a4c74889fa1cac Mon Sep 17 00:00:00 2001 From: macdonst Date: Tue, 19 Jun 2012 10:51:19 -0400 Subject: [PATCH 12/32] CB-910: Camera out of memory error Whenever possible do not load the image into a Bitmap as it takes too much memory and blows up the Java heap. --- .../org/apache/cordova/CameraLauncher.java | 55 +++++++++++---- framework/src/org/apache/cordova/Capture.java | 69 +++++++++++++------ 2 files changed, 91 insertions(+), 33 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 1afaf8db..3520247b 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -20,6 +20,7 @@ package org.apache.cordova; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -43,6 +44,7 @@ import android.graphics.Matrix; import android.graphics.Bitmap.CompressFormat; import android.net.Uri; import android.provider.MediaStore; +import android.util.Log; /** * This class launches the camera view, allows the user to take a picture, closes the camera view, @@ -277,6 +279,7 @@ public class CameraLauncher extends Plugin { Bitmap retval = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true); bitmap.recycle(); + System.gc(); return retval; } @@ -310,20 +313,12 @@ public class CameraLauncher extends Plugin { // If image available if (resultCode == Activity.RESULT_OK) { try { - // Read in bitmap of captured image - Bitmap bitmap; - try { - bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.cordova.getActivity().getContentResolver(), imageUri); - } catch (FileNotFoundException e) { - Uri uri = intent.getData(); - android.content.ContentResolver resolver = this.cordova.getActivity().getContentResolver(); - bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri)); - } - - bitmap = scaleBitmap(bitmap); + Bitmap bitmap = null; // If sending base64 image back if (destType == DATA_URL) { + bitmap = scaleBitmap(getBitmapFromResult(intent)); + this.processPicture(bitmap); checkForDuplicateImage(DATA_URL); } @@ -348,6 +343,27 @@ public class CameraLauncher extends Plugin { } } + // If all this is true we shouldn't compress the image. + if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100) { + FileInputStream fis = new FileInputStream(FileUtils.stripFileProtocol(imageUri.toString())); + OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); + byte[] buffer = new byte[4096]; + int len; + while ((len = fis.read(buffer)) != -1) { + os.write(buffer, 0, len); + } + os.flush(); + os.close(); + fis.close(); + + checkForDuplicateImage(FILE_URI); + + this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); + return; + } + + bitmap = scaleBitmap(getBitmapFromResult(intent)); + // Add compressed version of captured image to returned media store Uri OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); @@ -390,7 +406,7 @@ public class CameraLauncher extends Plugin { Uri uri = intent.getData(); android.content.ContentResolver resolver = this.cordova.getActivity().getContentResolver(); - // If you ask for video or all media type you will automatically get back a file URI + // If you ask for video or all media type you will automatically get back a file URI // and there will be no attempt to resize any returned data if (this.mediaType != PICTURE) { this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); @@ -447,7 +463,7 @@ public class CameraLauncher extends Plugin { bitmap.recycle(); bitmap = null; - // The resized image is cached by the app in order to get around this and not have to delete you + // The resized image is cached by the app in order to get around this and not have to delete you // application cache I'm adding the current system time to the end of the file url. this.success(new PluginResult(PluginResult.Status.OK, ("file://" + fileName + "?" + System.currentTimeMillis())), this.callbackId); System.gc(); @@ -471,6 +487,19 @@ public class CameraLauncher extends Plugin { } } + private Bitmap getBitmapFromResult(Intent intent) + throws IOException, FileNotFoundException { + Bitmap bitmap = null; + try { + bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getActivity().getContentResolver(), imageUri); + } catch (FileNotFoundException e) { + Uri uri = intent.getData(); + android.content.ContentResolver resolver = this.ctx.getActivity().getContentResolver(); + bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri)); + } + return bitmap; + } + /** * Creates a cursor that can be used to determine how many images we have. * diff --git a/framework/src/org/apache/cordova/Capture.java b/framework/src/org/apache/cordova/Capture.java index a2dfafdc..cd115d40 100644 --- a/framework/src/org/apache/cordova/Capture.java +++ b/framework/src/org/apache/cordova/Capture.java @@ -19,6 +19,7 @@ package org.apache.cordova; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; @@ -32,10 +33,11 @@ import org.json.JSONObject; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; -import android.graphics.Bitmap; +import android.database.Cursor; import android.graphics.BitmapFactory; import android.media.MediaPlayer; import android.net.Uri; +import android.provider.MediaStore; import android.util.Log; public class Capture extends Plugin { @@ -61,6 +63,7 @@ public class Capture extends Plugin { private double duration; // optional duration parameter for video recording private JSONArray results; // The array of results to be returned to the user private Uri imageUri; // Uri of captured image + private int numPics; // Number of pictures before capture activity //private CordovaInterface cordova; @@ -202,6 +205,9 @@ public class Capture extends Plugin { * Sets up an intent to capture images. Result handled by onActivityResult() */ private void captureImage() { + // Save the number of images currently on disk for later + this.numPics = queryImgDB().getCount(); + Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); // Specify file so that large image is captured and returned @@ -256,14 +262,6 @@ public class Capture extends Plugin { // It crashes in the emulator and on my phone with a null pointer exception // To work around it I had to grab the code from CameraLauncher.java try { - // Create an ExifHelper to save the exif data that is lost during compression - ExifHelper exif = new ExifHelper(); - exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/Capture.jpg"); - exif.readExifData(); - - // Read in bitmap of captured image - Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.cordova.getActivity().getContentResolver(), imageUri); - // Create entry in media store for image // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) ContentValues values = new ContentValues(); @@ -281,23 +279,22 @@ public class Capture extends Plugin { return; } } - - // Add compressed version of captured image to returned media store Uri + FileInputStream fis = new FileInputStream(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/Capture.jpg"); OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); - bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os); + byte[] buffer = new byte[4096]; + int len; + while ((len = fis.read(buffer)) != -1) { + os.write(buffer, 0, len); + } + os.flush(); os.close(); - - bitmap.recycle(); - bitmap = null; - System.gc(); - - // Restore exif data to file - exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.cordova)); - exif.writeExifData(); + fis.close(); // Add image to results results.put(createMediaFile(uri)); + checkForDuplicateImage(); + if (results.length() >= limit) { // Send Uri back to JavaScript for viewing image this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId); @@ -405,4 +402,36 @@ public class Capture extends Plugin { public void fail(JSONObject err) { this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId); } + + + /** + * Creates a cursor that can be used to determine how many images we have. + * + * @return a cursor + */ + private Cursor queryImgDB() { + return this.cordova.getActivity().getContentResolver().query( + android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + new String[] { MediaStore.Images.Media._ID }, + null, + null, + null); + } + + /** + * Used to find out if we are in a situation where the Camera Intent adds to images + * to the content store. + */ + private void checkForDuplicateImage() { + Cursor cursor = queryImgDB(); + int currentNumOfImages = cursor.getCount(); + + // delete the duplicate file if the difference is 2 + if ((currentNumOfImages - numPics) == 2) { + cursor.moveToLast(); + int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1; + Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id); + this.cordova.getActivity().getContentResolver().delete(uri, null, null); + } + } } From c1c907596233efd175ff611d35d82c53fe157577 Mon Sep 17 00:00:00 2001 From: macdonst Date: Wed, 20 Jun 2012 12:20:37 -0400 Subject: [PATCH 13/32] CB-919: Camera Plugin returned with empty error message Guarding against null cursor. --- .../org/apache/cordova/CameraLauncher.java | 22 ++++++++++--------- framework/src/org/apache/cordova/Capture.java | 16 ++++++++------ 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 3520247b..3d43b11c 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -524,18 +524,20 @@ public class CameraLauncher extends Plugin { private void checkForDuplicateImage(int type) { int diff = 1; Cursor cursor = queryImgDB(); - int currentNumOfImages = cursor.getCount(); + if (cursor != null) { + int currentNumOfImages = cursor.getCount(); - if (type == FILE_URI) { - diff = 2; - } + if (type == FILE_URI) { + diff = 2; + } - // delete the duplicate file if the difference is 2 for file URI or 1 for Data URL - if ((currentNumOfImages - numPics) == diff) { - cursor.moveToLast(); - int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1; - Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id); - this.cordova.getActivity().getContentResolver().delete(uri, null, null); + // delete the duplicate file if the difference is 2 for file URI or 1 for Data URL + if ((currentNumOfImages - numPics) == diff) { + cursor.moveToLast(); + int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1; + Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id); + this.cordova.getActivity().getContentResolver().delete(uri, null, null); + } } } diff --git a/framework/src/org/apache/cordova/Capture.java b/framework/src/org/apache/cordova/Capture.java index cd115d40..5898dc87 100644 --- a/framework/src/org/apache/cordova/Capture.java +++ b/framework/src/org/apache/cordova/Capture.java @@ -424,14 +424,16 @@ public class Capture extends Plugin { */ private void checkForDuplicateImage() { Cursor cursor = queryImgDB(); - int currentNumOfImages = cursor.getCount(); + if (cursor != null) { + int currentNumOfImages = cursor.getCount(); - // delete the duplicate file if the difference is 2 - if ((currentNumOfImages - numPics) == 2) { - cursor.moveToLast(); - int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1; - Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id); - this.cordova.getActivity().getContentResolver().delete(uri, null, null); + // delete the duplicate file if the difference is 2 + if ((currentNumOfImages - numPics) == 2) { + cursor.moveToLast(); + int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1; + Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id); + this.cordova.getActivity().getContentResolver().delete(uri, null, null); + } } } } From 4795133daf80f699379950677bb4fc1ed408348b Mon Sep 17 00:00:00 2001 From: macdonst Date: Wed, 20 Jun 2012 12:20:37 -0400 Subject: [PATCH 14/32] CB-919: Camera Plugin returned with empty error message Instead of guarding against a null cursor we detect if the device is using internal or external storage to save the photos and adjust our DB queries accordingly. --- .../org/apache/cordova/CameraLauncher.java | 24 +++++++++++--- framework/src/org/apache/cordova/Capture.java | 32 +++++++++++++------ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 3520247b..e9f4ea8f 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -43,6 +43,7 @@ import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.Bitmap.CompressFormat; import android.net.Uri; +import android.os.Environment; import android.provider.MediaStore; import android.util.Log; @@ -167,7 +168,7 @@ public class CameraLauncher extends Plugin { */ public void takePicture(int returnType, int encodingType) { // Save the number of images currently on disk for later - this.numPics = queryImgDB().getCount(); + this.numPics = queryImgDB(whichContentStore()).getCount(); // Display camera Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); @@ -505,9 +506,9 @@ public class CameraLauncher extends Plugin { * * @return a cursor */ - private Cursor queryImgDB() { + private Cursor queryImgDB(Uri contentStore) { return this.cordova.getActivity().getContentResolver().query( - android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + contentStore, new String[] { MediaStore.Images.Media._ID }, null, null, @@ -523,7 +524,8 @@ public class CameraLauncher extends Plugin { */ private void checkForDuplicateImage(int type) { int diff = 1; - Cursor cursor = queryImgDB(); + Uri contentStore = whichContentStore(); + Cursor cursor = queryImgDB(contentStore); int currentNumOfImages = cursor.getCount(); if (type == FILE_URI) { @@ -534,11 +536,23 @@ public class CameraLauncher extends Plugin { if ((currentNumOfImages - numPics) == diff) { cursor.moveToLast(); int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1; - Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id); + Uri uri = Uri.parse(contentStore + "/" + id); this.cordova.getActivity().getContentResolver().delete(uri, null, null); } } + /** + * Determine if we are storing the images in internal or external storage + * @return Uri + */ + private Uri whichContentStore() { + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + return android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else { + return android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI; + } + } + /** * Compress bitmap using jpeg, convert to Base64 encoded string, and return to JavaScript. * diff --git a/framework/src/org/apache/cordova/Capture.java b/framework/src/org/apache/cordova/Capture.java index cd115d40..d84c6268 100644 --- a/framework/src/org/apache/cordova/Capture.java +++ b/framework/src/org/apache/cordova/Capture.java @@ -37,6 +37,7 @@ import android.database.Cursor; import android.graphics.BitmapFactory; import android.media.MediaPlayer; import android.net.Uri; +import android.os.Environment; import android.provider.MediaStore; import android.util.Log; @@ -206,7 +207,7 @@ public class Capture extends Plugin { */ private void captureImage() { // Save the number of images currently on disk for later - this.numPics = queryImgDB().getCount(); + this.numPics = queryImgDB(whichContentStore()).getCount(); Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); @@ -409,13 +410,13 @@ public class Capture extends Plugin { * * @return a cursor */ - private Cursor queryImgDB() { + private Cursor queryImgDB(Uri contentStore) { return this.cordova.getActivity().getContentResolver().query( - android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - new String[] { MediaStore.Images.Media._ID }, - null, - null, - null); + contentStore, + new String[] { MediaStore.Images.Media._ID }, + null, + null, + null); } /** @@ -423,15 +424,28 @@ public class Capture extends Plugin { * to the content store. */ private void checkForDuplicateImage() { - Cursor cursor = queryImgDB(); + Uri contentStore = whichContentStore(); + Cursor cursor = queryImgDB(contentStore); int currentNumOfImages = cursor.getCount(); // delete the duplicate file if the difference is 2 if ((currentNumOfImages - numPics) == 2) { cursor.moveToLast(); int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1; - Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id); + Uri uri = Uri.parse(contentStore + "/" + id); this.cordova.getActivity().getContentResolver().delete(uri, null, null); } } + + /** + * Determine if we are storing the images in internal or external storage + * @return Uri + */ + private Uri whichContentStore() { + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + return android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else { + return android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI; + } + } } From d1905dbee8edb720b25547a72e1f7f843036089d Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Wed, 20 Jun 2012 14:16:02 -0700 Subject: [PATCH 15/32] Fixing work-around to work for both ? and # --- framework/src/org/apache/cordova/CordovaWebViewClient.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/framework/src/org/apache/cordova/CordovaWebViewClient.java b/framework/src/org/apache/cordova/CordovaWebViewClient.java index 85261c3e..4934c8f3 100755 --- a/framework/src/org/apache/cordova/CordovaWebViewClient.java +++ b/framework/src/org/apache/cordova/CordovaWebViewClient.java @@ -461,7 +461,7 @@ public class CordovaWebViewClient extends WebViewClient { @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { - if(url.contains("?")){ + if(url.contains("?") || url.contains("#")){ return generateWebResourceResponse(url); } else { return super.shouldInterceptRequest(view, url); @@ -476,6 +476,10 @@ public class CordovaWebViewClient extends WebViewClient { if(niceUrl.contains("?")){ niceUrl = niceUrl.split("\\?")[0]; } + else if(niceUrl.contains("#")) + { + niceUrl = niceUrl.split("#")[0]; + } String mimetype = null; if(niceUrl.endsWith(".html")){ From 56acd2953bfc6054fdbff6bb69e01f1a4bb68222 Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Thu, 21 Jun 2012 11:12:30 -0700 Subject: [PATCH 16/32] Adding updated JS --- framework/assets/js/cordova.android.js | 83 +++++++++++--------------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/framework/assets/js/cordova.android.js b/framework/assets/js/cordova.android.js index 16dab290..ae20b290 100644 --- a/framework/assets/js/cordova.android.js +++ b/framework/assets/js/cordova.android.js @@ -1,6 +1,6 @@ -// commit 347de1a785b7ecbe86c2189343ab2549a9297f9b +// commit 25033fceac7c800623f1f16881b784d19eba69cc -// File generated at :: Fri Jun 08 2012 16:17:50 GMT-0700 (PDT) +// File generated at :: Thu Jun 21 2012 10:45:32 GMT-0700 (PDT) /* Licensed to the Apache Software Foundation (ASF) under one @@ -190,7 +190,9 @@ var cordova = { fireDocumentEvent: function(type, data) { var evt = createEvent(type, data); if (typeof documentEventHandlers[type] != 'undefined') { - documentEventHandlers[type].fire(evt); + setTimeout(function() { + documentEventHandlers[type].fire(evt); + }, 0); } else { document.dispatchEvent(evt); } @@ -198,7 +200,9 @@ var cordova = { fireWindowEvent: function(type, data) { var evt = createEvent(type,data); if (typeof windowEventHandlers[type] != 'undefined') { - windowEventHandlers[type].fire(evt); + setTimeout(function() { + windowEventHandlers[type].fire(evt); + }, 0); } else { window.dispatchEvent(evt); } @@ -953,8 +957,7 @@ module.exports = function(success, fail, service, action, args) { // If a result was returned if (r.length > 0) { - var v; - eval("v="+r+";"); + var v = JSON.parse(r); // If status is OK, then return value back to caller if (v.status === cordova.callbackStatus.OK) { @@ -1067,28 +1070,6 @@ module.exports = { cordova.addDocumentEventHandler('menubutton'); cordova.addDocumentEventHandler('searchbutton'); - function bindButtonChannel(buttonName) { - // generic button bind used for volumeup/volumedown buttons - return cordova.addDocumentEventHandler(buttonName + 'button', { - onSubscribe:function() { - // If we just attached the first handler, let native know we need to override the button. - if (this.numHandlers === 1) { - exec(null, null, "App", "overrideButton", [buttonName, true]); - } - }, - onUnsubscribe:function() { - // If we just detached the last handler, let native know we no longer override the volumeup button. - if (this.numHandlers === 0) { - exec(null, null, "App", "overrideButton", [buttonName, false]); - } - } - }); - - } - // Inject a listener for the volume buttons on the document. - var volumeUpButtonChannel = bindButtonChannel('volumeup'); - var volumeDownButtonChannel = bindButtonChannel('volumedown'); - // Figure out if we need to shim-in localStorage and WebSQL // support from the native side. var storage = require('cordova/plugin/android/storage'); @@ -1308,7 +1289,7 @@ cameraExport.getPicture = function(successCallback, errorCallback, options) { cameraExport.cleanup = function(successCallback, errorCallback) { exec(successCallback, errorCallback, "Camera", "cleanup", []); -} +}; module.exports = cameraExport; }); @@ -2628,7 +2609,8 @@ module.exports = FileSystem; // file: lib/common/plugin/FileTransfer.js define("cordova/plugin/FileTransfer", function(require, exports, module) { -var exec = require('cordova/exec'); +var exec = require('cordova/exec'), + FileTransferError = require('cordova/plugin/FileTransferError'); /** * FileTransfer uploads a file to a remote server. @@ -2647,6 +2629,8 @@ var FileTransfer = function() {}; * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false */ FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, trustAllHosts) { + // sanity parameter checking + if (!filePath || !server) throw new Error("FileTransfer.upload requires filePath and server URL parameters at the minimum."); // check for options var fileKey = null; var fileName = null; @@ -2668,7 +2652,12 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro } } - exec(successCallback, errorCallback, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode]); + var fail = function(e) { + var error = new FileTransferError(e.code, e.source, e.target, e.http_status); + errorCallback(error); + }; + + exec(successCallback, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode]); }; /** @@ -2679,6 +2668,8 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro * @param errorCallback {Function} Callback to be invoked upon error */ FileTransfer.prototype.download = function(source, target, successCallback, errorCallback) { + // sanity parameter checking + if (!source || !target) throw new Error("FileTransfer.download requires source URI and target URI parameters at the minimum."); var win = function(result) { var entry = null; if (result.isDirectory) { @@ -2693,6 +2684,12 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro entry.fullPath = result.fullPath; successCallback(entry); }; + + var fail = function(e) { + var error = new FileTransferError(e.code, e.source, e.target, e.http_status); + errorCallback(error); + }; + exec(win, errorCallback, 'FileTransfer', 'download', [source, target]); }; @@ -2706,8 +2703,11 @@ define("cordova/plugin/FileTransferError", function(require, exports, module) { * FileTransferError * @constructor */ -var FileTransferError = function(code) { +var FileTransferError = function(code, source, target, status) { this.code = code || null; + this.source = source || null; + this.target = target || null; + this.http_status = status || null; }; FileTransferError.FILE_NOT_FOUND_ERR = 1; @@ -2715,6 +2715,7 @@ FileTransferError.INVALID_URL_ERR = 2; FileTransferError.CONNECTION_ERR = 3; module.exports = FileTransferError; + }); // file: lib/common/plugin/FileUploadOptions.js @@ -3665,21 +3666,6 @@ module.exports = { exec(null, null, "App", "overrideBackbutton", [override]); }, - /** - * Override the default behavior of the Android volume button. - * If overridden, when the volume button is pressed, the "volume[up|down]button" JavaScript event will be fired. - * - * Note: The user should not have to call this method. Instead, when the user - * registers for the "volume[up|down]button" event, this is automatically done. - * - * @param button volumeup, volumedown - * @param override T=override, F=cancel override - */ - overrideButton:function(button, override) { - exec(null, null, "App", "overrideButton", [button, override]); - }, - - /** * Exit and terminate the application. */ @@ -5509,6 +5495,9 @@ define("cordova/plugin/splashscreen", function(require, exports, module) { var exec = require('cordova/exec'); var splashscreen = { + show:function() { + exec(null, null, "SplashScreen", "show", []); + }, hide:function() { exec(null, null, "SplashScreen", "hide", []); } From b339330592fd7a4abffdf85f8fdc8cac64173eba Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Tue, 19 Jun 2012 17:14:05 -0700 Subject: [PATCH 17/32] Added MediaScanner abilities to camera launcher plugin. Now images saved to SD card should show up in the android gallery app right away --- .../org/apache/cordova/CameraLauncher.java | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index e9f4ea8f..ed0f928c 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -42,6 +42,8 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.Bitmap.CompressFormat; +import android.media.MediaScannerConnection; +import android.media.MediaScannerConnection.MediaScannerConnectionClient; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; @@ -52,7 +54,7 @@ import android.util.Log; * and returns the captured image. When the camera view is closed, the screen displayed before * the camera view was shown is redisplayed. */ -public class CameraLauncher extends Plugin { +public class CameraLauncher extends Plugin implements MediaScannerConnectionClient { private static final int DATA_URL = 0; // Return base64 encoded string private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android) @@ -82,6 +84,8 @@ public class CameraLauncher extends Plugin { public String callbackId; private int numPics; + + private MediaScannerConnection conn; // Used to update gallery app with newly-written files //This should never be null! //private CordovaInterface cordova; @@ -330,13 +334,13 @@ public class CameraLauncher extends Plugin { // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) ContentValues values = new ContentValues(); values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); - Uri uri = null; + try { - uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException e) { LOG.d(LOG_TAG, "Can't write to external media storage."); try { - uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); + this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException ex) { LOG.d(LOG_TAG, "Can't write to internal media storage."); this.failPicture("Error capturing image - no media storage found."); @@ -366,24 +370,28 @@ public class CameraLauncher extends Plugin { bitmap = scaleBitmap(getBitmapFromResult(intent)); // Add compressed version of captured image to returned media store Uri - OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); + OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(this.imageUri); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); os.close(); // Restore exif data to file if (this.encodingType == JPEG) { - exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.cordova)); + exif.createOutFile(FileUtils.getRealPathFromURI(this.imageUri, this.cordova)); exif.writeExifData(); } + // Scan for the gallery to update pic refs in gallery + this.scanForGallery(); + // Send Uri back to JavaScript for viewing image - this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); + this.success(new PluginResult(PluginResult.Status.OK, this.imageUri.toString()), this.callbackId); } bitmap.recycle(); bitmap = null; System.gc(); checkForDuplicateImage(FILE_URI); + } catch (IOException e) { e.printStackTrace(); this.failPicture("Error capturing image."); @@ -584,4 +592,26 @@ public class CameraLauncher extends Plugin { public void failPicture(String err) { this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId); } + + private void scanForGallery() { + if(this.conn!=null) this.conn.disconnect(); + this.conn = new MediaScannerConnection(this.ctx.getActivity().getApplicationContext(), this); + conn.connect(); + } + + @Override + public void onMediaScannerConnected() { + try{ + this.conn.scanFile(this.imageUri.toString(), "image/*"); + } catch (java.lang.IllegalStateException e){ + e.printStackTrace(); + LOG.d(LOG_TAG, "Can;t scan file in MediaScanner aftering taking picture"); + } + + } + + @Override + public void onScanCompleted(String path, Uri uri) { + this.conn.disconnect(); + } } From 9f66ccb5f3f5dc7c2ae3610daf03b22f96173d32 Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Wed, 20 Jun 2012 11:10:43 -0700 Subject: [PATCH 18/32] merge!!!!11one --- framework/src/org/apache/cordova/CameraLauncher.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index ed0f928c..f2c3e12d 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -81,6 +81,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie private Uri imageUri; // Uri of captured image private int encodingType; // Type of encoding to use private int mediaType; // What type of media to retrieve + private boolean saveToPhotoAlbum; // Should the picture be saved to the device's photo album public String callbackId; private int numPics; @@ -121,6 +122,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie if (action.equals("takePicture")) { int srcType = CAMERA; int destType = FILE_URI; + this.saveToPhotoAlbum = false; this.targetHeight = 0; this.targetWidth = 0; this.encodingType = JPEG; @@ -134,6 +136,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie this.targetHeight = args.getInt(4); this.encodingType = args.getInt(5); this.mediaType = args.getInt(6); + this.saveToPhotoAlbum = args.getBoolean(9); if (srcType == CAMERA) { this.takePicture(destType, encodingType); From f6d4402fdc8eae41352f2f268a69e578bf33754f Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Wed, 20 Jun 2012 14:12:06 -0700 Subject: [PATCH 19/32] Removing images and saving images to jail if SaveToPhotoAlbum is set to true --- .../org/apache/cordova/CameraLauncher.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index f2c3e12d..d9467fbc 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -338,6 +338,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie ContentValues values = new ContentValues(); values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); + try { this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException e) { @@ -350,6 +351,22 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie return; } } + if (!this.saveToPhotoAlbum) { + File tempFile = new File(this.imageUri.toString()); + Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); + + // Clean up initial URI before writing out safe URI + boolean didWeDeleteIt = tempFile.delete(); + if (!didWeDeleteIt) { + int result = this.cordova.getActivity().getContentResolver().delete( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + MediaStore.Images.Media.DATA + " = ?", + new String[] { this.imageUri.toString() } + ); + LOG.d("TAG!","result is " + result); + } + this.imageUri = jailURI; + } // If all this is true we shouldn't compress the image. if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100) { @@ -378,10 +395,18 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie os.close(); // Restore exif data to file + if (this.encodingType == JPEG) { - exif.createOutFile(FileUtils.getRealPathFromURI(this.imageUri, this.cordova)); + String exifPath; + if (this.saveToPhotoAlbum) { + exifPath = FileUtils.getRealPathFromURI(this.imageUri, this.cordova); + } else { + exifPath = this.imageUri.toString(); + } + exif.createOutFile(exifPath); exif.writeExifData(); } + // Scan for the gallery to update pic refs in gallery this.scanForGallery(); From 66872de8e53e837b1f5e6472e67e134e9c53eace Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Wed, 20 Jun 2012 14:38:22 -0700 Subject: [PATCH 20/32] Tacked on file extension to camera file --- framework/src/org/apache/cordova/CameraLauncher.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index d9467fbc..0e86d2c9 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -353,9 +353,10 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie } if (!this.saveToPhotoAlbum) { File tempFile = new File(this.imageUri.toString()); - Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); + Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName() + "." + (this.encodingType == JPEG ? "jpg" : "png" ))); - // Clean up initial URI before writing out safe URI + // Clean up initial URI before writing out safe URI. + // First try File-based approach to delete. Then use the media delete method. Neither seem to work on ICS right now... boolean didWeDeleteIt = tempFile.delete(); if (!didWeDeleteIt) { int result = this.cordova.getActivity().getContentResolver().delete( @@ -363,7 +364,6 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie MediaStore.Images.Media.DATA + " = ?", new String[] { this.imageUri.toString() } ); - LOG.d("TAG!","result is " + result); } this.imageUri = jailURI; } From ab3347d25d63ae48dafd7f1e705e4edd0a4fa8f3 Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Wed, 20 Jun 2012 15:40:40 -0700 Subject: [PATCH 21/32] added . in front of the temp files passed into camera app. presumably this hsould stop the gallery app from picking it up --- framework/src/org/apache/cordova/CameraLauncher.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 0e86d2c9..68389833 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -202,9 +202,9 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie private File createCaptureFile(int encodingType) { File photo = null; if (encodingType == JPEG) { - photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), "Pic.jpg"); + photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), ".Pic.jpg"); } else if (encodingType == PNG) { - photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), "Pic.png"); + photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), ".Pic.png"); } else { throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType); } @@ -310,7 +310,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie ExifHelper exif = new ExifHelper(); try { if (this.encodingType == JPEG) { - exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/Pic.jpg"); + exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/.Pic.jpg"); exif.readExifData(); } } catch (IOException e) { From b22c0e5b6d71aefd798ededb4f7781c2d3a2278b Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Thu, 21 Jun 2012 12:08:07 -0700 Subject: [PATCH 22/32] Fixed the 0-byte files in gallery. Also fixed exif rewriter for saveToPhotoAlbum:false JPG files. Thanks for your help Simon! --- .../org/apache/cordova/CameraLauncher.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 68389833..d3938ffd 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -333,27 +333,9 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie // If sending filename back else if (destType == FILE_URI) { - // Create entry in media store for image - // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) - ContentValues values = new ContentValues(); - values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); - - - try { - this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); - } catch (UnsupportedOperationException e) { - LOG.d(LOG_TAG, "Can't write to external media storage."); - try { - this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); - } catch (UnsupportedOperationException ex) { - LOG.d(LOG_TAG, "Can't write to internal media storage."); - this.failPicture("Error capturing image - no media storage found."); - return; - } - } if (!this.saveToPhotoAlbum) { File tempFile = new File(this.imageUri.toString()); - Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName() + "." + (this.encodingType == JPEG ? "jpg" : "png" ))); + Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); // Clean up initial URI before writing out safe URI. // First try File-based approach to delete. Then use the media delete method. Neither seem to work on ICS right now... @@ -366,6 +348,24 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie ); } this.imageUri = jailURI; + } else { + // Create entry in media store for image + // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) + ContentValues values = new ContentValues(); + values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); + + try { + this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + } catch (UnsupportedOperationException e) { + LOG.d(LOG_TAG, "Can't write to external media storage."); + try { + this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); + } catch (UnsupportedOperationException ex) { + LOG.d(LOG_TAG, "Can't write to internal media storage."); + this.failPicture("Error capturing image - no media storage found."); + return; + } + } } // If all this is true we shouldn't compress the image. @@ -401,7 +401,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie if (this.saveToPhotoAlbum) { exifPath = FileUtils.getRealPathFromURI(this.imageUri, this.cordova); } else { - exifPath = this.imageUri.toString(); + exifPath = this.imageUri.getPath(); } exif.createOutFile(exifPath); exif.writeExifData(); From 94568a4ec87219401711bc42e4f549b3bd49e3f9 Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Thu, 21 Jun 2012 12:37:44 -0700 Subject: [PATCH 23/32] Merging in use of uri variable between Simon and my changes. --- .../src/org/apache/cordova/CameraLauncher.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index d3938ffd..54ab9bbb 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -333,9 +333,10 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie // If sending filename back else if (destType == FILE_URI) { + Uri uri; if (!this.saveToPhotoAlbum) { File tempFile = new File(this.imageUri.toString()); - Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); + uri = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); // Clean up initial URI before writing out safe URI. // First try File-based approach to delete. Then use the media delete method. Neither seem to work on ICS right now... @@ -347,7 +348,6 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie new String[] { this.imageUri.toString() } ); } - this.imageUri = jailURI; } else { // Create entry in media store for image // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) @@ -355,11 +355,11 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); try { - this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException e) { LOG.d(LOG_TAG, "Can't write to external media storage."); try { - this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); + uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException ex) { LOG.d(LOG_TAG, "Can't write to internal media storage."); this.failPicture("Error capturing image - no media storage found."); @@ -390,7 +390,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie bitmap = scaleBitmap(getBitmapFromResult(intent)); // Add compressed version of captured image to returned media store Uri - OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(this.imageUri); + OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); os.close(); @@ -399,9 +399,9 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie if (this.encodingType == JPEG) { String exifPath; if (this.saveToPhotoAlbum) { - exifPath = FileUtils.getRealPathFromURI(this.imageUri, this.cordova); + exifPath = FileUtils.getRealPathFromURI(uri, this.cordova); } else { - exifPath = this.imageUri.getPath(); + exifPath = uri.getPath(); } exif.createOutFile(exifPath); exif.writeExifData(); @@ -412,7 +412,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie this.scanForGallery(); // Send Uri back to JavaScript for viewing image - this.success(new PluginResult(PluginResult.Status.OK, this.imageUri.toString()), this.callbackId); + this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); } bitmap.recycle(); bitmap = null; From 574731b853087f2044136fb728fac36eb1cbd4ff Mon Sep 17 00:00:00 2001 From: Joe Bowser Date: Thu, 21 Jun 2012 11:12:30 -0700 Subject: [PATCH 24/32] Adding updated JS --- framework/assets/js/cordova.android.js | 83 +++++++++++--------------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/framework/assets/js/cordova.android.js b/framework/assets/js/cordova.android.js index 16dab290..ae20b290 100644 --- a/framework/assets/js/cordova.android.js +++ b/framework/assets/js/cordova.android.js @@ -1,6 +1,6 @@ -// commit 347de1a785b7ecbe86c2189343ab2549a9297f9b +// commit 25033fceac7c800623f1f16881b784d19eba69cc -// File generated at :: Fri Jun 08 2012 16:17:50 GMT-0700 (PDT) +// File generated at :: Thu Jun 21 2012 10:45:32 GMT-0700 (PDT) /* Licensed to the Apache Software Foundation (ASF) under one @@ -190,7 +190,9 @@ var cordova = { fireDocumentEvent: function(type, data) { var evt = createEvent(type, data); if (typeof documentEventHandlers[type] != 'undefined') { - documentEventHandlers[type].fire(evt); + setTimeout(function() { + documentEventHandlers[type].fire(evt); + }, 0); } else { document.dispatchEvent(evt); } @@ -198,7 +200,9 @@ var cordova = { fireWindowEvent: function(type, data) { var evt = createEvent(type,data); if (typeof windowEventHandlers[type] != 'undefined') { - windowEventHandlers[type].fire(evt); + setTimeout(function() { + windowEventHandlers[type].fire(evt); + }, 0); } else { window.dispatchEvent(evt); } @@ -953,8 +957,7 @@ module.exports = function(success, fail, service, action, args) { // If a result was returned if (r.length > 0) { - var v; - eval("v="+r+";"); + var v = JSON.parse(r); // If status is OK, then return value back to caller if (v.status === cordova.callbackStatus.OK) { @@ -1067,28 +1070,6 @@ module.exports = { cordova.addDocumentEventHandler('menubutton'); cordova.addDocumentEventHandler('searchbutton'); - function bindButtonChannel(buttonName) { - // generic button bind used for volumeup/volumedown buttons - return cordova.addDocumentEventHandler(buttonName + 'button', { - onSubscribe:function() { - // If we just attached the first handler, let native know we need to override the button. - if (this.numHandlers === 1) { - exec(null, null, "App", "overrideButton", [buttonName, true]); - } - }, - onUnsubscribe:function() { - // If we just detached the last handler, let native know we no longer override the volumeup button. - if (this.numHandlers === 0) { - exec(null, null, "App", "overrideButton", [buttonName, false]); - } - } - }); - - } - // Inject a listener for the volume buttons on the document. - var volumeUpButtonChannel = bindButtonChannel('volumeup'); - var volumeDownButtonChannel = bindButtonChannel('volumedown'); - // Figure out if we need to shim-in localStorage and WebSQL // support from the native side. var storage = require('cordova/plugin/android/storage'); @@ -1308,7 +1289,7 @@ cameraExport.getPicture = function(successCallback, errorCallback, options) { cameraExport.cleanup = function(successCallback, errorCallback) { exec(successCallback, errorCallback, "Camera", "cleanup", []); -} +}; module.exports = cameraExport; }); @@ -2628,7 +2609,8 @@ module.exports = FileSystem; // file: lib/common/plugin/FileTransfer.js define("cordova/plugin/FileTransfer", function(require, exports, module) { -var exec = require('cordova/exec'); +var exec = require('cordova/exec'), + FileTransferError = require('cordova/plugin/FileTransferError'); /** * FileTransfer uploads a file to a remote server. @@ -2647,6 +2629,8 @@ var FileTransfer = function() {}; * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false */ FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, trustAllHosts) { + // sanity parameter checking + if (!filePath || !server) throw new Error("FileTransfer.upload requires filePath and server URL parameters at the minimum."); // check for options var fileKey = null; var fileName = null; @@ -2668,7 +2652,12 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro } } - exec(successCallback, errorCallback, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode]); + var fail = function(e) { + var error = new FileTransferError(e.code, e.source, e.target, e.http_status); + errorCallback(error); + }; + + exec(successCallback, fail, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, trustAllHosts, chunkedMode]); }; /** @@ -2679,6 +2668,8 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro * @param errorCallback {Function} Callback to be invoked upon error */ FileTransfer.prototype.download = function(source, target, successCallback, errorCallback) { + // sanity parameter checking + if (!source || !target) throw new Error("FileTransfer.download requires source URI and target URI parameters at the minimum."); var win = function(result) { var entry = null; if (result.isDirectory) { @@ -2693,6 +2684,12 @@ FileTransfer.prototype.download = function(source, target, successCallback, erro entry.fullPath = result.fullPath; successCallback(entry); }; + + var fail = function(e) { + var error = new FileTransferError(e.code, e.source, e.target, e.http_status); + errorCallback(error); + }; + exec(win, errorCallback, 'FileTransfer', 'download', [source, target]); }; @@ -2706,8 +2703,11 @@ define("cordova/plugin/FileTransferError", function(require, exports, module) { * FileTransferError * @constructor */ -var FileTransferError = function(code) { +var FileTransferError = function(code, source, target, status) { this.code = code || null; + this.source = source || null; + this.target = target || null; + this.http_status = status || null; }; FileTransferError.FILE_NOT_FOUND_ERR = 1; @@ -2715,6 +2715,7 @@ FileTransferError.INVALID_URL_ERR = 2; FileTransferError.CONNECTION_ERR = 3; module.exports = FileTransferError; + }); // file: lib/common/plugin/FileUploadOptions.js @@ -3665,21 +3666,6 @@ module.exports = { exec(null, null, "App", "overrideBackbutton", [override]); }, - /** - * Override the default behavior of the Android volume button. - * If overridden, when the volume button is pressed, the "volume[up|down]button" JavaScript event will be fired. - * - * Note: The user should not have to call this method. Instead, when the user - * registers for the "volume[up|down]button" event, this is automatically done. - * - * @param button volumeup, volumedown - * @param override T=override, F=cancel override - */ - overrideButton:function(button, override) { - exec(null, null, "App", "overrideButton", [button, override]); - }, - - /** * Exit and terminate the application. */ @@ -5509,6 +5495,9 @@ define("cordova/plugin/splashscreen", function(require, exports, module) { var exec = require('cordova/exec'); var splashscreen = { + show:function() { + exec(null, null, "SplashScreen", "show", []); + }, hide:function() { exec(null, null, "SplashScreen", "hide", []); } From c183d06ed1f48245f7d4ed2aceecdc63f4638eae Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Tue, 19 Jun 2012 17:14:05 -0700 Subject: [PATCH 25/32] Added MediaScanner abilities to camera launcher plugin. Now images saved to SD card should show up in the android gallery app right away --- .../org/apache/cordova/CameraLauncher.java | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index e9f4ea8f..ed0f928c 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -42,6 +42,8 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.Bitmap.CompressFormat; +import android.media.MediaScannerConnection; +import android.media.MediaScannerConnection.MediaScannerConnectionClient; import android.net.Uri; import android.os.Environment; import android.provider.MediaStore; @@ -52,7 +54,7 @@ import android.util.Log; * and returns the captured image. When the camera view is closed, the screen displayed before * the camera view was shown is redisplayed. */ -public class CameraLauncher extends Plugin { +public class CameraLauncher extends Plugin implements MediaScannerConnectionClient { private static final int DATA_URL = 0; // Return base64 encoded string private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android) @@ -82,6 +84,8 @@ public class CameraLauncher extends Plugin { public String callbackId; private int numPics; + + private MediaScannerConnection conn; // Used to update gallery app with newly-written files //This should never be null! //private CordovaInterface cordova; @@ -330,13 +334,13 @@ public class CameraLauncher extends Plugin { // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) ContentValues values = new ContentValues(); values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); - Uri uri = null; + try { - uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException e) { LOG.d(LOG_TAG, "Can't write to external media storage."); try { - uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); + this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException ex) { LOG.d(LOG_TAG, "Can't write to internal media storage."); this.failPicture("Error capturing image - no media storage found."); @@ -366,24 +370,28 @@ public class CameraLauncher extends Plugin { bitmap = scaleBitmap(getBitmapFromResult(intent)); // Add compressed version of captured image to returned media store Uri - OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); + OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(this.imageUri); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); os.close(); // Restore exif data to file if (this.encodingType == JPEG) { - exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.cordova)); + exif.createOutFile(FileUtils.getRealPathFromURI(this.imageUri, this.cordova)); exif.writeExifData(); } + // Scan for the gallery to update pic refs in gallery + this.scanForGallery(); + // Send Uri back to JavaScript for viewing image - this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); + this.success(new PluginResult(PluginResult.Status.OK, this.imageUri.toString()), this.callbackId); } bitmap.recycle(); bitmap = null; System.gc(); checkForDuplicateImage(FILE_URI); + } catch (IOException e) { e.printStackTrace(); this.failPicture("Error capturing image."); @@ -584,4 +592,26 @@ public class CameraLauncher extends Plugin { public void failPicture(String err) { this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId); } + + private void scanForGallery() { + if(this.conn!=null) this.conn.disconnect(); + this.conn = new MediaScannerConnection(this.ctx.getActivity().getApplicationContext(), this); + conn.connect(); + } + + @Override + public void onMediaScannerConnected() { + try{ + this.conn.scanFile(this.imageUri.toString(), "image/*"); + } catch (java.lang.IllegalStateException e){ + e.printStackTrace(); + LOG.d(LOG_TAG, "Can;t scan file in MediaScanner aftering taking picture"); + } + + } + + @Override + public void onScanCompleted(String path, Uri uri) { + this.conn.disconnect(); + } } From 6c465e25d361f5ef5f61a818507b7fc9166ea49e Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Wed, 20 Jun 2012 11:10:43 -0700 Subject: [PATCH 26/32] merge!!!!11one --- framework/src/org/apache/cordova/CameraLauncher.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index ed0f928c..f2c3e12d 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -81,6 +81,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie private Uri imageUri; // Uri of captured image private int encodingType; // Type of encoding to use private int mediaType; // What type of media to retrieve + private boolean saveToPhotoAlbum; // Should the picture be saved to the device's photo album public String callbackId; private int numPics; @@ -121,6 +122,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie if (action.equals("takePicture")) { int srcType = CAMERA; int destType = FILE_URI; + this.saveToPhotoAlbum = false; this.targetHeight = 0; this.targetWidth = 0; this.encodingType = JPEG; @@ -134,6 +136,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie this.targetHeight = args.getInt(4); this.encodingType = args.getInt(5); this.mediaType = args.getInt(6); + this.saveToPhotoAlbum = args.getBoolean(9); if (srcType == CAMERA) { this.takePicture(destType, encodingType); From 167b60013536dd20f74fb7041fee52e4278c3a99 Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Wed, 20 Jun 2012 14:12:06 -0700 Subject: [PATCH 27/32] Removing images and saving images to jail if SaveToPhotoAlbum is set to true --- .../org/apache/cordova/CameraLauncher.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index f2c3e12d..d9467fbc 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -338,6 +338,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie ContentValues values = new ContentValues(); values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); + try { this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException e) { @@ -350,6 +351,22 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie return; } } + if (!this.saveToPhotoAlbum) { + File tempFile = new File(this.imageUri.toString()); + Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); + + // Clean up initial URI before writing out safe URI + boolean didWeDeleteIt = tempFile.delete(); + if (!didWeDeleteIt) { + int result = this.cordova.getActivity().getContentResolver().delete( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + MediaStore.Images.Media.DATA + " = ?", + new String[] { this.imageUri.toString() } + ); + LOG.d("TAG!","result is " + result); + } + this.imageUri = jailURI; + } // If all this is true we shouldn't compress the image. if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100) { @@ -378,10 +395,18 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie os.close(); // Restore exif data to file + if (this.encodingType == JPEG) { - exif.createOutFile(FileUtils.getRealPathFromURI(this.imageUri, this.cordova)); + String exifPath; + if (this.saveToPhotoAlbum) { + exifPath = FileUtils.getRealPathFromURI(this.imageUri, this.cordova); + } else { + exifPath = this.imageUri.toString(); + } + exif.createOutFile(exifPath); exif.writeExifData(); } + // Scan for the gallery to update pic refs in gallery this.scanForGallery(); From 7c67f40fc45dce040608e6d96efa654c7b93ce97 Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Wed, 20 Jun 2012 14:38:22 -0700 Subject: [PATCH 28/32] Tacked on file extension to camera file --- framework/src/org/apache/cordova/CameraLauncher.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index d9467fbc..0e86d2c9 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -353,9 +353,10 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie } if (!this.saveToPhotoAlbum) { File tempFile = new File(this.imageUri.toString()); - Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); + Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName() + "." + (this.encodingType == JPEG ? "jpg" : "png" ))); - // Clean up initial URI before writing out safe URI + // Clean up initial URI before writing out safe URI. + // First try File-based approach to delete. Then use the media delete method. Neither seem to work on ICS right now... boolean didWeDeleteIt = tempFile.delete(); if (!didWeDeleteIt) { int result = this.cordova.getActivity().getContentResolver().delete( @@ -363,7 +364,6 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie MediaStore.Images.Media.DATA + " = ?", new String[] { this.imageUri.toString() } ); - LOG.d("TAG!","result is " + result); } this.imageUri = jailURI; } From 5143b8a492b24abf0f668014339e8246927e163e Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Wed, 20 Jun 2012 15:40:40 -0700 Subject: [PATCH 29/32] added . in front of the temp files passed into camera app. presumably this hsould stop the gallery app from picking it up --- framework/src/org/apache/cordova/CameraLauncher.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 0e86d2c9..68389833 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -202,9 +202,9 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie private File createCaptureFile(int encodingType) { File photo = null; if (encodingType == JPEG) { - photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), "Pic.jpg"); + photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), ".Pic.jpg"); } else if (encodingType == PNG) { - photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), "Pic.png"); + photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), ".Pic.png"); } else { throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType); } @@ -310,7 +310,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie ExifHelper exif = new ExifHelper(); try { if (this.encodingType == JPEG) { - exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/Pic.jpg"); + exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/.Pic.jpg"); exif.readExifData(); } } catch (IOException e) { From 9d1edc4554ef8d1cece0daea18ee51b41a157802 Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Thu, 21 Jun 2012 12:08:07 -0700 Subject: [PATCH 30/32] Fixed the 0-byte files in gallery. Also fixed exif rewriter for saveToPhotoAlbum:false JPG files. Thanks for your help Simon! --- .../org/apache/cordova/CameraLauncher.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 68389833..d3938ffd 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -333,27 +333,9 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie // If sending filename back else if (destType == FILE_URI) { - // Create entry in media store for image - // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) - ContentValues values = new ContentValues(); - values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); - - - try { - this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); - } catch (UnsupportedOperationException e) { - LOG.d(LOG_TAG, "Can't write to external media storage."); - try { - this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); - } catch (UnsupportedOperationException ex) { - LOG.d(LOG_TAG, "Can't write to internal media storage."); - this.failPicture("Error capturing image - no media storage found."); - return; - } - } if (!this.saveToPhotoAlbum) { File tempFile = new File(this.imageUri.toString()); - Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName() + "." + (this.encodingType == JPEG ? "jpg" : "png" ))); + Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); // Clean up initial URI before writing out safe URI. // First try File-based approach to delete. Then use the media delete method. Neither seem to work on ICS right now... @@ -366,6 +348,24 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie ); } this.imageUri = jailURI; + } else { + // Create entry in media store for image + // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) + ContentValues values = new ContentValues(); + values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); + + try { + this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + } catch (UnsupportedOperationException e) { + LOG.d(LOG_TAG, "Can't write to external media storage."); + try { + this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); + } catch (UnsupportedOperationException ex) { + LOG.d(LOG_TAG, "Can't write to internal media storage."); + this.failPicture("Error capturing image - no media storage found."); + return; + } + } } // If all this is true we shouldn't compress the image. @@ -401,7 +401,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie if (this.saveToPhotoAlbum) { exifPath = FileUtils.getRealPathFromURI(this.imageUri, this.cordova); } else { - exifPath = this.imageUri.toString(); + exifPath = this.imageUri.getPath(); } exif.createOutFile(exifPath); exif.writeExifData(); From f3f2ad9144950ff4ec414e02a4d0927b973c8502 Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Thu, 21 Jun 2012 12:37:44 -0700 Subject: [PATCH 31/32] Merging in use of uri variable between Simon and my changes. --- .../src/org/apache/cordova/CameraLauncher.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index d3938ffd..54ab9bbb 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -333,9 +333,10 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie // If sending filename back else if (destType == FILE_URI) { + Uri uri; if (!this.saveToPhotoAlbum) { File tempFile = new File(this.imageUri.toString()); - Uri jailURI = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); + uri = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); // Clean up initial URI before writing out safe URI. // First try File-based approach to delete. Then use the media delete method. Neither seem to work on ICS right now... @@ -347,7 +348,6 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie new String[] { this.imageUri.toString() } ); } - this.imageUri = jailURI; } else { // Create entry in media store for image // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) @@ -355,11 +355,11 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); try { - this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException e) { LOG.d(LOG_TAG, "Can't write to external media storage."); try { - this.imageUri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); + uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); } catch (UnsupportedOperationException ex) { LOG.d(LOG_TAG, "Can't write to internal media storage."); this.failPicture("Error capturing image - no media storage found."); @@ -390,7 +390,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie bitmap = scaleBitmap(getBitmapFromResult(intent)); // Add compressed version of captured image to returned media store Uri - OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(this.imageUri); + OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); os.close(); @@ -399,9 +399,9 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie if (this.encodingType == JPEG) { String exifPath; if (this.saveToPhotoAlbum) { - exifPath = FileUtils.getRealPathFromURI(this.imageUri, this.cordova); + exifPath = FileUtils.getRealPathFromURI(uri, this.cordova); } else { - exifPath = this.imageUri.getPath(); + exifPath = uri.getPath(); } exif.createOutFile(exifPath); exif.writeExifData(); @@ -412,7 +412,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie this.scanForGallery(); // Send Uri back to JavaScript for viewing image - this.success(new PluginResult(PluginResult.Status.OK, this.imageUri.toString()), this.callbackId); + this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); } bitmap.recycle(); bitmap = null; From 5ca4b4a8849a54edfbe61abcdd3bfe0f1db623f0 Mon Sep 17 00:00:00 2001 From: Fil Maj Date: Thu, 21 Jun 2012 14:22:09 -0700 Subject: [PATCH 32/32] Refactored cleanup in camera code a bit. Removed overrides for Scanner functionality --- .../org/apache/cordova/CameraLauncher.java | 84 +++++++++---------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java index 54ab9bbb..3b720b71 100755 --- a/framework/src/org/apache/cordova/CameraLauncher.java +++ b/framework/src/org/apache/cordova/CameraLauncher.java @@ -335,19 +335,7 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie else if (destType == FILE_URI) { Uri uri; if (!this.saveToPhotoAlbum) { - File tempFile = new File(this.imageUri.toString()); - uri = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", tempFile.getName())); - - // Clean up initial URI before writing out safe URI. - // First try File-based approach to delete. Then use the media delete method. Neither seem to work on ICS right now... - boolean didWeDeleteIt = tempFile.delete(); - if (!didWeDeleteIt) { - int result = this.cordova.getActivity().getContentResolver().delete( - MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - MediaStore.Images.Media.DATA + " = ?", - new String[] { this.imageUri.toString() } - ); - } + uri = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", (new File(FileUtils.stripFileProtocol(this.imageUri.toString()))).getName())); } else { // Create entry in media store for image // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) @@ -381,44 +369,36 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie os.close(); fis.close(); - checkForDuplicateImage(FILE_URI); - this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); - return; - } + } else { - bitmap = scaleBitmap(getBitmapFromResult(intent)); - - // Add compressed version of captured image to returned media store Uri - OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); - bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); - os.close(); - - // Restore exif data to file - - if (this.encodingType == JPEG) { - String exifPath; - if (this.saveToPhotoAlbum) { - exifPath = FileUtils.getRealPathFromURI(uri, this.cordova); - } else { - exifPath = uri.getPath(); + bitmap = scaleBitmap(getBitmapFromResult(intent)); + + // Add compressed version of captured image to returned media store Uri + OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); + bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); + os.close(); + + // Restore exif data to file + + if (this.encodingType == JPEG) { + String exifPath; + if (this.saveToPhotoAlbum) { + exifPath = FileUtils.getRealPathFromURI(uri, this.cordova); + } else { + exifPath = uri.getPath(); + } + exif.createOutFile(exifPath); + exif.writeExifData(); } - exif.createOutFile(exifPath); - exif.writeExifData(); + } - - - // Scan for the gallery to update pic refs in gallery - this.scanForGallery(); - // Send Uri back to JavaScript for viewing image this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); } - bitmap.recycle(); + + this.cleanup(FILE_URI, this.imageUri, bitmap); bitmap = null; - System.gc(); - - checkForDuplicateImage(FILE_URI); } catch (IOException e) { e.printStackTrace(); @@ -550,6 +530,22 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie null, null); } + + /** + * Cleans up after picture taking. Checking for duplicates and that kind of stuff. + */ + private void cleanup(int imageType, Uri oldImage, Bitmap bitmap) { + bitmap.recycle(); + + // Clean up initial camera-written image file. + (new File(FileUtils.stripFileProtocol(oldImage.toString()))).delete(); + + checkForDuplicateImage(imageType); + // Scan for the gallery to update pic refs in gallery + this.scanForGallery(); + + System.gc(); + } /** * Used to find out if we are in a situation where the Camera Intent adds to images @@ -627,7 +623,6 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie conn.connect(); } - @Override public void onMediaScannerConnected() { try{ this.conn.scanFile(this.imageUri.toString(), "image/*"); @@ -638,7 +633,6 @@ public class CameraLauncher extends Plugin implements MediaScannerConnectionClie } - @Override public void onScanCompleted(String path, Uri uri) { this.conn.disconnect(); }