You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by fi...@apache.org on 2013/01/22 02:57:58 UTC

[44/52] [partial] support for 2.4.0rc1. "vendored" the platform libs in. added Gord and Braden as contributors. removed dependency on unzip and axed the old download-cordova code.

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/build.xml
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/build.xml b/lib/cordova-android/framework/build.xml
new file mode 100644
index 0000000..9e7b127
--- /dev/null
+++ b/lib/cordova-android/framework/build.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+       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.
+-->
+<project name="Cordova" default="jar">
+
+    <!-- LOAD VERSION -->
+    <loadfile property="version" srcFile="../VERSION">
+        <filterchain>
+            <striplinebreaks/>
+        </filterchain>
+    </loadfile>
+
+    <!-- check that the version of ant is at least 1.8.0, as is needed
+         for the dblQuote property -->
+    <antversion property="thisantversion" atleast="1.8.0" />
+    <fail message="The required minimum version of ant is 1.8.0, you have ${ant.version}"
+          unless="thisantversion" />
+
+    <!-- check that commons codec is available. You should copy the codec jar to
+         framework/libs, as it is not included in the Cordova distribution. 
+         The name of the jar file in framework/libs does not matter. -->
+    <available classname="org.apache.commons.codec.binary.Base64"
+               property="exists.base64"
+               ignoresystemclasses="true">
+        <classpath>
+            <pathelement path="${classpath}" />
+            <fileset dir="libs">
+                <include name="*.jar" />
+            </fileset>
+        </classpath>
+    </available>
+    <fail message="You need to put a copy of Apache Commons Codec jar in the framework/libs directory"
+          unless="exists.base64" />
+
+    <!-- The local.properties file is created and updated by the 'android' 
+         tool. (For example "sdkdir/tools/android update project -p ." inside
+         of this directory where the AndroidManifest.xml file exists. This
+         properties file that gets built contains the path to the SDK. It 
+         should *NOT* be checked into Version Control Systems since it holds
+         data about the local machine. -->
+    <available file="local.properties" property="exists.local.properties" />
+    <fail message="You need to create the file 'local.properties' by running 'android update project -p .' here."
+          unless="exists.local.properties" />
+    <loadproperties srcFile="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- We need to setup the double quote. -->
+    <property name="dblQuote">"</property>
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'"
+            unless="sdk.dir"
+    />
+
+    <!-- version-tag: custom -->
+<!-- extension targets. Uncomment the ones where you want to do custom work
+     in between standard targets -->
+<!--
+    <target name="-pre-build">
+    </target>
+    <target name="-pre-compile">
+    </target>
+
+    /* This is typically used for code obfuscation.
+       Compiled code location: ${out.classes.absolute.dir}
+       If this is not done in place, override ${out.dex.input.absolute.dir} */
+    <target name="-post-compile">
+    </target>
+-->
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+    <!-- Combine JavaScript files into one cordova-uncompressed.js file. -->
+    <target name="build-javascript" depends="clean">
+
+      <!-- Clean up existing files -->
+      <!--<delete file="assets/www/cordova_${version}.js"/>-->
+
+      <!-- Create uncompressed JS file -->
+      <concat destfile="assets/www/cordova-${version}.js">
+        <filelist dir="assets/js" files="cordova.android.js"/>
+      </concat>
+
+      <!-- update project files to reference cordova-x.x.x.min.js -->
+      <replaceregexp match="cordova(.*)\.js" replace="cordova-${version}.js" byline="true">
+         <fileset file="assets/www/index.html" />
+         <fileset file="../bin/templates/project/assets/www/index.html" />
+      </replaceregexp>
+
+      <!-- This is sketchy, but it works, ${dblQuote} does not -->
+      <replaceregexp match="cordovaVersion = [\u0022].*[\u0022];" replace='cordovaVersion = ${dblQuote}${version}${dblQuote};' byline="true">
+        <fileset file="src/org/apache/cordova/Device.java" />
+      </replaceregexp>
+    </target>
+
+    <!-- Build Cordova jar file that includes all native code, and Cordova JS file
+         that includes all JavaScript code.
+    -->
+    <target name="jar" depends="build-javascript, -compile">
+      <jar jarfile="cordova-${version}.jar" basedir="bin/classes" excludes="org/apache/cordova/R.class,org/apache/cordova/R$*.class"/>
+    </target>
+
+    <!-- tests for Java files -->
+    <property name="test.dir" location="test/org/apache/cordova" />
+
+    <path id="test.classpath">
+        <!-- requires both junit and cordova -->
+        <pathelement location="libs/junit-4.10.jar" />
+        <pathelement location="cordova-${version}.jar" />
+        <pathelement location="${test.dir}" />
+    </path>
+
+    <target name="compile-test">
+        <javac srcdir="${test.dir}" >
+            <classpath refid="test.classpath" />
+        </javac>
+    </target>
+
+    <target name="test" depends="jar, compile-test">
+        <junit showoutput="true">
+            <classpath refid="test.classpath" />
+            <formatter type="brief" usefile="false" />
+            <batchtest fork="yes">
+                <fileset dir="${test.dir}">
+                    <include name="*Test.java" />
+                    <include name="**/*Test.java" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="cordova_debug" depends="build-javascript, debug">
+    </target>
+
+    <target name="cordova_release" depends="build-javascript, release">
+    </target>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/default.properties
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/default.properties b/lib/cordova-android/framework/default.properties
new file mode 100644
index 0000000..d4e24dc
--- /dev/null
+++ b/lib/cordova-android/framework/default.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=android-14
+apk-configurations=

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/gen/R.java.d
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/gen/R.java.d b/lib/cordova-android/framework/gen/R.java.d
new file mode 100644
index 0000000..c1939d1
--- /dev/null
+++ b/lib/cordova-android/framework/gen/R.java.d
@@ -0,0 +1,9 @@
+/Users/fil/src/cordova-cli/lib/cordova-android/framework/gen/org/apache/cordova/R.java \
+ : /Users/fil/src/cordova-cli/lib/cordova-android/framework/res/drawable/splash.png \
+/Users/fil/src/cordova-cli/lib/cordova-android/framework/res/drawable-hdpi/icon.png \
+/Users/fil/src/cordova-cli/lib/cordova-android/framework/res/drawable-ldpi/icon.png \
+/Users/fil/src/cordova-cli/lib/cordova-android/framework/res/drawable-mdpi/icon.png \
+/Users/fil/src/cordova-cli/lib/cordova-android/framework/res/layout/main.xml \
+/Users/fil/src/cordova-cli/lib/cordova-android/framework/res/values/strings.xml \
+/Users/fil/src/cordova-cli/lib/cordova-android/framework/res/xml/config.xml \
+/Users/fil/src/cordova-cli/lib/cordova-android/framework/bin/AndroidManifest.xml \

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/gen/org/apache/cordova/BuildConfig.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/gen/org/apache/cordova/BuildConfig.java b/lib/cordova-android/framework/gen/org/apache/cordova/BuildConfig.java
new file mode 100644
index 0000000..bba60a1
--- /dev/null
+++ b/lib/cordova-android/framework/gen/org/apache/cordova/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package org.apache.cordova;
+
+public final class BuildConfig {
+    public final static boolean DEBUG = false;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/gen/org/apache/cordova/R.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/gen/org/apache/cordova/R.java b/lib/cordova-android/framework/gen/org/apache/cordova/R.java
new file mode 100644
index 0000000..f2cbb9e
--- /dev/null
+++ b/lib/cordova-android/framework/gen/org/apache/cordova/R.java
@@ -0,0 +1,30 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+
+package org.apache.cordova;
+
+public final class R {
+    public static final class attr {
+    }
+    public static final class drawable {
+        public static int icon=0x7f020000;
+        public static int splash=0x7f020001;
+    }
+    public static final class id {
+        public static int appView=0x7f060000;
+    }
+    public static final class layout {
+        public static int main=0x7f030000;
+    }
+    public static final class string {
+        public static int app_name=0x7f050000;
+        public static int go=0x7f050001;
+    }
+    public static final class xml {
+        public static int config=0x7f040000;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/libs/commons-codec-1.7.jar
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/libs/commons-codec-1.7.jar b/lib/cordova-android/framework/libs/commons-codec-1.7.jar
new file mode 100644
index 0000000..efa7f72
Binary files /dev/null and b/lib/cordova-android/framework/libs/commons-codec-1.7.jar differ

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/local.properties
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/local.properties b/lib/cordova-android/framework/local.properties
new file mode 100644
index 0000000..793d18c
--- /dev/null
+++ b/lib/cordova-android/framework/local.properties
@@ -0,0 +1,10 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+
+# location of the SDK. This is only used by Ant
+# For customization when using a Version Control System, please read the
+# header note.
+sdk.dir=/Users/fil/SDKs/android-sdk-macosx

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/proguard-project.txt
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/proguard-project.txt b/lib/cordova-android/framework/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/lib/cordova-android/framework/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/project.properties
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/project.properties b/lib/cordova-android/framework/project.properties
new file mode 100644
index 0000000..d556741
--- /dev/null
+++ b/lib/cordova-android/framework/project.properties
@@ -0,0 +1,16 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=Google Inc.:Google APIs:17
+apk-configurations=
+renderscript.opt.level=O0
+android.library=true

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/res/drawable-hdpi/icon.png
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/res/drawable-hdpi/icon.png b/lib/cordova-android/framework/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..4d27634
Binary files /dev/null and b/lib/cordova-android/framework/res/drawable-hdpi/icon.png differ

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/res/drawable-ldpi/icon.png
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/res/drawable-ldpi/icon.png b/lib/cordova-android/framework/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..cd5032a
Binary files /dev/null and b/lib/cordova-android/framework/res/drawable-ldpi/icon.png differ

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/res/drawable-mdpi/icon.png
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/res/drawable-mdpi/icon.png b/lib/cordova-android/framework/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..e79c606
Binary files /dev/null and b/lib/cordova-android/framework/res/drawable-mdpi/icon.png differ

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/res/drawable/splash.png
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/res/drawable/splash.png b/lib/cordova-android/framework/res/drawable/splash.png
new file mode 100755
index 0000000..d498589
Binary files /dev/null and b/lib/cordova-android/framework/res/drawable/splash.png differ

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/res/layout/main.xml
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/res/layout/main.xml b/lib/cordova-android/framework/res/layout/main.xml
new file mode 100644
index 0000000..bf8a0ff
--- /dev/null
+++ b/lib/cordova-android/framework/res/layout/main.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+       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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+            <WebView android:id="@+id/appView"
+            android:layout_height="fill_parent"
+            android:layout_width="fill_parent"
+            />
+</LinearLayout>

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/res/values/strings.xml
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/res/values/strings.xml b/lib/cordova-android/framework/res/values/strings.xml
new file mode 100644
index 0000000..8bfae7c
--- /dev/null
+++ b/lib/cordova-android/framework/res/values/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+       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.
+-->
+<resources>
+  <string name="app_name">Cordova</string>
+  <string name="go">Snap</string>
+</resources>

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/res/xml/config.xml
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/res/xml/config.xml b/lib/cordova-android/framework/res/xml/config.xml
new file mode 100644
index 0000000..bc6ca0c
--- /dev/null
+++ b/lib/cordova-android/framework/res/xml/config.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+       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.
+-->
+<cordova>
+    <!--
+    access elements control the Android whitelist.
+    Domains are assumed blocked unless set otherwise
+     -->
+
+    <access origin="http://127.0.0.1*"/> <!-- allow local pages -->
+
+    <!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
+    <!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
+    <access origin=".*"/>
+
+    <!-- <content src="http://mysite.com/myapp.html" /> for external pages -->
+    <content src="index.html" />
+
+    <log level="DEBUG"/>
+    <preference name="useBrowserHistory" value="true" />
+    <preference name="exit-on-suspend" value="false" />
+<plugins>
+    <plugin name="App" value="org.apache.cordova.App"/>
+    <plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
+    <plugin name="Device" value="org.apache.cordova.Device"/>
+    <plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
+    <plugin name="Compass" value="org.apache.cordova.CompassListener"/>
+    <plugin name="Media" value="org.apache.cordova.AudioHandler"/>
+    <plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
+    <plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
+    <plugin name="File" value="org.apache.cordova.FileUtils"/>
+    <plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
+    <plugin name="Notification" value="org.apache.cordova.Notification"/>
+    <plugin name="Storage" value="org.apache.cordova.Storage"/>
+    <plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
+    <plugin name="Capture" value="org.apache.cordova.Capture"/>
+    <plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
+    <plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
+    <plugin name="Echo" value="org.apache.cordova.Echo" />
+    <plugin name="Globalization" value="org.apache.cordova.Globalization"/>
+    <plugin name="InAppBrowser" value="org.apache.cordova.InAppBrowser"/>
+</plugins>
+</cordova>
+

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/src/org/apache/cordova/AccelListener.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/AccelListener.java b/lib/cordova-android/framework/src/org/apache/cordova/AccelListener.java
new file mode 100755
index 0000000..934a8a8
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/AccelListener.java
@@ -0,0 +1,285 @@
+/*
+       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.util.List;
+
+import org.apache.cordova.api.CallbackContext;
+import org.apache.cordova.api.CordovaInterface;
+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.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+
+import android.os.Handler;
+import android.os.Looper;
+
+/**
+ * This class listens to the accelerometer sensor and stores the latest
+ * acceleration values x,y,z.
+ */
+public class AccelListener extends CordovaPlugin implements SensorEventListener {
+
+    public static int STOPPED = 0;
+    public static int STARTING = 1;
+    public static int RUNNING = 2;
+    public static int ERROR_FAILED_TO_START = 3;
+   
+    private float x,y,z;                                // most recent acceleration values
+    private long timestamp;                         // time of most recent value
+    private int status;                                 // status of listener
+    private int accuracy = SensorManager.SENSOR_STATUS_UNRELIABLE;
+
+    private SensorManager sensorManager;    // Sensor manager
+    private Sensor mSensor;                           // Acceleration sensor returned by sensor manager
+
+    private CallbackContext callbackContext;              // Keeps track of the JS callback context.
+
+    /**
+     * Create an accelerometer listener.
+     */
+    public AccelListener() {
+        this.x = 0;
+        this.y = 0;
+        this.z = 0;
+        this.timestamp = 0;
+        this.setStatus(AccelListener.STOPPED);
+     }
+
+    /**
+     * Sets the context of the Command. This can then be used to do things like
+     * get file paths associated with the Activity.
+     *
+     * @param cordova The context of the main Activity.
+     * @param webView The associated CordovaWebView.
+     */
+    @Override
+    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
+        super.initialize(cordova, webView);
+        this.sensorManager = (SensorManager) cordova.getActivity().getSystemService(Context.SENSOR_SERVICE);
+    }
+
+    /**
+     * Executes the request.
+     *
+     * @param action        The action to execute.
+     * @param args          The exec() arguments.
+     * @param callbackId    The callback id used when calling back into JavaScript.
+     * @return              Whether the action was valid.
+     */
+    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
+        if (action.equals("start")) {
+            this.callbackContext = callbackContext;
+            if (this.status != AccelListener.RUNNING) {
+                // If not running, then this is an async call, so don't worry about waiting
+                // We drop the callback onto our stack, call start, and let start and the sensor callback fire off the callback down the road
+                this.start();
+            }
+        }
+        else if (action.equals("stop")) {
+            if (this.status == AccelListener.RUNNING) {
+                this.stop();
+            }
+        } else {
+          // Unsupported action
+            return false;
+        }
+
+        PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT, "");
+        result.setKeepCallback(true);
+        callbackContext.sendPluginResult(result);
+        return true;
+    }
+
+    /**
+     * Called by AccelBroker when listener is to be shut down.
+     * Stop listener.
+     */
+    public void onDestroy() {
+        this.stop();
+    }
+
+    //--------------------------------------------------------------------------
+    // LOCAL METHODS
+    //--------------------------------------------------------------------------
+    //
+    /**
+     * Start listening for acceleration sensor.
+     * 
+     * @return          status of listener
+    */
+    private int start() {
+        // If already starting or running, then just return
+        if ((this.status == AccelListener.RUNNING) || (this.status == AccelListener.STARTING)) {
+            return this.status;
+        }
+
+        this.setStatus(AccelListener.STARTING);
+
+        // Get accelerometer from sensor manager
+        List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
+
+        // If found, then register as listener
+        if ((list != null) && (list.size() > 0)) {
+          this.mSensor = list.get(0);
+          this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_UI);
+          this.setStatus(AccelListener.STARTING);
+        } else {
+          this.setStatus(AccelListener.ERROR_FAILED_TO_START);
+          this.fail(AccelListener.ERROR_FAILED_TO_START, "No sensors found to register accelerometer listening to.");
+          return this.status;
+        }
+
+        // Set a timeout callback on the main thread.
+        Handler handler = new Handler(Looper.getMainLooper());
+        handler.postDelayed(new Runnable() {
+            public void run() {
+                AccelListener.this.timeout();
+            }
+        }, 2000);
+
+        return this.status;
+    }
+
+    /**
+     * Stop listening to acceleration sensor.
+     */
+    private void stop() {
+        if (this.status != AccelListener.STOPPED) {
+            this.sensorManager.unregisterListener(this);
+        }
+        this.setStatus(AccelListener.STOPPED);
+        this.accuracy = SensorManager.SENSOR_STATUS_UNRELIABLE;
+    }
+
+    /**
+     * Returns an error if the sensor hasn't started.
+     *
+     * Called two seconds after starting the listener.
+     */
+    private void timeout() {
+        if (this.status == AccelListener.STARTING) {
+            this.setStatus(AccelListener.ERROR_FAILED_TO_START);
+            this.fail(AccelListener.ERROR_FAILED_TO_START, "Accelerometer could not be started.");
+        }
+    }
+
+    /**
+     * Called when the accuracy of the sensor has changed.
+     *
+     * @param sensor
+     * @param accuracy
+     */
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        // Only look at accelerometer events
+        if (sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
+            return;
+        }
+
+        // If not running, then just return
+        if (this.status == AccelListener.STOPPED) {
+            return;
+        }
+        this.accuracy = accuracy;
+    }
+
+    /**
+     * Sensor listener event.
+     *
+     * @param SensorEvent event
+     */
+    public void onSensorChanged(SensorEvent event) {
+        // Only look at accelerometer events
+        if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
+            return;
+        }
+
+        // If not running, then just return
+        if (this.status == AccelListener.STOPPED) {
+            return;
+        }
+        this.setStatus(AccelListener.RUNNING);
+
+        if (this.accuracy >= SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM) {
+
+            // Save time that event was received
+            this.timestamp = System.currentTimeMillis();
+            this.x = event.values[0];
+            this.y = event.values[1];
+            this.z = event.values[2];
+
+            this.win();
+        }
+    }
+
+    /**
+     * Called when the view navigates.
+     */
+    @Override
+    public void onReset() {
+        if (this.status == AccelListener.RUNNING) {
+            this.stop();
+        }
+    }
+
+    // Sends an error back to JS
+    private void fail(int code, String message) {
+        // Error object
+        JSONObject errorObj = new JSONObject();
+        try {
+            errorObj.put("code", code);
+            errorObj.put("message", message);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        PluginResult err = new PluginResult(PluginResult.Status.ERROR, errorObj);
+        err.setKeepCallback(true);
+        callbackContext.sendPluginResult(err);
+    }
+
+    private void win() {
+        // Success return object
+        PluginResult result = new PluginResult(PluginResult.Status.OK, this.getAccelerationJSON());
+        result.setKeepCallback(true);
+        callbackContext.sendPluginResult(result);
+    }
+
+    private void setStatus(int status) {
+        this.status = status;
+    }
+    private JSONObject getAccelerationJSON() {
+        JSONObject r = new JSONObject();
+        try {
+            r.put("x", this.x);
+            r.put("y", this.y);
+            r.put("z", this.z);
+            r.put("timestamp", this.timestamp);
+        } catch (JSONException e) {
+            e.printStackTrace();
+        }
+        return r;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/src/org/apache/cordova/App.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/App.java b/lib/cordova-android/framework/src/org/apache/cordova/App.java
new file mode 100755
index 0000000..afdbf3f
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/App.java
@@ -0,0 +1,221 @@
+/*
+       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 org.apache.cordova.api.CallbackContext;
+import org.apache.cordova.api.CordovaPlugin;
+import org.apache.cordova.api.LOG;
+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 CordovaPlugin {
+
+    /**
+     * Executes the request and returns PluginResult.
+     *
+     * @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 boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
+        PluginResult.Status status = PluginResult.Status.OK;
+        String result = "";
+
+        try {
+            if (action.equals("clearCache")) {
+                this.clearCache();
+            }
+            else if (action.equals("show")) {
+                // This gets called from JavaScript onCordovaReady to show the webview.
+                // I recommend we change the name of the Message as spinner/stop is not
+                // indicative of what this actually does (shows the webview).
+                cordova.getActivity().runOnUiThread(new Runnable() {
+                    public void run() {
+                        webView.postMessage("spinner", "stop");
+                    }
+                });
+            }
+            else if (action.equals("loadUrl")) {
+                this.loadUrl(args.getString(0), args.optJSONObject(1));
+            }
+            else if (action.equals("cancelLoadUrl")) {
+                //this.cancelLoadUrl();
+            }
+            else if (action.equals("clearHistory")) {
+                this.clearHistory();
+            }
+            else if (action.equals("backHistory")) {
+                this.backHistory();
+            }
+            else if (action.equals("overrideButton")) {
+                this.overrideButton(args.getString(0), args.getBoolean(1));
+            }
+            else if (action.equals("overrideBackbutton")) {
+                this.overrideBackbutton(args.getBoolean(0));
+            }
+            else if (action.equals("exitApp")) {
+                this.exitApp();
+            }
+            callbackContext.sendPluginResult(new PluginResult(status, result));
+            return true;
+        } catch (JSONException e) {
+            callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
+            return false;
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    // LOCAL METHODS
+    //--------------------------------------------------------------------------
+
+    /**
+     * Clear the resource cache.
+     */
+    public void clearCache() {
+        this.webView.clearCache(true);
+    }
+
+    /**
+     * Load the url into the webview.
+     *
+     * @param url
+     * @param props			Properties that can be passed in to the DroidGap activity (i.e. loadingDialog, wait, ...)
+     * @throws JSONException
+     */
+    public void loadUrl(String url, JSONObject props) throws JSONException {
+        LOG.d("App", "App.loadUrl("+url+","+props+")");
+        int wait = 0;
+        boolean openExternal = false;
+        boolean clearHistory = false;
+
+        // If there are properties, then set them on the Activity
+        HashMap<String, Object> params = new HashMap<String, Object>();
+        if (props != null) {
+            JSONArray keys = props.names();
+            for (int i = 0; i < keys.length(); i++) {
+                String key = keys.getString(i);
+                if (key.equals("wait")) {
+                    wait = props.getInt(key);
+                }
+                else if (key.equalsIgnoreCase("openexternal")) {
+                    openExternal = props.getBoolean(key);
+                }
+                else if (key.equalsIgnoreCase("clearhistory")) {
+                    clearHistory = props.getBoolean(key);
+                }
+                else {
+                    Object value = props.get(key);
+                    if (value == null) {
+
+                    }
+                    else if (value.getClass().equals(String.class)) {
+                        params.put(key, (String)value);
+                    }
+                    else if (value.getClass().equals(Boolean.class)) {
+                        params.put(key, (Boolean)value);
+                    }
+                    else if (value.getClass().equals(Integer.class)) {
+                        params.put(key, (Integer)value);
+                    }
+                }
+            }
+        }
+
+        // If wait property, then delay loading
+
+        if (wait > 0) {
+            try {
+                synchronized(this) {
+                    this.wait(wait);
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        this.webView.showWebPage(url, openExternal, clearHistory, params);
+    }
+
+    /**
+     * Clear page history for the app.
+     */
+    public void clearHistory() {
+        this.webView.clearHistory();
+    }
+
+    /**
+     * Go to previous page displayed.
+     * This is the same as pressing the backbutton on Android device.
+     */
+    public void backHistory() {
+        cordova.getActivity().runOnUiThread(new Runnable() {
+            public void run() {
+                webView.backHistory();
+            }
+        });
+    }
+
+    /**
+     * Override the default behavior of the Android back button.
+     * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
+     *
+     * @param override		T=override, F=cancel override
+     */
+    public void overrideBackbutton(boolean override) {
+        LOG.i("App", "WARNING: Back Button Default Behaviour will be overridden.  The backbutton event will be fired!");
+        webView.bindButton(override);
+    }
+
+    /**
+     * Override the default behavior of the Android volume buttons.
+     * If overridden, when the volume button is pressed, the "volume[up|down]button" JavaScript event will be fired.
+     *
+     * @param button        volumeup, volumedown
+     * @param override      T=override, F=cancel override
+     */
+    public void overrideButton(String button, boolean override) {
+        LOG.i("DroidGap", "WARNING: Volume Button Default Behaviour will be overridden.  The volume event will be fired!");
+        webView.bindButton(button, override);
+    }
+
+    /**
+     * Return whether the Android back button is overridden by the user.
+     *
+     * @return boolean
+     */
+    public boolean isBackbuttonOverridden() {
+        return webView.isBackButtonBound();
+    }
+
+    /**
+     * Exit the Android application.
+     */
+    public void exitApp() {
+        this.webView.postMessage("exit", null);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/src/org/apache/cordova/AudioHandler.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/AudioHandler.java b/lib/cordova-android/framework/src/org/apache/cordova/AudioHandler.java
new file mode 100644
index 0000000..ed5757f
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/AudioHandler.java
@@ -0,0 +1,357 @@
+/*
+       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 org.apache.cordova.api.CallbackContext;
+import org.apache.cordova.api.CordovaPlugin;
+
+import android.content.Context;
+import android.media.AudioManager;
+
+import java.util.ArrayList;
+
+import org.apache.cordova.api.PluginResult;
+import org.json.JSONArray;
+import org.json.JSONException;
+import java.util.HashMap;
+
+/**
+ * This class called by CordovaActivity to play and record audio.
+ * The file can be local or over a network using http.
+ *
+ * Audio formats supported (tested):
+ * 	.mp3, .wav
+ *
+ * Local audio files must reside in one of two places:
+ * 		android_asset: 		file name must start with /android_asset/sound.mp3
+ * 		sdcard:				file name is just sound.mp3
+ */
+public class AudioHandler extends CordovaPlugin {
+
+    public static String TAG = "AudioHandler";
+    HashMap<String, AudioPlayer> players;	// Audio player object
+    ArrayList<AudioPlayer> pausedForPhone;     // Audio players that were paused when phone call came in
+
+    /**
+     * Constructor.
+     */
+    public AudioHandler() {
+        this.players = new HashMap<String, AudioPlayer>();
+        this.pausedForPhone = new ArrayList<AudioPlayer>();
+    }
+
+    /**
+     * Executes the request and returns PluginResult.
+     * @param action 		The action to execute.
+     * @param args 			JSONArry of arguments for the plugin.
+     * @param callbackContext		The callback context 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 = "";
+
+        if (action.equals("startRecordingAudio")) {
+            this.startRecordingAudio(args.getString(0), FileUtils.stripFileProtocol(args.getString(1)));
+        }
+        else if (action.equals("stopRecordingAudio")) {
+            this.stopRecordingAudio(args.getString(0));
+        }
+        else if (action.equals("startPlayingAudio")) {
+            this.startPlayingAudio(args.getString(0), FileUtils.stripFileProtocol(args.getString(1)));
+        }
+        else if (action.equals("seekToAudio")) {
+            this.seekToAudio(args.getString(0), args.getInt(1));
+        }
+        else if (action.equals("pausePlayingAudio")) {
+            this.pausePlayingAudio(args.getString(0));
+        }
+        else if (action.equals("stopPlayingAudio")) {
+            this.stopPlayingAudio(args.getString(0));
+        } else if (action.equals("setVolume")) {
+           try {
+               this.setVolume(args.getString(0), Float.parseFloat(args.getString(1)));
+           } catch (NumberFormatException nfe) {
+               //no-op
+           }
+        } else if (action.equals("getCurrentPositionAudio")) {
+            float f = this.getCurrentPositionAudio(args.getString(0));
+            callbackContext.sendPluginResult(new PluginResult(status, f));
+            return true;
+        }
+        else if (action.equals("getDurationAudio")) {
+            float f = this.getDurationAudio(args.getString(0), args.getString(1));
+            callbackContext.sendPluginResult(new PluginResult(status, f));
+            return true;
+        }
+        else if (action.equals("create")) {
+            String id = args.getString(0);
+            String src = FileUtils.stripFileProtocol(args.getString(1));
+            AudioPlayer audio = new AudioPlayer(this, id, src);
+            this.players.put(id, audio);
+        }
+        else if (action.equals("release")) {
+            boolean b = this.release(args.getString(0));
+            callbackContext.sendPluginResult(new PluginResult(status, b));
+            return true;
+        }
+        else { // Unrecognized action.
+            return false;
+        }
+
+        callbackContext.sendPluginResult(new PluginResult(status, result));
+
+        return true;
+    }
+
+    /**
+     * Stop all audio players and recorders.
+     */
+    public void onDestroy() {
+        for (AudioPlayer audio : this.players.values()) {
+            audio.destroy();
+        }
+        this.players.clear();
+    }
+
+    /**
+     * Stop all audio players and recorders on navigate.
+     */
+    @Override
+    public void onReset() {
+        onDestroy();
+    }
+
+    /**
+     * Called when a message is sent to plugin.
+     *
+     * @param id            The message id
+     * @param data          The message data
+     * @return              Object to stop propagation or null
+     */
+    public Object onMessage(String id, Object data) {
+
+        // If phone message
+        if (id.equals("telephone")) {
+
+            // If phone ringing, then pause playing
+            if ("ringing".equals(data) || "offhook".equals(data)) {
+
+                // Get all audio players and pause them
+                for (AudioPlayer audio : this.players.values()) {
+                    if (audio.getState() == AudioPlayer.STATE.MEDIA_RUNNING.ordinal()) {
+                        this.pausedForPhone.add(audio);
+                        audio.pausePlaying();
+                    }
+                }
+
+            }
+
+            // If phone idle, then resume playing those players we paused
+            else if ("idle".equals(data)) {
+                for (AudioPlayer audio : this.pausedForPhone) {
+                    audio.startPlaying(null);
+                }
+                this.pausedForPhone.clear();
+            }
+        }
+        return null;
+    }
+
+    //--------------------------------------------------------------------------
+    // LOCAL METHODS
+    //--------------------------------------------------------------------------
+
+    /**
+     * Release the audio player instance to save memory.
+     * @param id				The id of the audio player
+     */
+    private boolean release(String id) {
+        if (!this.players.containsKey(id)) {
+            return false;
+        }
+        AudioPlayer audio = this.players.get(id);
+        this.players.remove(id);
+        audio.destroy();
+        return true;
+    }
+
+    /**
+     * Start recording and save the specified file.
+     * @param id				The id of the audio player
+     * @param file				The name of the file
+     */
+    public void startRecordingAudio(String id, String file) {
+        AudioPlayer audio = this.players.get(id);
+        if ( audio == null) {
+            audio = new AudioPlayer(this, id, file);
+            this.players.put(id, audio);
+        }
+        audio.startRecording(file);
+    }
+
+    /**
+     * Stop recording and save to the file specified when recording started.
+     * @param id				The id of the audio player
+     */
+    public void stopRecordingAudio(String id) {
+        AudioPlayer audio = this.players.get(id);
+        if (audio != null) {
+            audio.stopRecording();
+        }
+    }
+
+    /**
+     * Start or resume playing audio file.
+     * @param id				The id of the audio player
+     * @param file				The name of the audio file.
+     */
+    public void startPlayingAudio(String id, String file) {
+        AudioPlayer audio = this.players.get(id);
+        if (audio == null) {
+            audio = new AudioPlayer(this, id, file);
+            this.players.put(id, audio);
+        }
+        audio.startPlaying(file);
+    }
+
+    /**
+     * Seek to a location.
+     * @param id				The id of the audio player
+     * @param milliseconds		int: number of milliseconds to skip 1000 = 1 second
+     */
+    public void seekToAudio(String id, int milliseconds) {
+        AudioPlayer audio = this.players.get(id);
+        if (audio != null) {
+            audio.seekToPlaying(milliseconds);
+        }
+    }
+
+    /**
+     * Pause playing.
+     * @param id				The id of the audio player
+     */
+    public void pausePlayingAudio(String id) {
+        AudioPlayer audio = this.players.get(id);
+        if (audio != null) {
+            audio.pausePlaying();
+        }
+    }
+
+    /**
+     * Stop playing the audio file.
+     * @param id				The id of the audio player
+     */
+    public void stopPlayingAudio(String id) {
+        AudioPlayer audio = this.players.get(id);
+        if (audio != null) {
+            audio.stopPlaying();
+            //audio.destroy();
+            //this.players.remove(id);
+        }
+    }
+
+    /**
+     * Get current position of playback.
+     * @param id				The id of the audio player
+     * @return 					position in msec
+     */
+    public float getCurrentPositionAudio(String id) {
+        AudioPlayer audio = this.players.get(id);
+        if (audio != null) {
+            return (audio.getCurrentPosition() / 1000.0f);
+        }
+        return -1;
+    }
+
+    /**
+     * Get the duration of the audio file.
+     * @param id				The id of the audio player
+     * @param file				The name of the audio file.
+     * @return					The duration in msec.
+     */
+    public float getDurationAudio(String id, String file) {
+
+        // Get audio file
+        AudioPlayer audio = this.players.get(id);
+        if (audio != null) {
+            return (audio.getDuration(file));
+        }
+
+        // If not already open, then open the file
+        else {
+            audio = new AudioPlayer(this, id, file);
+            this.players.put(id, audio);
+            return (audio.getDuration(file));
+        }
+    }
+
+    /**
+     * Set the audio device to be used for playback.
+     *
+     * @param output			1=earpiece, 2=speaker
+     */
+    @SuppressWarnings("deprecation")
+    public void setAudioOutputDevice(int output) {
+        AudioManager audiMgr = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE);
+        if (output == 2) {
+            audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);
+        }
+        else if (output == 1) {
+            audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL);
+        }
+        else {
+            System.out.println("AudioHandler.setAudioOutputDevice() Error: Unknown output device.");
+        }
+    }
+
+    /**
+     * Get the audio device to be used for playback.
+     *
+     * @return					1=earpiece, 2=speaker
+     */
+    @SuppressWarnings("deprecation")
+    public int getAudioOutputDevice() {
+        AudioManager audiMgr = (AudioManager) this.cordova.getActivity().getSystemService(Context.AUDIO_SERVICE);
+        if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_EARPIECE) {
+            return 1;
+        }
+        else if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_SPEAKER) {
+            return 2;
+        }
+        else {
+            return -1;
+        }
+    }
+
+    /**
+     * Set the volume for an audio device
+     *
+     * @param id				The id of the audio player
+     * @param volume            Volume to adjust to 0.0f - 1.0f
+     */
+    public void setVolume(String id, float volume) {
+        AudioPlayer audio = this.players.get(id);
+        if (audio != null) {
+            audio.setVolume(volume);
+        } else {
+            System.out.println("AudioHandler.setVolume() Error: Unknown Audio Player " + id);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/src/org/apache/cordova/AudioPlayer.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/AudioPlayer.java b/lib/cordova-android/framework/src/org/apache/cordova/AudioPlayer.java
new file mode 100644
index 0000000..99dbb3d
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/AudioPlayer.java
@@ -0,0 +1,548 @@
+/*
+       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 android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.media.MediaRecorder;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * This class implements the audio playback and recording capabilities used by Cordova.
+ * It is called by the AudioHandler Cordova class.
+ * Only one file can be played or recorded per class instance.
+ *
+ * Local audio files must reside in one of two places:
+ *      android_asset:      file name must start with /android_asset/sound.mp3
+ *      sdcard:             file name is just sound.mp3
+ */
+public class AudioPlayer implements OnCompletionListener, OnPreparedListener, OnErrorListener {
+
+    // AudioPlayer modes
+    public enum MODE { NONE, PLAY, RECORD };
+
+    // AudioPlayer states
+    public enum STATE { MEDIA_NONE,
+                        MEDIA_STARTING,
+                        MEDIA_RUNNING,
+                        MEDIA_PAUSED,
+                        MEDIA_STOPPED,
+                        MEDIA_LOADING
+                      };
+
+    private static final String LOG_TAG = "AudioPlayer";
+
+    // AudioPlayer message ids
+    private static int MEDIA_STATE = 1;
+    private static int MEDIA_DURATION = 2;
+    private static int MEDIA_POSITION = 3;
+    private static int MEDIA_ERROR = 9;
+
+    // Media error codes
+    private static int MEDIA_ERR_NONE_ACTIVE    = 0;
+    private static int MEDIA_ERR_ABORTED        = 1;
+    private static int MEDIA_ERR_NETWORK        = 2;
+    private static int MEDIA_ERR_DECODE         = 3;
+    private static int MEDIA_ERR_NONE_SUPPORTED = 4;
+
+    private AudioHandler handler;           // The AudioHandler object
+    private String id;                      // The id of this player (used to identify Media object in JavaScript)
+    private MODE mode = MODE.NONE;          // Playback or Recording mode
+    private STATE state = STATE.MEDIA_NONE; // State of recording or playback
+
+    private String audioFile = null;        // File name to play or record to
+    private float duration = -1;            // Duration of audio
+
+    private MediaRecorder recorder = null;  // Audio recording object
+    private String tempFile = null;         // Temporary recording file name
+
+    private MediaPlayer player = null;      // Audio player object
+    private boolean prepareOnly = true;     // playback after file prepare flag
+    private int seekOnPrepared = 0;     // seek to this location once media is prepared
+
+    /**
+     * Constructor.
+     *
+     * @param handler           The audio handler object
+     * @param id                The id of this audio player
+     */
+    public AudioPlayer(AudioHandler handler, String id, String file) {
+        this.handler = handler;
+        this.id = id;
+        this.audioFile = file;
+        this.recorder = new MediaRecorder();
+
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.3gp";
+        } else {
+            this.tempFile = "/data/data/" + handler.cordova.getActivity().getPackageName() + "/cache/tmprecording.3gp";
+        }
+
+    }
+
+    /**
+     * Destroy player and stop audio playing or recording.
+     */
+    public void destroy() {
+        // Stop any play or record
+        if (this.player != null) {
+            if ((this.state == STATE.MEDIA_RUNNING) || (this.state == STATE.MEDIA_PAUSED)) {
+                this.player.stop();
+                this.setState(STATE.MEDIA_STOPPED);
+            }
+            this.player.release();
+            this.player = null;
+        }
+        if (this.recorder != null) {
+            this.stopRecording();
+            this.recorder.release();
+            this.recorder = null;
+        }
+    }
+
+    /**
+     * Start recording the specified file.
+     *
+     * @param file              The name of the file
+     */
+    public void startRecording(String file) {
+        switch (this.mode) {
+        case PLAY:
+            Log.d(LOG_TAG, "AudioPlayer Error: Can't record in play mode.");
+            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
+            break;
+        case NONE:
+            this.audioFile = file;
+            this.recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+            this.recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // THREE_GPP);
+            this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); //AMR_NB);
+            this.recorder.setOutputFile(this.tempFile);
+            try {
+                this.recorder.prepare();
+                this.recorder.start();
+                this.setState(STATE.MEDIA_RUNNING);
+                return;
+            } catch (IllegalStateException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
+            break;
+        case RECORD:
+            Log.d(LOG_TAG, "AudioPlayer Error: Already recording.");
+            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
+        }
+    }
+
+    /**
+     * Save temporary recorded file to specified name
+     *
+     * @param file
+     */
+    public void moveFile(String file) {
+        /* this is a hack to save the file as the specified name */
+        File f = new File(this.tempFile);
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            f.renameTo(new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+                    + File.separator + file));
+        } else {
+            f.renameTo(new File("/data/data/" + handler.cordova.getActivity().getPackageName() + "/cache/" + file));
+        }
+
+    }
+
+    /**
+     * Stop recording and save to the file specified when recording started.
+     */
+    public void stopRecording() {
+        if (this.recorder != null) {
+            try{
+                if (this.state == STATE.MEDIA_RUNNING) {
+                    this.recorder.stop();
+                    this.setState(STATE.MEDIA_STOPPED);
+                }
+                this.recorder.reset();
+                this.moveFile(this.audioFile);
+            }
+            catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    //==========================================================================
+    // Playback
+    //==========================================================================
+
+    /**
+     * Start or resume playing audio file.
+     *
+     * @param file              The name of the audio file.
+     */
+    public void startPlaying(String file) {
+        if (this.readyPlayer(file) && this.player != null) {
+            this.player.start();
+            this.setState(STATE.MEDIA_RUNNING);
+            this.seekOnPrepared = 0; //insures this is always reset
+        } else {
+            this.prepareOnly = false;
+        }
+    }
+
+    /**
+     * Seek or jump to a new time in the track.
+     */
+    public void seekToPlaying(int milliseconds) {
+        if (this.readyPlayer(this.audioFile)) {
+            this.player.seekTo(milliseconds);
+            Log.d(LOG_TAG, "Send a onStatus update for the new seek");
+            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + milliseconds / 1000.0f + ");");
+        }
+        else {
+            this.seekOnPrepared = milliseconds;
+        }
+    }
+
+    /**
+     * Pause playing.
+     */
+    public void pausePlaying() {
+
+        // If playing, then pause
+        if (this.state == STATE.MEDIA_RUNNING && this.player != null) {
+            this.player.pause();
+            this.setState(STATE.MEDIA_PAUSED);
+        }
+        else {
+            Log.d(LOG_TAG, "AudioPlayer Error: pausePlaying() called during invalid state: " + this.state.ordinal());
+            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
+        }
+    }
+
+    /**
+     * Stop playing the audio file.
+     */
+    public void stopPlaying() {
+        if ((this.state == STATE.MEDIA_RUNNING) || (this.state == STATE.MEDIA_PAUSED)) {
+            this.player.pause();
+            this.player.seekTo(0);
+            Log.d(LOG_TAG, "stopPlaying is calling stopped");
+            this.setState(STATE.MEDIA_STOPPED);
+        }
+        else {
+            Log.d(LOG_TAG, "AudioPlayer Error: stopPlaying() called during invalid state: " + this.state.ordinal());
+            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
+        }
+    }
+
+    /**
+     * Callback to be invoked when playback of a media source has completed.
+     *
+     * @param player           The MediaPlayer that reached the end of the file
+     */
+    public void onCompletion(MediaPlayer player) {
+        Log.d(LOG_TAG, "on completion is calling stopped");
+        this.setState(STATE.MEDIA_STOPPED);
+    }
+
+    /**
+     * Get current position of playback.
+     *
+     * @return                  position in msec or -1 if not playing
+     */
+    public long getCurrentPosition() {
+        if ((this.state == STATE.MEDIA_RUNNING) || (this.state == STATE.MEDIA_PAUSED)) {
+            int curPos = this.player.getCurrentPosition();
+            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + curPos / 1000.0f + ");");
+            return curPos;
+        }
+        else {
+            return -1;
+        }
+    }
+
+    /**
+     * Determine if playback file is streaming or local.
+     * It is streaming if file name starts with "http://"
+     *
+     * @param file              The file name
+     * @return                  T=streaming, F=local
+     */
+    public boolean isStreaming(String file) {
+        if (file.contains("http://") || file.contains("https://")) {
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+
+    /**
+      * Get the duration of the audio file.
+      *
+      * @param file             The name of the audio file.
+      * @return                 The duration in msec.
+      *                             -1=can't be determined
+      *                             -2=not allowed
+      */
+    public float getDuration(String file) {
+
+        // Can't get duration of recording
+        if (this.recorder != null) {
+            return (-2); // not allowed
+        }
+
+        // If audio file already loaded and started, then return duration
+        if (this.player != null) {
+            return this.duration;
+        }
+
+        // If no player yet, then create one
+        else {
+            this.prepareOnly = true;
+            this.startPlaying(file);
+
+            // This will only return value for local, since streaming
+            // file hasn't been read yet.
+            return this.duration;
+        }
+    }
+
+    /**
+     * Callback to be invoked when the media source is ready for playback.
+     *
+     * @param player           The MediaPlayer that is ready for playback
+     */
+    public void onPrepared(MediaPlayer player) {
+        // Listen for playback completion
+        this.player.setOnCompletionListener(this);
+        // seek to any location received while not prepared
+        this.seekToPlaying(this.seekOnPrepared);
+        // If start playing after prepared
+        if (!this.prepareOnly) {
+            this.player.start();
+            this.setState(STATE.MEDIA_RUNNING);
+            this.seekOnPrepared = 0; //reset only when played
+        } else {
+            this.setState(STATE.MEDIA_STARTING);
+        }
+        // Save off duration
+        this.duration = getDurationInSeconds();
+        // reset prepare only flag
+        this.prepareOnly = true;
+
+        // Send status notification to JavaScript
+        this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_DURATION + "," + this.duration + ");");
+    }
+
+    /**
+     * By default Android returns the length of audio in mills but we want seconds
+     *
+     * @return length of clip in seconds
+     */
+    private float getDurationInSeconds() {
+        return (this.player.getDuration() / 1000.0f);
+    }
+
+    /**
+     * Callback to be invoked when there has been an error during an asynchronous operation
+     *  (other errors will throw exceptions at method call time).
+     *
+     * @param player           the MediaPlayer the error pertains to
+     * @param arg1              the type of error that has occurred: (MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_SERVER_DIED)
+     * @param arg2              an extra code, specific to the error.
+     */
+    public boolean onError(MediaPlayer player, int arg1, int arg2) {
+        Log.d(LOG_TAG, "AudioPlayer.onError(" + arg1 + ", " + arg2 + ")");
+
+        // TODO: Not sure if this needs to be sent?
+        this.player.stop();
+        this.player.release();
+
+        // Send error notification to JavaScript
+        this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', { \"code\":" + arg1 + "});");
+        return false;
+    }
+
+    /**
+     * Set the state and send it to JavaScript.
+     *
+     * @param state
+     */
+    private void setState(STATE state) {
+        if (this.state != state) {
+            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_STATE + ", " + state.ordinal() + ");");
+        }
+        this.state = state;
+    }
+
+    /**
+     * Set the mode and send it to JavaScript.
+     *
+     * @param state
+     */
+    private void setMode(MODE mode) {
+        if (this.mode != mode) {
+            //mode is not part of the expected behavior, so no notification
+            //this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_STATE + ", " + mode + ");");
+        }
+        this.mode = mode;
+    }
+
+    /**
+     * Get the audio state.
+     *
+     * @return int
+     */
+    public int getState() {
+        return this.state.ordinal();
+    }
+
+    /**
+     * Set the volume for audio player
+     *
+     * @param volume
+     */
+    public void setVolume(float volume) {
+        this.player.setVolume(volume, volume);
+    }
+
+    /**
+     * attempts to put the player in play mode
+     * @return true if in playmode, false otherwise
+     */
+    private boolean playMode() {
+        switch(this.mode) {
+        case NONE:
+            this.setMode(MODE.PLAY);
+            break;
+        case PLAY:
+            break;
+        case RECORD:
+            Log.d(LOG_TAG, "AudioPlayer Error: Can't play in record mode.");
+            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
+            return false; //player is not ready
+        }
+        return true;
+    }
+
+    /**
+     * attempts to initialize the media player for playback
+     * @param file the file to play
+     * @return false if player not ready, reports if in wrong mode or state
+     */
+    private boolean readyPlayer(String file) {
+        if (playMode()) {
+            switch (this.state) {
+                case MEDIA_NONE:
+                    if (this.player == null) {
+                        this.player = new MediaPlayer();
+                    }
+                    try {
+                        this.loadAudioFile(file);
+                    } catch (Exception e) {
+                        this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
+                    }
+                    return false;
+                case MEDIA_LOADING:
+                    //cordova js is not aware of MEDIA_LOADING, so we send MEDIA_STARTING instead
+                    Log.d(LOG_TAG, "AudioPlayer Loading: startPlaying() called during media preparation: " + STATE.MEDIA_STARTING.ordinal());
+                    this.prepareOnly = false;
+                    return false;
+                case MEDIA_STARTING:
+                case MEDIA_RUNNING:
+                case MEDIA_PAUSED:
+                    return true;
+                case MEDIA_STOPPED:
+                    //if we are readying the same file
+                    if (this.audioFile.compareTo(file) == 0) {
+                        //reset the audio file
+                        player.seekTo(0);
+                        player.pause();
+                        return true;
+                    } else {
+                        //reset the player
+                        this.player.reset();
+                        try {
+                            this.loadAudioFile(file);
+                        } catch (Exception e) {
+                            this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
+                        }
+                        //if we had to prepare= the file, we won't be in the correct state for playback
+                        return false;
+                    }
+                default:
+                    Log.d(LOG_TAG, "AudioPlayer Error: startPlaying() called during invalid state: " + this.state);
+                    this.handler.webView.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
+            }
+        }
+        return false;
+    }
+
+    /**
+     * load audio file
+     * @throws IOException
+     * @throws IllegalStateException
+     * @throws SecurityException
+     * @throws IllegalArgumentException
+     */
+    private void loadAudioFile(String file) throws IllegalArgumentException, SecurityException, IllegalStateException, IOException {
+        if (this.isStreaming(file)) {
+            this.player.setDataSource(file);
+            this.player.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            //if it's a streaming file, play mode is implied
+            this.setMode(MODE.PLAY);
+            this.setState(STATE.MEDIA_STARTING);
+            this.player.setOnPreparedListener(this);
+            this.player.prepareAsync();
+        }
+        else {
+            if (file.startsWith("/android_asset/")) {
+                String f = file.substring(15);
+                android.content.res.AssetFileDescriptor fd = this.handler.cordova.getActivity().getAssets().openFd(f);
+                this.player.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+            }
+            else {
+                File fp = new File(file);
+                if (fp.exists()) {
+                    FileInputStream fileInputStream = new FileInputStream(file);
+                    this.player.setDataSource(fileInputStream.getFD());
+                }
+                else {
+                    this.player.setDataSource("/sdcard/" + file);
+                }
+            }
+                this.setState(STATE.MEDIA_STARTING);
+                this.player.setOnPreparedListener(this);
+                this.player.prepare();
+
+                // Get duration
+                this.duration = getDurationInSeconds();
+            }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/src/org/apache/cordova/AuthenticationToken.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/AuthenticationToken.java b/lib/cordova-android/framework/src/org/apache/cordova/AuthenticationToken.java
new file mode 100644
index 0000000..d3a231a
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/AuthenticationToken.java
@@ -0,0 +1,69 @@
+/*
+       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;
+
+/**
+ * The Class AuthenticationToken defines the userName and password to be used for authenticating a web resource
+ */
+public class AuthenticationToken {
+    private String userName;
+    private String password;
+
+    /**
+     * Gets the user name.
+     *
+     * @return the user name
+     */
+    public String getUserName() {
+        return userName;
+    }
+
+    /**
+     * Sets the user name.
+     *
+     * @param userName
+     *            the new user name
+     */
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    /**
+     * Gets the password.
+     *
+     * @return the password
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Sets the password.
+     *
+     * @param password
+     *            the new password
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/d61deccd/lib/cordova-android/framework/src/org/apache/cordova/BatteryListener.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/BatteryListener.java b/lib/cordova-android/framework/src/org/apache/cordova/BatteryListener.java
new file mode 100755
index 0000000..85558c2
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/BatteryListener.java
@@ -0,0 +1,163 @@
+/*
+       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 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.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
+
+public class BatteryListener extends CordovaPlugin {
+
+    private static final String LOG_TAG = "BatteryManager";
+
+    BroadcastReceiver receiver;
+
+    private CallbackContext batteryCallbackContext = null;
+
+    /**
+     * Constructor.
+     */
+    public BatteryListener() {
+        this.receiver = null;
+    }
+
+    /**
+     * Executes the request.
+     *
+     * @param action        	The action to execute.
+     * @param args          	JSONArry of arguments for the plugin.
+     * @param callbackContext 	The callback context used when calling back into JavaScript.
+     * @return              	True if the action was valid, false if not.
+     */
+    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
+        if (action.equals("start")) {
+            if (this.batteryCallbackContext != null) {
+                callbackContext.error( "Battery listener already running.");
+                return true;
+            }
+            this.batteryCallbackContext = callbackContext;
+
+            // We need to listen to power events to update battery status
+            IntentFilter intentFilter = new IntentFilter();
+            intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
+            if (this.receiver == null) {
+                this.receiver = new BroadcastReceiver() {
+                    @Override
+                    public void onReceive(Context context, Intent intent) {
+                        updateBatteryInfo(intent);
+                    }
+                };
+                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
+            PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
+            pluginResult.setKeepCallback(true);
+            callbackContext.sendPluginResult(pluginResult);
+            return true;
+        }
+
+        else if (action.equals("stop")) {
+            removeBatteryListener();
+            this.sendUpdate(new JSONObject(), false); // release status callback in JS side
+            this.batteryCallbackContext = null;
+            callbackContext.success();
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Stop battery receiver.
+     */
+    public void onDestroy() {
+        removeBatteryListener();
+    }
+
+    /**
+     * Stop battery receiver.
+     */
+    public void onReset() {
+        removeBatteryListener();
+    }
+
+    /**
+     * Stop the battery receiver and set it to null.
+     */
+    private void removeBatteryListener() {
+        if (this.receiver != null) {
+            try {
+                this.cordova.getActivity().unregisterReceiver(this.receiver);
+                this.receiver = null;
+            } catch (Exception e) {
+                Log.e(LOG_TAG, "Error unregistering battery receiver: " + e.getMessage(), e);
+            }
+        }
+    }
+
+    /**
+     * Creates a JSONObject with the current battery information
+     *
+     * @param batteryIntent the current battery information
+     * @return a JSONObject containing the battery status information
+     */
+    private JSONObject getBatteryInfo(Intent batteryIntent) {
+        JSONObject obj = new JSONObject();
+        try {
+            obj.put("level", batteryIntent.getIntExtra(android.os.BatteryManager.EXTRA_LEVEL, 0));
+            obj.put("isPlugged", batteryIntent.getIntExtra(android.os.BatteryManager.EXTRA_PLUGGED, -1) > 0 ? true : false);
+        } catch (JSONException e) {
+            Log.e(LOG_TAG, e.getMessage(), e);
+        }
+        return obj;
+    }
+
+    /**
+     * Updates the JavaScript side whenever the battery changes
+     *
+     * @param batteryIntent the current battery information
+     * @return
+     */
+    private void updateBatteryInfo(Intent batteryIntent) {
+        sendUpdate(this.getBatteryInfo(batteryIntent), true);
+    }
+
+    /**
+     * Create a new plugin result and send it back to JavaScript
+     *
+     * @param connection the network info to set as navigator.connection
+     */
+    private void sendUpdate(JSONObject info, boolean keepCallback) {
+        if (this.batteryCallbackContext != null) {
+            PluginResult result = new PluginResult(PluginResult.Status.OK, info);
+            result.setKeepCallback(keepCallback);
+            this.batteryCallbackContext.sendPluginResult(result);
+        }
+    }
+}