Compare commits

...

62 Commits

Author SHA1 Message Date
macdonst e5e7c3fad3 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-06-29 15:55:34 -04:00
macdonst 2a8b9ab75e Tagging to 1.9.0 2012-06-29 15:55:03 -04:00
Fil Maj c8f0ffb42f Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-06-29 09:37:59 -07:00
Fil Maj b3e68b96cf Removing CordovaWebView Guide; its going into the docs 2012-06-29 09:37:31 -07:00
macdonst ae7a550a09 Only load Exif information if necessary 2012-06-29 11:31:33 -04:00
Anis Kadri e069bbb800 CB-937 fixing debug for windows 2012-06-28 17:11:21 -07:00
Anis Kadri 17ff6be6a9 CB-937 fixing debug 2012-06-28 17:08:32 -07:00
Anis Kadri d42489c67a Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-06-28 16:47:18 -07:00
macdonst e2047afa42 Wire rotation fix to correctOrientation parameter 2012-06-28 12:00:19 -04:00
macdonst 231b39d2dc Reset orientation exif information when photo is rotated
When a photo is taken in portrait mode we rotate it so it shows up properly in the webview. The Exif orientation must be reset to normal orientation (0) or the image will not display properly on desktops.
2012-06-28 12:00:19 -04:00
macdonst dddce30368 Rotate image if taken in portrait mode 2012-06-28 12:00:19 -04:00
macdonst e0e4ba2bd7 Fix double image problem on Samsung phones
On Samsung phones even if you tell the camera not to save to the photo gallery it still does. This small fix deletes the original file as it is not needed.
2012-06-28 12:00:19 -04:00
macdonst e0eadb6b76 Using a better scaling algorithm to resize the image
Instead of reading the entire image into a bitmap then scaling we use the
inSampleSize option to get a close to the target width and height as possible
then we scale that smaller image.
2012-06-28 12:00:19 -04:00
macdonst 483e5dfbea Switch getPicture from Gallery to use file instead of content resolver 2012-06-28 12:00:18 -04:00
macdonst 8aa9d8213d Cache bust returned Image URI if saveToPhotoAlbum is false 2012-06-28 12:00:18 -04:00
macdonst a74f71c935 Decode image from File instead of content resolver 2012-06-28 12:00:18 -04:00
macdonst 87b81e53f0 CB-978: FileTransfer.upload from a directory with a space fails 2012-06-28 11:57:06 -04:00
Joe Bowser a2816e31c3 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-06-28 08:00:59 -07:00
Joe Bowser f78af9f27b Forgot to add it renderscript.opt.level to the project. This will fix ant issues 2012-06-28 08:00:35 -07:00
Anis Kadri 98138a0a60 log was actually doing nothing...fixing it 2012-06-27 17:55:35 -07:00
Anis Kadri e639b6303e updating create script to work from distro and source 2012-06-27 17:54:57 -07:00
Anis Kadri 99fb3ebe00 creating project without source 2012-06-26 17:34:19 -07:00
Joe Bowser 5829840409 Re-adding getContext because yo dawg, I heard you like contexts in your contexts 2012-06-26 11:25:17 -07:00
Anis Kadri 4699ab5500 forgot to add +x on BOOM 2012-06-25 15:03:19 -07:00
Anis Kadri 69fc7f39b7 setting +x on script files 2012-06-25 14:59:35 -07:00
Anis Kadri 510a962a52 deleting old BOOM 2012-06-25 14:56:09 -07:00
Anis Kadri 570fc3cfb2 removing echoes 2012-06-25 14:46:10 -07:00
Joe Bowser 5d211f2fa6 Might as well keep isBackbuttonOverriden on the plugin 2012-06-22 10:38:42 -07:00
Joe Bowser dcb127c14d Weird merge error didn't account for isBackButtonBound 2012-06-22 10:37:33 -07:00
Fil Maj fba87de064 Removed some legacy button code that existed in droidgap + app plugins 2012-06-22 10:07:07 -07:00
Anis Kadri 576f8cba44 Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-06-21 21:15:59 -07:00
Anis Kadri b9f9429542 windows build/debug/launch scripts 2012-06-21 21:15:53 -07:00
Joe Bowser bf0df9f3c3 Since we moved binding of buttons into a view, let's remove it from the Interface 2012-06-21 15:21:56 -07:00
Joe Bowser 1d458f2782 After failed rebase, need to do merge in the branch to fix this 2012-06-21 14:49:19 -07:00
Fil Maj 5ca4b4a884 Refactored cleanup in camera code a bit. Removed overrides for Scanner functionality 2012-06-21 14:22:09 -07:00
Joe Bowser 5935052ead Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/incubator-cordova-android 2012-06-21 14:04:48 -07:00
Fil Maj f3f2ad9144 Merging in use of uri variable between Simon and my changes. 2012-06-21 14:03:59 -07:00
Fil Maj 9d1edc4554 Fixed the 0-byte files in gallery. Also fixed exif rewriter for saveToPhotoAlbum:false JPG files. Thanks for your help Simon! 2012-06-21 14:03:59 -07:00
Fil Maj 5143b8a492 added . in front of the temp files passed into camera app. presumably this hsould stop the gallery app from picking it up 2012-06-21 14:03:59 -07:00
Fil Maj 7c67f40fc4 Tacked on file extension to camera file 2012-06-21 14:03:58 -07:00
Fil Maj 167b600135 Removing images and saving images to jail if SaveToPhotoAlbum is set to true 2012-06-21 14:03:58 -07:00
Fil Maj 6c465e25d3 merge!!!!11one 2012-06-21 14:03:58 -07:00
Fil Maj c183d06ed1 Added MediaScanner abilities to camera launcher plugin. Now images saved to SD card should show up in the android gallery app right away 2012-06-21 14:03:58 -07:00
Joe Bowser 574731b853 Adding updated JS 2012-06-21 14:03:58 -07:00
Fil Maj 94568a4ec8 Merging in use of uri variable between Simon and my changes. 2012-06-21 12:37:44 -07:00
Fil Maj b22c0e5b6d Fixed the 0-byte files in gallery. Also fixed exif rewriter for saveToPhotoAlbum:false JPG files. Thanks for your help Simon! 2012-06-21 12:09:51 -07:00
Fil Maj ab3347d25d added . in front of the temp files passed into camera app. presumably this hsould stop the gallery app from picking it up 2012-06-21 12:09:51 -07:00
Fil Maj 66872de8e5 Tacked on file extension to camera file 2012-06-21 12:09:50 -07:00
Fil Maj f6d4402fdc Removing images and saving images to jail if SaveToPhotoAlbum is set to true 2012-06-21 12:09:50 -07:00
Fil Maj 9f66ccb5f3 merge!!!!11one 2012-06-21 12:09:50 -07:00
Fil Maj b339330592 Added MediaScanner abilities to camera launcher plugin. Now images saved to SD card should show up in the android gallery app right away 2012-06-21 12:09:50 -07:00
Anis Kadri 6f8e13297e fixing create 2012-06-20 19:08:18 -07:00
Anis Kadri e9a9144098 adding windows scripts 2012-06-20 19:07:41 -07:00
Joe Bowser d1905dbee8 Fixing work-around to work for both ? and # 2012-06-20 14:16:02 -07:00
Joe Bowser adc88f01b7 Attempt to test icecream_workaround from viafirma 2012-06-20 12:45:51 -07:00
Joe Bowser ccf0c5db67 Got up and down mixed 2012-06-20 12:07:04 -07:00
Joe Bowser f394f7457b Tweaks to CordovaWebView to support other keys 2012-06-19 16:35:22 -07:00
Joe Bowser 40b9810a63 Starting the Buttons Branch 2012-06-18 11:31:53 -07:00
Juan G. Hurtado dffd2deb53 Merge branch 'icecream_workaround' of github.com:viafirma/incubator-cordova-android into icecream_workaround 2012-05-18 08:49:26 +02:00
Juan G. Hurtado 8ff48b371e Fix imports for changes in 45680a5
Commit 45680a5 had errors importing packages. This commit fix them.
2012-05-18 08:48:08 +02:00
Juan G. Hurtado 6de66b87cb Add Android 4.0 workaround for links with params
Android 4.0.x has a known bug [1] while accessing local files with
params:

