Compare commits

..

42 Commits
0.9.3 ... 0.9.4

Author SHA1 Message Date
macdonst
f848527c28 Upping version to 0.9.4 2011-02-03 09:48:31 +08:00
Bryce Curtis
6aa055f46e Change super.setProperty() to use super.set<type>Property() in example comments. 2011-02-02 14:37:09 -06:00
macdonst
7952668cf7 Throwing error on FileWriter.abort() if writer is not in the correct state. Lining up with iPhone and BlackBerry 2011-02-03 02:26:49 +08:00
macdonst
a0c761664d Call onwriteend not onloadend in FileWriter.abort() 2011-02-03 02:08:41 +08:00
macdonst
9fd9cf55cf Adding version number to phonegap jar/js files 2011-02-03 01:51:59 +08:00
macdonst
3c9089b9c7 Enable hardware volume control buttons in DroidGap applications 2011-02-02 23:33:01 +08:00
Bryce Curtis
f220489543 Disable picture listener once event has occurred. 2011-02-01 11:25:01 -06:00
Bryce Curtis
b65f9517db Merge branch 'filmaj-splashscreenfix' 2011-02-01 11:00:02 -06:00
Bryce Curtis
1a0de5f626 Merge branch 'splashscreenfix' of https://github.com/filmaj/phonegap-android into filmaj-splashscreenfix 2011-02-01 10:46:38 -06:00
Fil Maj
3c0bef6cc1 Ticket 81: Tweak to label of local path to index.html in example app, now properly shows actual project-relative path. 2011-01-31 17:51:15 -08:00
Fil Maj
040194157f Ticket 80: running "droidgap gen example" leads to recursive directory creation. README fix included. 2011-01-31 17:48:56 -08:00
macdonst
7ebf8130e4 Set type to url for returned photos 2011-01-29 04:19:06 +08:00
macdonst
64310dc85c Fixing clone issue adding photos, removing relationships 2011-01-27 05:59:22 +08:00
macdonst
cd2e86af2f Removing excess logging in contact.save() 2011-01-27 03:44:27 +08:00
macdonst
b353f3608d Updating to latest W3C spec 2011-01-27 03:41:27 +08:00
macdonst
cda154209d Fixing merge issue 2011-01-26 11:22:08 -05:00
Sveinung Kval Bakken
e3c72fa915 Will now use a "smarter" approach to finding an account for Contact.save, the order of account search will be:
1. Exchange provider
2. Google
3. Any valid email address account
2011-01-25 11:36:08 +01:00
Fil Maj
9354b429f3 Fix for ticket #55: if phonegap source was on a path with "bin" in it would cause major fail. 2011-01-24 15:51:26 -08:00
Fil Maj
b1f0c037bd Getting rid of black screen between native loading screen and actual PhoneGap app. 2011-01-24 12:43:28 -08:00
macdonst
726f1094d9 Fixing bug found by tiny hippos 2011-01-25 03:05:59 +08:00
macdonst
1b8ab156df Adding http: and file: support when saving a contact photo. 2011-01-25 01:58:31 +08:00
macdonst
ee01b5058f Adding support to set a Contact photo 2011-01-22 01:52:20 +08:00
macdonst
03ea8a0b5a Enable the return of photos in a Contact object 2011-01-20 04:27:40 +08:00
macdonst
f090f9a70c Merge branch 'master' of https://github.com/filmaj/phonegap-android into filmaj 2011-01-17 11:54:52 -05:00
Bryce Curtis
b7abc2c344 Skip over beginning / in request when comparing to token. 2011-01-16 15:15:24 -06:00
Fil Maj
53bdf2dd6b Fix for specifying icon in config.xml; the @icon attribute would get overriden by defaults when going from create => classic::build. 2011-01-15 23:12:07 -08:00
Joe Bowser
b9e1b1d280 Adding Blank HTML page 2011-01-13 16:27:54 -08:00
Bryce Curtis
9051b157f8 Ticket 63: Android CallbackServer crashes on external attacks. 2011-01-13 14:45:15 -06:00
macdonst
f16d9b01b7 Fixing geo listner callback fail to send 3 args instead of 4. 2011-01-14 02:07:47 +08:00
macdonst
2a9bc2ddf8 Fixing issue where Android 2.1 and 2.2 don't return the same results on contact.find() 2011-01-14 02:02:21 +08:00
macdonst
6e39c46b07 Middle name for contact being updated incorrectly 2011-01-12 21:58:20 +08:00
macdonst
567ca94245 Adding debug mode so FileTransfer will accept self signed SSL certificates 2011-01-12 10:32:26 +08:00
macdonst
812a4b32b4 Adding file key properly 2011-01-07 23:17:05 +08:00
Bryce Curtis
023df10f31 Allow features/modules to initialize code before deviceready fires. CupcakeLocalStorage uses this capability to delay deviceready until local storage has been read and inited. 2011-01-06 22:50:13 -06:00
macdonst
8d513e2765 Remaining FileUploader to FileTransfer 2011-01-07 01:43:12 +08:00
Bryce Curtis
1eae6786c4 Better memory management when taking pictures. 2011-01-06 11:12:14 -06:00
macdonst
73f278963b Adding File Upload functionality 2011-01-06 07:09:07 +08:00
macdonst
54eff557d9 Guard against null request in Android 1.5/1.6 2011-01-06 04:08:23 +08:00
Bryce Curtis
a7415bcfc9 Support all URIs by passing them to their default activity. This works for market:// and content://. 2011-01-04 13:22:25 -06:00
macdonst
b6bd9ad5b8 Support Market Uri 2011-01-05 03:03:38 +08:00
macdonst
f71d9deb5e Fixing mimetypes for content:// Uri's. 2011-01-05 02:45:04 +08:00
macdonst
115b428a9d Fixing issue where Date's aren't cloned 2010-12-30 00:53:06 +08:00
24 changed files with 1113 additions and 553 deletions

View File

