diff --git a/.gitignore b/.gitignore
index 9f90a6b1..e73b34b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,28 +4,29 @@ gen
assets/www/cordova.js
framework/assets/www/.tmp*
local.properties
-framework/proguard.cfg
-framework/cordova.jar
-framework/cordova-*.jar
-framework/phonegap-*.jar
+framework/lib
+proguard.cfg
+proguard.cfg
+proguard-project.txt
framework/bin
framework/test/org/apache/cordova/*.class
framework/assets/www/.DS_Store
framework/assets/www/cordova-*.js
framework/assets/www/phonegap-*.js
framework/libs
+test/libs
example
./test
test/bin
test/assets/www/.tmp*
tmp/**
-*.tmp
-test/libs/*.jar
bin/node_modules
.metadata
-*.bak
tmp/**/*
-*.swp
Thumbs.db
Desktop.ini
-
+*.tmp
+*.bak
+*.swp
+*.class
+*.jar
diff --git a/VERSION b/VERSION
index ccbccc3d..d2a7ed1f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.0
+2.3.0rc1
diff --git a/bin/create b/bin/create
index 1bce739e..e01cef98 100755
--- a/bin/create
+++ b/bin/create
@@ -147,13 +147,13 @@ replace "s/__ACTIVITY__/${ACTIVITY}/g" "$MANIFEST_PATH"
replace "s/__PACKAGE__/${PACKAGE}/g" "$MANIFEST_PATH"
replace "s/__APILEVEL__/${API_LEVEL}/g" "$MANIFEST_PATH"
-# creating cordova folder and copying emulate/debug/log/launch scripts
+# creating cordova folder and copying run/build/log/launch scripts
mkdir "$PROJECT_PATH"/cordova
createAppInfoJar
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/build "$PROJECT_PATH"/cordova/build
+cp "$BUILD_PATH"/bin/templates/cordova/release "$PROJECT_PATH"/cordova/release
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
+cp "$BUILD_PATH"/bin/templates/cordova/run "$PROJECT_PATH"/cordova/run
diff --git a/bin/create.js b/bin/create.js
index 2d6b8d61..258c32cd 100644
--- a/bin/create.js
+++ b/bin/create.js
@@ -198,10 +198,9 @@ exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\appinfo.jar ' + PRO
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.js ' + PROJECT_PATH + '\\cordova\\cordova.js /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\cordova.bat ' + PROJECT_PATH + '\\cordova\\cordova.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\clean.bat ' + PROJECT_PATH + '\\cordova\\clean.bat /Y');
-exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\debug.bat ' + PROJECT_PATH + '\\cordova\\debug.bat /Y');
+exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\build.bat ' + PROJECT_PATH + '\\cordova\\build.bat /Y');
exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\log.bat ' + PROJECT_PATH + '\\cordova\\log.bat /Y');
-exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\emulate.bat ' + PROJECT_PATH + '\\cordova\\emulate.bat /Y');
-exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\BOOM.bat ' + PROJECT_PATH + '\\cordova\\BOOM.bat /Y');
+exec('%comspec% /c copy "'+ROOT+'"\\bin\\templates\\cordova\\run.bat ' + PROJECT_PATH + '\\cordova\\run.bat /Y');
// interpolate the activity name and package
WScript.Echo("Updating AndroidManifest.xml and Main Activity...");
diff --git a/bin/templates/cordova/debug b/bin/templates/cordova/build
similarity index 96%
rename from bin/templates/cordova/debug
rename to bin/templates/cordova/build
index aaa59780..e586e4d6 100755
--- a/bin/templates/cordova/debug
+++ b/bin/templates/cordova/build
@@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
-bash "$CORDOVA_PATH"/cordova debug
+bash "$CORDOVA_PATH"/cordova build
diff --git a/bin/templates/cordova/BOOM.bat b/bin/templates/cordova/build.bat
similarity index 97%
rename from bin/templates/cordova/BOOM.bat
rename to bin/templates/cordova/build.bat
index 7b83f2ac..8e6ca9ad 100644
--- a/bin/templates/cordova/BOOM.bat
+++ b/bin/templates/cordova/build.bat
@@ -15,4 +15,4 @@
:: specific language governing permissions and limitations
:: under the License.
-%~dp0\cordova.bat BOOM
+%~dp0\cordova.bat build
diff --git a/bin/templates/cordova/cordova b/bin/templates/cordova/cordova
index 1a1a4870..1945a4c4 100755
--- a/bin/templates/cordova/cordova
+++ b/bin/templates/cordova/cordova
@@ -17,12 +17,12 @@
#!/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 }}'`
+# FIXME
+ local devices=`adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}' | grep device`
if [ -z "$devices" ] ; then
echo "1"
else
@@ -37,7 +37,6 @@ function emulate {
# 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
@@ -62,8 +61,9 @@ function emulate {
do
echo "$i) ${avd_list[$i]}"
done
- echo -n "> "
- read avd_id
+ read -t 5 -p "> " avd_id
+ # default value if input timeout
+ if [ $avd_id -eq 1000 ] ; then avd_id=0 ; fi
done
emulator -cpu-delay 0 -no-boot-anim -cache /tmp/cache -avd ${avd_list[$avd_id]} 1> /dev/null 2>&1 &
fi
@@ -78,14 +78,75 @@ function log {
adb logcat
}
-function debug {
- if [ $(check_devices) == 0 ] ; then
- ant debug install
+function run {
+ clean && emulate && wait_for_device && install && launch
+}
+
+function install {
+
+ declare -a devices=($(adb devices | awk '/List of devices attached/ { while(getline > 0) { print }}' | grep device | cut -f 1))
+ local device_id="1000" #FIXME: hopefully user does not have 1000 AVDs
+
+ if [ ${#devices[@]} == 0 ]
+ then
+ # should not reach here. Emulator should launch or device should be attached
+ echo "Emulator not running or device not attached. Could not install debug package"
+ exit 70
+ fi
+
+ if [ ${#devices[@]} == 1 ]
+ then
+ export ANDROID_SERIAL=${devices[0]}
+ # User has more than 1 AVD
+ elif [ ${#devices[@]} -gt 1 ]
+ then
+ while [ -z ${devices[$device_id]} ]
+ do
+ echo "Choose from one of the following devices/emulators [0 to $((${#devices[@]}-1))]:"
+ for(( i = 0 ; i < ${#devices[@]} ; i++ ))
+ do
+ echo "$i) ${devices[$i]}"
+ done
+ read -t 5 -p "> " device_id
+ # default value if input timeout
+ if [ $device_id -eq 1000 ] ; then device_id=0 ; fi
+ done
+ export ANDROID_SERIAL=${devices[$device_id]}
+ fi
+
+ ant debug install
+}
+
+function build {
+ ant debug
+}
+
+function release {
+ ant release
+}
+
+function wait_for_device {
+ local i="0"
+ echo -n "Waiting for device..."
+
+ while [ $i -lt 300 ]
+ do
+ if [ $(check_devices) -eq 0 ]
+ then
+ break
+ else
+ sleep 1
+ i=$[i+1]
+ echo -n "."
+ fi
+ done
+ # Device timeout: emulator has not started in time or device not attached
+ if [ $i -eq 300 ]
+ then
+ echo "device timeout!"
+ exit 69
else
- ant debug
- echo "##################################################################"
- echo "# Plug in your device or launch an emulator with cordova/emulate #"
- echo "##################################################################"
+ echo "connected!"
fi
}
@@ -94,9 +155,5 @@ function launch {
adb shell am start -n $launch_str
}
-function BOOM {
- clean && debug && launch
-}
-
# TODO parse arguments
(cd "$PROJECT_PATH" && $1)
diff --git a/bin/templates/cordova/cordova.js b/bin/templates/cordova/cordova.js
index ff91430b..51533cb9 100644
--- a/bin/templates/cordova/cordova.js
+++ b/bin/templates/cordova/cordova.js
@@ -34,17 +34,19 @@ function exec(command) {
return output;
}
-function emulator_running() {
+function device_running() {
var local_devices = shell.Exec("%comspec% /c adb devices").StdOut.ReadAll();
- if(local_devices.match(/emulator/)) {
+ if(local_devices.match(/\w+\tdevice/)) {
+ WScript.Echo("Yes");
return true;
}
+ WScript.Echo("No");
return false;
}
function emulate() {
// don't run emulator if a device is plugged in or if emulator is already running
- if(emulator_running()) {
- WScript.Echo("Device or Emulator already running!");
+ if(device_running()) {
+ //WScript.Echo("Device or Emulator already running!");
return;
}
var oExec = shell.Exec("%comspec% /c android.bat list avd");
@@ -84,18 +86,18 @@ function emulate() {
}
function clean() {
+ WScript.Echo("Cleaning project...");
exec("%comspec% /c ant.bat clean -f "+ROOT+"\\build.xml 2>&1");
}
-function debug() {
- if(emulator_running()) {
- exec("%comspec% /c ant.bat debug install -f "+ROOT+"\\build.xml 2>&1");
- } else {
- exec("%comspec% /c ant.bat debug -f "+ROOT+"\\build.xml 2>&1");
- WScript.Echo("##################################################################");
- WScript.Echo("# Plug in your device or launch an emulator with cordova/emulate #");
- WScript.Echo("##################################################################");
- }
+function build() {
+ WScript.Echo("Building project...");
+ exec("%comspec% /c ant.bat debug -f "+ROOT+"\\build.xml 2>&1");
+}
+
+function install() {
+ WScript.Echo("Building/Installing project...");
+ exec("%comspec% /c ant.bat debug install -f "+ROOT+"\\build.xml 2>&1");
}
function log() {
@@ -103,14 +105,28 @@ function log() {
}
function launch() {
+ WScript.Echo("Launching app...");
var launch_str=exec("%comspec% /c java -jar "+ROOT+"\\cordova\\appinfo.jar "+ROOT+"\\AndroidManifest.xml");
//WScript.Echo(launch_str);
exec("%comspec% /c adb shell am start -n "+launch_str+" 2>&1");
}
-function BOOM() {
+function run() {
+ var i=0;
clean();
- debug();
+ emulate();
+ WScript.Stdout.Write('Waiting for device...');
+ while(!device_running() && i < 300) {
+ WScript.Stdout.Write('.');
+ WScript.sleep(1000);
+ i += 1;
+ }
+ if(i == 300) {
+ WScript.Stderr.WriteLine("device/emulator timeout!");
+ } else {
+ WScript.Stdout.WriteLine("connected!");
+ }
+ install();
launch();
}
var args = WScript.Arguments;
diff --git a/bin/templates/cordova/debug.bat b/bin/templates/cordova/debug.bat
deleted file mode 100644
index f980eb72..00000000
--- a/bin/templates/cordova/debug.bat
+++ /dev/null
@@ -1,18 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-%~dp0\cordova.bat debug
diff --git a/bin/templates/cordova/emulate.bat b/bin/templates/cordova/emulate.bat
deleted file mode 100644
index 87ef969f..00000000
--- a/bin/templates/cordova/emulate.bat
+++ /dev/null
@@ -1 +0,0 @@
-%~dp0\cordova.bat emulate
diff --git a/bin/templates/cordova/emulate b/bin/templates/cordova/release
similarity index 95%
rename from bin/templates/cordova/emulate
rename to bin/templates/cordova/release
index fe27b2f3..73d873e3 100755
--- a/bin/templates/cordova/emulate
+++ b/bin/templates/cordova/release
@@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
-bash "$CORDOVA_PATH"/cordova emulate
+bash "$CORDOVA_PATH"/cordova release
diff --git a/bin/templates/cordova/BOOM b/bin/templates/cordova/run
similarity index 96%
rename from bin/templates/cordova/BOOM
rename to bin/templates/cordova/run
index 443502d8..840a8d5a 100755
--- a/bin/templates/cordova/BOOM
+++ b/bin/templates/cordova/run
@@ -21,4 +21,4 @@ set -e
CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd )
-bash $CORDOVA_PATH/cordova BOOM
+bash "$CORDOVA_PATH"/cordova run
diff --git a/bin/templates/cordova/run.bat b/bin/templates/cordova/run.bat
new file mode 100644
index 00000000..7c470ed8
--- /dev/null
+++ b/bin/templates/cordova/run.bat
@@ -0,0 +1 @@
+%~dp0\cordova.bat run
diff --git a/bin/templates/project/assets/www/index.html b/bin/templates/project/assets/www/index.html
index 4f8dc5f2..0f8a50bc 100644
--- a/bin/templates/project/assets/www/index.html
+++ b/bin/templates/project/assets/www/index.html
@@ -33,7 +33,7 @@
Device is Ready
-
+
+
diff --git a/framework/project.properties b/framework/project.properties
index 4383e57e..d556741d 100644
--- a/framework/project.properties
+++ b/framework/project.properties
@@ -10,7 +10,7 @@
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
-target=Google Inc.:Google APIs:16
+target=Google Inc.:Google APIs:17
apk-configurations=
renderscript.opt.level=O0
android.library=true
diff --git a/framework/res/xml/config.xml b/framework/res/xml/config.xml
index da9c1f46..b6900078 100644
--- a/framework/res/xml/config.xml
+++ b/framework/res/xml/config.xml
@@ -51,6 +51,7 @@
+
diff --git a/framework/src/org/apache/cordova/App.java b/framework/src/org/apache/cordova/App.java
index 7bdf1166..dad34a07 100755
--- a/framework/src/org/apache/cordova/App.java
+++ b/framework/src/org/apache/cordova/App.java
@@ -19,28 +19,30 @@
package org.apache.cordova;
+import org.apache.cordova.api.CallbackContext;
+import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.LOG;
-import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+
import java.util.HashMap;
/**
* This class exposes methods in DroidGap that can be called from JavaScript.
*/
-public class App extends Plugin {
+public class App extends CordovaPlugin {
/**
* Executes the request and returns PluginResult.
*
- * @param action The action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param callbackId The callback id used when calling back into JavaScript.
- * @return A PluginResult object with a status and message.
+ * @param action The action to execute.
+ * @param args JSONArry of arguments for the plugin.
+ * @param callbackContext The callback context from which we were invoked.
+ * @return A PluginResult object with a status and message.
*/
- public PluginResult execute(String action, JSONArray args, String callbackId) {
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
PluginResult.Status status = PluginResult.Status.OK;
String result = "";
@@ -79,9 +81,11 @@ public class App extends Plugin {
else if (action.equals("exitApp")) {
this.exitApp();
}
- return new PluginResult(status, result);
+ callbackContext.sendPluginResult(new PluginResult(status, result));
+ return true;
} catch (JSONException e) {
- return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+ return false;
}
}
diff --git a/framework/src/org/apache/cordova/CameraLauncher.java b/framework/src/org/apache/cordova/CameraLauncher.java
index f9cfb94a..49a68c03 100755
--- a/framework/src/org/apache/cordova/CameraLauncher.java
+++ b/framework/src/org/apache/cordova/CameraLauncher.java
@@ -289,6 +289,17 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
// If sending base64 image back
if (destType == DATA_URL) {
bitmap = getScaledBitmap(FileUtils.stripFileProtocol(imageUri.toString()));
+ if (bitmap == null) {
+ // Try to get the bitmap from intent.
+ bitmap = (Bitmap)intent.getExtras().get("data");
+ }
+
+ // Double-check the bitmap.
+ if (bitmap == null) {
+ Log.d(LOG_TAG, "I either have a null image path or bitmap");
+ this.failPicture("Unable to create bitmap!");
+ return;
+ }
if (rotate != 0 && this.correctOrientation) {
bitmap = getRotatedBitmap(rotate, bitmap, exif);
@@ -567,6 +578,9 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, this.targetWidth, this.targetHeight);
Bitmap unscaledBitmap = BitmapFactory.decodeFile(imagePath, options);
+ if (unscaledBitmap == null) {
+ return null;
+ }
return Bitmap.createScaledBitmap(unscaledBitmap, widthHeight[0], widthHeight[1], true);
}
diff --git a/framework/src/org/apache/cordova/Capture.java b/framework/src/org/apache/cordova/Capture.java
index 4cf46dd5..3eecf379 100644
--- a/framework/src/org/apache/cordova/Capture.java
+++ b/framework/src/org/apache/cordova/Capture.java
@@ -127,7 +127,7 @@ public class Capture extends CordovaPlugin {
// If the mimeType isn't set the rest will fail
// so let's see if we can determine it.
- if (mimeType == null || mimeType.equals("")) {
+ if (mimeType == null || mimeType.equals("") || "null".equals(mimeType)) {
mimeType = FileUtils.getMimeType(filePath);
}
Log.d(LOG_TAG, "Mime type = " + mimeType);
diff --git a/framework/src/org/apache/cordova/ContactAccessorSdk5.java b/framework/src/org/apache/cordova/ContactAccessorSdk5.java
index 8497135e..73d05bc0 100644
--- a/framework/src/org/apache/cordova/ContactAccessorSdk5.java
+++ b/framework/src/org/apache/cordova/ContactAccessorSdk5.java
@@ -1579,7 +1579,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
Uri uri = Uri.parse(path);
return mApp.getActivity().getContentResolver().openInputStream(uri);
}
- if (path.startsWith("http:") || path.startsWith("file:")) {
+ if (path.startsWith("http:") || path.startsWith("https:") || path.startsWith("file:")) {
URL url = new URL(path);
return url.openStream();
}
diff --git a/framework/src/org/apache/cordova/CordovaWebView.java b/framework/src/org/apache/cordova/CordovaWebView.java
index a2b65663..336cf521 100755
--- a/framework/src/org/apache/cordova/CordovaWebView.java
+++ b/framework/src/org/apache/cordova/CordovaWebView.java
@@ -20,6 +20,8 @@
package org.apache.cordova;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -98,8 +100,8 @@ public class CordovaWebView extends WebView {
private long lastMenuEventTime = 0;
- NativeToJsMessageQueue jsMessageQueue;
- ExposedJsApi exposedJsApi;
+ NativeToJsMessageQueue jsMessageQueue;
+ ExposedJsApi exposedJsApi;
/** custom view created by the browser (a video player for example) */
private View mCustomView;
@@ -200,8 +202,8 @@ public class CordovaWebView extends WebView {
* @param defStyle
* @param privateBrowsing
*/
- @TargetApi(11)
- public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
+ @TargetApi(11)
+ public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
super(context, attrs, defStyle, privateBrowsing);
if (CordovaInterface.class.isInstance(context))
{
@@ -244,15 +246,28 @@ public class CordovaWebView extends WebView {
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
-
- //Set the nav dump for HTC 2.x devices (disabling for ICS/Jellybean)
- if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
- settings.setNavDump(true);
+ // Set the nav dump for HTC 2.x devices (disabling for ICS, deprecated entirely for Jellybean 4.2)
+ try {
+ Method gingerbread_getMethod = WebSettings.class.getMethod("setNavDump", new Class[] { boolean.class });
+ if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
+ {
+ gingerbread_getMethod.invoke(settings, true);
+ }
+ } catch (NoSuchMethodException e) {
+ Log.d(TAG, "We are on a modern version of Android, we will deprecate HTC 2.3 devices in 2.8");
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "Doing the NavDump failed with bad arguments");
+ } catch (IllegalAccessException e) {
+ Log.d(TAG, "This should never happen: IllegalAccessException means this isn't Android anymore");
+ } catch (InvocationTargetException e) {
+ Log.d(TAG, "This should never happen: InvocationTargetException means this isn't Android anymore.");
+ }
+
// Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
// while we do this
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
- Level16Apis.enableUniversalAccess(settings);
+ Level16Apis.enableUniversalAccess(settings);
// Enable database
settings.setDatabaseEnabled(true);
String databasePath = this.cordova.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
@@ -288,17 +303,19 @@ public class CordovaWebView extends WebView {
}
private void updateUserAgentString() {
- this.getSettings().getUserAgentString();
+ this.getSettings().getUserAgentString();
}
private void exposeJsInterface() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
+ int SDK_INT = Build.VERSION.SDK_INT;
+ boolean isHoneycomb = (SDK_INT >= Build.VERSION_CODES.HONEYCOMB && SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2);
+ if (isHoneycomb || (SDK_INT < Build.VERSION_CODES.GINGERBREAD)) {
Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");
// Bug being that Java Strings do not get converted to JS strings automatically.
// This isn't hard to work-around on the JS side, but it's easier to just
// use the prompt bridge instead.
return;
- } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) {
+ } else if (SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) {
// addJavascriptInterface crashes on the 2.3 emulator.
Log.i(TAG, "Disabled addJavascriptInterface() bridge callback due to a bug on the 2.3 emulator");
return;
@@ -610,7 +627,7 @@ public class CordovaWebView extends WebView {
// Check webview first to see if there is a history
// This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
if (super.canGoBack()) {
- printBackForwardList();
+ printBackForwardList();
super.goBack();
return true;
@@ -841,27 +858,27 @@ public class CordovaWebView extends WebView {
// If back key
if (keyCode == KeyEvent.KEYCODE_BACK) {
// A custom view is currently displayed (e.g. playing a video)
- if(mCustomView != null) {
- this.hideCustomView();
- } else {
- // The webview is currently displayed
- // If back key is bound, then send event to JavaScript
- if (this.bound) {
- this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
- return true;
- } else {
- // If not bound
- // Go to previous page in webview if it is possible to go back
- if (this.backHistory()) {
- return true;
- }
- // If not, then invoke default behaviour
- else {
- //this.activityState = ACTIVITY_EXITING;
- return false;
- }
- }
- }
+ if(mCustomView != null) {
+ this.hideCustomView();
+ } else {
+ // The webview is currently displayed
+ // If back key is bound, then send event to JavaScript
+ if (this.bound) {
+ this.loadUrl("javascript:cordova.fireDocumentEvent('backbutton');");
+ return true;
+ } else {
+ // If not bound
+ // Go to previous page in webview if it is possible to go back
+ if (this.backHistory()) {
+ return true;
+ }
+ // If not, then invoke default behaviour
+ else {
+ //this.activityState = ACTIVITY_EXITING;
+ return false;
+ }
+ }
+ }
}
// Legacy
else if (keyCode == KeyEvent.KEYCODE_MENU) {
@@ -1003,14 +1020,14 @@ public class CordovaWebView extends WebView {
}
public void printBackForwardList() {
- WebBackForwardList currentList = this.copyBackForwardList();
- int currentSize = currentList.getSize();
- for(int i = 0; i < currentSize; ++i)
- {
- WebHistoryItem item = currentList.getItemAtIndex(i);
- String url = item.getUrl();
- LOG.d(TAG, "The URL at index: " + Integer.toString(i) + "is " + url );
- }
+ WebBackForwardList currentList = this.copyBackForwardList();
+ int currentSize = currentList.getSize();
+ for(int i = 0; i < currentSize; ++i)
+ {
+ WebHistoryItem item = currentList.getItemAtIndex(i);
+ String url = item.getUrl();
+ LOG.d(TAG, "The URL at index: " + Integer.toString(i) + "is " + url );
+ }
}
@@ -1027,8 +1044,8 @@ public class CordovaWebView extends WebView {
}
public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
- // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
- Log.d(TAG, "showing Custom View");
+ // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
+ Log.d(TAG, "showing Custom View");
// if a view already exists then immediately terminate the new one
if (mCustomView != null) {
callback.onCustomViewHidden();
@@ -1036,57 +1053,57 @@ public class CordovaWebView extends WebView {
}
// Store the view and its callback for later (to kill it properly)
- mCustomView = view;
- mCustomViewCallback = callback;
-
+ mCustomView = view;
+ mCustomViewCallback = callback;
+
// Add the custom view to its container.
- ViewGroup parent = (ViewGroup) this.getParent();
- parent.addView(view, COVER_SCREEN_GRAVITY_CENTER);
-
- // Hide the content view.
- this.setVisibility(View.GONE);
-
- // Finally show the custom view container.
- parent.setVisibility(View.VISIBLE);
- parent.bringToFront();
+ ViewGroup parent = (ViewGroup) this.getParent();
+ parent.addView(view, COVER_SCREEN_GRAVITY_CENTER);
+
+ // Hide the content view.
+ this.setVisibility(View.GONE);
+
+ // Finally show the custom view container.
+ parent.setVisibility(View.VISIBLE);
+ parent.bringToFront();
}
- public void hideCustomView() {
- // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
- Log.d(TAG, "Hidding Custom View");
- if (mCustomView == null) return;
+ public void hideCustomView() {
+ // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
+ Log.d(TAG, "Hidding Custom View");
+ if (mCustomView == null) return;
- // Hide the custom view.
- mCustomView.setVisibility(View.GONE);
-
- // Remove the custom view from its container.
- ViewGroup parent = (ViewGroup) this.getParent();
- parent.removeView(mCustomView);
- mCustomView = null;
- mCustomViewCallback.onCustomViewHidden();
-
+ // Hide the custom view.
+ mCustomView.setVisibility(View.GONE);
+
+ // Remove the custom view from its container.
+ ViewGroup parent = (ViewGroup) this.getParent();
+ parent.removeView(mCustomView);
+ mCustomView = null;
+ mCustomViewCallback.onCustomViewHidden();
+
// Show the content view.
this.setVisibility(View.VISIBLE);
- }
-
- /**
- * if the video overlay is showing then we need to know
- * as it effects back button handling
- *
- * @return
- */
- public boolean isCustomViewShowing() {
- return mCustomView != null;
- }
-
- public WebBackForwardList restoreState(Bundle savedInstanceState)
- {
- WebBackForwardList myList = super.restoreState(savedInstanceState);
- Log.d(TAG, "WebView restoration crew now restoring!");
- //Initialize the plugin manager once more
- this.pluginManager.init();
- return myList;
- }
+ }
+
+ /**
+ * if the video overlay is showing then we need to know
+ * as it effects back button handling
+ *
+ * @return
+ */
+ public boolean isCustomViewShowing() {
+ return mCustomView != null;
+ }
+
+ public WebBackForwardList restoreState(Bundle savedInstanceState)
+ {
+ WebBackForwardList myList = super.restoreState(savedInstanceState);
+ Log.d(TAG, "WebView restoration crew now restoring!");
+ //Initialize the plugin manager once more
+ this.pluginManager.init();
+ return myList;
+ }
public void storeResult(int requestCode, int resultCode, Intent intent) {
mResult = new ActivityResult(requestCode, resultCode, intent);
diff --git a/framework/src/org/apache/cordova/Device.java b/framework/src/org/apache/cordova/Device.java
index 6a164740..8967bf47 100644
--- a/framework/src/org/apache/cordova/Device.java
+++ b/framework/src/org/apache/cordova/Device.java
@@ -39,7 +39,7 @@ import android.telephony.TelephonyManager;
public class Device extends CordovaPlugin {
public static final String TAG = "Device";
- public static String cordovaVersion = "2.2.0"; // Cordova version
+ public static String cordovaVersion = "2.3.0rc1"; // Cordova version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID
@@ -80,9 +80,7 @@ public class Device extends CordovaPlugin {
r.put("platform", Device.platform);
r.put("name", this.getProductName());
r.put("cordova", Device.cordovaVersion);
- //JSONObject pg = new JSONObject();
- //pg.put("version", Device.CordovaVersion);
- //r.put("cordova", pg);
+ r.put("model", this.getProductName());
callbackContext.success(r);
}
else {
diff --git a/framework/src/org/apache/cordova/DroidGap.java b/framework/src/org/apache/cordova/DroidGap.java
index 51c9c595..3288e726 100755
--- a/framework/src/org/apache/cordova/DroidGap.java
+++ b/framework/src/org/apache/cordova/DroidGap.java
@@ -40,7 +40,6 @@ import android.graphics.Color;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
-import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu;
@@ -156,11 +155,6 @@ public class DroidGap extends Activity implements CordovaInterface {
private static int ACTIVITY_EXITING = 2;
private int activityState = 0; // 0=starting, 1=running (after 1st resume), 2=shutting down
- // The base of the initial URL for our app.
- // Does not include file name. Ends with /
- // ie http://server/path/
- String baseUrl = null;
-
// Plugin to call when activity result is received
protected CordovaPlugin activityResultCallback = null;
protected boolean activityResultKeepRunning;
@@ -859,7 +853,7 @@ public class DroidGap extends Activity implements CordovaInterface {
// If errorUrl specified, then load it
final String errorUrl = me.getStringProperty("errorUrl", null);
- if ((errorUrl != null) && (errorUrl.startsWith("file://") || errorUrl.indexOf(me.baseUrl) == 0 || this.appView.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
+ if ((errorUrl != null) && (errorUrl.startsWith("file://") || this.appView.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
// Load URL on UI thread
me.runOnUiThread(new Runnable() {
diff --git a/framework/src/org/apache/cordova/ExposedJsApi.java b/framework/src/org/apache/cordova/ExposedJsApi.java
index b386a402..a36bb62b 100755
--- a/framework/src/org/apache/cordova/ExposedJsApi.java
+++ b/framework/src/org/apache/cordova/ExposedJsApi.java
@@ -18,6 +18,7 @@
*/
package org.apache.cordova;
+import android.webkit.JavascriptInterface;
import org.apache.cordova.api.PluginManager;
import org.apache.cordova.api.PluginResult;
import org.json.JSONException;
@@ -37,6 +38,7 @@ import org.json.JSONException;
this.jsMessageQueue = jsMessageQueue;
}
+ @JavascriptInterface
public String exec(String service, String action, String callbackId, String arguments) throws JSONException {
jsMessageQueue.setPaused(true);
try {
@@ -51,10 +53,12 @@ import org.json.JSONException;
}
}
+ @JavascriptInterface
public void setNativeToJsBridgeMode(int value) {
jsMessageQueue.setBridgeMode(value);
}
+ @JavascriptInterface
public String retrieveJsMessages() {
return jsMessageQueue.popAndEncode();
}
diff --git a/framework/src/org/apache/cordova/FileUtils.java b/framework/src/org/apache/cordova/FileUtils.java
index 973b820d..8aff2629 100755
--- a/framework/src/org/apache/cordova/FileUtils.java
+++ b/framework/src/org/apache/cordova/FileUtils.java
@@ -984,8 +984,16 @@ public class FileUtils extends CordovaPlugin {
* @return a mime type
*/
public static String getMimeType(String filename) {
+ // Stupid bug in getFileExtensionFromUrl when the file name has a space
+ // So we need to replace the space with a url encoded %20
+ String url = filename.replace(" ", "%20");
MimeTypeMap map = MimeTypeMap.getSingleton();
- return map.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(filename));
+ String extension = MimeTypeMap.getFileExtensionFromUrl(url);
+ if (extension.toLowerCase().equals("3ga")) {
+ return "audio/3gpp";
+ } else {
+ return map.getMimeTypeFromExtension(extension);
+ }
}
/**
@@ -1069,16 +1077,18 @@ public class FileUtils extends CordovaPlugin {
*/
@SuppressWarnings("deprecation")
protected static String getRealPathFromURI(Uri contentUri, CordovaInterface cordova) {
- String uri = contentUri.toString();
- if (uri.startsWith("content:")) {
+ final String scheme = contentUri.getScheme();
+
+ if (scheme.compareTo("content") == 0) {
String[] proj = { _DATA };
Cursor cursor = cordova.getActivity().managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(_DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
+ } else if (scheme.compareTo("file") == 0) {
+ return contentUri.getPath();
} else {
- return uri;
+ return contentUri.toString();
}
-
}
}
diff --git a/framework/src/org/apache/cordova/InAppBrowser.java b/framework/src/org/apache/cordova/InAppBrowser.java
new file mode 100644
index 00000000..338d3440
--- /dev/null
+++ b/framework/src/org/apache/cordova/InAppBrowser.java
@@ -0,0 +1,513 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+package org.apache.cordova;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import org.apache.cordova.api.CallbackContext;
+import org.apache.cordova.api.CordovaPlugin;
+import org.apache.cordova.api.PluginResult;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.text.InputType;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+
+public class InAppBrowser extends CordovaPlugin {
+
+ private static final String NULL = "null";
+ protected static final String LOG_TAG = "InAppBrowser";
+ private static final String SELF = "_self";
+ private static final String SYSTEM = "_system";
+ private static final String BLANK = "_blank";
+ private static final String LOCATION = "location";
+ private static int CLOSE_EVENT = 0;
+ private static int LOCATION_CHANGED_EVENT = 1;
+
+ private String browserCallbackId = null;
+
+ private Dialog dialog;
+ private WebView inAppWebView;
+ private EditText edittext;
+ private boolean showLocationBar = true;
+ private CallbackContext callbackContext;
+
+ /**
+ * Executes the request and returns PluginResult.
+ *
+ * @param action The action to execute.
+ * @param args JSONArry of arguments for the plugin.
+ * @param callbackId The callback id used when calling back into JavaScript.
+ * @return A PluginResult object with a status and message.
+ */
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+ PluginResult.Status status = PluginResult.Status.OK;
+ String result = "";
+ this.callbackContext = callbackContext;
+
+ try {
+ if (action.equals("open")) {
+ String url = args.getString(0);
+ String target = args.optString(1);
+ if (target == null || target.equals("") || target.equals(NULL)) {
+ target = SELF;
+ }
+ HashMap features = parseFeature(args.optString(2));
+
+ Log.d(LOG_TAG, "target = " + target);
+
+ url = updateUrl(url);
+
+ // SELF
+ if (SELF.equals(target)) {
+ Log.d(LOG_TAG, "in self");
+ // load in webview
+ if (url.startsWith("file://") || url.startsWith("javascript:")
+ || this.webView.isUrlWhiteListed(url)) {
+ this.webView.loadUrl(url);
+ }
+ // load in InAppBrowser
+ else {
+ result = this.showWebPage(url, features);
+ }
+ }
+ // SYSTEM
+ else if (SYSTEM.equals(target)) {
+ Log.d(LOG_TAG, "in system");
+ result = this.openExternal(url);
+ }
+ // BLANK - or anything else
+ else {
+ Log.d(LOG_TAG, "in blank");
+ result = this.showWebPage(url, features);
+ }
+ }
+ else if (action.equals("close")) {
+ closeDialog();
+
+ JSONObject obj = new JSONObject();
+ obj.put("type", CLOSE_EVENT);
+
+ PluginResult pluginResult = new PluginResult(status, obj);
+ pluginResult.setKeepCallback(false);
+ this.callbackContext.sendPluginResult(pluginResult);
+ }
+ else {
+ status = PluginResult.Status.INVALID_ACTION;
+ }
+ this.callbackContext.sendPluginResult(new PluginResult(status, result));
+ } catch (JSONException e) {
+ this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+ }
+ return true;
+ }
+
+ /**
+ * Put the list of features into a hash map
+ *
+ * @param optString
+ * @return
+ */
+ private HashMap parseFeature(String optString) {
+ if (optString.equals(NULL)) {
+ return null;
+ } else {
+ HashMap map = new HashMap();
+ StringTokenizer features = new StringTokenizer(optString, ",");
+ StringTokenizer option;
+ while(features.hasMoreElements()) {
+ option = new StringTokenizer(features.nextToken(), "=");
+ if (option.hasMoreElements()) {
+ String key = option.nextToken();
+ Boolean value = option.nextToken().equals("no") ? Boolean.FALSE : Boolean.TRUE;
+ map.put(key, value);
+ }
+ }
+ return map;
+ }
+ }
+
+ /**
+ * Convert relative URL to full path
+ *
+ * @param url
+ * @return
+ */
+ private String updateUrl(String url) {
+ Uri newUrl = Uri.parse(url);
+ if (newUrl.isRelative()) {
+ url = this.webView.getUrl().substring(0, this.webView.getUrl().lastIndexOf("/")+1) + url;
+ }
+ return url;
+ }
+
+ /**
+ * Display a new browser with the specified URL.
+ *
+ * @param url The url to load.
+ * @param usePhoneGap Load url in PhoneGap webview
+ * @return "" if ok, or error message.
+ */
+ public String openExternal(String url) {
+ try {
+ Intent intent = null;
+ intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ this.cordova.getActivity().startActivity(intent);
+ return "";
+ } catch (android.content.ActivityNotFoundException e) {
+ Log.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString());
+ return e.toString();
+ }
+ }
+
+ /**
+ * Closes the dialog
+ */
+ private void closeDialog() {
+ // TODO: fire 'exit' event
+ this.webView.sendJavascript("cordova.fireWindowEvent('exit');");
+ if (dialog != null) {
+ dialog.dismiss();
+ }
+ }
+
+ /**
+ * Checks to see if it is possible to go back one page in history, then does so.
+ */
+ private void goBack() {
+ if (this.inAppWebView.canGoBack()) {
+ this.inAppWebView.goBack();
+ }
+ }
+
+ /**
+ * Checks to see if it is possible to go forward one page in history, then does so.
+ */
+ private void goForward() {
+ if (this.inAppWebView.canGoForward()) {
+ this.inAppWebView.goForward();
+ }
+ }
+
+ /**
+ * Navigate to the new page
+ *
+ * @param url to load
+ */
+ private void navigate(String url) {
+ InputMethodManager imm = (InputMethodManager)this.cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
+
+ if (!url.startsWith("http") && !url.startsWith("file:")) {
+ this.inAppWebView.loadUrl("http://" + url);
+ } else {
+ this.inAppWebView.loadUrl(url);
+ }
+ this.inAppWebView.requestFocus();
+ }
+
+
+ /**
+ * Should we show the location bar?
+ *
+ * @return boolean
+ */
+ private boolean getShowLocationBar() {
+ return this.showLocationBar;
+ }
+
+ /**
+ * Display a new browser with the specified URL.
+ *
+ * @param url The url to load.
+ * @param jsonObject
+ */
+ public String showWebPage(final String url, HashMap features) {
+ // Determine if we should hide the location bar.
+ showLocationBar = true;
+ if (features != null) {
+ showLocationBar = features.get(LOCATION).booleanValue();
+ }
+
+ final CordovaWebView thatWebView = this.webView;
+
+ // Create dialog in new thread
+ Runnable runnable = new Runnable() {
+ /**
+ * Convert our DIP units to Pixels
+ *
+ * @return int
+ */
+ private int dpToPixels(int dipValue) {
+ int value = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP,
+ (float) dipValue,
+ cordova.getActivity().getResources().getDisplayMetrics()
+ );
+
+ return value;
+ }
+
+ public void run() {
+ // Let's create the main dialog
+ dialog = new Dialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
+ dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
+ dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ dialog.setCancelable(true);
+ dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ public void onDismiss(DialogInterface dialog) {
+ try {
+ JSONObject obj = new JSONObject();
+ obj.put("type", CLOSE_EVENT);
+
+ sendUpdate(obj, false);
+ } catch (JSONException e) {
+ Log.d(LOG_TAG, "Should never happen");
+ }
+ }
+ });
+
+ // Main container layout
+ LinearLayout main = new LinearLayout(cordova.getActivity());
+ main.setOrientation(LinearLayout.VERTICAL);
+
+ // Toolbar layout
+ RelativeLayout toolbar = new RelativeLayout(cordova.getActivity());
+ toolbar.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, this.dpToPixels(44)));
+ toolbar.setPadding(this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2));
+ toolbar.setHorizontalGravity(Gravity.LEFT);
+ toolbar.setVerticalGravity(Gravity.TOP);
+
+ // Action Button Container layout
+ RelativeLayout actionButtonContainer = new RelativeLayout(cordova.getActivity());
+ actionButtonContainer.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ actionButtonContainer.setHorizontalGravity(Gravity.LEFT);
+ actionButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL);
+ actionButtonContainer.setId(1);
+
+ // Back button
+ Button back = new Button(cordova.getActivity());
+ RelativeLayout.LayoutParams backLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
+ backLayoutParams.addRule(RelativeLayout.ALIGN_LEFT);
+ back.setLayoutParams(backLayoutParams);
+ back.setContentDescription("Back Button");
+ back.setId(2);
+ back.setText("<");
+ back.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ goBack();
+ }
+ });
+
+ // Forward button
+ Button forward = new Button(cordova.getActivity());
+ RelativeLayout.LayoutParams forwardLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
+ forwardLayoutParams.addRule(RelativeLayout.RIGHT_OF, 2);
+ forward.setLayoutParams(forwardLayoutParams);
+ forward.setContentDescription("Forward Button");
+ forward.setId(3);
+ forward.setText(">");
+ forward.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ goForward();
+ }
+ });
+
+ // Edit Text Box
+ edittext = new EditText(cordova.getActivity());
+ RelativeLayout.LayoutParams textLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+ textLayoutParams.addRule(RelativeLayout.RIGHT_OF, 1);
+ textLayoutParams.addRule(RelativeLayout.LEFT_OF, 5);
+ edittext.setLayoutParams(textLayoutParams);
+ edittext.setId(4);
+ edittext.setSingleLine(true);
+ edittext.setText(url);
+ edittext.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
+ edittext.setImeOptions(EditorInfo.IME_ACTION_GO);
+ edittext.setInputType(InputType.TYPE_NULL); // Will not except input... Makes the text NON-EDITABLE
+ edittext.setOnKeyListener(new View.OnKeyListener() {
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ // If the event is a key-down event on the "enter" button
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
+ navigate(edittext.getText().toString());
+ return true;
+ }
+ return false;
+ }
+ });
+
+ // Close button
+ Button close = new Button(cordova.getActivity());
+ RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
+ closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ close.setLayoutParams(closeLayoutParams);
+ forward.setContentDescription("Close Button");
+ close.setId(5);
+ close.setText("Done");
+ close.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ closeDialog();
+ }
+ });
+
+ // WebView
+ inAppWebView = new WebView(cordova.getActivity());
+ inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
+ inAppWebView.setWebChromeClient(new WebChromeClient());
+ WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
+ inAppWebView.setWebViewClient(client);
+ WebSettings settings = inAppWebView.getSettings();
+ settings.setJavaScriptEnabled(true);
+ settings.setJavaScriptCanOpenWindowsAutomatically(true);
+ settings.setBuiltInZoomControls(true);
+ settings.setPluginsEnabled(true);
+ settings.setDomStorageEnabled(true);
+ inAppWebView.loadUrl(url);
+ inAppWebView.setId(6);
+ inAppWebView.getSettings().setLoadWithOverviewMode(true);
+ inAppWebView.getSettings().setUseWideViewPort(true);
+ inAppWebView.requestFocus();
+ inAppWebView.requestFocusFromTouch();
+
+ // Add the back and forward buttons to our action button container layout
+ actionButtonContainer.addView(back);
+ actionButtonContainer.addView(forward);
+
+ // Add the views to our toolbar
+ toolbar.addView(actionButtonContainer);
+ toolbar.addView(edittext);
+ toolbar.addView(close);
+
+ // Don't add the toolbar if its been disabled
+ if (getShowLocationBar()) {
+ // Add our toolbar to our main view/layout
+ main.addView(toolbar);
+ }
+
+ // Add our webview to our main view/layout
+ main.addView(inAppWebView);
+
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
+ lp.copyFrom(dialog.getWindow().getAttributes());
+ lp.width = WindowManager.LayoutParams.FILL_PARENT;
+ lp.height = WindowManager.LayoutParams.FILL_PARENT;
+
+ dialog.setContentView(main);
+ dialog.show();
+ dialog.getWindow().setAttributes(lp);
+ }
+
+ private Bitmap loadDrawable(String filename) throws java.io.IOException {
+ InputStream input = cordova.getActivity().getAssets().open(filename);
+ return BitmapFactory.decodeStream(input);
+ }
+ };
+ this.cordova.getActivity().runOnUiThread(runnable);
+ return "";
+ }
+
+ /**
+ * Create a new plugin result and send it back to JavaScript
+ *
+ * @param obj a JSONObject contain event payload information
+ */
+ private void sendUpdate(JSONObject obj, boolean keepCallback) {
+ if (this.browserCallbackId != null) {
+ PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
+ result.setKeepCallback(keepCallback);
+ this.callbackContext.sendPluginResult(result);
+ }
+ }
+
+ /**
+ * The webview client receives notifications about appView
+ */
+ public class InAppBrowserClient extends WebViewClient {
+ EditText edittext;
+ CordovaWebView webView;
+
+ /**
+ * Constructor.
+ *
+ * @param mContext
+ * @param edittext
+ */
+ public InAppBrowserClient(CordovaWebView webView, EditText mEditText) {
+ this.webView = webView;
+ this.edittext = mEditText;
+ }
+
+ /**
+ * Notify the host application that a page has started loading.
+ *
+ * @param view The webview initiating the callback.
+ * @param url The url of the page.
+ */
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ super.onPageStarted(view, url, favicon);
+ String newloc;
+ if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
+ newloc = url;
+ } else {
+ newloc = "http://" + url;
+ }
+
+ if (!newloc.equals(edittext.getText().toString())) {
+ edittext.setText(newloc);
+ }
+
+ // TODO: Fire 'loadstart' event only on the InAppBrowser object
+ this.webView.sendJavascript("cordova.fireWindowEvent('loadstart', '" + url + "');");
+ }
+
+ public void onPageFinished(WebView view, String url) {
+ super.onPageFinished(view, url);
+ // TODO: Fire 'loadstop' event only on the InAppBrowser object
+ this.webView.sendJavascript("cordova.fireWindowEvent('loadstop', '" + url + "');");
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/org/apache/cordova/NetworkManager.java b/framework/src/org/apache/cordova/NetworkManager.java
index 5d879180..bb4743f2 100755
--- a/framework/src/org/apache/cordova/NetworkManager.java
+++ b/framework/src/org/apache/cordova/NetworkManager.java
@@ -74,6 +74,7 @@ public class NetworkManager extends CordovaPlugin {
ConnectivityManager sockMan;
BroadcastReceiver receiver;
+ private String lastStatus = "";
/**
* Constructor.
@@ -99,12 +100,11 @@ public class NetworkManager extends CordovaPlugin {
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
if (this.receiver == null) {
this.receiver = new BroadcastReceiver() {
- @SuppressWarnings("deprecation")
@Override
public void onReceive(Context context, Intent intent) {
// (The null check is for the ARM Emulator, please use Intel Emulator for better results)
- if(NetworkManager.this.webView != null)
- updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
+ if(NetworkManager.this.webView != null)
+ updateConnectionInfo(sockMan.getActiveNetworkInfo());
}
};
cordova.getActivity().registerReceiver(this.receiver, intentFilter);
@@ -147,13 +147,6 @@ public class NetworkManager extends CordovaPlugin {
}
}
- /**
- * Stop the network receiver on navigation.
- */
- public void onReset() {
- this.onDestroy();
- }
-
//--------------------------------------------------------------------------
// LOCAL METHODS
//--------------------------------------------------------------------------
@@ -166,7 +159,14 @@ public class NetworkManager extends CordovaPlugin {
*/
private void updateConnectionInfo(NetworkInfo info) {
// send update to javascript "navigator.network.connection"
- sendUpdate(this.getConnectionInfo(info));
+ // Jellybean sends its own info
+ String thisStatus = this.getConnectionInfo(info);
+ if(!thisStatus.equals(lastStatus))
+ {
+ sendUpdate(thisStatus);
+ lastStatus = thisStatus;
+ }
+
}
/**
@@ -186,6 +186,7 @@ public class NetworkManager extends CordovaPlugin {
type = getType(info);
}
}
+ Log.d("CordovaNetworkManager", "Connection Type: " + type);
return type;
}
@@ -200,7 +201,6 @@ public class NetworkManager extends CordovaPlugin {
result.setKeepCallback(true);
connectionCallbackContext.sendPluginResult(result);
}
-
webView.postMessage("networkconnection", type);
}
diff --git a/test/AndroidManifest.xml b/test/AndroidManifest.xml
index e35f6c67..aee2e04f 100755
--- a/test/AndroidManifest.xml
+++ b/test/AndroidManifest.xml
@@ -255,5 +255,15 @@
+
+
+
+
+
+
diff --git a/test/src/org/apache/cordova/test/BackButtonMultiPageTest.java b/test/src/org/apache/cordova/test/BackButtonMultiPageTest.java
index fa3e0b04..6d4a7ac8 100644
--- a/test/src/org/apache/cordova/test/BackButtonMultiPageTest.java
+++ b/test/src/org/apache/cordova/test/BackButtonMultiPageTest.java
@@ -26,6 +26,7 @@ import org.apache.cordova.test.actions.backbuttonmultipage;
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
+import android.view.inputmethod.BaseInputConnection;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
@@ -97,6 +98,54 @@ public class BackButtonMultiPageTest extends ActivityInstrumentationTestCase2