mirror of
https://github.com/apache/cordova-android.git
synced 2026-02-21 00:02:46 +08:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92a1e4a2d9 | ||
|
|
2504db13d7 | ||
|
|
43c72e684c | ||
|
|
46f0bf60c4 | ||
|
|
8bad4eb7eb | ||
|
|
fbe96f891b | ||
|
|
ab8950a5af | ||
|
|
26adfb6346 | ||
|
|
43b6b6d34e | ||
|
|
04ddc68dfd | ||
|
|
42cd10cf56 | ||
|
|
5f3bc33f8e | ||
|
|
2131070ee9 | ||
|
|
b2a82975e5 | ||
|
|
ddeba91faf | ||
|
|
6e572f05e4 | ||
|
|
50b435c4d1 | ||
|
|
af5c5dc021 | ||
|
|
87fd9665fe | ||
|
|
5e9ca84b40 | ||
|
|
090ad56d0b | ||
|
|
e3ebfea064 | ||
|
|
44761f87d2 | ||
|
|
04e3ceac96 | ||
|
|
afc7e605ff | ||
|
|
1c5aa6cd00 | ||
|
|
c1a87ebaaa | ||
|
|
46babe7a48 | ||
|
|
0dc64d2aa7 | ||
|
|
1d9e522bd9 | ||
|
|
5dcac6d7fe | ||
|
|
07418a3606 | ||
|
|
0e08af98ca | ||
|
|
b8b1ad8421 | ||
|
|
4fa1f40b44 | ||
|
|
5f55ebf1d9 | ||
|
|
9798de7efa | ||
|
|
102745875c | ||
|
|
dce0d93df8 | ||
|
|
1428ac5ed5 | ||
|
|
4f1bc1401f | ||
|
|
28ff6e1150 | ||
|
|
5ffe5fa3c5 | ||
|
|
49341356d7 | ||
|
|
e8b85f6cf7 | ||
|
|
4b2398b487 | ||
|
|
10f3313ed5 | ||
|
|
46664c6494 | ||
|
|
8ce7e61ed7 | ||
|
|
912458c679 | ||
|
|
e117b95057 | ||
|
|
3a0101261d | ||
|
|
48d3bc09f3 | ||
|
|
0b3e27b3fa | ||
|
|
b66535a17d | ||
|
|
fdc78e1b08 | ||
|
|
36064c564e | ||
|
|
7102810283 | ||
|
|
ab4d4e22da | ||
|
|
80c15de606 | ||
|
|
be5cac6d0b | ||
|
|
2bb67ee4b0 |
@@ -5,135 +5,25 @@
|
||||
<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" charset="utf-8">
|
||||
<script type="text/javascript" charset="utf-8" src="phonegap.js"></script>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
|
||||
var deviceInfo = function(){
|
||||
document.getElementById("platform").innerHTML = device.platform;
|
||||
document.getElementById("version").innerHTML = device.version;
|
||||
document.getElementById("uuid").innerHTML = device.uuid;
|
||||
}
|
||||
|
||||
var getLocation = function() {
|
||||
var suc = function(p){
|
||||
alert(p.coords.latitude + " " + p.coords.longitude);
|
||||
};
|
||||
var fail = function(){};
|
||||
navigator.geolocation.getCurrentPosition(suc,fail);
|
||||
}
|
||||
|
||||
var beep = function(){
|
||||
navigator.notification.beep(2);
|
||||
}
|
||||
|
||||
var vibrate = function(){
|
||||
navigator.notification.vibrate(0);
|
||||
}
|
||||
|
||||
var getContact = function(){
|
||||
var suc = function(c){ alert("Contact 4: " + c.contacts[3].name); };
|
||||
var fail = function(){};
|
||||
navigator.ContactManager.get(suc, fail);
|
||||
}
|
||||
|
||||
var watchAccel = function() {
|
||||
var suc = function(a){
|
||||
document.getElementById('x').innerHTML = roundNumber(a.x);
|
||||
document.getElementById('y').innerHTML = roundNumber(a.y);
|
||||
document.getElementById('z').innerHTML = roundNumber(a.z);
|
||||
};
|
||||
var fail = function(){};
|
||||
var opt = {};
|
||||
opt.frequency = 100;
|
||||
timer = navigator.accelerometer.watchAcceleration(suc,fail,opt);
|
||||
}
|
||||
|
||||
function roundNumber(num) {
|
||||
var dec = 3;
|
||||
var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
|
||||
return result;
|
||||
}
|
||||
|
||||
var preventBehavior = function(e) {
|
||||
e.preventDefault();
|
||||
};
|
||||
<script type="text/javascript" charset="utf-8" src="phonegap.js"></script>
|
||||
<script type="text/javascript" charset="utf-8" src="main.js"></script>
|
||||
|
||||
function show_pic()
|
||||
{
|
||||
var viewport = document.getElementById('viewport');
|
||||
viewport.style.display = "";
|
||||
navigator.camera.getPicture(dump_pic, fail, { quality: 50 });
|
||||
}
|
||||
|
||||
function dump_pic(data)
|
||||
{
|
||||
var viewport = document.getElementById('viewport');
|
||||
console.log(data);
|
||||
viewport.style.display = "";
|
||||
viewport.style.position = "absolute";
|
||||
viewport.style.top = "10px";
|
||||
viewport.style.left = "10px";
|
||||
document.getElementById("test_img").src = "data:image/jpeg;base64," + data;
|
||||
}
|
||||
|
||||
function close()
|
||||
{
|
||||
var viewport = document.getElementById('viewport');
|
||||
viewport.style.position = "relative";
|
||||
viewport.style.display = "none";
|
||||
}
|
||||
|
||||
function fail(fail)
|
||||
{
|
||||
alert(fail);
|
||||
}
|
||||
|
||||
// This is just to do this.
|
||||
function readFile()
|
||||
{
|
||||
navigator.file.read('/sdcard/phonegap.txt', fail , fail);
|
||||
}
|
||||
|
||||
function writeFile()
|
||||
{
|
||||
navigator.file.write('foo.txt', "This is a test of writing to a file", fail, fail);
|
||||
}
|
||||
|
||||
function get_contacts()
|
||||
{
|
||||
var obj = new ContactFindOptions();
|
||||
obj.filter="";
|
||||
obj.multiple=true;
|
||||
obj.limit=5;
|
||||
navigator.service.contacts.find(["displayName", "phoneNumbers", "emails"], count_contacts, fail, obj);
|
||||
}
|
||||
|
||||
function count_contacts(contacts)
|
||||
{
|
||||
alert(contacts.length);
|
||||
}
|
||||
|
||||
function init(){
|
||||
document.addEventListener("touchmove", preventBehavior, false);
|
||||
document.addEventListener("deviceready", deviceInfo, true);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init();" id="stage" class="theme">
|
||||
<h1>Welcome to PhoneGap!</h1>
|
||||
<h2>this file is located at assets/index.html</h2>
|
||||
<div id="info">
|
||||
<h4>Platform: <span id="platform"> </span></h4>
|
||||
<h4>Version: <span id="version"> </span></h4>
|
||||
<h4>UUID: <span id="uuid"> </span></h4>
|
||||
</div>
|
||||
<h4>Platform: <span id="platform"> </span>, Version: <span id="version"> </span></h4>
|
||||
<h4>UUID: <span id="uuid"> </span>, Name: <span id="name"> </span></h4>
|
||||
<h4>Width: <span id="width"> </span>, Height: <span id="height">
|
||||
</span>, Color Depth: <span id="colorDepth"></span></h4>
|
||||
</div>
|
||||
<dl id="accel-data">
|
||||
<dt>X:</dt><dd id="x"> </dd>
|
||||
<dt>Y:</dt><dd id="y"> </dd>
|
||||
<dt>Z:</dt><dd id="z"> </dd>
|
||||
</dl>
|
||||
<a href="#" class="btn large" onclick="watchAccel();">Watch Accelerometer</a>
|
||||
<a href="#" class="btn large" onclick="toggleAccel();">Toggle Accelerometer</a>
|
||||
<a href="#" class="btn large" onclick="getLocation();">Get Location</a>
|
||||
<a href="tel://411" class="btn large">Call 411</a>
|
||||
<a href="#" class="btn large" onclick="beep();">Beep</a>
|
||||
|
||||
127
example/main.js
Normal file
127
example/main.js
Normal file
@@ -0,0 +1,127 @@
|
||||
var deviceInfo = function(){
|
||||
document.getElementById("platform").innerHTML = device.platform;
|
||||
document.getElementById("version").innerHTML = device.version;
|
||||
document.getElementById("uuid").innerHTML = device.uuid;
|
||||
document.getElementById("name").innerHTML = device.name;
|
||||
document.getElementById("width").innerHTML = screen.width;
|
||||
document.getElementById("height").innerHTML = screen.height;
|
||||
document.getElementById("colorDepth").innerHTML = screen.colorDepth;
|
||||
};
|
||||
|
||||
var getLocation = function() {
|
||||
var suc = function(p){
|
||||
alert(p.coords.latitude + " " + p.coords.longitude);
|
||||
};
|
||||
var fail = function(){};
|
||||
navigator.geolocation.getCurrentPosition(suc,fail);
|
||||
};
|
||||
|
||||
var beep = function(){
|
||||
navigator.notification.beep(2);
|
||||
};
|
||||
|
||||
var vibrate = function(){
|
||||
navigator.notification.vibrate(0);
|
||||
};
|
||||
|
||||
function roundNumber(num) {
|
||||
var dec = 3;
|
||||
var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
|
||||
return result;
|
||||
}
|
||||
|
||||
var accelerationWatch = false;
|
||||
|
||||
var toggleAccel = function() {
|
||||
if (accelerationWatch) {
|
||||
navigator.accelerometer.clearWatch(accelerationWatch);
|
||||
updateAcceleration( {
|
||||
x : "",
|
||||
y : "",
|
||||
z : ""
|
||||
});
|
||||
accelerationWatch = false;
|
||||
} else {
|
||||
accelerationWatch = true;
|
||||
var options = new Object();
|
||||
options.frequency = 1000;
|
||||
accelerationWatch = navigator.accelerometer.watchAcceleration(
|
||||
updateAcceleration, function(ex) {
|
||||
navigator.accelerometer.clearWatch(accel_watch_id);
|
||||
alert("accel fail (" + ex.name + ": " + ex.message + ")");
|
||||
}, options);
|
||||
}
|
||||
};
|
||||
|
||||
function updateAcceleration(a) {
|
||||
document.getElementById('x').innerHTML = roundNumber(a.x);
|
||||
document.getElementById('y').innerHTML = roundNumber(a.y);
|
||||
document.getElementById('z').innerHTML = roundNumber(a.z);
|
||||
}
|
||||
|
||||
var preventBehavior = function(e) {
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
function show_pic()
|
||||
{
|
||||
var viewport = document.getElementById('viewport');
|
||||
viewport.style.display = "";
|
||||
navigator.camera.getPicture(dump_pic, fail, { quality: 50 });
|
||||
}
|
||||
|
||||
function dump_pic(data)
|
||||
{
|
||||
var viewport = document.getElementById('viewport');
|
||||
console.log(data);
|
||||
viewport.style.display = "";
|
||||
viewport.style.position = "absolute";
|
||||
viewport.style.top = "10px";
|
||||
viewport.style.left = "10px";
|
||||
document.getElementById("test_img").src = "data:image/jpeg;base64," + data;
|
||||
}
|
||||
|
||||
function close()
|
||||
{
|
||||
var viewport = document.getElementById('viewport');
|
||||
viewport.style.position = "relative";
|
||||
viewport.style.display = "none";
|
||||
}
|
||||
|
||||
function fail(fail)
|
||||
{
|
||||
alert(fail);
|
||||
}
|
||||
|
||||
// This is just to do this.
|
||||
function readFile()
|
||||
{
|
||||
navigator.file.read('/sdcard/phonegap.txt', fail , fail);
|
||||
}
|
||||
|
||||
function writeFile()
|
||||
{
|
||||
navigator.file.write('foo.txt', "This is a test of writing to a file", fail, fail);
|
||||
}
|
||||
|
||||
function get_contacts()
|
||||
{
|
||||
var obj = new ContactFindOptions();
|
||||
obj.filter="";
|
||||
obj.multiple=true;
|
||||
obj.limit=5;
|
||||
navigator.service.contacts.find(["displayName", "phoneNumbers", "emails"], contacts_success, fail, obj);
|
||||
}
|
||||
|
||||
function contacts_success(contacts)
|
||||
{
|
||||
alert(contacts.length + ' contacts returned.' +
|
||||
(contacts[2] ? (' Third contact is ' + contacts[2].displayName) : ''));
|
||||
}
|
||||
|
||||
|
||||
function init(){
|
||||
//the next line makes it impossible to see Contacts on the HTC Evo since it doesn't have a scroll button
|
||||
// document.addEventListener("touchmove", preventBehavior, false);
|
||||
document.addEventListener("deviceready", deviceInfo, true);
|
||||
}
|
||||
66
framework/assets/js/app.js
Executable file
66
framework/assets/js/app.js
Executable file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function App() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the resource cache.
|
||||
*/
|
||||
App.prototype.clearCache = function() {
|
||||
PhoneGap.exec(null, null, "App", "clearCache", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the url into the webview.
|
||||
*
|
||||
* @param url The URL to load
|
||||
* @param props Properties that can be passed in to the activity:
|
||||
* wait: int => wait msec before loading URL
|
||||
* loadingDialog: "Title,Message" => display a native loading dialog
|
||||
* hideLoadingDialogOnPage: boolean => hide loadingDialog when page loaded instead of when deviceready event occurs.
|
||||
* loadInWebView: boolean => cause all links on web page to be loaded into existing web view, instead of being loaded into new browser.
|
||||
* loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
|
||||
* errorUrl: URL => URL to load if there's an error loading specified URL with loadUrl(). Should be a local URL such as file:///android_asset/www/error.html");
|
||||
* keepRunning: boolean => enable app to keep running in background
|
||||
*
|
||||
* Example:
|
||||
* App app = new App();
|
||||
* app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
|
||||
*/
|
||||
App.prototype.loadUrl = function(url, props) {
|
||||
PhoneGap.exec(null, null, "App", "loadUrl", [url, props]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel loadUrl that is waiting to be loaded.
|
||||
*/
|
||||
App.prototype.cancelLoadUrl = function() {
|
||||
PhoneGap.exec(null, null, "App", "cancelLoadUrl", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear web history in this web view.
|
||||
* Instead of BACK button loading the previous web page, it will exit the app.
|
||||
*/
|
||||
App.prototype.clearHistory = function() {
|
||||
PhoneGap.exec(null, null, "App", "clearHistory", []);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a class that implements a service.
|
||||
*
|
||||
* @param serviceType
|
||||
* @param className
|
||||
*/
|
||||
App.prototype.addService = function(serviceType, className) {
|
||||
PhoneGap.exec(null, null, "App", "addService", [serviceType, className]);
|
||||
};
|
||||
@@ -36,6 +36,7 @@ var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, ad
|
||||
ims, organizations, published, updated, birthday, anniversary, gender, note,
|
||||
preferredUsername, photos, tags, relationships, urls, accounts, utcOffset, connected) {
|
||||
this.id = id || null;
|
||||
this.rawId = null;
|
||||
this.displayName = displayName || null;
|
||||
this.name = name || null; // ContactName
|
||||
this.nickname = nickname || null;
|
||||
@@ -71,8 +72,9 @@ Contact.prototype.remove = function(successCB, errorCB) {
|
||||
errorObj.code = ContactError.NOT_FOUND_ERROR;
|
||||
errorCB(errorObj);
|
||||
}
|
||||
|
||||
PhoneGap.exec(successCB, errorCB, "Contacts", "remove", [this.id]);
|
||||
else {
|
||||
PhoneGap.exec(successCB, errorCB, "Contacts", "remove", [this.id]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -83,6 +85,48 @@ Contact.prototype.remove = function(successCB, errorCB) {
|
||||
Contact.prototype.clone = function() {
|
||||
var clonedContact = PhoneGap.clone(this);
|
||||
clonedContact.id = null;
|
||||
clonedContact.rawId = null;
|
||||
// Loop through and clear out any id's in phones, emails, etc.
|
||||
if (clonedContact.phoneNumbers) {
|
||||
for (i=0; i<clonedContact.phoneNumbers.length; i++) {
|
||||
clonedContact.phoneNumbers[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.emails) {
|
||||
for (i=0; i<clonedContact.emails.length; i++) {
|
||||
clonedContact.emails[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.addresses) {
|
||||
for (i=0; i<clonedContact.addresses.length; i++) {
|
||||
clonedContact.addresses[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.ims) {
|
||||
for (i=0; i<clonedContact.ims.length; i++) {
|
||||
clonedContact.ims[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.organizations) {
|
||||
for (i=0; i<clonedContact.organizations.length; i++) {
|
||||
clonedContact.organizations[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.tags) {
|
||||
for (i=0; i<clonedContact.tags.length; i++) {
|
||||
clonedContact.tags[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.relationships) {
|
||||
for (i=0; i<clonedContact.relationships.length; i++) {
|
||||
clonedContact.relationships[i].id = null;
|
||||
}
|
||||
}
|
||||
if (clonedContact.urls) {
|
||||
for (i=0; i<clonedContact.urls.length; i++) {
|
||||
clonedContact.urls[i].id = null;
|
||||
}
|
||||
}
|
||||
return clonedContact;
|
||||
};
|
||||
|
||||
@@ -92,6 +136,7 @@ Contact.prototype.clone = function() {
|
||||
* @param errorCB error callback
|
||||
*/
|
||||
Contact.prototype.save = function(successCB, errorCB) {
|
||||
PhoneGap.exec(successCB, errorCB, "Contacts", "save", [this]);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -114,11 +159,13 @@ var ContactName = function(formatted, familyName, givenName, middle, prefix, suf
|
||||
|
||||
/**
|
||||
* Generic contact field.
|
||||
* @param {DOMString} id unique identifier, should only be set by native code
|
||||
* @param type
|
||||
* @param value
|
||||
* @param primary
|
||||
*/
|
||||
var ContactField = function(type, value, primary) {
|
||||
this.id = null;
|
||||
this.type = type || null;
|
||||
this.value = value || null;
|
||||
this.primary = primary || null;
|
||||
@@ -126,6 +173,7 @@ var ContactField = function(type, value, primary) {
|
||||
|
||||
/**
|
||||
* Contact address.
|
||||
* @param {DOMString} id unique identifier, should only be set by native code
|
||||
* @param formatted
|
||||
* @param streetAddress
|
||||
* @param locality
|
||||
@@ -134,6 +182,7 @@ var ContactField = function(type, value, primary) {
|
||||
* @param country
|
||||
*/
|
||||
var ContactAddress = function(formatted, streetAddress, locality, region, postalCode, country) {
|
||||
this.id = null;
|
||||
this.formatted = formatted || null;
|
||||
this.streetAddress = streetAddress || null;
|
||||
this.locality = locality || null;
|
||||
@@ -144,6 +193,7 @@ var ContactAddress = function(formatted, streetAddress, locality, region, postal
|
||||
|
||||
/**
|
||||
* Contact organization.
|
||||
* @param {DOMString} id unique identifier, should only be set by native code
|
||||
* @param name
|
||||
* @param dept
|
||||
* @param title
|
||||
@@ -153,6 +203,7 @@ var ContactAddress = function(formatted, streetAddress, locality, region, postal
|
||||
* @param desc
|
||||
*/
|
||||
var ContactOrganization = function(name, dept, title, startDate, endDate, location, desc) {
|
||||
this.id = null;
|
||||
this.name = name || null;
|
||||
this.department = dept || null;
|
||||
this.title = title || null;
|
||||
@@ -164,11 +215,13 @@ var ContactOrganization = function(name, dept, title, startDate, endDate, locati
|
||||
|
||||
/**
|
||||
* 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;
|
||||
@@ -201,7 +254,7 @@ Contacts.prototype.find = function(fields, successCB, errorCB, options) {
|
||||
* @returns new Contact object
|
||||
*/
|
||||
Contacts.prototype.create = function(properties) {
|
||||
var contact = new Contact();
|
||||
var contact = new Contact();
|
||||
for (i in properties) {
|
||||
if (contact[i]!='undefined') {
|
||||
contact[i]=properties[i];
|
||||
@@ -210,6 +263,23 @@ Contacts.prototype.create = function(properties) {
|
||||
return contact;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function returns and array of contacts. It is required as we need to convert raw
|
||||
* JSON objects into concrete Contact objects. Currently this method is called after
|
||||
* navigator.service.contacts.find but before the find methods success call back.
|
||||
*
|
||||
* @param jsonArray an array of JSON Objects that need to be converted to Contact objects.
|
||||
* @returns an array of Contact objects
|
||||
*/
|
||||
Contacts.prototype.cast = function(pluginResult) {
|
||||
var contacts = new Array();
|
||||
for (var i=0; i<pluginResult.message.length; i++) {
|
||||
contacts.push(navigator.service.contacts.create(pluginResult.message[i]));
|
||||
}
|
||||
pluginResult.message = contacts;
|
||||
return pluginResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* ContactFindOptions.
|
||||
* @param filter used to match contacts against
|
||||
|
||||
@@ -25,6 +25,7 @@ function Device() {
|
||||
me.available = true;
|
||||
me.platform = info.platform;
|
||||
me.version = info.version;
|
||||
me.name = info.name;
|
||||
me.uuid = info.uuid;
|
||||
me.phonegap = info.phonegap;
|
||||
PhoneGap.onPhoneGapInfoReady.fire();
|
||||
|
||||
@@ -12,19 +12,14 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* List of files
|
||||
* This class provides some useful information about a file.
|
||||
* This is the fields returned when navigator.fileMgr.getFileProperties()
|
||||
* is called.
|
||||
*/
|
||||
function FileList() {
|
||||
this.files = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Describes a single file in a FileList
|
||||
*/
|
||||
function File() {
|
||||
this.name = null;
|
||||
this.type = null;
|
||||
this.urn = null;
|
||||
function FileProperties(filePath) {
|
||||
this.filePath = filePath;
|
||||
this.size = 0;
|
||||
this.lastModifiedDate = null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -44,22 +39,22 @@ File._createEvent = function(type, target) {
|
||||
};
|
||||
|
||||
function FileError() {
|
||||
// File error codes
|
||||
// Found in DOMException
|
||||
this.NOT_FOUND_ERR = 1;
|
||||
this.SECURITY_ERR = 2;
|
||||
this.ABORT_ERR = 3;
|
||||
|
||||
// Added by this specification
|
||||
this.NOT_READABLE_ERR = 4;
|
||||
this.ENCODING_ERR = 5;
|
||||
this.NO_MODIFICATION_ALLOWED_ERR = 6;
|
||||
this.INVALID_STATE_ERR = 7;
|
||||
this.SYNTAX_ERR = 8;
|
||||
|
||||
this.code = null;
|
||||
};
|
||||
|
||||
// File error codes
|
||||
// Found in DOMException
|
||||
FileError.NOT_FOUND_ERR = 1;
|
||||
FileError.SECURITY_ERR = 2;
|
||||
FileError.ABORT_ERR = 3;
|
||||
|
||||
// Added by this specification
|
||||
FileError.NOT_READABLE_ERR = 4;
|
||||
FileError.ENCODING_ERR = 5;
|
||||
FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
|
||||
FileError.INVALID_STATE_ERR = 7;
|
||||
FileError.SYNTAX_ERR = 8;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// File manager
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -67,41 +62,53 @@ function FileError() {
|
||||
function FileMgr() {
|
||||
};
|
||||
|
||||
FileMgr.prototype.getFileProperties = function(filePath) {
|
||||
return PhoneGap.exec(null, null, "File", "getFile", [filePath]);
|
||||
};
|
||||
|
||||
FileMgr.prototype.getFileBasePaths = function() {
|
||||
};
|
||||
|
||||
FileMgr.prototype.getRootPaths = function() {
|
||||
return PhoneGap.exec(null, null, "File", "getRootPaths", []);
|
||||
};
|
||||
|
||||
FileMgr.prototype.testSaveLocationExists = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "testSaveLocationExists", []);
|
||||
return PhoneGap.exec(successCallback, errorCallback, "File", "testSaveLocationExists", []);
|
||||
};
|
||||
|
||||
FileMgr.prototype.testFileExists = function(fileName, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "testFileExists", [fileName]);
|
||||
return PhoneGap.exec(successCallback, errorCallback, "File", "testFileExists", [fileName]);
|
||||
};
|
||||
|
||||
FileMgr.prototype.testDirectoryExists = function(dirName, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "testDirectoryExists", [dirName]);
|
||||
return PhoneGap.exec(successCallback, errorCallback, "File", "testDirectoryExists", [dirName]);
|
||||
};
|
||||
|
||||
FileMgr.prototype.createDirectory = function(dirName, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "createDirectory", [dirName]);
|
||||
return PhoneGap.exec(successCallback, errorCallback, "File", "createDirectory", [dirName]);
|
||||
};
|
||||
|
||||
FileMgr.prototype.deleteDirectory = function(dirName, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "deleteDirectory", [dirName]);
|
||||
return PhoneGap.exec(successCallback, errorCallback, "File", "deleteDirectory", [dirName]);
|
||||
};
|
||||
|
||||
FileMgr.prototype.deleteFile = function(fileName, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "deleteFile", [fileName]);
|
||||
return PhoneGap.exec(successCallback, errorCallback, "File", "deleteFile", [fileName]);
|
||||
};
|
||||
|
||||
FileMgr.prototype.getFreeDiskSpace = function(successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "getFreeDiskSpace", []);
|
||||
return PhoneGap.exec(successCallback, errorCallback, "File", "getFreeDiskSpace", []);
|
||||
};
|
||||
|
||||
FileMgr.prototype.writeAsText = function(fileName, data, append, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "writeAsText", [fileName, data, append]);
|
||||
};
|
||||
|
||||
FileMgr.prototype.write = function(fileName, data, position, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "write", [fileName, data, position]);
|
||||
};
|
||||
|
||||
FileMgr.prototype.truncate = function(fileName, size, successCallback, errorCallback) {
|
||||
PhoneGap.exec(successCallback, errorCallback, "File", "truncate", [fileName, size]);
|
||||
};
|
||||
@@ -161,14 +168,28 @@ FileReader.DONE = 2;
|
||||
*/
|
||||
FileReader.prototype.abort = function() {
|
||||
this.readyState = FileReader.DONE;
|
||||
this.result = null;
|
||||
|
||||
// set error
|
||||
var error = new FileError();
|
||||
error.code = error.ABORT_ERR;
|
||||
this.error = error;
|
||||
|
||||
// If error callback
|
||||
if (typeof this.onerror == "function") {
|
||||
var evt = File._createEvent("error", this);
|
||||
this.onerror(evt);
|
||||
}
|
||||
// If abort callback
|
||||
if (typeof this.onabort == "function") {
|
||||
var evt = File._createEvent("abort", this);
|
||||
this.onabort(evt);
|
||||
}
|
||||
|
||||
// TODO: Anything else to do? Maybe sent to native?
|
||||
// If load end callback
|
||||
if (typeof this.onloadend == "function") {
|
||||
var evt = File._createEvent("loadend", this);
|
||||
this.onloadend(evt);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -208,15 +229,15 @@ FileReader.prototype.readAsText = function(file, encoding) {
|
||||
// Save result
|
||||
me.result = r;
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onload callback
|
||||
if (typeof me.onload == "function") {
|
||||
var evt = File._createEvent("load", me);
|
||||
me.onload(evt);
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onloadend callback
|
||||
if (typeof me.onloadend == "function") {
|
||||
var evt = File._createEvent("loadend", me);
|
||||
@@ -235,15 +256,15 @@ FileReader.prototype.readAsText = function(file, encoding) {
|
||||
// Save error
|
||||
me.error = e;
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror == "function") {
|
||||
var evt = File._createEvent("error", me);
|
||||
me.onerror(evt);
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onloadend callback
|
||||
if (typeof me.onloadend == "function") {
|
||||
var evt = File._createEvent("loadend", me);
|
||||
@@ -289,15 +310,15 @@ FileReader.prototype.readAsDataURL = function(file) {
|
||||
// Save result
|
||||
me.result = r;
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onload callback
|
||||
if (typeof me.onload == "function") {
|
||||
var evt = File._createEvent("load", me);
|
||||
me.onload(evt);
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onloadend callback
|
||||
if (typeof me.onloadend == "function") {
|
||||
var evt = File._createEvent("loadend", me);
|
||||
@@ -316,15 +337,15 @@ FileReader.prototype.readAsDataURL = function(file) {
|
||||
// Save error
|
||||
me.error = e;
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror == "function") {
|
||||
var evt = File._createEvent("error", me);
|
||||
me.onerror(evt);
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileReader.DONE;
|
||||
|
||||
// If onloadend callback
|
||||
if (typeof me.onloadend == "function") {
|
||||
var evt = File._createEvent("loadend", me);
|
||||
@@ -364,9 +385,20 @@ FileReader.prototype.readAsArrayBuffer = function(file) {
|
||||
* For Android:
|
||||
* The root directory is the root of the file system.
|
||||
* To write to the SD card, the file name is "sdcard/my_file.txt"
|
||||
*
|
||||
* @param filePath the file to write to
|
||||
* @param append if true write to the end of the file, otherwise overwrite the file
|
||||
*/
|
||||
function FileWriter() {
|
||||
function FileWriter(filePath, append) {
|
||||
this.fileName = "";
|
||||
this.length = 0;
|
||||
if (filePath) {
|
||||
var f = navigator.fileMgr.getFileProperties(filePath);
|
||||
this.fileName = f.name;
|
||||
this.length = f.size;
|
||||
}
|
||||
// default is to write at the beginning of the file
|
||||
this.position = (append !== true) ? 0 : this.length;
|
||||
|
||||
this.readyState = 0; // EMPTY
|
||||
|
||||
@@ -393,17 +425,38 @@ FileWriter.DONE = 2;
|
||||
* Abort writing file.
|
||||
*/
|
||||
FileWriter.prototype.abort = function() {
|
||||
this.readyState = FileWriter.DONE;
|
||||
|
||||
// set error
|
||||
var error = new FileError();
|
||||
error.code = error.ABORT_ERR;
|
||||
this.error = error;
|
||||
|
||||
// If error callback
|
||||
if (typeof this.onerror == "function") {
|
||||
var evt = File._createEvent("error", this);
|
||||
this.onerror(evt);
|
||||
}
|
||||
// If abort callback
|
||||
if (typeof this.onabort == "function") {
|
||||
var evt = File._createEvent("abort", this);
|
||||
this.onabort(evt);
|
||||
}
|
||||
|
||||
this.readyState = FileWriter.DONE;
|
||||
|
||||
// TODO: Anything else to do? Maybe sent to native?
|
||||
// If load end callback
|
||||
if (typeof this.onloadend == "function") {
|
||||
var evt = File._createEvent("writeend", this);
|
||||
this.onloadend(evt);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @Deprecated: use write instead
|
||||
*
|
||||
* @param file to write the data to
|
||||
* @param text to be written
|
||||
* @param bAppend if true write to end of file, otherwise overwrite the file
|
||||
*/
|
||||
FileWriter.prototype.writeAsText = function(file, text, bAppend) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState == FileWriter.WRITING) {
|
||||
@@ -487,14 +540,17 @@ FileWriter.prototype.writeAsText = function(file, text, bAppend) {
|
||||
|
||||
};
|
||||
|
||||
FileWriter.prototype.truncate = function(file, size) {
|
||||
/**
|
||||
* Writes data to the file
|
||||
*
|
||||
* @param text to be written
|
||||
*/
|
||||
FileWriter.prototype.write = function(text) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState == FileWriter.WRITING) {
|
||||
throw FileError.INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
this.fileName = file;
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
@@ -507,7 +563,7 @@ FileWriter.prototype.truncate = function(file, size) {
|
||||
}
|
||||
|
||||
// Write file
|
||||
navigator.fileMgr.truncate(file, size,
|
||||
navigator.fileMgr.write(this.fileName, text, this.position,
|
||||
|
||||
// Success callback
|
||||
function(r) {
|
||||
@@ -517,8 +573,128 @@ FileWriter.prototype.truncate = function(file, size) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save result
|
||||
me.result = r;
|
||||
// So if the user wants to keep appending to the file
|
||||
me.length = Math.max(me.length, me.position + r);
|
||||
// position always increases by bytes written because file would be extended
|
||||
me.position += r;
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite == "function") {
|
||||
var evt = File._createEvent("write", me);
|
||||
me.onwrite(evt);
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend == "function") {
|
||||
var evt = File._createEvent("writeend", me);
|
||||
me.onwriteend(evt);
|
||||
}
|
||||
},
|
||||
|
||||
// Error callback
|
||||
function(e) {
|
||||
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState == FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save error
|
||||
me.error = e;
|
||||
|
||||
// If onerror callback
|
||||
if (typeof me.onerror == "function") {
|
||||
var evt = File._createEvent("error", me);
|
||||
me.onerror(evt);
|
||||
}
|
||||
|
||||
// DONE state
|
||||
me.readyState = FileWriter.DONE;
|
||||
|
||||
// If onwriteend callback
|
||||
if (typeof me.onwriteend == "function") {
|
||||
var evt = File._createEvent("writeend", me);
|
||||
me.onwriteend(evt);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves the file pointer to the location specified.
|
||||
*
|
||||
* If the offset is a negative number the position of the file
|
||||
* pointer is rewound. If the offset is greater than the file
|
||||
* size the position is set to the end of the file.
|
||||
*
|
||||
* @param offset is the location to move the file pointer to.
|
||||
*/
|
||||
FileWriter.prototype.seek = function(offset) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState === FileWriter.WRITING) {
|
||||
throw FileError.INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
if (!offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
// See back from end of file.
|
||||
if (offset < 0) {
|
||||
this.position = Math.max(offset + this.length, 0);
|
||||
}
|
||||
// Offset is bigger then file size so set position
|
||||
// to the end of the file.
|
||||
else if (offset > this.length) {
|
||||
this.position = this.length;
|
||||
}
|
||||
// Offset is between 0 and file size so set the position
|
||||
// to start writing.
|
||||
else {
|
||||
this.position = offset;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Truncates the file to the size specified.
|
||||
*
|
||||
* @param size to chop the file at.
|
||||
*/
|
||||
FileWriter.prototype.truncate = function(size) {
|
||||
// Throw an exception if we are already writing a file
|
||||
if (this.readyState == FileWriter.WRITING) {
|
||||
throw FileError.INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
// WRITING state
|
||||
this.readyState = FileWriter.WRITING;
|
||||
|
||||
var me = this;
|
||||
|
||||
// If onwritestart callback
|
||||
if (typeof me.onwritestart == "function") {
|
||||
var evt = File._createEvent("writestart", me);
|
||||
me.onwritestart(evt);
|
||||
}
|
||||
|
||||
// Write file
|
||||
navigator.fileMgr.truncate(this.fileName, size,
|
||||
|
||||
// Success callback
|
||||
function(r) {
|
||||
|
||||
// If DONE (cancelled), then don't do anything
|
||||
if (me.readyState == FileWriter.DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the length of the file
|
||||
me.length = r;
|
||||
me.position = Math.min(me.position, r);;
|
||||
|
||||
// If onwrite callback
|
||||
if (typeof me.onwrite == "function") {
|
||||
|
||||
@@ -5,9 +5,3 @@
|
||||
* Copyright (c) 2005-2010, Nitobi Software Inc.
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof navigator.splashScreen == "undefined") {
|
||||
navigator.splashScreen = SplashScreen; // SplashScreen object come from native side through addJavaScriptInterface
|
||||
}
|
||||
});
|
||||
@@ -6,18 +6,27 @@
|
||||
* Copyright (c) 2010, IBM Corporation
|
||||
*/
|
||||
|
||||
function KeyEvent()
|
||||
{
|
||||
function KeyEvent() {
|
||||
}
|
||||
|
||||
KeyEvent.prototype.backTrigger = function()
|
||||
{
|
||||
var e = document.createEvent('Events');
|
||||
e.initEvent('backKeyDown');
|
||||
document.dispatchEvent(e);
|
||||
}
|
||||
KeyEvent.prototype.backTrigger = function() {
|
||||
var e = document.createEvent('Events');
|
||||
e.initEvent('backKeyDown');
|
||||
document.dispatchEvent(e);
|
||||
};
|
||||
|
||||
if (document.keyEvent == null || typeof document.keyEvent == 'undefined')
|
||||
{
|
||||
window.keyEvent = document.keyEvent = new KeyEvent();
|
||||
KeyEvent.prototype.menuTrigger = function() {
|
||||
var e = document.createEvent('Events');
|
||||
e.initEvent('menuKeyDown');
|
||||
document.dispatchEvent(e);
|
||||
};
|
||||
|
||||
KeyEvent.prototype.searchTrigger = function() {
|
||||
var e = document.createEvent('Events');
|
||||
e.initEvent('searchKeyDown');
|
||||
document.dispatchEvent(e);
|
||||
};
|
||||
|
||||
if (document.keyEvent == null || typeof document.keyEvent == 'undefined') {
|
||||
window.keyEvent = document.keyEvent = new KeyEvent();
|
||||
}
|
||||
|
||||
@@ -192,3 +192,10 @@ Media.prototype.stopRecord = function() {
|
||||
PhoneGap.exec(null, null, "Media", "stopRecordingAudio", [this.id]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Release the resources.
|
||||
*/
|
||||
Media.prototype.release = function() {
|
||||
PhoneGap.exec(null, null, "Media", "release", [this.id]);
|
||||
};
|
||||
|
||||
|
||||
@@ -157,26 +157,32 @@ PhoneGap.addConstructor = function(func) {
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
if (typeof(debug['log']) == 'function') {
|
||||
debug.log("Failed to run constructor: " + debug.processMessage(e));
|
||||
} else {
|
||||
alert("Failed to run constructor: " + e.message);
|
||||
}
|
||||
console.log("Failed to run constructor: " + e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a plugin object to window.plugins
|
||||
* Plugins object
|
||||
*/
|
||||
if (!window.plugins) {
|
||||
window.plugins = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a plugin object to window.plugins.
|
||||
* The plugin is accessed using window.plugins.<name>
|
||||
*
|
||||
* @param name The plugin name
|
||||
* @param obj The plugin object
|
||||
*/
|
||||
PhoneGap.addPlugin = function(name, obj) {
|
||||
if ( !window.plugins ) {
|
||||
window.plugins = {};
|
||||
}
|
||||
|
||||
if ( !window.plugins[name] ) {
|
||||
window.plugins[name] = obj;
|
||||
}
|
||||
if (!window.plugins[name]) {
|
||||
window.plugins[name] = obj;
|
||||
}
|
||||
else {
|
||||
console.log("Error: Plugin "+name+" already exists.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,7 +292,7 @@ document.addEventListener = function(evt, handler, capture) {
|
||||
} else if (e == 'pause') {
|
||||
PhoneGap.onPause.subscribe(handler);
|
||||
} else {
|
||||
PhoneGap.m_document_addEventListener.call(document, evt, handler);
|
||||
PhoneGap.m_document_addEventListener.call(document, evt, handler, capture);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -315,18 +321,27 @@ PhoneGap.stringify = function(args) {
|
||||
var start = true;
|
||||
s = s + '{';
|
||||
for (var name in args[i]) {
|
||||
if (!start) {
|
||||
s = s + ',';
|
||||
}
|
||||
s = s + '"' + name + '":';
|
||||
var nameType = typeof args[i][name];
|
||||
if ((nameType == "number") || (nameType == "boolean")) {
|
||||
s = s + args[i][name];
|
||||
}
|
||||
else {
|
||||
s = s + '"' + args[i][name] + '"';
|
||||
}
|
||||
start=false;
|
||||
if (args[i][name] != null) {
|
||||
if (!start) {
|
||||
s = s + ',';
|
||||
}
|
||||
s = s + '"' + name + '":';
|
||||
var nameType = typeof args[i][name];
|
||||
if ((nameType == "number") || (nameType == "boolean")) {
|
||||
s = s + args[i][name];
|
||||
}
|
||||
else if ((typeof args[i][name]) == 'function') {
|
||||
// don't copy the functions
|
||||
s = s + '""';
|
||||
}
|
||||
else if (args[i][name] instanceof Object) {
|
||||
s = s + this.stringify(args[i][name]);
|
||||
}
|
||||
else {
|
||||
s = s + '"' + args[i][name] + '"';
|
||||
}
|
||||
start=false;
|
||||
}
|
||||
}
|
||||
s = s + '}';
|
||||
}
|
||||
@@ -430,7 +445,7 @@ PhoneGap.exec = function(success, fail, service, action, args) {
|
||||
// If there is a success callback, then call it now with returned value
|
||||
if (success) {
|
||||
try {
|
||||
success(v.message);
|
||||
success(v.message);
|
||||
}
|
||||
catch (e) {
|
||||
console.log("Error in success callback: "+callbackId+" = "+e);
|
||||
@@ -492,7 +507,7 @@ PhoneGap.callbackSuccess = function(callbackId, args) {
|
||||
if (args.status == PhoneGap.callbackStatus.OK) {
|
||||
try {
|
||||
if (PhoneGap.callbacks[callbackId].success) {
|
||||
PhoneGap.callbacks[callbackId].success(args.message);
|
||||
PhoneGap.callbacks[callbackId].success(args.message);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
@@ -578,8 +593,8 @@ PhoneGap.run_command = function() {
|
||||
|
||||
};
|
||||
|
||||
PhoneGap.JSCallbackPort = CallbackServer.getPort();
|
||||
PhoneGap.JSCallbackToken = CallbackServer.getToken();
|
||||
PhoneGap.JSCallbackPort = null;
|
||||
PhoneGap.JSCallbackToken = null;
|
||||
|
||||
/**
|
||||
* This is only for Android.
|
||||
@@ -605,7 +620,7 @@ PhoneGap.JSCallback = function() {
|
||||
}
|
||||
catch (e) {
|
||||
// If we're getting an error here, seeing the message will help in debugging
|
||||
console.log("Message from Server: " + msg);
|
||||
console.log("JSCallback: Message from Server: " + msg);
|
||||
console.log("JSCallback Error: "+e);
|
||||
}
|
||||
}, 1);
|
||||
@@ -617,15 +632,38 @@ PhoneGap.JSCallback = function() {
|
||||
setTimeout(PhoneGap.JSCallback, 10);
|
||||
}
|
||||
|
||||
// If security error
|
||||
else if (xmlhttp.status == 403) {
|
||||
console.log("JSCallback Error: Invalid token. Stopping callbacks.");
|
||||
}
|
||||
|
||||
// If server is stopping
|
||||
else if (xmlhttp.status == 503) {
|
||||
console.log("JSCallback Error: Service unavailable. Stopping callbacks.");
|
||||
}
|
||||
|
||||
// If request wasn't GET
|
||||
else if (xmlhttp.status == 400) {
|
||||
console.log("JSCallback Error: Bad request. Stopping callbacks.");
|
||||
}
|
||||
|
||||
// If error, restart callback server
|
||||
else {
|
||||
console.log("JSCallback Error: Request failed.");
|
||||
CallbackServer.restartServer();
|
||||
PhoneGap.JSCallbackPort = null;
|
||||
PhoneGap.JSCallbackToken = null;
|
||||
setTimeout(PhoneGap.JSCallback, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PhoneGap.JSCallbackPort == null) {
|
||||
PhoneGap.JSCallbackPort = CallbackServer.getPort();
|
||||
}
|
||||
if (PhoneGap.JSCallbackToken == null) {
|
||||
PhoneGap.JSCallbackToken = CallbackServer.getToken();
|
||||
}
|
||||
xmlhttp.open("GET", "http://127.0.0.1:"+PhoneGap.JSCallbackPort+"/"+PhoneGap.JSCallbackToken , true);
|
||||
xmlhttp.send();
|
||||
};
|
||||
@@ -651,6 +689,7 @@ PhoneGap.JSCallbackPolling = function() {
|
||||
var t = eval(""+msg);
|
||||
}
|
||||
catch (e) {
|
||||
console.log("JSCallbackPolling: Message from Server: " + msg);
|
||||
console.log("JSCallbackPolling Error: "+e);
|
||||
}
|
||||
}, 1);
|
||||
@@ -698,3 +737,19 @@ PhoneGap.close = function(context, func, params) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a JavaScript file after page has loaded.
|
||||
*
|
||||
* @param {String} jsfile The url of the JavaScript file to load.
|
||||
* @param {Function} successCallback The callback to call when the file has been loaded.
|
||||
*/
|
||||
PhoneGap.includeJavascript = function(jsfile, successCallback) {
|
||||
var id = document.getElementsByTagName("head")[0];
|
||||
var el = document.createElement('script');
|
||||
el.type = 'text/javascript';
|
||||
if (typeof successCallback == 'function') {
|
||||
el.onload = successCallback;
|
||||
}
|
||||
el.src = jsfile;
|
||||
id.appendChild(el);
|
||||
};
|
||||
|
||||
@@ -20,30 +20,13 @@ var DroidDB = function() {
|
||||
this.queryQueue = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback from native code when result from a query is available.
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param rawdata JSON string of the row data
|
||||
* @param id Query id
|
||||
*/
|
||||
DroidDB.prototype.addResult = function(rawdata, id) {
|
||||
try {
|
||||
eval("var data = " + rawdata + ";");
|
||||
var query = this.queryQueue[id];
|
||||
query.resultSet.push(data);
|
||||
} catch (e) {
|
||||
console.log("DroidDB.addResult(): Error="+e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback from native code when query is complete.
|
||||
* PRIVATE METHOD
|
||||
*
|
||||
* @param id Query id
|
||||
*/
|
||||
DroidDB.prototype.completeQuery = function(id) {
|
||||
DroidDB.prototype.completeQuery = function(id, data) {
|
||||
var query = this.queryQueue[id];
|
||||
if (query) {
|
||||
try {
|
||||
@@ -59,8 +42,8 @@ DroidDB.prototype.completeQuery = function(id) {
|
||||
|
||||
// Save query results
|
||||
var r = new DroidDB_Result();
|
||||
r.rows.resultSet = query.resultSet;
|
||||
r.rows.length = query.resultSet.length;
|
||||
r.rows.resultSet = data;
|
||||
r.rows.length = data.length;
|
||||
try {
|
||||
if (typeof query.successCallback == 'function') {
|
||||
query.successCallback(query.tx, r);
|
||||
@@ -127,7 +110,7 @@ var DatabaseShell = function() {
|
||||
* @param successCallback {Function}
|
||||
* @param errorCallback {Function}
|
||||
*/
|
||||
DatabaseShell.prototype.transaction = function(process, successCallback, errorCallback) {
|
||||
DatabaseShell.prototype.transaction = function(process, errorCallback, successCallback) {
|
||||
var tx = new DroidDB_Tx();
|
||||
tx.successCallback = successCallback;
|
||||
tx.errorCallback = errorCallback;
|
||||
@@ -308,9 +291,71 @@ DroidDB_openDatabase = function(name, version, display_name, size) {
|
||||
return db;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* For browsers with no localStorage we emulate it with SQLite. Follows the w3c api.
|
||||
* TODO: Do similar for sessionStorage.
|
||||
*/
|
||||
|
||||
var CupcakeLocalStorage = function() {
|
||||
try {
|
||||
|
||||
this.db = openDatabase('localStorage', '1.0', 'localStorage', 2621440);
|
||||
var storage = {};
|
||||
this.db.transaction(
|
||||
function (transaction) {
|
||||
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
|
||||
transaction.executeSql('SELECT * FROM storage', [], function(tx, result) {
|
||||
for(var i = 0; i < result.rows.length; i++) {
|
||||
storage[result.rows.item(i)['id']] = result.rows.item(i)['body'];
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
function (err) {
|
||||
alert(err.message);
|
||||
}
|
||||
);
|
||||
this.setItem = function(key, val) {
|
||||
console.log('set');
|
||||
storage[key] = val;
|
||||
|
||||
this.db.transaction(
|
||||
function (transaction) {
|
||||
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
|
||||
|
||||
transaction.executeSql('REPLACE INTO storage (id, body) values(?,?)', [key,val]);
|
||||
}
|
||||
);
|
||||
}
|
||||
this.getItem = function(key) {
|
||||
return storage[key];
|
||||
}
|
||||
this.removeItem = function(key) {
|
||||
delete storage[key];
|
||||
this.db.transaction(
|
||||
function (transaction) {
|
||||
transaction.executeSql('CREATE TABLE IF NOT EXISTS storage (id NVARCHAR(40) PRIMARY KEY, body NVARCHAR(255))');
|
||||
|
||||
transaction.executeSql('DELETE FROM storage where id=?', [key]);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
} catch(e) {
|
||||
alert("Database error "+e+".");
|
||||
return;
|
||||
}
|
||||
};
|
||||
PhoneGap.addConstructor(function() {
|
||||
if (typeof window.openDatabase == "undefined") {
|
||||
if (typeof window.openDatabase == "undefined") {
|
||||
navigator.openDatabase = window.openDatabase = DroidDB_openDatabase;
|
||||
window.droiddb = new DroidDB();
|
||||
}
|
||||
|
||||
if (typeof window.localStorage == "undefined") {
|
||||
navigator.localStorage = window.localStorage = new CupcakeLocalStorage();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
50
framework/build.xml
Normal file → Executable file
50
framework/build.xml
Normal file → Executable file
@@ -95,16 +95,60 @@
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="build-javascript">
|
||||
<delete file="assets/www/phonegap.js"/>
|
||||
<!-- Combine JavaScript files into one phonegap.js file.
|
||||
This task does not create a compressed JavaScript file. -->
|
||||
<target name="build-uncompressed-javascript">
|
||||
|
||||
<!-- Clean up existing files -->
|
||||
<delete file="assets/www/phonegap.js"/>
|
||||
<delete file="assets/www/phonegap-tmp.js"/>
|
||||
<delete file="assets/www/phonegap-uncompressed.js"/>
|
||||
|
||||
<!-- Create uncompressed JS file -->
|
||||
<concat destfile="assets/www/phonegap.js">
|
||||
<fileset dir="assets/js" includes="phonegap.js.base" />
|
||||
<fileset dir="assets/js" includes="*.js" />
|
||||
</concat>
|
||||
</target>
|
||||
|
||||
<!-- Combine JavaScript files into one phonegap-uncompressed.js file.
|
||||
Compress this file using yuicompressor to create phonegap.js. -->
|
||||
<target name="build-javascript">
|
||||
|
||||
<!-- Clean up existing files -->
|
||||
<delete file="assets/www/phonegap.js"/>
|
||||
<delete file="assets/www/phonegap-tmp.js"/>
|
||||
<delete file="assets/www/phonegap-uncompressed.js"/>
|
||||
|
||||
<!-- Create uncompressed JS file -->
|
||||
<concat destfile="assets/www/phonegap-uncompressed.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"/>
|
||||
</java>
|
||||
<concat destfile="assets/www/phonegap.js">
|
||||
<fileset dir="assets/js" includes="header.txt" />
|
||||
<fileset dir="assets/www" includes="phonegap-tmp.js" />
|
||||
</concat>
|
||||
|
||||
<!-- Delete temp file -->
|
||||
<delete file="assets/www/phonegap-tmp.js"/>
|
||||
</target>
|
||||
|
||||
<!-- Build PhoneGap jar file that includes all native code, and PhoneGap JS file
|
||||
that includes all JavaScript code.
|
||||
|
||||
The default is to compress the JavaScript code using yuicompressor.
|
||||
|
||||
If you want uncompressed JavaScript, change
|
||||
"build-javascript" => "build-uncompressed-javascript".
|
||||
-->
|
||||
<target name="jar" depends="build-javascript, compile">
|
||||
<jar jarfile="phonegap.jar" basedir="bin/classes" excludes="**/R*.class" />
|
||||
<jar jarfile="phonegap.jar" basedir="bin/classes" excludes="com/phonegap/R.class,com/phonegap/R$*.class"/>
|
||||
</target>
|
||||
|
||||
<target name="phonegap_debug" depends="build-javascript, debug">
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
@@ -60,7 +61,7 @@ public class AccelListener extends Plugin implements SensorEventListener {
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
public void setContext(DroidGap ctx) {
|
||||
public void setContext(PhonegapActivity ctx) {
|
||||
super.setContext(ctx);
|
||||
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
|
||||
}
|
||||
|
||||
135
framework/src/com/phonegap/App.java
Executable file
135
framework/src/com/phonegap/App.java
Executable file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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 org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
/**
|
||||
* This class exposes methods in DroidGap that can be called from JavaScript.
|
||||
*/
|
||||
public class App extends Plugin {
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
*
|
||||
* @param action The action to execute.
|
||||
* @param args JSONArry of arguments for the plugin.
|
||||
* @param callbackId The callback id used when calling back into JavaScript.
|
||||
* @return A PluginResult object with a status and message.
|
||||
*/
|
||||
public PluginResult execute(String action, JSONArray args, String callbackId) {
|
||||
PluginResult.Status status = PluginResult.Status.OK;
|
||||
String result = "";
|
||||
|
||||
try {
|
||||
if (action.equals("clearCache")) {
|
||||
this.clearCache();
|
||||
}
|
||||
else if (action.equals("loadUrl")) {
|
||||
this.loadUrl(args.getString(0), args.optJSONObject(1));
|
||||
}
|
||||
else if (action.equals("cancelLoadUrl")) {
|
||||
this.cancelLoadUrl();
|
||||
}
|
||||
else if (action.equals("clearHistory")) {
|
||||
this.clearHistory();
|
||||
}
|
||||
else if (action.equals("addService")) {
|
||||
this.addService(args.getString(0), args.getString(1));
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clear the resource cache.
|
||||
*/
|
||||
public void clearCache() {
|
||||
((DroidGap)this.ctx).clearCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the url into the webview.
|
||||
*
|
||||
* @param url
|
||||
* @param props Properties that can be passed in to the DroidGap activity (i.e. loadingDialog, wait, ...)
|
||||
* @throws JSONException
|
||||
*/
|
||||
public void loadUrl(String url, JSONObject props) throws JSONException {
|
||||
System.out.println("App.loadUrl("+url+","+props+")");
|
||||
int wait = 0;
|
||||
|
||||
// If there are properties, then set them on the Activity
|
||||
if (props != null) {
|
||||
JSONArray keys = props.names();
|
||||
for (int i=0; i<keys.length(); i++) {
|
||||
String key = keys.getString(i);
|
||||
if (key.equals("wait")) {
|
||||
wait = props.getInt(key);
|
||||
}
|
||||
else {
|
||||
Object value = props.get(key);
|
||||
if (value == null) {
|
||||
|
||||
}
|
||||
else if (value.getClass().equals(String.class)) {
|
||||
this.ctx.getIntent().putExtra(key, (String)value);
|
||||
}
|
||||
else if (value.getClass().equals(Boolean.class)) {
|
||||
this.ctx.getIntent().putExtra(key, (Boolean)value);
|
||||
}
|
||||
else if (value.getClass().equals(Integer.class)) {
|
||||
this.ctx.getIntent().putExtra(key, (Integer)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If wait property, then delay loading
|
||||
if (wait > 0) {
|
||||
((DroidGap)this.ctx).loadUrl(url, wait);
|
||||
}
|
||||
else {
|
||||
((DroidGap)this.ctx).loadUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel loadUrl before it has been loaded.
|
||||
*/
|
||||
public void cancelLoadUrl() {
|
||||
((DroidGap)this.ctx).cancelLoadUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear web history in this web view.
|
||||
*/
|
||||
public void clearHistory() {
|
||||
((DroidGap)this.ctx).clearHistory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a class that implements a service.
|
||||
*
|
||||
* @param serviceType
|
||||
* @param className
|
||||
*/
|
||||
public void addService(String serviceType, String className) {
|
||||
this.ctx.addService(serviceType, className);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
|
||||
/**
|
||||
* This class called by DroidGap to play and record audio.
|
||||
* This class called by PhonegapActivity to play and record audio.
|
||||
* The file can be local or over a network using http.
|
||||
*
|
||||
* Audio formats supported (tested):
|
||||
@@ -77,13 +77,17 @@ public class AudioHandler extends Plugin {
|
||||
long l = this.getDurationAudio(args.getString(0), args.getString(1));
|
||||
return new PluginResult(status, l);
|
||||
}
|
||||
else if (action.equals("release")) {
|
||||
boolean b = this.release(args.getString(0));
|
||||
return new PluginResult(status, b);
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Identifies if action to be executed returns a value and should be run synchronously.
|
||||
*
|
||||
@@ -117,6 +121,21 @@ public class AudioHandler extends Plugin {
|
||||
//--------------------------------------------------------------------------
|
||||
// LOCAL METHODS
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Release the audio player instance to save memory.
|
||||
*
|
||||
* @param id The id of the audio player
|
||||
*/
|
||||
private boolean release(String id) {
|
||||
if (!this.players.containsKey(id)) {
|
||||
return false;
|
||||
}
|
||||
AudioPlayer audio = this.players.get(id);
|
||||
this.players.remove(id);
|
||||
audio.destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start recording and save the specified file.
|
||||
|
||||
@@ -84,10 +84,28 @@ public class CallbackServer implements Runnable {
|
||||
this.active = false;
|
||||
this.empty = true;
|
||||
this.port = 0;
|
||||
this.javascript = new LinkedList<String>();
|
||||
|
||||
if (android.net.Proxy.getDefaultHost() != null) {
|
||||
this.javascript = new LinkedList<String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init callback server and start XHR if running local app.
|
||||
*
|
||||
* If PhoneGap app is loaded from file://, then we can use XHR
|
||||
* otherwise we have to use polling due to cross-domain security restrictions.
|
||||
*
|
||||
* @param url The URL of the PhoneGap app being loaded
|
||||
*/
|
||||
public void init(String url) {
|
||||
//System.out.println("CallbackServer.start("+url+")");
|
||||
|
||||
// Determine if XHR or polling is to be used
|
||||
if ((url != null) && !url.startsWith("file://")) {
|
||||
this.usePolling = true;
|
||||
this.stopServer();
|
||||
}
|
||||
else if (android.net.Proxy.getDefaultHost() != null) {
|
||||
this.usePolling = true;
|
||||
this.stopServer();
|
||||
}
|
||||
else {
|
||||
this.usePolling = false;
|
||||
@@ -96,7 +114,7 @@ public class CallbackServer implements Runnable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if polling should be used instead of XHR.
|
||||
* Return if polling is being used instead of XHR.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@@ -158,9 +176,9 @@ public class CallbackServer implements Runnable {
|
||||
String request;
|
||||
ServerSocket waitSocket = new ServerSocket(0);
|
||||
this.port = waitSocket.getLocalPort();
|
||||
//System.out.println(" -- using port " +this.port);
|
||||
//System.out.println("CallbackServer -- using port " +this.port);
|
||||
this.token = java.util.UUID.randomUUID().toString();
|
||||
//System.out.println(" -- using token "+this.token);
|
||||
//System.out.println("CallbackServer -- using token "+this.token);
|
||||
|
||||
while (this.active) {
|
||||
//System.out.println("CallbackServer: Waiting for data on socket");
|
||||
@@ -168,20 +186,21 @@ public class CallbackServer implements Runnable {
|
||||
BufferedReader xhrReader = new BufferedReader(new InputStreamReader(connection.getInputStream()),40);
|
||||
DataOutputStream output = new DataOutputStream(connection.getOutputStream());
|
||||
request = xhrReader.readLine();
|
||||
//System.out.println("Request="+request);
|
||||
String response = "";
|
||||
//System.out.println("CallbackServerRequest="+request);
|
||||
if (request.contains("GET")) {
|
||||
|
||||
// Must have security token
|
||||
if (request.substring(5,41).equals(this.token)) {
|
||||
//System.out.println(" -- Processing GET request");
|
||||
//System.out.println("CallbackServer -- Processing GET request");
|
||||
|
||||
// Wait until there is some data to send, or send empty data every 30 sec
|
||||
// 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(30000); // prevent timeout from happening
|
||||
//System.out.println(">>> break <<<");
|
||||
this.wait(10000); // prevent timeout from happening
|
||||
//System.out.println("CallbackServer>>> break <<<");
|
||||
break;
|
||||
}
|
||||
catch (Exception e) { }
|
||||
@@ -193,17 +212,29 @@ public class CallbackServer implements Runnable {
|
||||
|
||||
// If no data, then send 404 back to client before it times out
|
||||
if (this.empty) {
|
||||
//System.out.println(" -- sending data 0");
|
||||
output.writeBytes("HTTP/1.1 404 NO DATA\r\n\r\n");
|
||||
//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(" -- sending item");
|
||||
output.writeBytes("HTTP/1.1 200 OK\r\n\r\n"+this.getJavascript());
|
||||
//System.out.println("CallbackServer -- sending item");
|
||||
response = "HTTP/1.1 200 OK\r\n\r\n"+this.getJavascript();
|
||||
}
|
||||
}
|
||||
else {
|
||||
response = "HTTP/1.1 503 Service Unavailable\r\n\r\n ";
|
||||
}
|
||||
}
|
||||
else {
|
||||
response = "HTTP/1.1 403 Forbidden\r\n\r\n ";
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -219,11 +250,13 @@ public class CallbackServer implements Runnable {
|
||||
*/
|
||||
public void stopServer() {
|
||||
//System.out.println("CallbackServer.stopServer()");
|
||||
this.active = false;
|
||||
if (this.active) {
|
||||
this.active = false;
|
||||
|
||||
// Break out of server wait
|
||||
synchronized (this) {
|
||||
this.notify();
|
||||
// Break out of server wait
|
||||
synchronized (this) {
|
||||
this.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ public class CameraLauncher extends Plugin {
|
||||
this.takePicture(args.getInt(0), destType);
|
||||
}
|
||||
else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) {
|
||||
this.getImage(srcType, destType);
|
||||
this.getImage(args.getInt(0), srcType, destType);
|
||||
}
|
||||
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
|
||||
r.setKeepCallback(true);
|
||||
@@ -100,7 +100,7 @@ public class CameraLauncher extends Plugin {
|
||||
/**
|
||||
* Take a picture with the camera.
|
||||
* When an image is captured or the camera view is cancelled, the result is returned
|
||||
* in DroidGap.onActivityResult, which forwards the result to this.onActivityResult.
|
||||
* in PhonegapActivity.onActivityResult, which forwards the result to this.onActivityResult.
|
||||
*
|
||||
* The image can either be returned as a base64 string or a URI that points to the file.
|
||||
* To display base64 string in an img tag, set the source to:
|
||||
@@ -129,10 +129,14 @@ public class CameraLauncher extends Plugin {
|
||||
/**
|
||||
* Get image from photo library.
|
||||
*
|
||||
* @param returnType
|
||||
* @param quality Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
|
||||
* @param srcType The album to get image from.
|
||||
* @param returnType Set the type of image to return.
|
||||
*/
|
||||
// TODO: Images selected from SDCARD don't display correctly, but from CAMERA ALBUM do!
|
||||
public void getImage(int srcType, int returnType) {
|
||||
public void getImage(int quality, int srcType, int returnType) {
|
||||
this.mQuality = quality;
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setType("image/*");
|
||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.List;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
@@ -55,7 +56,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
public void setContext(DroidGap ctx) {
|
||||
public void setContext(PhonegapActivity ctx) {
|
||||
super.setContext(ctx);
|
||||
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
|
||||
}
|
||||
|
||||
@@ -162,11 +162,36 @@ public abstract class ContactAccessor {
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to get a string from a JSON object. Saves a
|
||||
* lot of try/catch writing.
|
||||
* If the property is not found in the object null will be returned.
|
||||
*
|
||||
* @param obj contact object to search
|
||||
* @param property to be looked up
|
||||
* @return The value of the property
|
||||
*/
|
||||
protected String getJsonString(JSONObject obj, String property) {
|
||||
String value = null;
|
||||
try {
|
||||
value = obj.getString(property);
|
||||
if (value.equals("null")) {
|
||||
Log.d(LOG_TAG, property + " is string called 'null'");
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.d(LOG_TAG, "Could not get = " + e.getMessage());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles adding a JSON Contact object into the database.
|
||||
* @return TODO
|
||||
*/
|
||||
public abstract void save(JSONObject contact);
|
||||
public abstract boolean save(JSONObject contact);
|
||||
|
||||
/**
|
||||
* Handles searching through SDK-specific contacts API.
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.json.JSONObject;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.Contacts;
|
||||
@@ -62,6 +63,7 @@ import android.webkit.WebView;
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class ContactAccessorSdk3_4 extends ContactAccessor {
|
||||
private static final String PEOPLE_ID_EQUALS = "people._id = ?";
|
||||
/**
|
||||
* A static map that converts the JavaScript property name to Android database column name.
|
||||
*/
|
||||
@@ -140,7 +142,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
|
||||
// Do query for name and note
|
||||
Cursor cur = cr.query(People.CONTENT_URI,
|
||||
new String[] {People.DISPLAY_NAME, People.NOTES},
|
||||
"people._id = ?",
|
||||
PEOPLE_ID_EQUALS,
|
||||
new String[] {contactId},
|
||||
null);
|
||||
cur.moveToFirst();
|
||||
@@ -305,11 +307,13 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
|
||||
while (cursor.moveToNext()) {
|
||||
im = new JSONObject();
|
||||
try{
|
||||
im.put("id", cursor.getString(
|
||||
cursor.getColumnIndex(ContactMethods._ID)));
|
||||
im.put("primary", false);
|
||||
im.put("value", cursor.getString(
|
||||
cursor.getColumnIndex(ContactMethodsColumns.DATA)));
|
||||
im.put("type", cursor.getString(
|
||||
cursor.getColumnIndex(ContactMethodsColumns.TYPE)));
|
||||
im.put("type", getContactType(cursor.getInt(
|
||||
cursor.getColumnIndex(ContactMethodsColumns.TYPE))));
|
||||
ims.put(im);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
@@ -335,6 +339,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
|
||||
while (cursor.moveToNext()) {
|
||||
organization = new JSONObject();
|
||||
try{
|
||||
organization.put("id", cursor.getString(cursor.getColumnIndex(Organizations._ID)));
|
||||
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)));
|
||||
@@ -368,6 +373,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
|
||||
while (cursor.moveToNext()) {
|
||||
address = new JSONObject();
|
||||
try{
|
||||
address.put("id", cursor.getString(cursor.getColumnIndex(ContactMethods._ID)));
|
||||
address.put("formatted", cursor.getString(cursor.getColumnIndex(ContactMethodsColumns.DATA)));
|
||||
addresses.put(address);
|
||||
} catch (JSONException e) {
|
||||
@@ -394,9 +400,10 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
|
||||
while (cursor.moveToNext()) {
|
||||
phone = new JSONObject();
|
||||
try{
|
||||
phone.put("id", cursor.getString(cursor.getColumnIndex(Phones._ID)));
|
||||
phone.put("primary", false);
|
||||
phone.put("value", cursor.getString(cursor.getColumnIndex(Phones.NUMBER)));
|
||||
phone.put("type", cursor.getString(cursor.getColumnIndex(Phones.TYPE)));
|
||||
phone.put("type", getPhoneType(cursor.getInt(cursor.getColumnIndex(Phones.TYPE))));
|
||||
phones.put(phone);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
@@ -422,6 +429,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
|
||||
while (cursor.moveToNext()) {
|
||||
email = new JSONObject();
|
||||
try{
|
||||
email.put("id", cursor.getString(cursor.getColumnIndex(ContactMethods._ID)));
|
||||
email.put("primary", false);
|
||||
email.put("value", cursor.getString(cursor.getColumnIndex(ContactMethods.DATA)));
|
||||
// TODO Find out why adding an email type throws and exception
|
||||
@@ -434,10 +442,372 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
|
||||
return emails;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will save a contact object into the devices contacts database.
|
||||
*
|
||||
* @param contact the contact to be saved.
|
||||
* @returns true if the contact is successfully saved, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public void save(JSONObject contact) {
|
||||
// TODO Auto-generated method stub
|
||||
public boolean save(JSONObject contact) {
|
||||
ContentValues personValues = new ContentValues();
|
||||
|
||||
String id = getJsonString(contact, "id");
|
||||
|
||||
String name = getJsonString(contact, "displayName");
|
||||
if (name != null) {
|
||||
personValues.put(Contacts.People.NAME, name);
|
||||
}
|
||||
String note = getJsonString(contact, "note");
|
||||
if (note != null) {
|
||||
personValues.put(Contacts.People.NOTES, note);
|
||||
}
|
||||
|
||||
/* STARRED 0 = Contacts, 1 = Favorites */
|
||||
personValues.put(Contacts.People.STARRED, 0);
|
||||
|
||||
Uri newPersonUri;
|
||||
// Add new contact
|
||||
if (id == null) {
|
||||
newPersonUri = Contacts.People.createPersonInMyContactsGroup(mApp.getContentResolver(), personValues);
|
||||
}
|
||||
// modify existing contact
|
||||
else {
|
||||
newPersonUri = Uri.withAppendedPath(Contacts.People.CONTENT_URI, id);
|
||||
mApp.getContentResolver().update(newPersonUri, personValues, PEOPLE_ID_EQUALS, new String[]{id});
|
||||
}
|
||||
|
||||
if (newPersonUri != null) {
|
||||
// phoneNumbers
|
||||
savePhoneNumbers(contact, newPersonUri);
|
||||
// emails
|
||||
saveEntries(contact, newPersonUri, "emails", Contacts.KIND_EMAIL);
|
||||
// addresses
|
||||
saveAddresses(contact, newPersonUri);
|
||||
// organizations
|
||||
saveOrganizations(contact, newPersonUri);
|
||||
// ims
|
||||
saveEntries(contact, newPersonUri, "ims", Contacts.KIND_IM);
|
||||
|
||||
// Successfully create a Contact
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a JSON contact object and loops through the available organizations. If the
|
||||
* organization has an id that is not equal to null the organization will be updated in the database.
|
||||
* If the id is null then we treat it as a new organization.
|
||||
*
|
||||
* @param contact the contact to extract the organizations from
|
||||
* @param uri the base URI for this contact.
|
||||
*/
|
||||
private void saveOrganizations(JSONObject contact, Uri newPersonUri) {
|
||||
ContentValues values = new ContentValues();
|
||||
Uri orgUri = Uri.withAppendedPath(newPersonUri,
|
||||
Contacts.Organizations.CONTENT_DIRECTORY);
|
||||
String id = null;
|
||||
try {
|
||||
JSONArray orgs = contact.getJSONArray("organizations");
|
||||
if (orgs != null && orgs.length() > 0) {
|
||||
JSONObject org;
|
||||
for (int i=0; i<orgs.length(); i++) {
|
||||
org = orgs.getJSONObject(i);
|
||||
id = getJsonString(org, "id");
|
||||
values.put(Contacts.Organizations.COMPANY, getJsonString(org, "name"));
|
||||
values.put(Contacts.Organizations.TITLE, getJsonString(org, "title"));
|
||||
if (id == null) {
|
||||
Uri contactUpdate = mApp.getContentResolver().insert(orgUri, values);
|
||||
}
|
||||
else {
|
||||
Uri tempUri = Uri.withAppendedPath(orgUri, id);
|
||||
mApp.getContentResolver().update(tempUri, values, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.d(LOG_TAG, "Could not save organizations = " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a JSON contact object and loops through the available addresses. If the
|
||||
* address has an id that is not equal to null the address will be updated in the database.
|
||||
* If the id is null then we treat it as a new address.
|
||||
*
|
||||
* @param contact the contact to extract the addresses from
|
||||
* @param uri the base URI for this contact.
|
||||
*/
|
||||
private void saveAddresses(JSONObject contact, Uri uri) {
|
||||
ContentValues values = new ContentValues();
|
||||
Uri newUri = Uri.withAppendedPath(uri,
|
||||
Contacts.People.ContactMethods.CONTENT_DIRECTORY);
|
||||
String id = null;
|
||||
try {
|
||||
JSONArray entries = contact.getJSONArray("addresses");
|
||||
if (entries != null && entries.length() > 0) {
|
||||
JSONObject entry;
|
||||
values.put(Contacts.ContactMethods.KIND, Contacts.KIND_POSTAL);
|
||||
for (int i=0; i<entries.length(); i++) {
|
||||
entry = entries.getJSONObject(i);
|
||||
id = getJsonString(entry, "id");
|
||||
|
||||
String address = getJsonString(entry, "formatted");
|
||||
if (address != null) {
|
||||
values.put(Contacts.ContactMethods.DATA, address);
|
||||
}
|
||||
else {
|
||||
values.put(Contacts.ContactMethods.DATA, createAddressString(entry));
|
||||
}
|
||||
|
||||
if (id == null) {
|
||||
Uri contactUpdate = mApp.getContentResolver().insert(newUri, values);
|
||||
}
|
||||
else {
|
||||
Uri tempUri = Uri.withAppendedPath(newUri, id);
|
||||
mApp.getContentResolver().update(tempUri, values, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.d(LOG_TAG, "Could not save address = " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a ContactAddress JSON object and creates a fully
|
||||
* formatted address string.
|
||||
*
|
||||
* @param entry the full address object
|
||||
* @return a formatted address string
|
||||
*/
|
||||
private String createAddressString(JSONObject entry) {
|
||||
StringBuffer buffer = new StringBuffer("");
|
||||
if (getJsonString(entry, "locality") != null ) {
|
||||
buffer.append(getJsonString(entry, "locality"));
|
||||
}
|
||||
if (getJsonString(entry, "region") != null ) {
|
||||
if (buffer.length() > 0 ) {
|
||||
buffer.append(", ");
|
||||
}
|
||||
buffer.append(getJsonString(entry, "region"));
|
||||
}
|
||||
if (getJsonString(entry, "postalCode") != null ) {
|
||||
if (buffer.length() > 0 ) {
|
||||
buffer.append(", ");
|
||||
}
|
||||
buffer.append(getJsonString(entry, "postalCode"));
|
||||
}
|
||||
if (getJsonString(entry, "country") != null ) {
|
||||
if (buffer.length() > 0 ) {
|
||||
buffer.append(", ");
|
||||
}
|
||||
buffer.append(getJsonString(entry, "country"));
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a JSON contact object and loops through the available entries (Emails/IM's). If the
|
||||
* entry has an id that is not equal to null the entry will be updated in the database.
|
||||
* If the id is null then we treat it as a new entry.
|
||||
*
|
||||
* @param contact the contact to extract the entries from
|
||||
* @param uri the base URI for this contact.
|
||||
*/
|
||||
private void saveEntries(JSONObject contact, Uri uri, String dataType, int contactKind) {
|
||||
ContentValues values = new ContentValues();
|
||||
Uri newUri = Uri.withAppendedPath(uri,
|
||||
Contacts.People.ContactMethods.CONTENT_DIRECTORY);
|
||||
String id = null;
|
||||
|
||||
try {
|
||||
JSONArray entries = contact.getJSONArray(dataType);
|
||||
if (entries != null && entries.length() > 0) {
|
||||
JSONObject entry;
|
||||
values.put(Contacts.ContactMethods.KIND, contactKind);
|
||||
for (int i=0; i<entries.length(); i++) {
|
||||
entry = entries.getJSONObject(i);
|
||||
id = getJsonString(entry, "id");
|
||||
values.put(Contacts.ContactMethods.DATA, getJsonString(entry, "value"));
|
||||
values.put(Contacts.ContactMethods.TYPE, getContactType(getJsonString(entry, "type")));
|
||||
if (id==null) {
|
||||
Uri contactUpdate = mApp.getContentResolver().insert(newUri, values);
|
||||
}
|
||||
else {
|
||||
Uri tempUri = Uri.withAppendedPath(newUri, id);
|
||||
mApp.getContentResolver().update(tempUri, values, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.d(LOG_TAG, "Could not save " + dataType + " = " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string from the W3C Contact API to it's Android int value.
|
||||
* @param string
|
||||
* @return Android int value
|
||||
*/
|
||||
private int getContactType(String string) {
|
||||
int type = Contacts.ContactMethods.TYPE_OTHER;
|
||||
if (string!=null) {
|
||||
if ("home".equals(string.toLowerCase())) {
|
||||
return Contacts.ContactMethods.TYPE_HOME;
|
||||
}
|
||||
else if ("work".equals(string.toLowerCase())) {
|
||||
return Contacts.ContactMethods.TYPE_WORK;
|
||||
}
|
||||
else if ("other".equals(string.toLowerCase())) {
|
||||
return Contacts.ContactMethods.TYPE_OTHER;
|
||||
}
|
||||
else if ("custom".equals(string.toLowerCase())) {
|
||||
return Contacts.ContactMethods.TYPE_CUSTOM;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* getPhoneType converts an Android phone type into a string
|
||||
* @param type
|
||||
* @return phone type as string.
|
||||
*/
|
||||
private String getContactType(int type) {
|
||||
String stringType;
|
||||
switch (type) {
|
||||
case Contacts.ContactMethods.TYPE_CUSTOM:
|
||||
stringType = "custom";
|
||||
break;
|
||||
case Contacts.ContactMethods.TYPE_HOME:
|
||||
stringType = "home";
|
||||
break;
|
||||
case Contacts.ContactMethods.TYPE_WORK:
|
||||
stringType = "work";
|
||||
break;
|
||||
case Contacts.ContactMethods.TYPE_OTHER:
|
||||
default:
|
||||
stringType = "other";
|
||||
break;
|
||||
}
|
||||
return stringType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a JSON contact object and loops through the available phone numbers. If the phone
|
||||
* number has an id that is not equal to null the phone number will be updated in the database.
|
||||
* If the id is null then we treat it as a new phone number.
|
||||
*
|
||||
* @param contact the contact to extract the phone numbers from
|
||||
* @param uri the base URI for this contact.
|
||||
*/
|
||||
private void savePhoneNumbers(JSONObject contact, Uri uri) {
|
||||
ContentValues values = new ContentValues();
|
||||
Uri phonesUri = Uri.withAppendedPath(uri,
|
||||
Contacts.People.Phones.CONTENT_DIRECTORY);
|
||||
String id = null;
|
||||
|
||||
try {
|
||||
JSONArray phones = contact.getJSONArray("phoneNumbers");
|
||||
if (phones != null && phones.length() > 0) {
|
||||
JSONObject phone;
|
||||
for (int i=0; i<phones.length(); i++) {
|
||||
phone = phones.getJSONObject(i);
|
||||
id = getJsonString(phone, "id");
|
||||
values.put(Contacts.Phones.NUMBER, getJsonString(phone, "value"));
|
||||
values.put(Contacts.Phones.TYPE, getPhoneType(getJsonString(phone, "type")));
|
||||
if (id==null) {
|
||||
Uri phoneUpdate = mApp.getContentResolver().insert(phonesUri, values);
|
||||
}
|
||||
else {
|
||||
Uri newUri = Uri.withAppendedPath(phonesUri, id);
|
||||
mApp.getContentResolver().update(newUri, values, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.d(LOG_TAG, "Could not save phones = " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string from the W3C Contact API to it's Android int value.
|
||||
* @param string
|
||||
* @return Android int value
|
||||
*/
|
||||
private int getPhoneType(String string) {
|
||||
int type = Contacts.Phones.TYPE_OTHER;
|
||||
if ("home".equals(string.toLowerCase())) {
|
||||
return Contacts.Phones.TYPE_HOME;
|
||||
}
|
||||
else if ("mobile".equals(string.toLowerCase())) {
|
||||
return Contacts.Phones.TYPE_MOBILE;
|
||||
}
|
||||
else if ("work".equals(string.toLowerCase())) {
|
||||
return Contacts.Phones.TYPE_WORK;
|
||||
}
|
||||
else if ("work fax".equals(string.toLowerCase())) {
|
||||
return Contacts.Phones.TYPE_FAX_WORK;
|
||||
}
|
||||
else if ("home fax".equals(string.toLowerCase())) {
|
||||
return Contacts.Phones.TYPE_FAX_HOME;
|
||||
}
|
||||
else if ("fax".equals(string.toLowerCase())) {
|
||||
return Contacts.Phones.TYPE_FAX_WORK;
|
||||
}
|
||||
else if ("pager".equals(string.toLowerCase())) {
|
||||
return Contacts.Phones.TYPE_PAGER;
|
||||
}
|
||||
else if ("other".equals(string.toLowerCase())) {
|
||||
return Contacts.Phones.TYPE_OTHER;
|
||||
}
|
||||
else if ("custom".equals(string.toLowerCase())) {
|
||||
return Contacts.Phones.TYPE_CUSTOM;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* getPhoneType converts an Android phone type into a string
|
||||
* @param type
|
||||
* @return phone type as string.
|
||||
*/
|
||||
private String getPhoneType(int type) {
|
||||
String stringType;
|
||||
switch (type) {
|
||||
case Contacts.Phones.TYPE_CUSTOM:
|
||||
stringType = "custom";
|
||||
break;
|
||||
case Contacts.Phones.TYPE_FAX_HOME:
|
||||
stringType = "home fax";
|
||||
break;
|
||||
case Contacts.Phones.TYPE_FAX_WORK:
|
||||
stringType = "work fax";
|
||||
break;
|
||||
case Contacts.Phones.TYPE_HOME:
|
||||
stringType = "home";
|
||||
break;
|
||||
case Contacts.Phones.TYPE_MOBILE:
|
||||
stringType = "mobile";
|
||||
break;
|
||||
case Contacts.Phones.TYPE_PAGER:
|
||||
stringType = "pager";
|
||||
break;
|
||||
case Contacts.Phones.TYPE_WORK:
|
||||
stringType = "work";
|
||||
break;
|
||||
case Contacts.Phones.TYPE_OTHER:
|
||||
default:
|
||||
stringType = "custom";
|
||||
break;
|
||||
}
|
||||
return stringType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -447,7 +817,7 @@ public class ContactAccessorSdk3_4 extends ContactAccessor {
|
||||
*/
|
||||
public boolean remove(String id) {
|
||||
int result = mApp.getContentResolver().delete(People.CONTENT_URI,
|
||||
"people._id = ?",
|
||||
PEOPLE_ID_EQUALS,
|
||||
new String[] {id});
|
||||
|
||||
return (result > 0) ? true : false;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,10 +43,10 @@ public class ContactManager extends Plugin {
|
||||
try {
|
||||
if (action.equals("search")) {
|
||||
JSONArray res = contactAccessor.search(args.getJSONArray(0), args.getJSONObject(1));
|
||||
return new PluginResult(status, res);
|
||||
return new PluginResult(status, res, "navigator.service.contacts.cast");
|
||||
}
|
||||
else if (action.equals("save")) {
|
||||
// TODO Coming soon!
|
||||
return new PluginResult(status, contactAccessor.save(args.getJSONObject(0)));
|
||||
}
|
||||
else if (action.equals("remove")) {
|
||||
if (contactAccessor.remove(args.getString(0))) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.TimeZone;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import android.content.Context;
|
||||
@@ -19,7 +20,7 @@ import android.telephony.TelephonyManager;
|
||||
|
||||
public class Device extends Plugin {
|
||||
|
||||
public static String phonegapVersion = "0.9.2"; // PhoneGap version
|
||||
public static String phonegapVersion = "0.9.3"; // PhoneGap version
|
||||
public static String platform = "Android"; // Device OS
|
||||
public static String uuid; // Device UUID
|
||||
|
||||
@@ -35,7 +36,7 @@ public class Device extends Plugin {
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
public void setContext(DroidGap ctx) {
|
||||
public void setContext(PhonegapActivity ctx) {
|
||||
super.setContext(ctx);
|
||||
Device.uuid = getUuid();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
package com.phonegap;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.os.StatFs;
|
||||
@@ -21,6 +26,8 @@ import android.util.Log;
|
||||
*/
|
||||
public class DirectoryManager {
|
||||
|
||||
private static final String LOG_TAG = "DirectoryManager";
|
||||
|
||||
/**
|
||||
* Determine if a file or directory exists.
|
||||
*
|
||||
@@ -36,7 +43,6 @@ public class DirectoryManager {
|
||||
File newPath = constructFilePaths(path.toString(), name);
|
||||
status = newPath.exists();
|
||||
}
|
||||
|
||||
// If no SD card
|
||||
else{
|
||||
status = false;
|
||||
@@ -215,8 +221,53 @@ public class DirectoryManager {
|
||||
*/
|
||||
private static File constructFilePaths (String file1, String file2) {
|
||||
File newPath;
|
||||
newPath = new File(file1+"/"+file2);
|
||||
if (file2.startsWith(file1)) {
|
||||
newPath = new File(file2);
|
||||
}
|
||||
else {
|
||||
newPath = new File(file1+"/"+file2);
|
||||
}
|
||||
return newPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will determine the file properties of the file specified
|
||||
* by the filePath. Creates a JSONObject with name, lastModifiedDate and
|
||||
* size properties.
|
||||
*
|
||||
* @param filePath the file to get the properties of
|
||||
* @return a JSONObject with the files properties
|
||||
*/
|
||||
protected static JSONObject getFile(String filePath) {
|
||||
File fp = new File(filePath);
|
||||
|
||||
JSONObject obj = new JSONObject();
|
||||
try {
|
||||
obj.put("name", fp.getAbsolutePath());
|
||||
obj.put("lastModifiedDate", new Date(fp.lastModified()).toString());
|
||||
obj.put("size", fp.length());
|
||||
}
|
||||
catch (JSONException e) {
|
||||
Log.e(LOG_TAG, e.getMessage(), e);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a JSONArray of file paths. Android's default
|
||||
* location where files can be written is Environment.getExternalStorageDirectory().
|
||||
* We are returning a array with one element so the interface can remain
|
||||
* consistent with BlackBerry as they have two areas where files can be
|
||||
* written.
|
||||
*
|
||||
* @return an array of file paths
|
||||
*/
|
||||
protected static JSONArray getRootPaths() {
|
||||
JSONArray retVal = new JSONArray();
|
||||
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
|
||||
retVal.put(path);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,10 @@ import java.nio.channels.FileChannel;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
@@ -82,6 +86,9 @@ public class FileUtils extends Plugin {
|
||||
else if (action.equals("createDirectory")) {
|
||||
boolean b = DirectoryManager.createDirectory(args.getString(0));
|
||||
return new PluginResult(status, b);
|
||||
}
|
||||
else if (action.equals("getRootPaths")) {
|
||||
return new PluginResult(status, DirectoryManager.getRootPaths());
|
||||
}
|
||||
else if (action.equals("readAsText")) {
|
||||
try {
|
||||
@@ -118,9 +125,10 @@ public class FileUtils extends Plugin {
|
||||
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR);
|
||||
}
|
||||
}
|
||||
else if (action.equals("truncate")) {
|
||||
else if (action.equals("write")) {
|
||||
try {
|
||||
this.truncateFile(args.getString(0), args.getLong(1));
|
||||
long fileSize = this.write(args.getString(0), args.getString(1), args.getLong(2));
|
||||
return new PluginResult(status, fileSize);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR);
|
||||
@@ -129,6 +137,22 @@ public class FileUtils extends Plugin {
|
||||
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR);
|
||||
}
|
||||
}
|
||||
else if (action.equals("truncate")) {
|
||||
try {
|
||||
long fileSize = this.truncateFile(args.getString(0), args.getLong(1));
|
||||
return new PluginResult(status, fileSize);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_READABLE_ERR);
|
||||
}
|
||||
}
|
||||
else if (action.equals("getFile")) {
|
||||
JSONObject obj = DirectoryManager.getFile(args.getString(0));
|
||||
return new PluginResult(status, obj);
|
||||
}
|
||||
return new PluginResult(status, result);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
@@ -169,14 +193,14 @@ public class FileUtils extends Plugin {
|
||||
* @throws FileNotFoundException, IOException
|
||||
*/
|
||||
public String readAsText(String filename, String encoding) throws FileNotFoundException, IOException {
|
||||
StringBuilder data = new StringBuilder();
|
||||
FileInputStream fis = new FileInputStream(filename);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(fis, encoding), 1024);
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
data.append(line);
|
||||
}
|
||||
return data.toString();
|
||||
byte[] bytes = new byte[1000];
|
||||
BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
int numRead = 0;
|
||||
while ((numRead = bis.read(bytes, 0, 1000)) >= 0) {
|
||||
bos.write(bytes, 0, numRead);
|
||||
}
|
||||
return new String(bos.toByteArray(), encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,7 +212,7 @@ public class FileUtils extends Plugin {
|
||||
*/
|
||||
public String readAsDataURL(String filename) throws FileNotFoundException, IOException {
|
||||
byte[] bytes = new byte[1000];
|
||||
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename), 1024);
|
||||
BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
int numRead = 0;
|
||||
while ((numRead = bis.read(bytes, 0, 1000)) >= 0) {
|
||||
@@ -196,8 +220,11 @@ public class FileUtils extends Plugin {
|
||||
}
|
||||
|
||||
// Determine content type from file name
|
||||
// TODO
|
||||
String contentType = "";
|
||||
MimeTypeMap map = MimeTypeMap.getSingleton();
|
||||
String contentType = map.getMimeTypeFromExtension(map.getFileExtensionFromUrl(filename));
|
||||
if (contentType == null && filename.startsWith("content")) {
|
||||
contentType = "image/jpeg";
|
||||
}
|
||||
|
||||
byte[] base64 = Base64.encodeBase64(bos.toByteArray());
|
||||
String data = "data:" + contentType + ";base64," + new String(base64);
|
||||
@@ -224,6 +251,23 @@ public class FileUtils extends Plugin {
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write contents of file.
|
||||
*
|
||||
* @param filename The name of the file.
|
||||
* @param data The contents of the file.
|
||||
* @param offset The position to begin writing the file.
|
||||
* @throws FileNotFoundException, IOException
|
||||
*/
|
||||
public long write(String filename, String data, long offset) throws FileNotFoundException, IOException {
|
||||
RandomAccessFile file = new RandomAccessFile(filename, "rw");
|
||||
file.seek(offset);
|
||||
file.writeBytes(data);
|
||||
file.close();
|
||||
|
||||
return data.length();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Truncate the file to size
|
||||
@@ -232,13 +276,32 @@ public class FileUtils extends Plugin {
|
||||
* @param size
|
||||
* @throws FileNotFoundException, IOException
|
||||
*/
|
||||
private void truncateFile(String filename, long size) throws FileNotFoundException, IOException {
|
||||
private long truncateFile(String filename, long size) throws FileNotFoundException, IOException {
|
||||
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
|
||||
|
||||
|
||||
if (raf.length() >= size) {
|
||||
FileChannel channel = raf.getChannel();
|
||||
channel.truncate(size);
|
||||
return size;
|
||||
}
|
||||
|
||||
return raf.length();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
@@ -19,7 +21,7 @@ import android.os.Bundle;
|
||||
*/
|
||||
public class GpsListener implements LocationListener {
|
||||
|
||||
private DroidGap mCtx; // DroidGap object
|
||||
private PhonegapActivity mCtx; // PhonegapActivity object
|
||||
|
||||
private LocationManager mLocMan; // Location manager object
|
||||
private GeoListener owner; // Geolistener object (parent)
|
||||
@@ -35,7 +37,7 @@ public class GpsListener implements LocationListener {
|
||||
* @param interval
|
||||
* @param m
|
||||
*/
|
||||
public GpsListener(DroidGap ctx, int interval, GeoListener m) {
|
||||
public GpsListener(PhonegapActivity ctx, int interval, GeoListener m) {
|
||||
this.owner = m;
|
||||
this.mCtx = ctx;
|
||||
this.mLocMan = (LocationManager) this.mCtx.getSystemService(Context.LOCATION_SERVICE);
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.location.LocationManager;
|
||||
@@ -15,7 +17,7 @@ import android.os.Bundle;
|
||||
|
||||
public class NetworkListener implements LocationListener {
|
||||
|
||||
private DroidGap mCtx; // DroidGap object
|
||||
private PhonegapActivity mCtx; // PhonegapActivity object
|
||||
|
||||
private LocationManager mLocMan; // Location manager object
|
||||
private GeoListener owner; // Geolistener object (parent)
|
||||
@@ -31,7 +33,7 @@ public class NetworkListener implements LocationListener {
|
||||
* @param interval
|
||||
* @param m
|
||||
*/
|
||||
public NetworkListener(DroidGap ctx, int interval, GeoListener m) {
|
||||
public NetworkListener(PhonegapActivity ctx, int interval, GeoListener m) {
|
||||
this.owner = m;
|
||||
this.mCtx = ctx;
|
||||
this.mLocMan = (LocationManager) this.mCtx.getSystemService(Context.LOCATION_SERVICE);
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
@@ -38,7 +39,7 @@ public class NetworkManager extends Plugin {
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
public void setContext(DroidGap ctx) {
|
||||
public void setContext(PhonegapActivity ctx) {
|
||||
super.setContext(ctx);
|
||||
this.sockMan = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.phonegap;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.PluginResult;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
@@ -172,7 +173,7 @@ public class Notification extends Plugin {
|
||||
*/
|
||||
public synchronized void alert(final String message, final String title, final String buttonLabel, final String callbackId) {
|
||||
|
||||
final DroidGap ctx = this.ctx;
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
final Notification notification = this;
|
||||
|
||||
Runnable runnable = new Runnable() {
|
||||
@@ -208,7 +209,7 @@ public class Notification extends Plugin {
|
||||
*/
|
||||
public synchronized void confirm(final String message, final String title, String buttonLabels, final String callbackId) {
|
||||
|
||||
final DroidGap ctx = this.ctx;
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
final Notification notification = this;
|
||||
final String[] fButtons = buttonLabels.split(",");
|
||||
|
||||
@@ -272,7 +273,7 @@ public class Notification extends Plugin {
|
||||
this.spinnerDialog = null;
|
||||
}
|
||||
final Notification notification = this;
|
||||
final DroidGap ctx = this.ctx;
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
notification.spinnerDialog = ProgressDialog.show(ctx, title , message, true, true,
|
||||
@@ -308,7 +309,7 @@ public class Notification extends Plugin {
|
||||
this.progressDialog = null;
|
||||
}
|
||||
final Notification notification = this;
|
||||
final DroidGap ctx = this.ctx;
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
notification.progressDialog = new ProgressDialog(ctx);
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
package com.phonegap;
|
||||
|
||||
public class SplashScreen {
|
||||
private final DroidGap gap;
|
||||
public SplashScreen(DroidGap gap) {
|
||||
this.gap = gap;
|
||||
}
|
||||
public void hide() {
|
||||
gap.runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
gap.hideSplashScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -160,24 +160,25 @@ public class Storage extends Plugin {
|
||||
*/
|
||||
public void processResults(Cursor cur, String tx_id) {
|
||||
|
||||
String result = "[]";
|
||||
// If query result has rows
|
||||
|
||||
if (cur.moveToFirst()) {
|
||||
JSONArray fullresult = new JSONArray();
|
||||
String key = "";
|
||||
String value = "";
|
||||
int colCount = cur.getColumnCount();
|
||||
|
||||
// Build up JSON result object for each row
|
||||
do {
|
||||
JSONObject result = new JSONObject();
|
||||
JSONObject row = new JSONObject();
|
||||
try {
|
||||
for (int i = 0; i < colCount; ++i) {
|
||||
key = cur.getColumnName(i);
|
||||
value = cur.getString(i).replace("\"", "\\\""); // must escape " with \" for JavaScript
|
||||
result.put(key, value);
|
||||
value = cur.getString(i);
|
||||
row.put(key, value);
|
||||
}
|
||||
|
||||
// Send row back to JavaScript
|
||||
this.sendJavascript("droiddb.addResult('" + result.toString() + "','" + tx_id + "');");
|
||||
fullresult.put(row);
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
@@ -185,9 +186,11 @@ public class Storage extends Plugin {
|
||||
|
||||
} while (cur.moveToNext());
|
||||
|
||||
result = fullresult.toString();
|
||||
}
|
||||
|
||||
// Let JavaScript know that there are no more rows
|
||||
this.sendJavascript("droiddb.completeQuery('" + tx_id + "');");
|
||||
this.sendJavascript("droiddb.completeQuery('" + tx_id + "', "+result+");");
|
||||
|
||||
}
|
||||
|
||||
|
||||
3
framework/src/com/phonegap/TempListener.java
Normal file → Executable file
3
framework/src/com/phonegap/TempListener.java
Normal file → Executable file
@@ -11,6 +11,7 @@ import java.util.List;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import com.phonegap.api.PhonegapActivity;
|
||||
import com.phonegap.api.Plugin;
|
||||
import com.phonegap.api.PluginResult;
|
||||
|
||||
@@ -37,7 +38,7 @@ public class TempListener extends Plugin implements SensorEventListener {
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
public void setContext(DroidGap ctx) {
|
||||
public void setContext(PhonegapActivity ctx) {
|
||||
super.setContext(ctx);
|
||||
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
package com.phonegap.api;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import com.phonegap.DroidGap;
|
||||
import android.content.Intent;
|
||||
import android.webkit.WebView;
|
||||
|
||||
@@ -43,7 +42,7 @@ public interface IPlugin {
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
void setContext(DroidGap ctx);
|
||||
void setContext(PhonegapActivity ctx);
|
||||
|
||||
/**
|
||||
* Sets the main View of the application, this is the WebView within which
|
||||
|
||||
43
framework/src/com/phonegap/api/PhonegapActivity.java
Executable file
43
framework/src/com/phonegap/api/PhonegapActivity.java
Executable file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* The Phonegap activity abstract class that is extended by DroidGap.
|
||||
* It is used to isolate plugin development, and remove dependency on entire Phonegap library.
|
||||
*/
|
||||
public abstract class PhonegapActivity extends Activity {
|
||||
|
||||
/**
|
||||
* Add a class that implements a service.
|
||||
*
|
||||
* @param serviceType
|
||||
* @param className
|
||||
*/
|
||||
abstract public void addService(String serviceType, String className);
|
||||
|
||||
/**
|
||||
* Send JavaScript statement back to JavaScript.
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
abstract public void sendJavascript(String statement);
|
||||
|
||||
/**
|
||||
* Launch an activity for which you would like a result when it finished. When this activity exits,
|
||||
* your onActivityResult() method will be called.
|
||||
*
|
||||
* @param command The command object
|
||||
* @param intent The intent to start
|
||||
* @param requestCode The request code that is passed to callback to identify the activity
|
||||
*/
|
||||
abstract public void startActivityForResult(Plugin command, Intent intent, int requestCode);
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
package com.phonegap.api;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import com.phonegap.DroidGap;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.webkit.WebView;
|
||||
|
||||
@@ -20,7 +20,7 @@ import android.webkit.WebView;
|
||||
public abstract class Plugin implements IPlugin {
|
||||
|
||||
public WebView webView; // WebView object
|
||||
public DroidGap ctx; // DroidGap object
|
||||
public PhonegapActivity ctx; // PhonegapActivity object
|
||||
|
||||
/**
|
||||
* Executes the request and returns PluginResult.
|
||||
@@ -48,7 +48,7 @@ public abstract class Plugin implements IPlugin {
|
||||
*
|
||||
* @param ctx The context of the main Activity.
|
||||
*/
|
||||
public void setContext(DroidGap ctx) {
|
||||
public void setContext(PhonegapActivity ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import android.webkit.WebView;
|
||||
import com.phonegap.DroidGap;
|
||||
|
||||
/**
|
||||
* PluginManager is exposed to JavaScript in the PhoneGap WebView.
|
||||
@@ -27,7 +26,7 @@ public final class PluginManager {
|
||||
private HashMap<String, Plugin> plugins = new HashMap<String,Plugin>();
|
||||
private HashMap<String, String> services = new HashMap<String,String>();
|
||||
|
||||
private final DroidGap ctx;
|
||||
private final PhonegapActivity ctx;
|
||||
private final WebView app;
|
||||
|
||||
/**
|
||||
@@ -36,7 +35,7 @@ public final class PluginManager {
|
||||
* @param app
|
||||
* @param ctx
|
||||
*/
|
||||
public PluginManager(WebView app, DroidGap ctx) {
|
||||
public PluginManager(WebView app, PhonegapActivity ctx) {
|
||||
this.ctx = ctx;
|
||||
this.app = app;
|
||||
}
|
||||
@@ -76,7 +75,7 @@ public final class PluginManager {
|
||||
}
|
||||
if (isPhoneGapPlugin(c)) {
|
||||
final Plugin plugin = this.addPlugin(clazz, c);
|
||||
final DroidGap ctx = this.ctx;
|
||||
final PhonegapActivity ctx = this.ctx;
|
||||
runAsync = async && !plugin.isSynch(action);
|
||||
if (runAsync) {
|
||||
// Run this on a different thread so that this one can return back to JS
|
||||
@@ -195,7 +194,7 @@ public final class PluginManager {
|
||||
try {
|
||||
Plugin plugin = (Plugin)clazz.newInstance();
|
||||
this.plugins.put(className, plugin);
|
||||
plugin.setContext((DroidGap)this.ctx);
|
||||
plugin.setContext(this.ctx);
|
||||
plugin.setView(this.app);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public class PluginResult {
|
||||
private final int status;
|
||||
private final String message;
|
||||
private boolean keepCallback = false;
|
||||
private String cast = null;
|
||||
|
||||
public PluginResult(Status status) {
|
||||
this.status = status.ordinal();
|
||||
@@ -22,7 +23,13 @@ public class PluginResult {
|
||||
|
||||
public PluginResult(Status status, String message) {
|
||||
this.status = status.ordinal();
|
||||
this.message = "'" + message + "'";
|
||||
this.message = JSONObject.quote(message);
|
||||
}
|
||||
|
||||
public PluginResult(Status status, JSONArray message, String cast) {
|
||||
this.status = status.ordinal();
|
||||
this.message = message.toString();
|
||||
this.cast = cast;
|
||||
}
|
||||
|
||||
public PluginResult(Status status, JSONArray message) {
|
||||
@@ -71,7 +78,15 @@ public class PluginResult {
|
||||
}
|
||||
|
||||
public String toSuccessCallbackString(String callbackId) {
|
||||
return "PhoneGap.callbackSuccess('"+callbackId+"', " + this.getJSONString() + " );";
|
||||
StringBuffer buf = new StringBuffer("");
|
||||
if (cast != null) {
|
||||
buf.append("var temp = "+cast+"("+this.getJSONString() + ");\n");
|
||||
buf.append("PhoneGap.callbackSuccess('"+callbackId+"',temp);");
|
||||
}
|
||||
else {
|
||||
buf.append("PhoneGap.callbackSuccess('"+callbackId+"',"+this.getJSONString()+");");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String toErrorCallbackString(String callbackId) {
|
||||
|
||||
3
lib/classic.rb
Normal file → Executable file
3
lib/classic.rb
Normal file → Executable file
@@ -126,8 +126,7 @@ class Classic
|
||||
end
|
||||
end
|
||||
|
||||
# this is so fucking unholy yet oddly beautiful
|
||||
# not sure if I should thank Ruby or apologize for this abusive use of string interpolation
|
||||
# create java source file
|
||||
def write_java
|
||||
j = "
|
||||
package #{ @pkg };
|
||||
|
||||
20
lib/update.rb
Normal file → Executable file
20
lib/update.rb
Normal file → Executable file
@@ -15,9 +15,9 @@ class Update
|
||||
end
|
||||
|
||||
# removes local.properties and recreates based on android_sdk_path
|
||||
# then generates framework/phonegap.jar
|
||||
# then generates framework/phonegap.jar & framework/assets/www/phonegap.js
|
||||
def build_jar
|
||||
puts "Building the JAR..."
|
||||
puts "Building the JAR and combining JS files..."
|
||||
%w(local.properties phonegap.js phonegap.jar).each do |f|
|
||||
FileUtils.rm File.join(@framework_dir, f) if File.exists? File.join(@framework_dir, f)
|
||||
end
|
||||
@@ -32,23 +32,13 @@ class Update
|
||||
# copies stuff from framework into the project
|
||||
# TODO need to allow for www import inc icon
|
||||
def copy_libs
|
||||
puts "Copying over libraries and assets and creating phonegap.js..."
|
||||
puts "Copying over libraries and assets..."
|
||||
|
||||
FileUtils.mkdir_p File.join(@path, "libs")
|
||||
FileUtils.cp File.join(@framework_dir, "phonegap.jar"), File.join(@path, "libs")
|
||||
|
||||
# concat JS and put into www folder.
|
||||
js_dir = File.join(@framework_dir, "assets", "js")
|
||||
|
||||
phonegapjs = IO.read(File.join(js_dir, 'phonegap.js.base'))
|
||||
|
||||
Dir.new(js_dir).entries.each do |script|
|
||||
next if script[0].chr == "." or script == "phonegap.js.base"
|
||||
phonegapjs << IO.read(File.join(js_dir, script))
|
||||
phonegapjs << "\n\n"
|
||||
end
|
||||
|
||||
File.open(File.join(@path, "assets", "www", "phonegap.js"), 'w') {|f| f.write(phonegapjs) }
|
||||
FileUtils.mkdir_p File.join(@path, "assets", "www")
|
||||
FileUtils.cp File.join(@framework_dir, "assets", "www", "phonegap.js"), File.join(@path, "assets", "www")
|
||||
end
|
||||
#
|
||||
end
|
||||
31
util/yuicompressor/LICENSE
Executable file
31
util/yuicompressor/LICENSE
Executable file
@@ -0,0 +1,31 @@
|
||||
YUI is issued by Yahoo! under the BSD License below.
|
||||
|
||||
Copyright (c) 2010, Yahoo! Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms, with or
|
||||
without modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of Yahoo! Inc. nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission of Yahoo! Inc.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
http://developer.yahoo.com/yui/license.html
|
||||
|
||||
140
util/yuicompressor/README
Executable file
140
util/yuicompressor/README
Executable file
@@ -0,0 +1,140 @@
|
||||
==============================================================================
|
||||
YUI Compressor
|
||||
==============================================================================
|
||||
|
||||
NAME
|
||||
|
||||
YUI Compressor - The Yahoo! JavaScript and CSS Compressor
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
Usage: java -jar yuicompressor-x.y.z.jar [options] [input file]
|
||||
|
||||
Global Options
|
||||
-h, --help Displays this information
|
||||
--type <js|css> Specifies the type of the input file
|
||||
--charset <charset> Read the input file using <charset>
|
||||
--line-break <column> Insert a line break after the specified column number
|
||||
-v, --verbose Display informational messages and warnings
|
||||
-o <file> Place the output into <file>. Defaults to stdout.
|
||||
|
||||
JavaScript Options
|
||||
--nomunge Minify only, do not obfuscate
|
||||
--preserve-semi Preserve all semicolons
|
||||
--disable-optimizations Disable all micro optimizations
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
The YUI Compressor is a JavaScript compressor which, in addition to removing
|
||||
comments and white-spaces, obfuscates local variables using the smallest
|
||||
possible variable name. This obfuscation is safe, even when using constructs
|
||||
such as 'eval' or 'with' (although the compression is not optimal is those
|
||||
cases) Compared to jsmin, the average savings is around 20%.
|
||||
|
||||
The YUI Compressor is also able to safely compress CSS files. The decision
|
||||
on which compressor is being used is made on the file extension (js or css)
|
||||
|
||||
GLOBAL OPTIONS
|
||||
|
||||
-h, --help
|
||||
Prints help on how to use the YUI Compressor
|
||||
|
||||
--line-break
|
||||
Some source control tools don't like files containing lines longer than,
|
||||
say 8000 characters. The linebreak option is used in that case to split
|
||||
long lines after a specific column. It can also be used to make the code
|
||||
more readable, easier to debug (especially with the MS Script Debugger)
|
||||
Specify 0 to get a line break after each semi-colon in JavaScript, and
|
||||
after each rule in CSS.
|
||||
|
||||
--type js|css
|
||||
The type of compressor (JavaScript or CSS) is chosen based on the
|
||||
extension of the input file name (.js or .css) This option is required
|
||||
if no input file has been specified. Otherwise, this option is only
|
||||
required if the input file extension is neither 'js' nor 'css'.
|
||||
|
||||
--charset character-set
|
||||
If a supported character set is specified, the YUI Compressor will use it
|
||||
to read the input file. Otherwise, it will assume that the platform's
|
||||
default character set is being used. The output file is encoded using
|
||||
the same character set.
|
||||
|
||||
-o outfile
|
||||
Place output in file outfile. If not specified, the YUI Compressor will
|
||||
default to the standard output, which you can redirect to a file.
|
||||
|
||||
-v, --verbose
|
||||
Display informational messages and warnings.
|
||||
|
||||
JAVASCRIPT ONLY OPTIONS
|
||||
|
||||
--nomunge
|
||||
Minify only. Do not obfuscate local symbols.
|
||||
|
||||
--preserve-semi
|
||||
Preserve unnecessary semicolons (such as right before a '}') This option
|
||||
is useful when compressed code has to be run through JSLint (which is the
|
||||
case of YUI for example)
|
||||
|
||||
--disable-optimizations
|
||||
Disable all the built-in micro optimizations.
|
||||
|
||||
NOTES
|
||||
|
||||
+ If no input file is specified, it defaults to stdin.
|
||||
|
||||
+ The YUI Compressor requires Java version >= 1.4.
|
||||
|
||||
+ It is possible to prevent a local variable, nested function or function
|
||||
argument from being obfuscated by using "hints". A hint is a string that
|
||||
is located at the very beginning of a function body like so:
|
||||
|
||||
function fn (arg1, arg2, arg3) {
|
||||
"arg2:nomunge, localVar:nomunge, nestedFn:nomunge";
|
||||
|
||||
...
|
||||
var localVar;
|
||||
...
|
||||
|
||||
function nestedFn () {
|
||||
....
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
The hint itself disappears from the compressed file.
|
||||
|
||||
+ C-style comments starting with /*! are preserved. This is useful with
|
||||
comments containing copyright/license information. For example:
|
||||
|
||||
/*!
|
||||
* TERMS OF USE - EASING EQUATIONS
|
||||
* Open source under the BSD License.
|
||||
* Copyright 2001 Robert Penner All rights reserved.
|
||||
*/
|
||||
|
||||
becomes:
|
||||
|
||||
/*
|
||||
* TERMS OF USE - EASING EQUATIONS
|
||||
* Open source under the BSD License.
|
||||
* Copyright 2001 Robert Penner All rights reserved.
|
||||
*/
|
||||
|
||||
AUTHOR
|
||||
|
||||
The YUI Compressor was written and is maintained by:
|
||||
Julien Lecomte <jlecomte@yahoo-inc.com>
|
||||
The CSS portion is a port of Isaac Schlueter's cssmin utility.
|
||||
|
||||
COPYRIGHT
|
||||
|
||||
Copyright (c) 2007-2009, Yahoo! Inc. All rights reserved.
|
||||
|
||||
LICENSE
|
||||
|
||||
All code specific to YUI Compressor is issued under a BSD license.
|
||||
YUI Compressor extends and implements code from Mozilla's Rhino project.
|
||||
Rhino is issued under the Mozilla Public License (MPL), and MPL applies
|
||||
to the Rhino source and binaries that are distributed with YUI Compressor.
|
||||
BIN
util/yuicompressor/yuicompressor-2.4.2.jar
Executable file
BIN
util/yuicompressor/yuicompressor-2.4.2.jar
Executable file
Binary file not shown.
Reference in New Issue
Block a user