@@ -31,7 +31,7 @@ Commands:
<pre>
help ...... See this message. Type help [command name] to see specific help topics.
gen ....... Generate an example PhoneGap application to current directory.
gen ....... Generate the example PhoneGap application to current directory (or optionally provide an output directory as parameter).
create .... Creates an Android compatible project from a WWW folder.
classic ... Backwards support for droidgap script. Run "droidgap help classic" for more info.
update .... Copy a fresh phonegap.jar and phonegap.js into a valid PhoneGap/Android project.
@@ -41,8 +41,8 @@ Commands:
Quickstart:
<pre>
$ droidgap gen example
$ cd example
$ droidgap gen exampleapp
$ cd exampleapp
$ ant debug install && adb logcat
</pre>

1
VERSION Normal file
View File

@@ -0,0 +1 @@
0.9.4

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env ruby
ROOT = File.expand_path(File.dirname(__FILE__).gsub('bin',''))
ROOT = File.expand_path(File.dirname(__FILE__).gsub(/bin$/,''))
require 'fileutils'
require File.join(ROOT, "lib", "generate.rb")
require File.join(ROOT, "lib", "classic.rb")
@@ -60,7 +60,7 @@ if ARGV.first.nil? || ARGV.first == 'help'
Commands:
help ...... See this message. Type help [command name] to see specific help topics.
gen ....... Generate an example PhoneGap application to current directory.
gen ....... Generate the example PhoneGap application to current directory (or optionally provide an output directory as parameter).
create .... Creates an Android compatible project from a WWW folder.
classic ... Backwards support for droidgap script. Run "droidgap help classic" for more info.
update .... Copy a fresh phonegap.jar and phonegap.js into a valid PhoneGap/Android project.
@@ -68,8 +68,8 @@ if ARGV.first.nil? || ARGV.first == 'help'
Quickstart:
$ droidgap gen example
$ cd example
$ droidgap gen exampleapp
$ cd exampleapp
$ ant debug install && adb logcat
EOF
@@ -79,11 +79,13 @@ if ARGV.first.nil? || ARGV.first == 'help'
DroidGap Generate
-----------------
Generate an example PhoneGap application to path supplied or current working directory if none is supplied.
Generate the example PhoneGap application to path supplied or current working directory if none is supplied.
Usage:
droidgap gen [path]
NOTE: Do *not* run "droidgap gen example" - you will end up with a recursive directory problem.
EOF

View File

@@ -11,7 +11,7 @@
</head>
<body onload="init();" id="stage" class="theme">
<h1>Welcome to PhoneGap!</h1>
<h2>this file is located at assets/index.html</h2>
<h2>this file is located at assets/www/index.html</h2>
<div id="info">
<h4>Platform: <span id="platform"> &nbsp;</span>, Version: <span id="version">&nbsp;</span></h4>
<h4>UUID: <span id="uuid"> &nbsp;</span>, Name: <span id="name">&nbsp;</span></h4>

View File

