Merge branch 'master' of github.com:callback/callback-android

This commit is contained in:
Joe Bowser 2012-01-04 16:02:03 -08:00
commit cc04b54adf
13 changed files with 1247 additions and 1285 deletions

View File

@ -1 +1 @@
1.2.0
1.3.0

View File

@ -4,8 +4,8 @@
<meta name="viewport" content="width=320; user-scalable=no" />
<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-1.2.0.js"></script>
<link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="phonegap-1.3.0.js"></script>
<script type="text/javascript" charset="utf-8" src="main.js"></script>
</head>
@ -29,8 +29,12 @@
<a href="#" class="btn large" onclick="beep();">Beep</a>
<a href="#" class="btn large" onclick="vibrate();">Vibrate</a>
<a href="#" class="btn large" onclick="show_pic();">Get a Picture</a>
<a href="#" class="btn large" onclick="get_contacts();">Get Phone's Contacts</a>
<a href="#" class="btn large" onclick="check_network();">Check Network</a>
<a href="#" class="btn large" onclick="get_contacts();return false;">Get Phone's Contacts</a>
<a href="#" class="btn large" onclick="check_network();return false;">Check Network</a>
<dl>
<dt>Compass Heading:</dt><dd id="h">Off</dd>
</dl>
<a href="#" class="btn large" onclick="toggleCompass();return false;">Toggle Compass</a>
<div id="viewport" class="viewport" style="display: none;">
<img style="width:60px;height:60px" id="test_img" src="" />
</div>

View File

@ -119,6 +119,25 @@ function check_network() {
confirm('Connection type:\n ' + states[networkState]);
}
var watchID = null;
function updateHeading(h) {
document.getElementById('h').innerHTML = h.magneticHeading;
}
function toggleCompass() {
if (watchID !== null) {
navigator.compass.clearWatch(watchID);
watchID = null;
updateHeading({ magneticHeading : "Off"});
} else {
var options = { frequency: 1000 };
watchID = navigator.compass.watchHeading(updateHeading, function(e) {
alert('Compass Error: ' + e.code);
}, options);
}
}
function init() {
// the next line makes it impossible to see Contacts on the HTC Evo since it
// doesn't have a scroll button

View File

@ -83,6 +83,17 @@ FileTransfer.prototype.upload = function(filePath, server, successCallback, erro
PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'upload', [filePath, server, fileKey, fileName, mimeType, params, debug, chunkedMode]);
};
/**
* Downloads a file form a given URL and saves it to the specified directory.
* @param source {String} URL of the server to receive the file
* @param target {String} Full path of the file on the device
* @param successCallback (Function} Callback to be invoked when upload has completed
* @param errorCallback {Function} Callback to be invoked upon error
*/
FileTransfer.prototype.download = function(source, target, successCallback, errorCallback) {
PhoneGap.exec(successCallback, errorCallback, 'FileTransfer', 'download', [source, target]);
};
/**
* Options to customize the HTTP request used to upload files.
* @constructor

View File

@ -1,7 +1,7 @@
<html>
<head>
<title></title>
<script src="phonegap-1.2.0.js"></script>
<script src="phonegap-1.3.0.js"></script>
</head>
<body>

View File

@ -49,6 +49,13 @@ public class Capture extends Plugin {
private static final int CAPTURE_IMAGE = 1; // Constant for capture image
private static final int CAPTURE_VIDEO = 2; // Constant for capture video
private static final String LOG_TAG = "Capture";
private static final int CAPTURE_INTERNAL_ERR = 0;
private static final int CAPTURE_APPLICATION_BUSY = 1;
private static final int CAPTURE_INVALID_ARGUMENT = 2;
private static final int CAPTURE_NO_MEDIA_FILES = 3;
private static final int CAPTURE_NOT_SUPPORTED = 20;
private String callbackId; // The ID of the callback to be invoked with our result
private long limit; // the number of pics/vids/clips to take
private double duration; // optional duration parameter for video recording
@ -260,7 +267,7 @@ public class Capture extends Plugin {
uri = this.ctx.getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException ex) {
LOG.d(LOG_TAG, "Can't write to internal media storage.");
this.fail("Error capturing image - no media storage found.");
this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image - no media storage found."));
return;
}
}
@ -290,7 +297,7 @@ public class Capture extends Plugin {
}
} catch (IOException e) {
e.printStackTrace();
this.fail("Error capturing image.");
this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image."));
}
} else if (requestCode == CAPTURE_VIDEO) {
// Get the uri of the video clip
@ -315,7 +322,7 @@ public class Capture extends Plugin {
}
// user canceled the action
else {
this.fail("Canceled.");
this.fail(createErrorObject(CAPTURE_NO_MEDIA_FILES, "Canceled."));
}
}
// If something else
@ -326,7 +333,7 @@ public class Capture extends Plugin {
}
// something bad happened
else {
this.fail("Did not complete!");
this.fail(createErrorObject(CAPTURE_NO_MEDIA_FILES, "Did not complete!"));
}
}
}
@ -370,12 +377,23 @@ public class Capture extends Plugin {
return obj;
}
private JSONObject createErrorObject(int code, String message) {
JSONObject obj = new JSONObject();
try {
obj.put("code", code);
obj.put("message", message);
} catch (JSONException e) {
// This will never happen
}
return obj;
}
/**
* Send error message to JavaScript.
*
* @param err
*/
public void fail(String err) {
public void fail(JSONObject err) {
this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId);
}
}