file://file.html?param=2

This commit adds a workaround for this problem by removing the params
part of the local URI before accessing the file.

[1] http://code.google.com/p/android/issues/detail?id=17535
2012-05-18 08:48:07 +02:00
Juan G. Hurtado 45680a562e Add Android 4.0 workaround for links with params
Android 4.0.x has a known bug [1] while accessing local files with
params:

file://file.html?param=2

This commit adds a workaround for this problem by removing the params
part of the local URI before accessing the file.

[1] http://code.google.com/p/android/issues/detail?id=17535
2012-05-16 08:42:50 +02:00
36 changed files with 735 additions and 467 deletions
+1 -1
View File
@@ -1 +1 @@
1.9.0rc1
1.9.0
-21
View File
@@ -1,21 +0,0 @@
#! /bin/sh
# 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.
#
#
./bin/create
cd ./example && ./cordova/debug && ./cordova/log
+34 -25
View File
@@ -46,11 +46,16 @@ fi
# cleanup after exit and/or on error
function on_exit {
echo "Cleaning up ..."
# [ -f $BUILD_PATH/framework/libs/commons-codec-1.6.jar ] && rm $BUILD_PATH/framework/libs/commons-codec-1.6.jar
# [ -d $BUILD_PATH/framework/libs ] && rmdir $BUILD_PATH/framework/libs
[ -f $BUILD_PATH/framework/assets/www/cordova-$VERSION.js ] && rm $BUILD_PATH/framework/assets/www/cordova-$VERSION.js
[ -f $BUILD_PATH/framework/cordova-$VERSION.jar ] && rm $BUILD_PATH/framework/cordova-$VERSION.jar
if [ -f $BUILD_PATH/framework/assets/www/cordova-$VERSION.js ]
then
rm $BUILD_PATH/framework/assets/www/cordova-$VERSION.js
fi
if [ -f $BUILD_PATH/framework/cordova-$VERSION.jar ]
then
rm $BUILD_PATH/framework/cordova-$VERSION.jar
fi
}
function on_error {
@@ -69,43 +74,47 @@ MANIFEST_PATH=$PROJECT_PATH/AndroidManifest.xml
TARGET=$($ANDROID_BIN list targets | grep id: | tail -1 | cut -f 2 -d ' ' )
# if this a distribution release no need to build a jar
if [ ! -e $BUILD_PATH/cordova-$VERSION.jar ] && [ -d $BUILD_PATH/framework ]
then
# update the cordova-android framework for the desired target
$ANDROID_BIN update project --target $TARGET --path $BUILD_PATH/framework &> /dev/null
$ANDROID_BIN update project --target $TARGET --path $BUILD_PATH/framework &> /dev/null
if [ ! -e $BUILD_PATH/framework/libs/commons-codec-1.6.jar ]; then
# Use curl to get the jar (TODO: Support Apache Mirrors)
echo "Downloading common-codecs-1.6 ..."
curl -OL http://mirror.symnds.com/software/Apache//commons/codec/binaries/commons-codec-1.6-bin.zip &> /dev/null
unzip commons-codec-1.6-bin.zip &> /dev/null
mkdir -p $BUILD_PATH/framework/libs
cp commons-codec-1.6/commons-codec-1.6.jar $BUILD_PATH/framework/libs
# cleanup yo
rm commons-codec-1.6-bin.zip && rm -rf commons-codec-1.6
fi
if [ ! -e $BUILD_PATH/framework/libs/commons-codec-1.6.jar ]; then
# Use curl to get the jar (TODO: Support Apache Mirrors)
curl -OL http://mirror.symnds.com/software/Apache//commons/codec/binaries/commons-codec-1.6-bin.zip &> /dev/null
unzip commons-codec-1.6-bin.zip &> /dev/null
mkdir -p $BUILD_PATH/framework/libs
cp commons-codec-1.6/commons-codec-1.6.jar $BUILD_PATH/framework/libs
# cleanup yo
rm commons-codec-1.6-bin.zip && rm -rf commons-codec-1.6
fi
# compile cordova.js and cordova.jar
echo "Building cordova-$VERSION.jar and cordova-$VERSION.js ..."
(cd $BUILD_PATH/framework && ant jar &> /dev/null )
(cd $BUILD_PATH/framework && ant jar &> /dev/null )
fi
# create new android project
echo "Creating a new cordova android project ..."
$ANDROID_BIN create project --target $TARGET --path $PROJECT_PATH --package $PACKAGE --activity $ACTIVITY &> /dev/null
# copy project template
echo "Copying assets and resources ..."
cp -r $BUILD_PATH/bin/templates/project/assets $PROJECT_PATH
cp -r $BUILD_PATH/bin/templates/project/res $PROJECT_PATH
# copy cordova.js, cordova.jar and res/xml
echo "Setting up config and plugins list ..."
cp -r $BUILD_PATH/framework/res/xml $PROJECT_PATH/res
echo "Adding cordova-$VERSION.js and cordova-$VERSION.jar ..."
cp $BUILD_PATH/framework/assets/www/cordova-$VERSION.js $PROJECT_PATH/assets/www/cordova-$VERSION.js
cp $BUILD_PATH/framework/cordova-$VERSION.jar $PROJECT_PATH/libs/cordova-$VERSION.jar
if [ -d $BUILD_PATH/framework ]
then
cp -r $BUILD_PATH/framework/res/xml $PROJECT_PATH/res
cp $BUILD_PATH/framework/assets/www/cordova-$VERSION.js $PROJECT_PATH/assets/www/cordova-$VERSION.js
cp $BUILD_PATH/framework/cordova-$VERSION.jar $PROJECT_PATH/libs/cordova-$VERSION.jar
else
cp -r $BUILD_PATH/xml $PROJECT_PATH/res/xml
cp $BUILD_PATH/cordova-$VERSION.js $PROJECT_PATH/assets/www/cordova-$VERSION.js
cp $BUILD_PATH/cordova-$VERSION.jar $PROJECT_PATH/libs/cordova-$VERSION.jar
fi
# interpolate the activity name and package
echo "Updating Activity and AndroidManifest ..."
cp $BUILD_PATH/bin/templates/project/Activity.java $ACTIVITY_PATH
sed -i '' -e "s/__ACTIVITY__/${ACTIVITY}/g" $ACTIVITY_PATH
sed -i '' -e "s/__ID__/${PACKAGE}/g" $ACTIVITY_PATH
+49 -24
View File
@@ -33,6 +33,10 @@ function read(filename) {
f.Close();
return s;
}
function setTarget() {
var targets = shell.Exec('android.bat list targets').StdOut.ReadAll().match(/id:\s\d+/g);
return targets[targets.length - 1].replace(/id: /, ""); // TODO: give users the option to set their target
}
function write(filename, contents) {
var fso=WScript.CreateObject("Scripting.FileSystemObject");
var f=fso.OpenTextFile(filename, 2, true);
@@ -42,12 +46,11 @@ function write(filename, contents) {
function replaceInFile(filename, regexp, replacement) {
write(filename, read(filename).replace(regexp, replacement));
}
function exec(s, output) {
var o=shell.Exec(s);
while (o.Status == 0) {
WScript.Sleep(100);
function exec(command) {
var oShell=shell.Exec(command);
while (oShell.Status == 0) {
WScript.sleep(100);
}
//WScript.Echo("Command exited with code " + o.Status);
}
function cleanup() {
@@ -125,33 +128,55 @@ if(fso.FolderExists(PROJECT_PATH)) {
var PACKAGE_AS_PATH=PACKAGE.replace(/\./g, '\\');
var ACTIVITY_PATH=PROJECT_PATH+'\\src\\'+PACKAGE_AS_PATH+'\\'+ACTIVITY+'.java';
var MANIFEST_PATH=PROJECT_PATH+'\\AndroidManifest.xml';
var TARGET=shell.Exec('android.bat list targets').StdOut.ReadAll().match(/id:\s([0-9]).*/)[1];
var TARGET=setTarget();
var VERSION=read(ROOT+'\\VERSION').replace(/\r\n/,'').replace(/\n/,'');
// create the project
exec('android.bat create project --target '+TARGET+' --path '+PROJECT_PATH+' --package '+PACKAGE+' --activity '+ACTIVITY);
// update the cordova framework project to a target that exists on this machine
exec('android.bat update project --target '+TARGET+' --path '+ROOT+'\\framework');
// pull down commons codec if necessary
downloadCommonsCodec();
exec('ant.bat -f '+ ROOT +'\\framework\\build.xml jar');
// build from source. distro should have these files
if (!fso.FileExists(ROOT+'\\cordova-'+VERSION+'.jar') &&
!fso.FileExists(ROOT+'\\cordova-'+VERSION+'.js')) {
// update the cordova framework project to a target that exists on this machine
exec('android.bat update project --target '+TARGET+' --path '+ROOT+'\\framework');
// pull down commons codec if necessary
downloadCommonsCodec();
exec('ant.bat -f '+ ROOT +'\\framework\\build.xml jar');
}
// copy in the project template
exec('cmd /c xcopy '+ ROOT + '\\bin\\templates\\project\\* '+PROJECT_PATH+' /S /Y');
exec('%comspec% /c xcopy '+ ROOT + '\\bin\\templates\\project\\res '+PROJECT_PATH+'\\res\\ /E /Y');
exec('%comspec% /c xcopy '+ ROOT + '\\bin\\templates\\project\\assets '+PROJECT_PATH+'\\assets\\ /E /Y');
exec('%comspec% /c copy '+ROOT+'\\bin\\templates\\project\\AndroidManifest.xml ' + PROJECT_PATH + '\\AndroidManifest.xml /Y');
exec('%comspec% /c copy '+ROOT+'\\bin\\templates\\project\\Activity.java '+ ACTIVITY_PATH +' /Y');
// copy in cordova.js
exec('cmd /c copy '+ROOT+'\\framework\\assets\\www\\cordova-'+VERSION+'.js '+PROJECT_PATH+'\\assets\\www\\cordova-'+VERSION+'.js /Y');
// check if we have the source or the distro files
if(fso.FolderExists(ROOT + '\\framework')) {
exec('%comspec% /c copy '+ROOT+'\\framework\\assets\\www\\cordova-'+VERSION+'.js '+PROJECT_PATH+'\\assets\\www\\cordova-'+VERSION+'.js /Y');
exec('%comspec% /c copy '+ROOT+'\\framework\\cordova-'+VERSION+'.jar '+PROJECT_PATH+'\\libs\\cordova-'+VERSION+'.jar /Y');
fso.CreateFolder(PROJECT_PATH + '\\res\\xml');
exec('%comspec% /c copy '+ROOT+'\\framework\\res\\xml\\cordova.xml ' + PROJECT_PATH + '\\res\\xml\\cordova.xml /Y');
exec('%comspec% /c copy '+ROOT+'\\framework\\res\\xml\\plugins.xml ' + PROJECT_PATH + '\\res\\xml\\plugins.xml /Y');
} else {
// copy in cordova.js
exec('%comspec% /c copy '+ROOT+'\\cordova-'+VERSION+'.js '+PROJECT_PATH+'\\assets\\www\\cordova-'+VERSION+'.js /Y');
// copy in cordova.jar
exec('%comspec% /c copy '+ROOT+'\\cordova-'+VERSION+'.jar '+PROJECT_PATH+'\\libs\\cordova-'+VERSION+'.jar /Y');
// copy in xml
fso.CreateFolder(PROJECT_PATH + '\\res\\xml');
exec('%comspec% /c copy '+ROOT+'\\xml\\cordova.xml ' + PROJECT_PATH + '\\res\\xml\\cordova.xml /Y');
exec('%comspec% /c copy '+ROOT+'\\xml\\plugins.xml ' + PROJECT_PATH + '\\res\\xml\\plugins.xml /Y');
}
// copy in cordova.jar
exec('cmd /c copy '+ROOT+'\\framework\\cordova-'+VERSION+'.jar '+PROJECT_PATH+'\\libs\\cordova-'+VERSION+'.jar /Y');
// copy in xml
fso.CreateFolder(PROJECT_PATH + '\\res\\xml');
exec('cmd /c copy '+ROOT+'\\framework\\res\\xml\\cordova.xml ' + PROJECT_PATH + '\\res\\xml\\cordova.xml /Y');
exec('cmd /c copy '+ROOT+'\\framework\\res\\xml\\plugins.xml ' + PROJECT_PATH + '\\res\\xml\\plugins.xml /Y');
// copy cordova scripts
fso.CreateFolder(PROJECT_PATH + '\\cordova');
exec('%comspec% /c copy '+ROOT+'\\bin\\templates\\cordova\\appinfo.jar ' + PROJECT_PATH + '\\cordova\\appinfo.jar /Y');
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\\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');
// interpolate the activity name and package
replaceInFile(ACTIVITY_PATH, /__ACTIVITY__/, ACTIVITY);
@@ -21,7 +21,7 @@ public class ApplicationInfo {
// getting activity name
String activity = ((Element)dom.getElementsByTagName("activity").item(0)).getAttribute("android:name");
System.out.println(String.format("%s/%s.%s", pakkage, pakkage, activity));
System.out.println(String.format("%s/.%s", pakkage, activity.replace(".", "")));
} catch(ParserConfigurationException pce) {
pce.printStackTrace();
} catch(SAXException se) {
@@ -1 +0,0 @@
Main-Class: ApplicationInfo
Regular → Executable
View File
+1
View File
@@ -0,0 +1 @@
%~dp0\cordova.bat BOOM
Binary file not shown.
Regular → Executable
View File
+1
View File
@@ -0,0 +1 @@
%~dp0\cordova.bat clean
Regular → Executable
+9 -15
View File
@@ -61,12 +61,15 @@ function log {
adb logcat
}
function debug_install {
ant debug install
}
function debug {
ant debug
if [ $(check_devices) == 0 ] ; then
ant debug install
else
ant debug
echo "##################################################################"
echo "# Plug in your device or launch an emulator with cordova/emulate #"
echo "##################################################################"
fi
}
function launch {
@@ -75,16 +78,7 @@ function launch {
}
function BOOM {
clean
if [ $(check_devices) == 0 ] ; then
debug_install && launch
return
else
debug
echo "##################################################################"
echo "# Plug in your device or launch an emulator with cordova/emulate #"
echo "##################################################################"
fi
clean && debug && launch
}
# TODO parse arguments
+15
View File
@@ -0,0 +1,15 @@
@ECHO OFF
IF NOT DEFINED JAVA_HOME GOTO MISSING
FOR %%X in (java.exe ant.bat android.bat) do (
SET FOUND=%%~$PATH:X
IF NOT DEFINED FOUND GOTO MISSING
)
cscript %~dp0\cordova.js %*
GOTO END
:MISSING
ECHO Missing one of the following:
ECHO JDK: http://java.oracle.com
ECHO Android SDK: http://developer.android.com
ECHO Apache ant: http://ant.apache.org
EXIT /B 1
:END
+104
View File
@@ -0,0 +1,104 @@
var ROOT = WScript.ScriptFullName.split('\\cordova\\cordova.js').join(''),
shell=WScript.CreateObject("WScript.Shell");
function exec(command) {
var oExec=shell.Exec(command);
var output = new String();
while(oExec.Status == 0) {
if(!oExec.StdOut.AtEndOfStream) {
var line = oExec.StdOut.ReadLine();
// XXX: Change to verbose mode
// WScript.StdOut.WriteLine(line);
output += line;
}
WScript.sleep(100);
}
return output;
}
function emulator_running() {
var local_devices = shell.Exec("%comspec% /c adb devices").StdOut.ReadAll();
if(local_devices.match(/emulator/)) {
return true;
}
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!");
return;
}
var oExec = shell.Exec("%comspec% /c android.bat list avd");
var avd_list = [];
var avd_id = -10;
while(!oExec.StdOut.AtEndOfStream) {
var output = oExec.StdOut.ReadLine();
if(output.match(/Name: (.)*/)) {
avd_list.push(output.replace(/ *Name:\s/, ""));
}
}
// user has no AVDs
if(avd_list.length == 0) {
WScript.Echo("You don't have any Android Virtual Devices. Please create at least one AVD.");
WScript.Echo("android");
WScript.Quit(1);
}
// user has only one AVD so we launch that one
if(avd_list.length == 1) {
shell.Run("emulator -cpu-delay 0 -no-boot-anim -cache %Temp%\cache -avd "+avd_list[0]);
}
// user has more than one avd so we ask them to choose
if(avd_list.length > 1) {
while(!avd_list[avd_id]) {
WScript.Echo("Choose from one of the following Android Virtual Devices [0 to "+(avd_list.length - 1)+"]:")
for(i = 0, j = avd_list.length ; i < j ; i++) {
WScript.Echo((i)+") "+avd_list[i]);
}
WScript.StdOut.Write("> ");
avd_id = new Number(WScript.StdIn.ReadLine());
}
shell.Run("emulator -cpu-delay 0 -no-boot-anim -cache %Temp%\\cache -avd "+avd_list[avd_id], 0, false);
}
}
function clean() {
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 log() {
shell.Run("%comspec% /c adb logcat");
}
function launch() {
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() {
clean();
debug();
launch();
}
var args = WScript.Arguments;
if(args.count() != 1) {
WScript.StdErr.Write("An error has occured!\n");
WScript.Quit(1);
}
eval(args(0)+"()");
Regular → Executable
View File
+1
View File
@@ -0,0 +1 @@
%~dp0\cordova.bat debug
Regular → Executable
View File
+1
View File
@@ -0,0 +1 @@
%~dp0\cordova.bat emulate
Regular → Executable
View File
+1
View File
@@ -0,0 +1 @@
%~dp0\cordova.bat log
+1 -1
View File
@@ -23,7 +23,7 @@
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>PhoneGap</title>
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="cordova-1.9.0rc1.js"></script>
<script type="text/javascript" charset="utf-8" src="cordova-1.9.0.js"></script>
<script type="text/javascript" charset="utf-8" src="main.js"></script>
</head>
+37 -2
View File
@@ -91,8 +91,43 @@ create_project.on('exit', function(code) {
assert(exists, 'cordova.js did not get added');
});
// check that project compiles && creates a cordovaExample-debug.apk
// XXX: !@##!@# WINDOWS
// make sure cordova master script was added
path.exists(util.format('%s/cordova/cordova.bat', project_path), function(exists) {
assert(exists, 'cordova script did not get added');
});
// make sure debug script was added
path.exists(util.format('%s/cordova/debug.bat', project_path), function(exists) {
assert(exists, 'debug script did not get added');
});
// make sure BOOM script was added
path.exists(util.format('%s/cordova/BOOM.bat', project_path), function(exists) {
assert(exists, 'BOOM script did not get added');
});
// make sure log script was added
path.exists(util.format('%s/cordova/log.bat', project_path), function(exists) {
assert(exists, 'log script did not get added');
});
// make sure clean script was added
path.exists(util.format('%s/cordova/clean.bat', project_path), function(exists) {
assert(exists, 'clean script did not get added');
});
// make sure emulate script was added
path.exists(util.format('%s/cordova/emulate.bat', project_path), function(exists) {
assert(exists, 'emulate script did not get added');
});
// make sure appinfo.jar script was added
path.exists(util.format('%s/cordova/appinfo.jar', project_path), function(exists) {
assert(exists, 'appinfo.jar script did not get added');
});
// check that project compiles && creates a cordovaExample-debug.apk
// XXX: !@##!@# WINDOWS
exec('ant debug -f ' + project_path + "\\build.xml", function(error, stdout, stderr) {
assert(error == null, "Cordova Android Project does not compile");
path.exists(util.format('%s/bin/%s-debug.apk', project_path, project_name),
+2 -2
View File
@@ -1,6 +1,6 @@
// commit 25033fceac7c800623f1f16881b784d19eba69cc
// commit 5647225e12e18e15aefc33b151430d9a3804d9ea
// File generated at :: Thu Jun 21 2012 10:45:32 GMT-0700 (PDT)
// File generated at :: Fri Jun 29 2012 12:32:24 GMT-0400 (EDT)
/*
Licensed to the Apache Software Foundation (ASF) under one
+1 -1
View File
@@ -19,7 +19,7 @@
<html>
<head>
<title></title>
<script src="cordova-1.9.0rc1.js"></script>
<script src="cordova-1.9.0.js"></script>
</head>
<body>
+1
View File
@@ -12,3 +12,4 @@ split.density=false
# Project target.
target=Google Inc.:Google APIs:15
apk-configurations=
renderscript.opt.level=O0
+4 -7
View File
@@ -73,10 +73,6 @@ public class App extends Plugin {
else if (action.equals("overrideBackbutton")) {
this.overrideBackbutton(args.getBoolean(0));
}
else if (action.equals("isBackbuttonOverridden")) {
boolean b = this.isBackbuttonOverridden();
return new PluginResult(status, b);
}
else if (action.equals("exitApp")) {
this.exitApp();
}
@@ -188,7 +184,7 @@ public class App extends Plugin {
*/
public void overrideBackbutton(boolean override) {
LOG.i("App", "WARNING: Back Button Default Behaviour will be overridden. The backbutton event will be fired!");
this.cordova.bindBackButton(override);
webView.bindButton(override);
}
/**
@@ -200,15 +196,16 @@ public class App extends Plugin {
*/
public void overrideButton(String button, boolean override) {
LOG.i("DroidGap", "WARNING: Volume Button Default Behaviour will be overridden. The volume event will be fired!");
this.cordova.bindButton(button, override);
webView.bindButton(button, override);
}
/**
* Return whether the Android back button is overridden by the user.
*
* @return boolean
*/
public boolean isBackbuttonOverridden() {
return this.cordova.isBackButtonBound();
return webView.isBackButtonBound();
}
/**
@@ -40,8 +40,11 @@ import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Bitmap.CompressFormat;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
@@ -52,7 +55,7 @@ import android.util.Log;
* and returns the captured image. When the camera view is closed, the screen displayed before
* the camera view was shown is redisplayed.
*/
public class CameraLauncher extends Plugin {
public class CameraLauncher extends Plugin implements MediaScannerConnectionClient {
private static final int DATA_URL = 0; // Return base64 encoded string
private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android)
@@ -79,10 +82,15 @@ public class CameraLauncher extends Plugin {
private Uri imageUri; // Uri of captured image
private int encodingType; // Type of encoding to use
private int mediaType; // What type of media to retrieve
private boolean saveToPhotoAlbum; // Should the picture be saved to the device's photo album
private boolean correctOrientation; // Should the pictures orientation be corrected
private boolean allowEdit; // Should we allow the user to crop the image
public String callbackId;
private int numPics;
private MediaScannerConnection conn; // Used to update gallery app with newly-written files
//This should never be null!
//private CordovaInterface cordova;
@@ -117,6 +125,7 @@ public class CameraLauncher extends Plugin {
if (action.equals("takePicture")) {
int srcType = CAMERA;
int destType = FILE_URI;
this.saveToPhotoAlbum = false;
this.targetHeight = 0;
this.targetWidth = 0;
this.encodingType = JPEG;
@@ -130,6 +139,9 @@ public class CameraLauncher extends Plugin {
this.targetHeight = args.getInt(4);
this.encodingType = args.getInt(5);
this.mediaType = args.getInt(6);
this.allowEdit = args.getBoolean(7);
this.correctOrientation = args.getBoolean(8);
this.saveToPhotoAlbum = args.getBoolean(9);
if (srcType == CAMERA) {
this.takePicture(destType, encodingType);
@@ -174,7 +186,6 @@ public class CameraLauncher extends Plugin {
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
// Specify file so that large image is captured and returned
// TODO: What if there isn't any external storage?
File photo = createCaptureFile(encodingType);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
this.imageUri = Uri.fromFile(photo);
@@ -195,9 +206,9 @@ public class CameraLauncher extends Plugin {
private File createCaptureFile(int encodingType) {
File photo = null;
if (encodingType == JPEG) {
photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), "Pic.jpg");
photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), ".Pic.jpg");
} else if (encodingType == PNG) {
photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), "Pic.png");
photo = new File(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()), ".Pic.png");
} else {
throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
}
@@ -237,53 +248,6 @@ public class CameraLauncher extends Plugin {
}
}
/**
* Scales the bitmap according to the requested size.
*
* @param bitmap The bitmap to scale.
* @return Bitmap A new Bitmap object of the same bitmap after scaling.
*/
public Bitmap scaleBitmap(Bitmap bitmap) {
int newWidth = this.targetWidth;
int newHeight = this.targetHeight;
int origWidth = bitmap.getWidth();
int origHeight = bitmap.getHeight();
// If no new width or height were specified return the original bitmap
if (newWidth <= 0 && newHeight <= 0) {
return bitmap;
}
// Only the width was specified
else if (newWidth > 0 && newHeight <= 0) {
newHeight = (newWidth * origHeight) / origWidth;
}
// only the height was specified
else if (newWidth <= 0 && newHeight > 0) {
newWidth = (newHeight * origWidth) / origHeight;
}
// If the user specified both a positive width and height
// (potentially different aspect ratio) then the width or height is
// scaled so that the image fits while maintaining aspect ratio.
// Alternatively, the specified width and height could have been
// kept and Bitmap.SCALE_TO_FIT specified when scaling, but this
// would result in whitespace in the new image.
else {
double newRatio = newWidth / (double) newHeight;
double origRatio = origWidth / (double) origHeight;
if (origRatio > newRatio) {
newHeight = (newWidth * origHeight) / origWidth;
} else if (origRatio < newRatio) {
newWidth = (newHeight * origWidth) / origHeight;
}
}
Bitmap retval = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
bitmap.recycle();
System.gc();
return retval;
}
/**
* Called when the camera view exits.
*
@@ -299,18 +263,19 @@ public class CameraLauncher extends Plugin {
int destType = (requestCode % 16) - 1;
int rotate = 0;
// Create an ExifHelper to save the exif data that is lost during compression
ExifHelper exif = new ExifHelper();
try {
if (this.encodingType == JPEG) {
exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/Pic.jpg");
exif.readExifData();
}
} catch (IOException e) {
e.printStackTrace();
}
// If CAMERA
if (srcType == CAMERA) {
// Create an ExifHelper to save the exif data that is lost during compression
ExifHelper exif = new ExifHelper();
try {
if (this.encodingType == JPEG) {
exif.createInFile(DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/.Pic.jpg");
exif.readExifData();
rotate = exif.getOrientation();
}
} catch (IOException e) {
e.printStackTrace();
}
// If image available
if (resultCode == Activity.RESULT_OK) {
try {
@@ -318,7 +283,11 @@ public class CameraLauncher extends Plugin {
// If sending base64 image back
if (destType == DATA_URL) {
bitmap = scaleBitmap(getBitmapFromResult(intent));
bitmap = getScaledBitmap(FileUtils.stripFileProtocol(imageUri.toString()));
if (rotate != 0 && this.correctOrientation) {
bitmap = getRotatedBitmap(rotate, bitmap, exif);
}
this.processPicture(bitmap);
checkForDuplicateImage(DATA_URL);
@@ -326,64 +295,61 @@ public class CameraLauncher extends Plugin {
// If sending filename back
else if (destType == FILE_URI) {
// Create entry in media store for image
// (Don't use insertImage() because it uses default compression setting of 50 - no way to change it)
ContentValues values = new ContentValues();
values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
Uri uri = null;
try {
uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException e) {
LOG.d(LOG_TAG, "Can't write to external media storage.");
try {
uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException ex) {
LOG.d(LOG_TAG, "Can't write to internal media storage.");
this.failPicture("Error capturing image - no media storage found.");
return;
}
Uri uri;
if (!this.saveToPhotoAlbum) {
uri = Uri.fromFile(new File("/data/data/" + this.cordova.getActivity().getPackageName() + "/", (new File(FileUtils.stripFileProtocol(this.imageUri.toString()))).getName()));
} else {
uri = getUriFromMediaStore();
}
if (uri == null) {
this.failPicture("Error capturing image - no media storage found.");
}
// If all this is true we shouldn't compress the image.
if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100) {
FileInputStream fis = new FileInputStream(FileUtils.stripFileProtocol(imageUri.toString()));
OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
byte[] buffer = new byte[4096];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
os.flush();
os.close();
fis.close();
checkForDuplicateImage(FILE_URI);
if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 && rotate == 0) {
writeUncompressedImage(uri);
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
return;
} else {
bitmap = getScaledBitmap(FileUtils.stripFileProtocol(imageUri.toString()));
if (rotate != 0 && this.correctOrientation) {
bitmap = getRotatedBitmap(rotate, bitmap, exif);
}
// Add compressed version of captured image to returned media store Uri
OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
os.close();
// Restore exif data to file
if (this.encodingType == JPEG) {
String exifPath;
if (this.saveToPhotoAlbum) {
exifPath = FileUtils.getRealPathFromURI(uri, this.cordova);
} else {
exifPath = uri.getPath();
}
exif.createOutFile(exifPath);
exif.writeExifData();
}
}
bitmap = scaleBitmap(getBitmapFromResult(intent));
// Add compressed version of captured image to returned media store Uri
OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
os.close();
// Restore exif data to file
if (this.encodingType == JPEG) {
exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.cordova));
exif.writeExifData();
}
// Send Uri back to JavaScript for viewing image
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
if (saveToPhotoAlbum) {
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
} else {
// If you don't want to save the file to the photo album you need to append a timestamp
// to the returned URI to do some cache busting.
this.success(new PluginResult(PluginResult.Status.OK, uri.toString() + "?" + System.currentTimeMillis()), this.callbackId);
}
}
bitmap.recycle();
bitmap = null;
System.gc();
checkForDuplicateImage(FILE_URI);
this.cleanup(FILE_URI, this.imageUri, bitmap);
bitmap = null;
} catch (IOException e) {
e.printStackTrace();
this.failPicture("Error capturing image.");
@@ -405,7 +371,6 @@ public class CameraLauncher extends Plugin {
else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) {
if (resultCode == Activity.RESULT_OK) {
Uri uri = intent.getData();
android.content.ContentResolver resolver = this.cordova.getActivity().getContentResolver();
// If you ask for video or all media type you will automatically get back a file URI
// and there will be no attempt to resize any returned data
@@ -413,33 +378,28 @@ public class CameraLauncher extends Plugin {
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
}
else {
// Get the path to the image. Makes loading so much easier.
String imagePath = FileUtils.getRealPathFromURI(uri, this.cordova);
Bitmap bitmap = getScaledBitmap(imagePath);
// If sending base64 image back
if (destType == DATA_URL) {
try {
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
String[] cols = { MediaStore.Images.Media.ORIENTATION };
Cursor cursor = this.cordova.getActivity().getContentResolver().query(intent.getData(),
cols,
null, null, null);
if (cursor != null) {
cursor.moveToPosition(0);
rotate = cursor.getInt(0);
cursor.close();
}
if (rotate != 0) {
Matrix matrix = new Matrix();
matrix.setRotate(rotate);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
bitmap = scaleBitmap(bitmap);
this.processPicture(bitmap);
bitmap.recycle();
bitmap = null;
System.gc();
} catch (FileNotFoundException e) {
e.printStackTrace();
this.failPicture("Error retrieving image.");
String[] cols = { MediaStore.Images.Media.ORIENTATION };
Cursor cursor = this.cordova.getActivity().getContentResolver().query(intent.getData(),
cols,
null, null, null);
if (cursor != null) {
cursor.moveToPosition(0);
rotate = cursor.getInt(0);
cursor.close();
}
if (rotate != 0) {
Matrix matrix = new Matrix();
matrix.setRotate(rotate);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
this.processPicture(bitmap);
}
// If sending filename back
@@ -447,11 +407,20 @@ public class CameraLauncher extends Plugin {
// Do we need to scale the returned file
if (this.targetHeight > 0 && this.targetWidth > 0) {
try {
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
bitmap = scaleBitmap(bitmap);
// Create an ExifHelper to save the exif data that is lost during compression
String resizePath = DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/resize.jpg";
ExifHelper exif = new ExifHelper();
try {
if (this.encodingType == JPEG) {
exif.createInFile(resizePath);
exif.readExifData();
rotate = exif.getOrientation();
}
} catch (IOException e) {
e.printStackTrace();
}
String fileName = DirectoryManager.getTempDirectoryPath(this.cordova.getActivity()) + "/resize.jpg";
OutputStream os = new FileOutputStream(fileName);
OutputStream os = new FileOutputStream(resizePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
os.close();
@@ -461,13 +430,9 @@ public class CameraLauncher extends Plugin {
exif.writeExifData();
}
bitmap.recycle();
bitmap = null;
// The resized image is cached by the app in order to get around this and not have to delete you
// application cache I'm adding the current system time to the end of the file url.
this.success(new PluginResult(PluginResult.Status.OK, ("file://" + fileName + "?" + System.currentTimeMillis())), this.callbackId);
System.gc();
this.success(new PluginResult(PluginResult.Status.OK, ("file://" + resizePath + "?" + System.currentTimeMillis())), this.callbackId);
} catch (Exception e) {
e.printStackTrace();
this.failPicture("Error retrieving image.");
@@ -477,6 +442,9 @@ public class CameraLauncher extends Plugin {
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
}
}
bitmap.recycle();
bitmap = null;
System.gc();
}
}
else if (resultCode == Activity.RESULT_CANCELED) {
@@ -488,19 +456,108 @@ public class CameraLauncher extends Plugin {
}
}
private Bitmap getBitmapFromResult(Intent intent)
throws IOException, FileNotFoundException {
Bitmap bitmap = null;
try {
bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getActivity().getContentResolver(), imageUri);
} catch (FileNotFoundException e) {
Uri uri = intent.getData();
android.content.ContentResolver resolver = this.ctx.getActivity().getContentResolver();
bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
/**
* Figure out if the bitmap should be rotated. For instance if the picture was taken in
* portrait mode
*
* @param rotate
* @param bitmap
* @return rotated bitmap
*/
private Bitmap getRotatedBitmap(int rotate, Bitmap bitmap, ExifHelper exif) {
Matrix matrix = new Matrix();
if (rotate == 180) {
matrix.setRotate(rotate);
} else {
matrix.setRotate(rotate, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);
}
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
exif.resetOrientation();
return bitmap;
}
/**
* In the special case where the default width, height and quality are unchanged
* we just write the file out to disk saving the expensive Bitmap.compress function.
*
* @param uri
* @throws FileNotFoundException
* @throws IOException
*/
private void writeUncompressedImage(Uri uri) throws FileNotFoundException,
IOException {
FileInputStream fis = new FileInputStream(FileUtils.stripFileProtocol(imageUri.toString()));
OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri);
byte[] buffer = new byte[4096];
int len;
while ((len = fis.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
os.flush();
os.close();
fis.close();
}
/**
* Create entry in media store for image
*
* @return uri
*/
private Uri getUriFromMediaStore() {
ContentValues values = new ContentValues();
values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
Uri uri;
try {
uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException e) {
LOG.d(LOG_TAG, "Can't write to external media storage.");
try {
uri = this.cordova.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException ex) {
LOG.d(LOG_TAG, "Can't write to internal media storage.");
return null;
}
}
return uri;
}
/**
* Return a scaled bitmap based on the target width and height
*
* @param imagePath
* @return
*/
private Bitmap getScaledBitmap(String imagePath) {
// If no new width or height were specified return the original bitmap
if (this.targetWidth <= 0 && this.targetHeight <= 0) {
return BitmapFactory.decodeFile(imagePath);
}
Bitmap unscaledBitmap = decodeFile(imagePath,
this.targetWidth, this.targetHeight);
return Bitmap.createScaledBitmap(unscaledBitmap, this.targetWidth, this.targetHeight, true);
}
public static Bitmap decodeFile(String pathName, int dstWidth, int dstHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathName, options);
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth, dstHeight);
return BitmapFactory.decodeFile(pathName, options);
}
public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return srcWidth / dstWidth;
} else {
return srcHeight / dstHeight;
}
}
/**
* Creates a cursor that can be used to determine how many images we have.
*
@@ -515,6 +572,24 @@ public class CameraLauncher extends Plugin {
null);
}
/**
* Cleans up after picture taking. Checking for duplicates and that kind of stuff.
*/
private void cleanup(int imageType, Uri oldImage, Bitmap bitmap) {
if (bitmap != null) {
bitmap.recycle();
}
// Clean up initial camera-written image file.
(new File(FileUtils.stripFileProtocol(oldImage.toString()))).delete();
checkForDuplicateImage(imageType);
// Scan for the gallery to update pic refs in gallery
this.scanForGallery();
System.gc();
}
/**
* Used to find out if we are in a situation where the Camera Intent adds to images
* to the content store. If we are using a FILE_URI and the number of images in the DB
@@ -528,7 +603,7 @@ public class CameraLauncher extends Plugin {
Cursor cursor = queryImgDB(contentStore);
int currentNumOfImages = cursor.getCount();
if (type == FILE_URI) {
if (type == FILE_URI && this.saveToPhotoAlbum) {
diff = 2;
}
@@ -584,4 +659,24 @@ public class CameraLauncher extends Plugin {
public void failPicture(String err) {
this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId);
}
private void scanForGallery() {
if(this.conn!=null) this.conn.disconnect();
this.conn = new MediaScannerConnection(this.ctx.getActivity().getApplicationContext(), this);
conn.connect();
}
public void onMediaScannerConnected() {
try{
this.conn.scanFile(this.imageUri.toString(), "image/*");
} catch (java.lang.IllegalStateException e){
e.printStackTrace();
LOG.d(LOG_TAG, "Can;t scan file in MediaScanner aftering taking picture");
}
}
public void onScanCompleted(String path, Uri uri) {
this.conn.disconnect();
}
}
@@ -39,6 +39,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
@@ -51,16 +52,20 @@ public class CordovaWebView extends WebView {
/** The whitelist **/
private ArrayList<Pattern> whiteList = new ArrayList<Pattern>();
private HashMap<String, Boolean> whiteListCache = new HashMap<String, Boolean>();
private ArrayList<Integer> keyDownCodes = new ArrayList<Integer>();
private ArrayList<Integer> keyUpCodes = new ArrayList<Integer>();
public PluginManager pluginManager;
public CallbackServer callbackServer;
/** Actvities and other important classes **/
private CordovaInterface cordova;
CordovaWebViewClient viewClient;
@SuppressWarnings("unused")
private CordovaChromeClient chromeClient;
//This is for the polyfil history
//This is for the polyfil history
private String url;
String baseUrl;
private Stack<String> urls = new Stack<String>();
@@ -70,9 +75,15 @@ public class CordovaWebView extends WebView {
// Flag to track that a loadUrl timeout occurred
int loadUrlTimeout = 0;
private boolean bound;
private boolean volumedownBound;
private boolean volumeupBound;
/**
* Constructor.
*
*
* @param context
*/
public CordovaWebView(Context context) {
@@ -91,7 +102,7 @@ public class CordovaWebView extends WebView {
/**
* Constructor.
*
*
* @param context
* @param attrs
*/
@@ -113,11 +124,11 @@ public class CordovaWebView extends WebView {
/**
* Constructor.
*
*
* @param context
* @param attrs
* @param defStyle
*
*
*/
public CordovaWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
@@ -137,7 +148,7 @@ public class CordovaWebView extends WebView {
/**
* Constructor.
*
*
* @param context
* @param attrs
* @param defStyle
@@ -200,7 +211,7 @@ public class CordovaWebView extends WebView {
/**
* Set the WebViewClient.
*
*
* @param client
*/
public void setWebViewClient(CordovaWebViewClient client) {
@@ -210,7 +221,7 @@ public class CordovaWebView extends WebView {
/**
* Set the WebChromeClient.
*
*
* @param client
*/
public void setWebChromeClient(CordovaChromeClient client) {
@@ -220,7 +231,7 @@ public class CordovaWebView extends WebView {
/**
* Add entry to approved list of URLs (whitelist)
*
*
* @param origin URL regular expression to allow
* @param subdomains T=include all subdomains under origin
*/
@@ -258,7 +269,7 @@ public class CordovaWebView extends WebView {
/**
* Determine if URL is in approved list of URLs to load.
*
*
* @param url
* @return
*/
@@ -286,7 +297,7 @@ public class CordovaWebView extends WebView {
/**
* Load the url into the webview.
*
*
* @param url
*/
@Override
@@ -312,7 +323,7 @@ public class CordovaWebView extends WebView {
/**
* Load the url into the webview after waiting for period of time.
* This is used to display the splashscreen for certain amount of time.
*
*
* @param url
* @param time The number of ms to wait before loading webview
*/
@@ -331,7 +342,7 @@ public class CordovaWebView extends WebView {
/**
* Load the url into the webview.
*
*
* @param url
*/
public void loadUrlIntoView(final String url) {
@@ -400,7 +411,7 @@ public class CordovaWebView extends WebView {
/**
* Load URL in webview.
*
*
* @param url
*/
private void loadUrlNow(String url) {
@@ -411,7 +422,7 @@ public class CordovaWebView extends WebView {
/**
* Load the url into the webview after waiting for period of time.
* This is used to display the splashscreen for certain amount of time.
*
*
* @param url
* @param time The number of ms to wait before loading webview
*/
@@ -438,7 +449,7 @@ public class CordovaWebView extends WebView {
/**
* Send JavaScript statement back to JavaScript.
* (This is a convenience method)
*
*
* @param message
*/
public void sendJavascript(String statement) {
@@ -448,8 +459,8 @@ public class CordovaWebView extends WebView {
}
/**
* Send a message to all plugins.
*
* Send a message to all plugins.
*
* @param id The message id
* @param data The message data
*/
@@ -459,8 +470,8 @@ public class CordovaWebView extends WebView {
}
}
/**
* Returns the top url on the stack without removing it from
/**
* Returns the top url on the stack without removing it from
* the stack.
*/
public String peekAtUrlStack() {
@@ -472,7 +483,7 @@ public class CordovaWebView extends WebView {
/**
* Add a url to the stack
*
*
* @param url
*/
public void pushUrl(String url) {
@@ -481,7 +492,7 @@ public class CordovaWebView extends WebView {
/**
* Go to previous page in history. (We manage our own history)
*
*
* @return true if we went back, false if we are already at top
*/
public boolean backHistory() {
@@ -506,7 +517,7 @@ public class CordovaWebView extends WebView {
/**
* Return true if there is a history item.
*
*
* @return
*/
public boolean canGoBack() {
@@ -521,7 +532,7 @@ public class CordovaWebView extends WebView {
/**
* Load the specified URL in the Cordova webview or a new browser instance.
*
*
* NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
*
* @param url The url to load.
@@ -614,6 +625,7 @@ public class CordovaWebView extends WebView {
String value = xml.getAttributeValue(null, "value");
LOG.i("CordovaLog", "Found preference for %s=%s", name, value);
Log.d("CordovaLog", "Found preference for " + name + "=" + value);
// Save preferences in Intent
this.cordova.getActivity().getIntent().putExtra(name, value);
@@ -629,7 +641,7 @@ public class CordovaWebView extends WebView {
}
// Init preferences
if ("true".equals(this.getProperty("useBrowserHistory", "true"))) {
if ("true".equals(this.getProperty("useBrowserHistory", "false"))) {
this.useBrowserHistory = true;
}
else {
@@ -644,7 +656,7 @@ public class CordovaWebView extends WebView {
/**
* Get string property for activity.
*
*
* @param name
* @param defaultValue
* @return
@@ -660,4 +672,109 @@ public class CordovaWebView extends WebView {
}
return p.toString();
}
/*
* onKeyDown
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if(keyDownCodes.contains(keyCode))
{
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
// only override default behaviour is event bound
LOG.d(TAG, "Down Key Hit");
this.loadUrl("javascript:cordova.fireDocumentEvent('volumedownbutton');");
return true;
}
// If volumeup key
else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
LOG.d(TAG, "Up Key Hit");
this.loadUrl("javascript:cordova.fireDocumentEvent('volumeupbutton');");
return true;
}
else
{
//Do some other stuff!
}
}
return false;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event)
{
Log.d(TAG, "KeyDown has been triggered on the view");
// If back key
if (keyCode == KeyEvent.KEYCODE_BACK) {
// 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) {
this.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');");
return super.onKeyUp(keyCode, event);
}
// If search key
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
this.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');");
return true;
}
else if(keyUpCodes.contains(keyCode))
{
//What the hell should this do?
}
Log.d(TAG, "KeyUp has been triggered on the view");
return false;
}
public void bindButton(boolean override)
{
this.bound = override;
}
public void bindButton(String button, boolean override) {
// TODO Auto-generated method stub
if (button.compareTo("volumeup")==0) {
keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_UP);
}
else if (button.compareTo("volumedown")==0) {
keyDownCodes.add(KeyEvent.KEYCODE_VOLUME_DOWN);
}
}
public void bindButton(int keyCode, boolean keyDown, boolean override) {
if(keyDown)
{
keyDownCodes.add(keyCode);
}
else
{
keyUpCodes.add(keyCode);
}
}
public boolean isBackButtonBound()
{
return this.bound;
}
}
@@ -21,20 +21,26 @@ package org.apache.cordova;
import java.util.Hashtable;
import org.apache.cordova.api.CordovaInterface;
import java.io.IOException;
import java.io.InputStream;
import org.apache.cordova.api.LOG;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.view.View;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
@@ -241,6 +247,7 @@ public class CordovaWebViewClient extends WebViewClient {
* Notify the host application that a page has finished loading.
* This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet.
*
*
* @param view The webview initiating the callback.
* @param url The url of the page.
*/
@@ -344,6 +351,7 @@ public class CordovaWebViewClient extends WebViewClient {
final String packageName = this.cordova.getActivity().getPackageName();
final PackageManager pm = this.cordova.getActivity().getPackageManager();
ApplicationInfo appInfo;
try {
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
@@ -451,4 +459,43 @@ public class CordovaWebViewClient extends WebViewClient {
this.authenticationTokens.clear();
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if(url.contains("?") || url.contains("#")){
return generateWebResourceResponse(url);
} else {
return super.shouldInterceptRequest(view, url);
}
}
private WebResourceResponse generateWebResourceResponse(String url) {
final String ANDROID_ASSET = "file:///android_asset/";
if (url.startsWith(ANDROID_ASSET)) {
String niceUrl = url;
niceUrl = url.replaceFirst(ANDROID_ASSET, "");
if(niceUrl.contains("?")){
niceUrl = niceUrl.split("\\?")[0];
}
else if(niceUrl.contains("#"))
{
niceUrl = niceUrl.split("#")[0];
}
String mimetype = null;
if(niceUrl.endsWith(".html")){
mimetype = "text/html";
}
try {
AssetManager assets = cordova.getActivity().getAssets();
Uri uri = Uri.parse(niceUrl);
InputStream stream = assets.open(uri.getPath(), AssetManager.ACCESS_STREAMING);
WebResourceResponse response = new WebResourceResponse(mimetype, "UTF-8", stream);
return response;
} catch (IOException e) {
LOG.e("generateWebResourceResponse", e.getMessage(), e);
}
}
return null;
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ import android.telephony.TelephonyManager;
public class Device extends Plugin {
public static final String TAG = "Device";
public static String cordovaVersion = "1.9.0rc1"; // Cordova version
public static String cordovaVersion = "1.9.0"; // Cordova version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID
+2 -114
View File
@@ -138,7 +138,6 @@ public class DroidGap extends Activity implements CordovaInterface {
protected CordovaWebViewClient webViewClient;
protected LinearLayout root;
public boolean bound = false;
protected boolean cancelLoadUrl = false;
protected ProgressDialog spinnerDialog = null;
@@ -181,10 +180,6 @@ public class DroidGap extends Activity implements CordovaInterface {
// when another application (activity) is started.
protected boolean keepRunning = true;
private boolean volumeupBound;
private boolean volumedownBound;
/**
* Sets the authentication token.
*
@@ -784,87 +779,7 @@ public class DroidGap extends Activity implements CordovaInterface {
super.finish();
}
/**
* Called when a key is released. (Key UP)
*
* @param keyCode
* @param event
*/
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (this.appView == null) {
return super.onKeyUp(keyCode, event);
}
// If back key
if (keyCode == KeyEvent.KEYCODE_BACK) {
// If back key is bound, then send event to JavaScript
if (this.bound) {
this.appView.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 behavior of super class
else {
this.activityState = ACTIVITY_EXITING;
return super.onKeyUp(keyCode, event);
}
}
}
// If menu key
else if (keyCode == KeyEvent.KEYCODE_MENU) {
this.appView.loadUrl("javascript:cordova.fireDocumentEvent('menubutton');");
return super.onKeyUp(keyCode, event);
}
// If search key
else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
this.appView.loadUrl("javascript:cordova.fireDocumentEvent('searchbutton');");
return true;
}
return false;
}
/**
* Called when a key is pressed. (Key DOWN)
*
* @param keyCode
* @param event
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (this.appView == null) {
return super.onKeyDown(keyCode, event);
}
// If volumedown key
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (this.volumedownBound==true) {
// only override default behaviour is event bound
LOG.d(TAG, "Down Key Hit");
this.appView.loadUrl("javascript:cordova.fireDocumentEvent('volumedownbutton');");
return true;
}
}
// If volumeup key
else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
if (this.volumeupBound==true) {
// only override default behaviour is event bound
LOG.d(TAG, "Up Key Hit");
this.appView.loadUrl("javascript:cordova.fireDocumentEvent('volumeupbutton');");
return true;
}
}
return super.onKeyDown(keyCode, event);
}
/**
* Launch an activity for which you would like a result when it finished. When this activity exits,
* your onActivityResult() method will be called.
@@ -1025,27 +940,10 @@ public class DroidGap extends Activity implements CordovaInterface {
* @return
*/
public Context getContext() {
LOG.d(TAG, "This will be deprecated December 2012");
return this.getContext();
}
/**
* Override the backbutton.
*
* @param override
*/
public void bindBackButton(boolean override) {
this.bound = override;
}
/**
* Determine of backbutton is overridden.
*
* @return
*/
public boolean isBackButtonBound() {
return this.bound;
}
/**
* Load the specified URL in the Cordova webview or a new browser instance.
*
@@ -1062,16 +960,6 @@ public class DroidGap extends Activity implements CordovaInterface {
}
}
public void bindButton(String button, boolean override) {
// TODO Auto-generated method stub
if (button.compareTo("volumeup")==0) {
this.volumeupBound = override;
}
else if (button.compareTo("volumedown")==0) {
this.volumedownBound = override;
}
}
protected Dialog splashDialog;
/**
@@ -162,4 +162,24 @@ public class ExifHelper {
this.outFile.saveAttributes();
}
public int getOrientation() {
int o = Integer.parseInt(this.orientation);
if (o == ExifInterface.ORIENTATION_NORMAL) {
return 0;
} else if (o == ExifInterface.ORIENTATION_ROTATE_90) {
return 90;
} else if (o == ExifInterface.ORIENTATION_ROTATE_180) {
return 180;
} else if (o == ExifInterface.ORIENTATION_ROTATE_270) {
return 270;
} else {
return 0;
}
}
public void resetOrientation() {
this.orientation = "" + ExifInterface.ORIENTATION_NORMAL;
}
}
@@ -29,6 +29,7 @@ import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
@@ -73,7 +74,7 @@ public class FileTransfer extends Plugin {
String source = null;
String target = null;
try {
source = args.getString(0);
source = URLDecoder.decode(args.getString(0));
target = args.getString(1);
} catch (JSONException e) {
Log.d(LOG_TAG, "Missing source or target");
@@ -321,7 +322,7 @@ public class FileTransfer extends Plugin {
} catch (Throwable t) {
// Shouldn't happen, but will
JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, conn);
Log.wtf(LOG_TAG, error.toString(), t);
Log.e(LOG_TAG, error.toString(), t);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} finally {
if (conn != null) {
@@ -19,6 +19,7 @@
package org.apache.cordova.api;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
/**
@@ -44,19 +45,6 @@ public interface CordovaInterface {
*/
abstract public void setActivityResultCallback(IPlugin plugin);
/**
* Causes the Activity to override the back button behavior.
*
* @param override
*/
public abstract void bindBackButton(boolean override);
/**
* A hook required to check if the Back Button is bound.
*
* @return
*/
public abstract boolean isBackButtonBound();
/**
* Get the Android activity.
@@ -64,7 +52,10 @@ public interface CordovaInterface {
* @return
*/
public abstract Activity getActivity();
@Deprecated
public abstract Context getContext();
@Deprecated
public abstract void cancelLoadUrl();
@@ -77,5 +68,4 @@ public interface CordovaInterface {
*/
public Object onMessage(String id, Object data);
public abstract void bindButton(String button, boolean override);
}
-53
View File
@@ -1,53 +0,0 @@
# How to use Cordova as a component #
Beginning in Cordova 1.8, with the assistance of the CordovaActivity, you can use Cordova as a component in your Android applications. This component is known in Android
as the CordovaWebView, and new Cordova-based applications from 1.8 and greater will be using the CordovaWebView as its main view, whether the legacy DroidGap approach is
used or not.
The pre-requisites are the same as the pre-requisites for Android application development. It is assumed that you are familiar with Android Development. If not, please
look at the Getting Started guide to developing an Cordova Application and start there before continuing with this approach. Since this is not the main method that people use
to run applications, the instructions are currently manual. In the future, we may try to further automate the project generation.
## Pre-requisites ##
1. **Cordova 1.8** or greater downloaded
2. Android SDK updated with 15
## Guide to using CordovaWebView in an Android Project ##
1. Use bin/create to fetch the commons-codec-1.6.jar
2. Go into framework and run ant jar to build the cordova jar (currently cordova-1.8.jar at the time of writing)
3. Copy the cordova jar into your Android project libs directory
4. Edit your main.xml to look similar the following. The layout_height, layout_width and ID can be modified to suit your application:
` <org.apache.cordova.CordovaWebView$
android:id="@+id/tutorialView"$
android:layout_width="match_parent"$
android:layout_height="match_parent" />$
`
5. Modify your activity so that it implements the CordovaInterface. It is recommended that you implement the methods that are included. You may wish to copy the methods from framework/src/org/apache/cordova/DroidGap.java, or you may wish to implement your own methods. Below is a fragment of code from a basic application that uses the interface:
`
public class CordovaViewTestActivity extends Activity implements CordovaInterface {$
CordovaWebView phoneGap;$
$
/** Called when the activity is first created. */$
@Override$
public void onCreate(Bundle savedInstanceState) {$
super.onCreate(savedInstanceState);$
setContentView(R.layout.main);$
$
phoneGap = (CordovaWebView) findViewById(R.id.phoneGapView);$
$
phoneGap.loadUrl("file:///android_asset/www/index.html");$
}$
`
6. Copy the HTML and Javascript used to the assets directory of your Android project
7. Copy cordova.xml and plugins.xml from framework/res/xml to the framework/res/xml in your project