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

View File

@ -119,6 +119,25 @@ function check_network() {
confirm('Connection type:\n ' + states[networkState]); 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() { function init() {
// the next line makes it impossible to see Contacts on the HTC Evo since it // the next line makes it impossible to see Contacts on the HTC Evo since it
// doesn't have a scroll button // 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]); 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. * Options to customize the HTTP request used to upload files.
* @constructor * @constructor

View File

@ -1,7 +1,7 @@
<html> <html>
<head> <head>
<title></title> <title></title>
<script src="phonegap-1.2.0.js"></script> <script src="phonegap-1.3.0.js"></script>
</head> </head>
<body> <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_IMAGE = 1; // Constant for capture image
private static final int CAPTURE_VIDEO = 2; // Constant for capture video private static final int CAPTURE_VIDEO = 2; // Constant for capture video
private static final String LOG_TAG = "Capture"; 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 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 long limit; // the number of pics/vids/clips to take
private double duration; // optional duration parameter for video recording 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); uri = this.ctx.getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException ex) { } catch (UnsupportedOperationException ex) {
LOG.d(LOG_TAG, "Can't write to internal media storage."); 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; return;
} }
} }
@ -290,7 +297,7 @@ public class Capture extends Plugin {
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
this.fail("Error capturing image."); this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image."));
} }
} else if (requestCode == CAPTURE_VIDEO) { } else if (requestCode == CAPTURE_VIDEO) {
// Get the uri of the video clip // Get the uri of the video clip
@ -315,7 +322,7 @@ public class Capture extends Plugin {
} }
// user canceled the action // user canceled the action
else { else {
this.fail("Canceled."); this.fail(createErrorObject(CAPTURE_NO_MEDIA_FILES, "Canceled."));
} }
} }
// If something else // If something else
@ -326,7 +333,7 @@ public class Capture extends Plugin {
} }
// something bad happened // something bad happened
else { else {
this.fail("Did not complete!"); this.fail(createErrorObject(CAPTURE_NO_MEDIA_FILES, "Did not complete!"));
} }
} }
} }
@ -369,13 +376,24 @@ public class Capture extends Plugin {
return obj; 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. * Send error message to JavaScript.
* *
* @param err * @param err
*/ */
public void fail(String err) { public void fail(JSONObject err) {
this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId); this.error(new PluginResult(PluginResult.Status.ERROR, err), this.callbackId);
} }
} }

View File

@ -1054,7 +1054,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
if (organizations != null) { if (organizations != null) {
for (int i=0; i<organizations.length(); i++) { for (int i=0; i<organizations.length(); i++) {
JSONObject org = (JSONObject)organizations.get(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 // This is a new organization so do a DB insert
if (orgId==null) { if (orgId==null) {
ContentValues contentValues = new ContentValues(); ContentValues contentValues = new ContentValues();
@ -1094,7 +1094,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
if (ims != null) { if (ims != null) {
for (int i=0; i<ims.length(); i++) { for (int i=0; i<ims.length(); i++) {
JSONObject im = (JSONObject)ims.get(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 // This is a new IM so do a DB insert
if (imId==null) { if (imId==null) {
ContentValues contentValues = new ContentValues(); ContentValues contentValues = new ContentValues();
@ -1150,7 +1150,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
if (websites != null) { if (websites != null) {
for (int i=0; i<websites.length(); i++) { for (int i=0; i<websites.length(); i++) {
JSONObject website = (JSONObject)websites.get(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 // This is a new website so do a DB insert
if (websiteId==null) { if (websiteId==null) {
ContentValues contentValues = new ContentValues(); ContentValues contentValues = new ContentValues();
@ -1603,10 +1603,8 @@ public class ContactAccessorSdk5 extends ContactAccessor {
} }
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(LOG_TAG, e.getMessage(), e); Log.e(LOG_TAG, e.getMessage(), e);
newId = null;
} catch (OperationApplicationException e) { } catch (OperationApplicationException e) {
Log.e(LOG_TAG, e.getMessage(), e); Log.e(LOG_TAG, e.getMessage(), e);
newId = null;
} }
return newId; 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 class Device extends Plugin {
public static final String TAG = "Device"; 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 platform = "Android"; // Device OS
public static String uuid; // Device UUID public static String uuid; // Device UUID

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -18,8 +18,8 @@
*/ */
package com.phonegap; package com.phonegap;
import java.io.EOFException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
@ -56,27 +56,25 @@ public class HttpHandler {
return entity; 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 * writes a HTTP entity to the specified filename and location on disk
*/ */
{ {
int i=0; int i=0;
String FilePath="/sdcard/" + file; String FilePath="/sdcard/" + file;
try { InputStream in = entity.getContent();
InputStream in = entity.getContent(); byte buff[] = new byte[1024];
byte buff[] = new byte[1024]; FileOutputStream out=
FileOutputStream out= new FileOutputStream(FilePath);
new FileOutputStream(FilePath); do {
do { int numread = in.read(buff);
int numread = in.read(buff); if (numread <= 0)
if (numread <= 0) break;
break; out.write(buff, 0, numread);
out.write(buff, 0, numread); i++;
i++; } while (true);
} while (true); out.flush();
out.flush(); out.close();
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 */
}
}
}