@@ -17,24 +17,17 @@
* @param {ContactAddress[]} addresses array of addresses
* @param {ContactField[]} ims instant messaging user ids
* @param {ContactOrganization[]} organizations
* @param {DOMString} published date contact was first created
* @param {DOMString} updated date contact was last updated
* @param {DOMString} revision date contact was last updated
* @param {DOMString} birthday contact's birthday
* @param (DOMString} anniversary contact's anniversary
* @param {DOMString} gender contact's gender
* @param {DOMString} note user notes about contact
* @param {DOMString} preferredUsername
* @param {ContactField[]} photos
* @param {ContactField[]} tags
* @param {ContactField[]} relationships
* @param {ContactField[]} categories
* @param {ContactField[]} urls contact's web sites
* @param {ContactAccounts[]} accounts contact's online accounts
* @param {DOMString} utcOffset UTC time zone offset
* @param {DOMString} connected
* @param {DOMString} timezone the contacts time zone
*/
var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses,
ims, organizations, published, updated, birthday, anniversary, gender, note,
preferredUsername, photos, tags, relationships, urls, accounts, utcOffset, connected) {
ims, organizations, revision, birthday, gender, note, photos, categories, urls, timezone) {
this.id = id || null;
this.rawId = null;
this.displayName = displayName || null;
@@ -45,20 +38,14 @@ var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, ad
this.addresses = addresses || null; // ContactAddress[]
this.ims = ims || null; // ContactField[]
this.organizations = organizations || null; // ContactOrganization[]
this.published = published || null;
this.updated = updated || null;
this.revision = revision || null;
this.birthday = birthday || null;
this.anniversary = anniversary || null;
this.gender = gender || null;
this.note = note || null;
this.preferredUsername = preferredUsername || null;
this.photos = photos || null; // ContactField[]
this.tags = tags || null; // ContactField[]
this.relationships = relationships || null; // ContactField[]
this.categories = categories || null; // ContactField[]
this.urls = urls || null; // ContactField[]
this.accounts = accounts || null; // ContactAccount[]
this.utcOffset = utcOffset || null;
this.connected = connected || null;
this.timezone = timezone || null;
};
/**
@@ -117,9 +104,9 @@ Contact.prototype.clone = function() {
clonedContact.tags[i].id = null;
}
}
if (clonedContact.relationships) {
for (i=0; i<clonedContact.relationships.length; i++) {
clonedContact.relationships[i].id = null;
if (clonedContact.photos) {
for (i=0; i<clonedContact.photos.length; i++) {
clonedContact.photos[i].id = null;
}
}
if (clonedContact.urls) {
@@ -162,13 +149,13 @@ var ContactName = function(formatted, familyName, givenName, middle, prefix, suf
* @param {DOMString} id unique identifier, should only be set by native code
* @param type
* @param value
* @param primary
* @param pref
*/
var ContactField = function(type, value, primary) {
var ContactField = function(type, value, pref) {
this.id = null;
this.type = type || null;
this.value = value || null;
this.primary = primary || null;
this.pref = pref || null;
};
/**
@@ -202,31 +189,13 @@ var ContactAddress = function(formatted, streetAddress, locality, region, postal
* @param location
* @param desc
*/
var ContactOrganization = function(name, dept, title, startDate, endDate, location, desc) {
var ContactOrganization = function(name, dept, title) {
this.id = null;
this.name = name || null;
this.department = dept || null;
this.title = title || null;
this.startDate = startDate || null;
this.endDate = endDate || null;
this.location = location || null;
this.description = desc || null;
};
/**
* Contact account.
* @param {DOMString} id unique identifier, should only be set by native code
* @param domain
* @param username
* @param userid
*/
var ContactAccount = function(domain, username, userid) {
this.id = null;
this.domain = domain || null;
this.username = username || null;
this.userid = userid || null;
}
/**
* Represents a group of Contacts.
*/
@@ -284,13 +253,11 @@ Contacts.prototype.cast = function(pluginResult) {
* ContactFindOptions.
* @param filter used to match contacts against
* @param multiple boolean used to determine if more than one contact should be returned
* @param limit maximum number of results to return from the contacts search
* @param updatedSince return only contact records that have been updated on or after the given time
*/
var ContactFindOptions = function(filter, multiple, limit, updatedSince) {
var ContactFindOptions = function(filter, multiple, updatedSince) {
this.filter = filter || '';
this.multiple = multiple || false;
this.limit = limit || 1;
this.multiple = multiple || true;
this.updatedSince = updatedSince || '';
};

View File

@@ -425,6 +425,11 @@ FileWriter.DONE = 2;
* Abort writing file.
*/
FileWriter.prototype.abort = function() {
// check for invalid state
if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
throw FileError.INVALID_STATE_ERR;
}
// set error
var error = new FileError();
error.code = error.ABORT_ERR;
@@ -443,10 +448,10 @@ FileWriter.prototype.abort = function() {
this.readyState = FileWriter.DONE;
// If load end callback
if (typeof this.onloadend == "function") {
// If write end callback
if (typeof this.onwriteend == "function") {
var evt = File._createEvent("writeend", this);
this.onloadend(evt);
this.onwriteend(evt);
}
};

View File

@@ -0,0 +1,77 @@
/*
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
*/
/**
* FileTransfer uploads a file to a remote server.
*/
function FileTransfer() {};
/**
* FileUploadResult
*/
function FileUploadResult() {
this.bytesSent = 0;
this.responseCode = null;
this.response = null;
};
/**
* FileTransferError
*/
function FileTransferError() {
this.code = null;
};
FileTransferError.FILE_NOT_FOUND_ERR = 1;
FileTransferError.INVALID_URL_ERR = 2;
FileTransferError.CONNECTION_ERR = 3;
/**
* Given an absolute file path, uploads a file on the device to a remote server
* using a multipart HTTP request.
* @param filePath {String} Full path of the file on the device
* @param server {String} URL of the server to receive the file
* @param successCallback (Function} Callback to be invoked when upload has completed
* @param errorCallback {Function} Callback to be invoked upon error
* @param options {FileUploadOptions} Optional parameters such as file name and mimetype
*/
FileTransfer.prototype.upload = function(filePath, server, successCallback, errorCallback, options, debug) {
// check for options
var fileKey = null;
var fileName = null;
var mimeType = null;
var params = null;
if (options) {
fileKey = options.fileKey;
fileName = options.fileName;
mimeType = options.mimeType;
if (options.params) {
params = options.params;
}
else {
params = {};
}
}
PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, debug]);
};
/**
* Options to customize the HTTP request used to upload files.
* @param fileKey {String} Name of file request parameter.
* @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
* @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
* @param params {Object} Object with key: value params to send to the server.
*/
function FileUploadOptions(fileKey, fileName, mimeType, params) {
this.fileKey = fileKey || null;
this.fileName = fileName || null;
this.mimeType = mimeType || null;
this.params = params || null;
};

View File

@@ -136,8 +136,14 @@ PhoneGap.Channel.join = function(h, c) {
var f = function() {
if (!(--i)) h();
}
for (var j=0; j<i; j++) {
(!c[j].fired?c[j].subscribeOnce(f):i--);
var len = i;
for (var j=0; j<len; j++) {
if (!c[j].fired) {
c[j].subscribeOnce(f);
}
else {
i--;
}
}
if (!i) h();
};
@@ -238,6 +244,39 @@ if (typeof _nativeReady !== 'undefined') { PhoneGap.onNativeReady.fire(); }
PhoneGap.onDeviceReady = new PhoneGap.Channel('onDeviceReady');
// Array of channels that must fire before "deviceready" is fired
PhoneGap.deviceReadyChannelsArray = [ PhoneGap.onPhoneGapReady, PhoneGap.onPhoneGapInfoReady];
// Hashtable of user defined channels that must also fire before "deviceready" is fired
PhoneGap.deviceReadyChannelsMap = {};
/**
* Indicate that a feature needs to be initialized before it is ready to be used.
* This holds up PhoneGap's "deviceready" event until the feature has been initialized
* and PhoneGap.initComplete(feature) is called.
*
* @param feature {String} The unique feature name
*/
PhoneGap.waitForInitialization = function(feature) {
if (feature) {
var channel = new PhoneGap.Channel(feature);
PhoneGap.deviceReadyChannelsMap[feature] = channel;
PhoneGap.deviceReadyChannelsArray.push(channel);
}
};
/**
* Indicate that initialization code has completed and the feature is ready to be used.
*
* @param feature {String} The unique feature name
*/
PhoneGap.initializationComplete = function(feature) {
var channel = PhoneGap.deviceReadyChannelsMap[feature];
if (channel) {
channel.fire();
}
};
/**
* Create all PhoneGap objects once page has fully loaded and native side is ready.
*/
@@ -259,12 +298,24 @@ PhoneGap.Channel.join(function() {
// Fire event to notify that all objects are created
PhoneGap.onPhoneGapReady.fire();
PhoneGap.Channel.join(function() {
// Turn off app loading dialog
navigator.notification.activityStop();
PhoneGap.onDeviceReady.fire();
// Fire the onresume event, since first one happens before JavaScript is loaded
PhoneGap.onResume.fire();
}, PhoneGap.deviceReadyChannelsArray);
}, [ PhoneGap.onDOMContentLoaded, PhoneGap.onNativeReady ]);
/**
* Fire onDeviceReady event once all constructors have run and PhoneGap info has been
* received from native side.
*/
/*
PhoneGap.Channel.join(function() {
// Turn off app loading dialog
navigator.notification.activityStop();
@@ -274,6 +325,7 @@ PhoneGap.Channel.join(function() {
// Fire the onresume event, since first one happens before JavaScript is loaded
PhoneGap.onResume.fire();
}, [ PhoneGap.onPhoneGapReady, PhoneGap.onPhoneGapInfoReady]);
*/
// Listen for DOMContentLoaded and notify our channel subscribers
document.addEventListener('DOMContentLoaded', function() {
@@ -289,6 +341,9 @@ document.addEventListener = function(evt, handler, capture) {
PhoneGap.onDeviceReady.subscribeOnce(handler);
} else if (e == 'resume') {
PhoneGap.onResume.subscribe(handler);
if (PhoneGap.onDeviceReady.fired) {
PhoneGap.onResume.fire();
}
} else if (e == 'pause') {
PhoneGap.onPause.subscribe(handler);
} else {
@@ -385,7 +440,11 @@ PhoneGap.clone = function(obj) {
if(!(obj instanceof Object)){
return obj;
}
if (obj instanceof Date) {
return obj;
}
retVal = new Object();
for(i in obj){
if(!(i in retVal) || retVal[i] != obj[i]) {

View File

@@ -309,6 +309,7 @@ var CupcakeLocalStorage = function() {
for(var i = 0; i < result.rows.length; i++) {
storage[result.rows.item(i)['id']] = result.rows.item(i)['body'];
}
PhoneGap.initializationComplete("cupcakeStorage");
});
},
@@ -356,6 +357,7 @@ PhoneGap.addConstructor(function() {
if (typeof window.localStorage == "undefined") {
navigator.localStorage = window.localStorage = new CupcakeLocalStorage();
PhoneGap.waitForInitialization("cupcakeStorage");
}
});

View File

@@ -0,0 +1,9 @@
<html>
<head>
<title></title>
<script src="phonegap.js"></script>
</head>
<body>
</body>
</html>

View File

@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="PhoneGap" default="help">
<!-- LOAD VERSION -->
<loadfile property="version" srcFile="../VERSION">
<filterchain>
<striplinebreaks/>
</filterchain>
</loadfile>
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked in in Version
Control Systems. -->
@@ -73,7 +80,7 @@
<include name="lint.js" />
</fileset>
<fileset dir="assets/www">
<include name="phonegap.js" />
<include name="phonegap.${version}.js" />
</fileset>
</concat>
@@ -100,15 +107,21 @@
<target name="build-uncompressed-javascript">
<!-- Clean up existing files -->
<delete file="assets/www/phonegap.js"/>
<delete file="assets/www/phonegap.${version}.min.js"/>
<delete file="assets/www/phonegap-tmp.js"/>
<delete file="assets/www/phonegap-uncompressed.js"/>
<delete file="assets/www/phonegap.${version}.js"/>
<!-- Create uncompressed JS file -->
<concat destfile="assets/www/phonegap.js">
<concat destfile="assets/www/phonegap.${version}.js">
<fileset dir="assets/js" includes="phonegap.js.base" />
<fileset dir="assets/js" includes="*.js" />
</concat>
<!-- update project files to reference phonegap-x.x.x.js -->
<replaceregexp match="phonegap(.*)\.js" replace="phonegap.${version}.js" byline="true">
<fileset file="assets/www/index.html" />
<fileset file="../example/index.html" />
</replaceregexp>
</target>
<!-- Combine JavaScript files into one phonegap-uncompressed.js file.
@@ -116,24 +129,30 @@
<target name="build-javascript">
<!-- Clean up existing files -->
<delete file="assets/www/phonegap.js"/>
<delete file="assets/www/phonegap_${version}.min.js"/>
<delete file="assets/www/phonegap-tmp.js"/>
<delete file="assets/www/phonegap-uncompressed.js"/>
<delete file="assets/www/phonegap_${version}.js"/>
<!-- Create uncompressed JS file -->
<concat destfile="assets/www/phonegap-uncompressed.js">
<concat destfile="assets/www/phonegap.${version}.js">
<fileset dir="assets/js" includes="phonegap.js.base" />
<fileset dir="assets/js" includes="*.js" />
</concat>
<!-- Compress JS file -->
<java jar="${basedir}/../util/yuicompressor/yuicompressor-2.4.2.jar" fork="true" failonerror="true">
<arg line="--nomunge -o assets/www/phonegap-tmp.js assets/www/phonegap-uncompressed.js"/>
<arg line="--nomunge -o assets/www/phonegap-tmp.js assets/www/phonegap.${version}.js"/>
</java>
<concat destfile="assets/www/phonegap.js">
<concat destfile="assets/www/phonegap.${version}.min.js">
<fileset dir="assets/js" includes="header.txt" />
<fileset dir="assets/www" includes="phonegap-tmp.js" />
</concat>
<!-- update project files to reference phonegap-x.x.x.min.js -->
<replaceregexp match="phonegap(.*)\.js" replace="phonegap.${version}.min.js" byline="true">
<fileset file="assets/www/index.html" />
<fileset file="../example/index.html" />
</replaceregexp>
<!-- Delete temp file -->
<delete file="assets/www/phonegap-tmp.js"/>
@@ -148,7 +167,7 @@
"build-javascript" => "build-uncompressed-javascript".
-->
<target name="jar" depends="build-javascript, compile">
<jar jarfile="phonegap.jar" basedir="bin/classes" excludes="com/phonegap/R.class,com/phonegap/R$*.class"/>
<jar jarfile="phonegap.${version}.jar" basedir="bin/classes" excludes="com/phonegap/R.class,com/phonegap/R$*.class"/>
</target>
<target name="phonegap_debug" depends="build-javascript, debug">

View File

@@ -188,54 +188,60 @@ public class CallbackServer implements Runnable {
request = xhrReader.readLine();
String response = "";
//System.out.println("CallbackServerRequest="+request);
if (request.contains("GET")) {
if (this.active && (request != null)) {
if (request.contains("GET")) {
// Get requested file
String[] requestParts = request.split(" ");
// Must have security token
if ((requestParts.length == 3) && (requestParts[1].substring(1).equals(this.token))) {
//System.out.println("CallbackServer -- Processing GET request");
// Must have security token
if (request.substring(5,41).equals(this.token)) {
//System.out.println("CallbackServer -- Processing GET request");
// Wait until there is some data to send, or send empty data every 10 sec
// to prevent XHR timeout on the client
synchronized (this) {
while (this.empty) {
try {
this.wait(10000); // prevent timeout from happening
//System.out.println("CallbackServer>>> break <<<");
break;
// Wait until there is some data to send, or send empty data every 10 sec
// to prevent XHR timeout on the client
synchronized (this) {
while (this.empty) {
try {
this.wait(10000); // prevent timeout from happening
//System.out.println("CallbackServer>>> break <<<");
break;
}
catch (Exception e) { }
}
catch (Exception e) { }
}
}
}
// If server is still running
if (this.active) {
// If server is still running
if (this.active) {
// If no data, then send 404 back to client before it times out
if (this.empty) {
//System.out.println("CallbackServer -- sending data 0");
response = "HTTP/1.1 404 NO DATA\r\n\r\n "; // need to send content otherwise some Android devices fail, so send space
// If no data, then send 404 back to client before it times out
if (this.empty) {
//System.out.println("CallbackServer -- sending data 0");
response = "HTTP/1.1 404 NO DATA\r\n\r\n "; // need to send content otherwise some Android devices fail, so send space
}
else {
//System.out.println("CallbackServer -- sending item");
response = "HTTP/1.1 200 OK\r\n\r\n"+this.getJavascript();
}
}
else {
//System.out.println("CallbackServer -- sending item");
response = "HTTP/1.1 200 OK\r\n\r\n"+this.getJavascript();
response = "HTTP/1.1 503 Service Unavailable\r\n\r\n ";
}
}
else {
response = "HTTP/1.1 503 Service Unavailable\r\n\r\n ";
response = "HTTP/1.1 403 Forbidden\r\n\r\n ";
}
}
else {
response = "HTTP/1.1 403 Forbidden\r\n\r\n ";
response = "HTTP/1.1 400 Bad Request\r\n\r\n ";
}
//System.out.println("CallbackServer: response="+response);
//System.out.println("CallbackServer: closing output");
output.writeBytes(response);
output.flush();
}
else {
response = "HTTP/1.1 400 Bad Request\r\n\r\n ";
}
//System.out.println("CallbackServer: response="+response);
//System.out.println("CallbackServer: closing output");
output.writeBytes(response);
output.flush();
output.close();
output.close();
xhrReader.close();
}
} catch (IOException e) {
e.printStackTrace();

View File

@@ -201,6 +201,9 @@ public class CameraLauncher extends Plugin {
// Send Uri back to JavaScript for viewing image
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
}
bitmap.recycle();
bitmap = null;
System.gc();
} catch (IOException e) {
e.printStackTrace();
this.failPicture("Error capturing image.");
@@ -228,6 +231,9 @@ public class CameraLauncher extends Plugin {
try {
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
this.processPicture(bitmap);
bitmap.recycle();
bitmap = null;
System.gc();
} catch (FileNotFoundException e) {
e.printStackTrace();
this.failPicture("Error retrieving image.");
@@ -261,11 +267,15 @@ public class CameraLauncher extends Plugin {
byte[] output = Base64.encodeBase64(code);
String js_out = new String(output);
this.success(new PluginResult(PluginResult.Status.OK, js_out), this.callbackId);
js_out = null;
output = null;
code = null;
}
}
catch(Exception e) {
this.failPicture("Error compressing image.");
}
jpeg_data = null;
}
/**

View File

@@ -155,6 +155,9 @@ public abstract class ContactAccessor {
else if (key.startsWith("urls")) {
map.put("urls", true);
}
else if (key.startsWith("photos")) {
map.put("photos", true);
}
}
}
catch (JSONException e) {

View File

@@ -104,22 +104,28 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
*/
public JSONArray search(JSONArray fields, JSONObject options) {
String searchTerm = "";
int limit = 1;
boolean multiple = false;
try {
searchTerm = options.getString("filter");
int limit = Integer.MAX_VALUE;
boolean multiple = true;
if (options != null) {
searchTerm = options.optString("filter");
if (searchTerm.length()==0) {
searchTerm = "%";
}
else {
searchTerm = "%" + searchTerm + "%";
}
multiple = options.getBoolean("multiple");
if (multiple) {
limit = options.getInt("limit");
try {
multiple = options.getBoolean("multiple");
if (!multiple) {
limit = 1;
}
} catch (JSONException e) {
// Multiple was not specified so we assume the default is true.
}
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
else {
searchTerm = "%";
}
ContentResolver cr = mApp.getContentResolver();
@@ -309,7 +315,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
try{
im.put("id", cursor.getString(
cursor.getColumnIndex(ContactMethods._ID)));
im.put("primary", false);
im.put("perf", false);
im.put("value", cursor.getString(
cursor.getColumnIndex(ContactMethodsColumns.DATA)));
im.put("type", getContactType(cursor.getInt(
@@ -343,10 +349,6 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
organization.put("name", cursor.getString(cursor.getColumnIndex(Organizations.COMPANY)));
organization.put("title", cursor.getString(cursor.getColumnIndex(Organizations.TITLE)));
// organization.put("department", cursor.getString(cursor.getColumnIndex(Organizations)));
// organization.put("description", cursor.getString(cursor.getColumnIndex(Organizations)));
// organization.put("endDate", cursor.getString(cursor.getColumnIndex(Organizations)));
// organization.put("location", cursor.getString(cursor.getColumnIndex(Organizations)));
// organization.put("startDate", cursor.getString(cursor.getColumnIndex(Organizations)));
organizations.put(organization);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
@@ -401,7 +403,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
phone = new JSONObject();
try{
phone.put("id", cursor.getString(cursor.getColumnIndex(Phones._ID)));
phone.put("primary", false);
phone.put("perf", false);
phone.put("value", cursor.getString(cursor.getColumnIndex(Phones.NUMBER)));
phone.put("type", getPhoneType(cursor.getInt(cursor.getColumnIndex(Phones.TYPE))));
phones.put(phone);
@@ -430,7 +432,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
email = new JSONObject();
try{
email.put("id", cursor.getString(cursor.getColumnIndex(ContactMethods._ID)));
email.put("primary", false);
email.put("perf", false);
email.put("value", cursor.getString(cursor.getColumnIndex(ContactMethods.DATA)));
// TODO Find out why adding an email type throws and exception
//email.put("type", cursor.getString(cursor.getColumnIndex(ContactMethods.TYPE)));

File diff suppressed because it is too large Load Diff

View File

@@ -42,7 +42,7 @@ public class ContactManager extends Plugin {
try {
if (action.equals("search")) {
JSONArray res = contactAccessor.search(args.getJSONArray(0), args.getJSONObject(1));
JSONArray res = contactAccessor.search(args.getJSONArray(0), args.optJSONObject(1));
return new PluginResult(status, res, "navigator.service.contacts.cast");
}
else if (action.equals("save")) {

View File

@@ -20,7 +20,7 @@ import android.telephony.TelephonyManager;
public class Device extends Plugin {
public static String phonegapVersion = "0.9.3"; // PhoneGap version
public static String phonegapVersion = "0.9.4"; // PhoneGap version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID

View File

@@ -15,6 +15,8 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Picture;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
@@ -27,6 +29,7 @@ import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebStorage;
import android.webkit.WebView;
import android.webkit.WebView.PictureListener;
import android.webkit.WebViewClient;
import android.webkit.GeolocationPermissions.Callback;
import android.webkit.WebSettings.LayoutAlgorithm;
@@ -53,8 +56,8 @@ import com.phonegap.api.PhonegapActivity;
* super.onCreate(savedInstanceState);
*
* // Set properties for activity
* super.setProperty("loadingDialog", "Title,Message"); // show loading dialog
* super.setProperty("errorUrl", "file:///android_asset/www/error.html"); // if error loading file in super.loadUrl().
* super.setStringProperty("loadingDialog", "Title,Message"); // show loading dialog
* super.setStringProperty("errorUrl", "file:///android_asset/www/error.html"); // if error loading file in super.loadUrl().
*
* // Initialize activity
* super.init();
@@ -66,7 +69,7 @@ import com.phonegap.api.PhonegapActivity;
* super.appView.clearCache(true);
*
* // Load your application
* super.setProperty("splashscreen", R.drawable.splash); // load splash.jpg image from the resource drawable directory
* super.setIntegerProperty("splashscreen", R.drawable.splash); // load splash.jpg image from the resource drawable directory
* super.loadUrl("file:///android_asset/www/index.html", 3000); // show splash screen 3 sec before loading app
* }
* }
@@ -75,30 +78,30 @@ import com.phonegap.api.PhonegapActivity;
*
* // Display a native loading dialog. Format for value = "Title,Message".
* // (String - default=null)
* super.setProperty("loadingDialog", "Wait,Loading Demo...");
* super.setStringProperty("loadingDialog", "Wait,Loading Demo...");
*
* // Hide loadingDialog when page loaded instead of when deviceready event
* // occurs. (Boolean - default=false)
* super.setProperty("hideLoadingDialogOnPage", true);
* super.setBooleanProperty("hideLoadingDialogOnPage", true);
*
* // Cause all links on web page to be loaded into existing web view,
* // instead of being loaded into new browser. (Boolean - default=false)
* super.setProperty("loadInWebView", true);
* super.setBooleanProperty("loadInWebView", true);
*
* // Load a splash screen image from the resource drawable directory.
* // (Integer - default=0)
* super.setProperty("splashscreen", R.drawable.splash);
* super.setIntegerProperty("splashscreen", R.drawable.splash);
*
* // Time in msec to wait before triggering a timeout error when loading
* // with super.loadUrl(). (Integer - default=20000)
* super.setProperty("loadUrlTimeoutValue", 60000);
* super.setIntegerProperty("loadUrlTimeoutValue", 60000);
*
* // URL to load if there's an error loading specified URL with loadUrl().
* // Should be a local URL starting with file://. (String - default=null)
* super.setProperty("errorUrl", "file:///android_asset/www/error.html");
* super.setStringProperty("errorUrl", "file:///android_asset/www/error.html");
*
* // Enable app to keep running in background. (Boolean - default=true)
* super.setProperty("keepRunning", false);
* super.setBooleanProperty("keepRunning", false);
*/
public class DroidGap extends PhonegapActivity {
@@ -177,6 +180,8 @@ public class DroidGap extends PhonegapActivity {
this.init();
}
}
// Setup the hardware volume controls to handle volume control
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
/**
@@ -284,6 +289,7 @@ public class DroidGap extends PhonegapActivity {
this.addService("Notification", "com.phonegap.Notification");
this.addService("Storage", "com.phonegap.Storage");
this.addService("Temperature", "com.phonegap.TempListener");
this.addService("FileTransfer", "com.phonegap.FileTransfer");
}
/**
@@ -901,8 +907,8 @@ public class DroidGap extends PhonegapActivity {
return true;
}
// If http, https or file
else if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("file://")) {
// All else
else {
int i = url.lastIndexOf('/');
String newBaseUrl = url;
@@ -911,6 +917,8 @@ public class DroidGap extends PhonegapActivity {
}
// If our app or file:, then load into our webview
// NOTE: This replaces our app with new URL. When BACK is pressed,
// our app is reloaded and restarted. All state is lost.
if (this.ctx.loadInWebView || url.startsWith("file://") || this.ctx.baseUrl.equals(newBaseUrl)) {
this.ctx.appView.loadUrl(url);
}
@@ -927,8 +935,6 @@ public class DroidGap extends PhonegapActivity {
}
return true;
}
return false;
}
/**
@@ -952,7 +958,12 @@ public class DroidGap extends PhonegapActivity {
// If splash screen is showing, clear it
if (this.ctx.splashscreen != 0) {
this.ctx.splashscreen = 0;
appView.setBackgroundResource(0);
appView.setPictureListener(new PictureListener(){
public void onNewPicture(WebView viewtwo, Picture picture) {
appView.setBackgroundResource(0);
appView.setPictureListener(null);
}
});
}
// Stop "app loading" spinner if showing

View File

@@ -0,0 +1,359 @@
/*
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
*/
package com.phonegap;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.net.Uri;
import android.util.Log;
import android.webkit.CookieManager;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
public class FileTransfer extends Plugin {
private static final String LOG_TAG = "FileUploader";
private static final String LINE_START = "--";
private static final String LINE_END = "\r\n";
private static final String BOUNDRY = "*****";
public static int FILE_NOT_FOUND_ERR = 1;
public static int INVALID_URL_ERR = 2;
public static int CONNECTION_ERR = 3;
private SSLSocketFactory defaultSSLSocketFactory = null;
private HostnameVerifier defaultHostnameVerifier = null;
/* (non-Javadoc)
* @see com.phonegap.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String)
*/
@Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
String file = null;
String server = null;
try {
file = args.getString(0);
server = args.getString(1);
}
catch (JSONException e) {
Log.d(LOG_TAG, "Missing filename or server name");
return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing filename or server name");
}
// Setup the options
String fileKey = null;
String fileName = null;
String mimeType = null;
fileKey = getArgument(args, 2, "file");
fileName = getArgument(args, 3, "image.jpg");
mimeType = getArgument(args, 4, "image/jpeg");
try {
JSONObject params = args.optJSONObject(5);
boolean trustEveryone = args.optBoolean(6);
if (action.equals("upload")) {
FileUploadResult r = upload(file, server, fileKey, fileName, mimeType, params, trustEveryone);
Log.d(LOG_TAG, "****** About to return a result from upload");
return new PluginResult(PluginResult.Status.OK, r.toJSONObject());
} else {
return new PluginResult(PluginResult.Status.INVALID_ACTION);
}
} catch (FileNotFoundException e) {
Log.e(LOG_TAG, e.getMessage(), e);
JSONObject error = createFileUploadError(FILE_NOT_FOUND_ERR);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (IllegalArgumentException e) {
Log.e(LOG_TAG, e.getMessage(), e);
JSONObject error = createFileUploadError(INVALID_URL_ERR);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (SSLException e) {
Log.e(LOG_TAG, e.getMessage(), e);
Log.d(LOG_TAG, "Got my ssl exception!!!");
JSONObject error = createFileUploadError(CONNECTION_ERR);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (IOException e) {
Log.e(LOG_TAG, e.getMessage(), e);
JSONObject error = createFileUploadError(CONNECTION_ERR);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
// always verify the host - don't check for certificate
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
/**
* This function will install a trust manager that will blindly trust all SSL
* certificates. The reason this code is being added is to enable developers
* to do development using self signed SSL certificates on their web server.
*
* The standard HttpsURLConnection class will throw an exception on self
* signed certificates if this code is not run.
*/
private void trustAllHosts() {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
} };
// Install the all-trusting trust manager
try {
// Backup the current SSL socket factory
defaultSSLSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
// Install our all trusting manager
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
}
/**
* Create an error object based on the passed in errorCode
* @param errorCode the error
* @return JSONObject containing the error
*/
private JSONObject createFileUploadError(int errorCode) {
JSONObject error = null;
try {
error = new JSONObject();
error.put("code", errorCode);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
return error;
}
/**
* Convenience method to read a parameter from the list of JSON args.
* @param args the args passed to the Plugin
* @param position the position to retrieve the arg from
* @param defaultString the default to be used if the arg does not exist
* @return String with the retrieved value
*/
private String getArgument(JSONArray args, int position, String defaultString) {
String arg = defaultString;
if(args.length() >= position) {
arg = args.optString(position);
if (arg == null || "null".equals(arg)) {
arg = defaultString;
}
}
return arg;
}
/**
* Uploads the specified file to the server URL provided using an HTTP
* multipart request.
* @param file Full path of the file on the file system
* @param server URL of the server to receive the file
* @param fileKey Name of file request parameter
* @param fileName File name to be used on server
* @param mimeType Describes file content type
* @param params key:value pairs of user-defined parameters
* @return FileUploadResult containing result of upload request
*/
public FileUploadResult upload(String file, String server, final String fileKey, final String fileName,
final String mimeType, JSONObject params, boolean trustEveryone) throws IOException, SSLException {
// Create return object
FileUploadResult result = new FileUploadResult();
// Get a input stream of the file on the phone
InputStream fileInputStream = getPathFromUri(file);
HttpURLConnection conn = null;
DataOutputStream dos = null;
int bytesRead, bytesAvailable, bufferSize;
long totalBytes;
byte[] buffer;
int maxBufferSize = 8096;
//------------------ CLIENT REQUEST
// open a URL connection to the server
URL url = new URL(server);
// Open a HTTP connection to the URL based on protocol
if (url.getProtocol().toLowerCase().equals("https")) {
// Using standard HTTPS connection. Will not allow self signed certificate
if (!trustEveryone) {
conn = (HttpsURLConnection) url.openConnection();
}
// Use our HTTPS connection that blindly trusts everyone.
// This should only be used in debug environments
else {
// Setup the HTTPS connection class to trust everyone
trustAllHosts();
HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
// Save the current hostnameVerifier
defaultHostnameVerifier = https.getHostnameVerifier();
// Setup the connection not to verify hostnames
https.setHostnameVerifier(DO_NOT_VERIFY);
conn = https;
}
}
// Return a standard HTTP conneciton
else {
conn = (HttpURLConnection) url.openConnection();
}
// Allow Inputs
conn.setDoInput(true);
// Allow Outputs
conn.setDoOutput(true);
// Don't use a cached copy.
conn.setUseCaches(false);
// Use a post method.
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY);
// Set the cookies on the response
String cookie = CookieManager.getInstance().getCookie(server);
if (cookie != null) {
conn.setRequestProperty("Cookie", cookie);
}
dos = new DataOutputStream( conn.getOutputStream() );
// Send any extra parameters
try {
for (Iterator iter = params.keys(); iter.hasNext();) {
Object key = iter.next();
dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
dos.writeBytes("Content-Disposition: form-data; name=\"" + key.toString() + "\"; ");
dos.writeBytes(LINE_END + LINE_END);
dos.writeBytes(params.getString(key.toString()));
dos.writeBytes(LINE_END);
}
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
dos.writeBytes("Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"" + fileName +"\"" + LINE_END);
dos.writeBytes("Content-Type: " + mimeType + LINE_END);
dos.writeBytes(LINE_END);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
totalBytes = 0;
while (bytesRead > 0) {
totalBytes += bytesRead;
result.setBytesSent(totalBytes);
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(LINE_END);
dos.writeBytes(LINE_START + BOUNDRY + LINE_START + LINE_END);
// close streams
fileInputStream.close();
dos.flush();
dos.close();
//------------------ read the SERVER RESPONSE
StringBuffer responseString = new StringBuffer("");
DataInputStream inStream = new DataInputStream ( conn.getInputStream() );
String line;
while (( line = inStream.readLine()) != null) {
responseString.append(line);
}
Log.d(LOG_TAG, "got response from server");
Log.d(LOG_TAG, responseString.toString());
// send request and retrieve response
result.setResponseCode(conn.getResponseCode());
result.setResponse(responseString.toString());
inStream.close();
conn.disconnect();
// Revert back to the proper verifier and socket factories
if (trustEveryone && url.getProtocol().toLowerCase().equals("https")) {
((HttpsURLConnection)conn).setHostnameVerifier(defaultHostnameVerifier);
HttpsURLConnection.setDefaultSSLSocketFactory(defaultSSLSocketFactory);
}
return result;
}
/**
* Get an input stream based on file path or content:// uri
*
* @param path
* @return an input stream
* @throws FileNotFoundException
*/
private InputStream getPathFromUri(String path) throws FileNotFoundException {
if (path.startsWith("content:")) {
Uri uri = Uri.parse(path);
return ctx.getContentResolver().openInputStream(uri);
}
else {
return new FileInputStream(path);
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* PhoneGap is available under *either* the terms of the modified BSD license *or* the
* MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
*
* Copyright (c) 2005-2010, Nitobi
* Copyright (c) 2010, IBM Corporation
*/
package com.phonegap;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Encapsulates the result and/or status of uploading a file to a remote server.
*/
public class FileUploadResult {
private long bytesSent = 0; // bytes sent
private int responseCode = -1; // HTTP response code
private String response = null; // HTTP response
public long getBytesSent() {
return bytesSent;
}
public void setBytesSent(long bytes) {
this.bytesSent = bytes;
}
public int getResponseCode() {
return responseCode;
}
public void setResponseCode(int responseCode) {
this.responseCode = responseCode;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public JSONObject toJSONObject() throws JSONException {
return new JSONObject(
"{bytesSent:" + bytesSent +
",responseCode:" + responseCode +
",response:" + JSONObject.quote(response) + "}");
}
}

View File

@@ -220,10 +220,14 @@ public class FileUtils extends Plugin {
}
// Determine content type from file name
MimeTypeMap map = MimeTypeMap.getSingleton();
String contentType = map.getMimeTypeFromExtension(map.getFileExtensionFromUrl(filename));
if (contentType == null && filename.startsWith("content")) {
contentType = "image/jpeg";
String contentType = null;
if (filename.startsWith("content:")) {
Uri fileUri = Uri.parse(filename);
contentType = this.ctx.getContentResolver().getType(fileUri);
}
else {
MimeTypeMap map = MimeTypeMap.getSingleton();
contentType = map.getMimeTypeFromExtension(map.getFileExtensionFromUrl(filename));
}
byte[] base64 = Base64.encodeBase64(bos.toByteArray());

View File

@@ -86,7 +86,7 @@ public class GeoListener {
* @param msg The error message
*/
void fail(int code, String msg) {
this.broker.sendJavascript("navigator._geo.fail('" + this.id + "', " + ", " + code + ", '" + msg + "');");
this.broker.sendJavascript("navigator._geo.fail('" + this.id + "', '" + code + "', '" + msg + "');");
this.stop();
}

View File

@@ -21,7 +21,7 @@ class Classic
def setup
@android_dir = File.expand_path(File.dirname(__FILE__).gsub('lib',''))
@framework_dir = File.join(@android_dir, "framework")
@icon = File.join(@www, 'icon.png')
@icon = File.join(@www, 'icon.png') unless File.exists?(@icon)
@app_js_dir = ''
@content = 'index.html'
end