View File

@ -1054,7 +1054,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
if (organizations != null) {
for (int i=0; i<organizations.length(); i++) {
JSONObject org = (JSONObject)organizations.get(i);
String orgId = getJsonString(org, "id");;
String orgId = getJsonString(org, "id");
// This is a new organization so do a DB insert
if (orgId==null) {
ContentValues contentValues = new ContentValues();
@ -1094,7 +1094,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
if (ims != null) {
for (int i=0; i<ims.length(); i++) {
JSONObject im = (JSONObject)ims.get(i);
String imId = getJsonString(im, "id");;
String imId = getJsonString(im, "id");
// This is a new IM so do a DB insert
if (imId==null) {
ContentValues contentValues = new ContentValues();
@ -1150,7 +1150,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
if (websites != null) {
for (int i=0; i<websites.length(); i++) {
JSONObject website = (JSONObject)websites.get(i);
String websiteId = getJsonString(website, "id");;
String websiteId = getJsonString(website, "id");
// This is a new website so do a DB insert
if (websiteId==null) {
ContentValues contentValues = new ContentValues();
@ -1603,10 +1603,8 @@ public class ContactAccessorSdk5 extends ContactAccessor {
}
} catch (RemoteException e) {
Log.e(LOG_TAG, e.getMessage(), e);
newId = null;
} catch (OperationApplicationException e) {
Log.e(LOG_TAG, e.getMessage(), e);
newId = null;
}
return newId;
}

2
framework/src/com/phonegap/Device.java Executable file → Normal file
View File

@ -37,7 +37,7 @@ import android.telephony.TelephonyManager;
public class Device extends Plugin {
public static final String TAG = "Device";
public static String phonegapVersion = "1.2.0"; // PhoneGap version
public static String phonegapVersion = "1.3.0"; // PhoneGap version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID

View File

@ -19,7 +19,6 @@
package com.phonegap;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.ArrayList;
import java.util.Stack;
import java.util.regex.Pattern;
@ -30,7 +29,6 @@ import java.io.IOException;
import org.json.JSONArray;
import org.json.JSONException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
@ -43,12 +41,10 @@ import android.content.res.Configuration;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.media.AudioManager;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu;
@ -277,8 +273,6 @@ public class DroidGap extends PhonegapActivity {
ViewGroup.LayoutParams.FILL_PARENT,
1.0F));
WebViewReflect.checkCompatibility();
this.appView.setWebChromeClient(new GapClient(DroidGap.this));
this.setWebViewClient(this.appView, new GapViewClient(this));
@ -313,10 +307,10 @@ public class DroidGap extends PhonegapActivity {
settings.setDatabasePath(databasePath);
// Enable DOM storage
WebViewReflect.setDomStorage(settings);
settings.setDomStorageEnabled(true);
// Enable built-in geolocation
WebViewReflect.setGeolocationEnabled(settings, true);
settings.setGeolocationEnabled(true);
// Add web view but make it invisible while loading URL
this.appView.setVisibility(View.INVISIBLE);
@ -325,7 +319,6 @@ public class DroidGap extends PhonegapActivity {
// Clear cancel flag
this.cancelLoadUrl = false;
}
/**
@ -1716,15 +1709,19 @@ public class DroidGap extends PhonegapActivity {
// If the height as gotten bigger then we will assume the soft keyboard has
// gone away.
else if (height > oldHeight) {
if (callbackServer != null) {
LOG.v(TAG, "Throw hide keyboard event");
callbackServer.sendJavascript("PhoneGap.fireDocumentEvent('hidekeyboard');");
}
}
// If the height as gotten smaller then we will assume the soft keyboard has
// been displayed.
else if (height < oldHeight) {
if (callbackServer != null) {
LOG.v(TAG, "Throw show keyboard event");
callbackServer.sendJavascript("PhoneGap.fireDocumentEvent('showkeyboard');");
}
}
// Update the old height for the next event
oldHeight = height;

View File

@ -20,8 +20,10 @@ package com.phonegap;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
@ -69,17 +71,19 @@ public class FileTransfer extends Plugin {
*/
@Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
String file = null;
String server = null;
String source = null;
String target = null;
try {
file = args.getString(0);
server = args.getString(1);
source = args.getString(0);
target = args.getString(1);
}
catch (JSONException e) {
Log.d(LOG_TAG, "Missing filename or server name");
return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing filename or server name");
Log.d(LOG_TAG, "Missing source or target");
return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing source or target");
}
try {
if (action.equals("upload")) {
// Setup the options
String fileKey = null;
String fileName = null;
@ -88,35 +92,35 @@ public class FileTransfer extends Plugin {
fileKey = getArgument(args, 2, "file");
fileName = getArgument(args, 3, "image.jpg");
mimeType = getArgument(args, 4, "image/jpeg");
try {
JSONObject params = args.optJSONObject(5);
boolean trustEveryone = args.optBoolean(6);
boolean chunkedMode = args.getBoolean(7);
if (action.equals("upload")) {
FileUploadResult r = upload(file, server, fileKey, fileName, mimeType, params, trustEveryone, chunkedMode);
boolean chunkedMode = args.optBoolean(7);
FileUploadResult r = upload(source, target, fileKey, fileName, mimeType, params, trustEveryone, chunkedMode);
Log.d(LOG_TAG, "****** About to return a result from upload");
return new PluginResult(PluginResult.Status.OK, r.toJSONObject());
} else if (action.equals("download")) {
JSONObject r = download(source, target);
Log.d(LOG_TAG, "****** About to return a result from download");
return new PluginResult(PluginResult.Status.OK, r, "window.localFileSystem._castEntry");
} else {
return new PluginResult(PluginResult.Status.INVALID_ACTION);
}
} catch (FileNotFoundException e) {
Log.e(LOG_TAG, e.getMessage(), e);
JSONObject error = createFileUploadError(FILE_NOT_FOUND_ERR);
JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (IllegalArgumentException e) {
Log.e(LOG_TAG, e.getMessage(), e);
JSONObject error = createFileUploadError(INVALID_URL_ERR);
JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (SSLException e) {
Log.e(LOG_TAG, e.getMessage(), e);
Log.d(LOG_TAG, "Got my ssl exception!!!");
JSONObject error = createFileUploadError(CONNECTION_ERR);
JSONObject error = createFileTransferError(CONNECTION_ERR, source, target);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (IOException e) {
Log.e(LOG_TAG, e.getMessage(), e);
JSONObject error = createFileUploadError(CONNECTION_ERR);
JSONObject error = createFileTransferError(CONNECTION_ERR, source, target);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
@ -173,11 +177,13 @@ public class FileTransfer extends Plugin {
* @param errorCode the error
* @return JSONObject containing the error
*/
private JSONObject createFileUploadError(int errorCode) {
private JSONObject createFileTransferError(int errorCode, String source, String target) {
JSONObject error = null;
try {
error = new JSONObject();
error.put("code", errorCode);
error.put("source", source);
error.put("target", target);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
}
@ -362,6 +368,54 @@ public class FileTransfer extends Plugin {
return result;
}
/**
* Downloads a file form a given URL and saves it to the specified directory.
*
* @param source URL of the server to receive the file
* @param target Full path of the file on the file system
* @return JSONObject the downloaded file
*/
public JSONObject download(String source, String target) throws IOException {
try {
File file = new File(target);
// create needed directories
file.getParentFile().mkdirs();
// connect to server
URL url = new URL(source);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.connect();
Log.d(LOG_TAG, "Download file:" + url);
InputStream inputStream = connection.getInputStream();
byte[] buffer = new byte[1024];
int bytesRead = 0;
FileOutputStream outputStream = new FileOutputStream(file);
// write bytes to file
while ( (bytesRead = inputStream.read(buffer)) > 0 ) {
outputStream.write(buffer,0, bytesRead);
}
outputStream.close();
Log.d(LOG_TAG, "Saved file: " + target);
// create FileEntry object
FileUtils fileUtil = new FileUtils();
return fileUtil.getEntry(file);
} catch (Exception e) {
Log.d(LOG_TAG, e.getMessage(), e);
throw new IOException("Error while downloading");
}
}
/**
* Get an input stream based on file path or content:// uri
*
@ -375,7 +429,12 @@ public class FileTransfer extends Plugin {
return ctx.getContentResolver().openInputStream(uri);
}
else if (path.startsWith("file://")) {
int question = path.indexOf("?");
if (question == -1) {
return new FileInputStream(path.substring(7));
} else {
return new FileInputStream(path.substring(7, question));
}
}
else {
return new FileInputStream(path);

View File

@ -322,14 +322,13 @@ public class FileUtils extends Plugin {
* @param newName for the file directory to be called, if null use existing file name
* @param move if false do a copy, if true do a move
* @return a Entry object
* @throws FileExistsException
* @throws NoModificationAllowedException
* @throws IOException
* @throws InvalidModificationException
* @throws EncodingException
* @throws JSONException
*/
private JSONObject transferTo(String fileName, JSONObject newParent, String newName, boolean move) throws JSONException, FileExistsException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException {
private JSONObject transferTo(String fileName, JSONObject newParent, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException {
// Check for invalid file name
if (newName != null && newName.contains(":")) {
throw new EncodingException("Bad file name");
@ -528,10 +527,9 @@ public class FileUtils extends Plugin {
* @return a DirectoryEntry object
* @throws JSONException
* @throws IOException
* @throws NoModificationAllowedException
* @throws InvalidModificationException
*/
private JSONObject moveDirectory(File srcDir, File destinationDir) throws JSONException, FileExistsException, NoModificationAllowedException, InvalidModificationException {
private JSONObject moveDirectory(File srcDir, File destinationDir) throws JSONException, InvalidModificationException {
// Renaming a file to an existing directory should fail
if (destinationDir.exists() && destinationDir.isFile()) {
throw new InvalidModificationException("Can't rename a file to a directory");
@ -838,7 +836,7 @@ public class FileUtils extends Plugin {
* @return
* @throws JSONException
*/
private JSONObject getEntry(File file) throws JSONException {
public JSONObject getEntry(File file) throws JSONException {
JSONObject entry = new JSONObject();
entry.put("isFile", file.isFile());

View File

@ -18,8 +18,8 @@
*/
package com.phonegap;
import java.io.EOFException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
@ -56,14 +56,13 @@ public class HttpHandler {
return entity;
}
private void writeToDisk(HttpEntity entity, String file) throws EOFException
private void writeToDisk(HttpEntity entity, String file) throws IllegalStateException, IOException
/**
* writes a HTTP entity to the specified filename and location on disk
*/
{
int i=0;
String FilePath="/sdcard/" + file;
try {
InputStream in = entity.getContent();
byte buff[] = new byte[1024];
FileOutputStream out=
@ -77,6 +76,5 @@ public class HttpHandler {
} while (true);
out.flush();
out.close();
} catch (Exception e) { e.printStackTrace(); }
}
}

View File

@ -1,140 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package com.phonegap;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.webkit.WebSettings;
public class WebViewReflect {
private static Method mWebSettings_setDatabaseEnabled;
private static Method mWebSettings_setDatabasePath;
private static Method mWebSettings_setDomStorageEnabled;
private static Method mWebSettings_setGeolocationEnabled;
static
{
checkCompatibility();
}
private static void setDatabaseEnabled(boolean e) throws IOException {
try
{
mWebSettings_setDatabaseEnabled.invoke(e);
}
catch (InvocationTargetException ite) {
/* unpack original exception when possible */
Throwable cause = ite.getCause();
if (cause instanceof IOException) {
throw (IOException) cause;
} else if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
} else {
/* unexpected checked exception; wrap and re-throw */
throw new RuntimeException(ite);
}
} catch (IllegalAccessException ie) {
System.err.println("unexpected " + ie);
}
}
public static void checkCompatibility() {
try {
mWebSettings_setDatabaseEnabled = WebSettings.class.getMethod(
"setDatabaseEnabled", new Class[] { boolean.class } );
mWebSettings_setDatabasePath = WebSettings.class.getMethod(
"setDatabasePath", new Class[] { String.class });
mWebSettings_setDomStorageEnabled = WebSettings.class.getMethod(
"setDomStorageEnabled", new Class[] { boolean.class });
mWebSettings_setGeolocationEnabled = WebSettings.class.getMethod(
"setGeolocationEnabled", new Class[] { boolean.class });
/* success, this is a newer device */
} catch (NoSuchMethodException nsme) {
/* failure, must be older device */
}
}
public static void setStorage(WebSettings setting, boolean enable, String path) {
if (mWebSettings_setDatabaseEnabled != null) {
/* feature is supported */
try {
mWebSettings_setDatabaseEnabled.invoke(setting, enable);
mWebSettings_setDatabasePath.invoke(setting, path);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
/* feature not supported, do something else */
}
}
public static void setGeolocationEnabled(WebSettings setting, boolean enable) {
if (mWebSettings_setGeolocationEnabled != null) {
/* feature is supported */
try {
mWebSettings_setGeolocationEnabled.invoke(setting, enable);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
/* feature not supported, do something else */
System.out.println("Native Geolocation not supported - we're ok");
}
}
public static void setDomStorage(WebSettings setting)
{
if(mWebSettings_setDomStorageEnabled != null)
{
/* feature is supported */
try {
mWebSettings_setDomStorageEnabled.invoke(setting, true);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
/* feature not supported, do something else */
}
}
}