This commit is contained in:
Bryce Curtis 2012-05-14 21:49:30 -05:00
parent f3e70c79eb
commit c8fafa6bbd
36 changed files with 5650 additions and 5225 deletions

View File

@ -18,6 +18,7 @@
*/ */
package com.phonegap.api; package com.phonegap.api;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.api.CordovaInterface; import org.apache.cordova.api.CordovaInterface;
import android.webkit.WebView; import android.webkit.WebView;
@ -31,6 +32,6 @@ import android.webkit.WebView;
public class PluginManager extends org.apache.cordova.api.PluginManager { public class PluginManager extends org.apache.cordova.api.PluginManager {
public PluginManager(WebView app, CordovaInterface ctx) throws Exception { public PluginManager(WebView app, CordovaInterface ctx) throws Exception {
super(app, ctx); super((CordovaWebView) app, ctx);
} }
} }

View File

@ -27,7 +27,6 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.hardware.Sensor; import android.hardware.Sensor;
import android.hardware.SensorEvent; import android.hardware.SensorEvent;
import android.hardware.SensorEventListener; import android.hardware.SensorEventListener;
@ -40,14 +39,14 @@ import android.content.Context;
*/ */
public class AccelListener extends Plugin implements SensorEventListener { public class AccelListener extends Plugin implements SensorEventListener {
public static int STOPPED = 0; public static int STOPPED = 0;
public static int STARTING = 1; public static int STARTING = 1;
public static int RUNNING = 2; public static int RUNNING = 2;
public static int ERROR_FAILED_TO_START = 3; public static int ERROR_FAILED_TO_START = 3;
public float TIMEOUT = 30000; // Timeout in msec to shut off listener public float TIMEOUT = 30000; // Timeout in msec to shut off listener
float x,y,z; // most recent acceleration values float x, y, z; // most recent acceleration values
long timestamp; // time of most recent value long timestamp; // time of most recent value
int status; // status of listener int status; // status of listener
long lastAccessTime; // time the value was last retrieved long lastAccessTime; // time the value was last retrieved
@ -64,128 +63,129 @@ public class AccelListener extends Plugin implements SensorEventListener {
this.z = 0; this.z = 0;
this.timestamp = 0; this.timestamp = 0;
this.setStatus(AccelListener.STOPPED); this.setStatus(AccelListener.STOPPED);
}
/**
* Sets the context of the Command. This can then be used to do things like
* get file paths associated with the Activity.
*
* @param ctx The context of the main Activity.
*/
public void setContext(Context ctx) {
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
} }
/** /**
* Executes the request and returns PluginResult. * Sets the context of the Command. This can then be used to do things like
* * get file paths associated with the Activity.
* @param action The action to execute. *
* @param args JSONArry of arguments for the plugin. * @param ctx The context of the main Activity.
* @param callbackId The callback id used when calling back into JavaScript. */
* @return A PluginResult object with a status and message.
*/ public void setContext(CordovaInterface ctx) {
public PluginResult execute(String action, JSONArray args, String callbackId) { super.setContext(ctx);
PluginResult.Status status = PluginResult.Status.OK; this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE);
String result = ""; }
try { /**
if (action.equals("getStatus")) { * Executes the request and returns PluginResult.
int i = this.getStatus(); *
return new PluginResult(status, i); * @param action The action to execute.
} * @param args JSONArry of arguments for the plugin.
else if (action.equals("start")) { * @param callbackId The callback id used when calling back into JavaScript.
int i = this.start(); * @return A PluginResult object with a status and message.
return new PluginResult(status, i); */
} public PluginResult execute(String action, JSONArray args, String callbackId) {
else if (action.equals("stop")) { PluginResult.Status status = PluginResult.Status.OK;
this.stop(); String result = "";
return new PluginResult(status, 0);
} try {
else if (action.equals("getAcceleration")) { if (action.equals("getStatus")) {
// If not running, then this is an async call, so don't worry about waiting int i = this.getStatus();
if (this.status != AccelListener.RUNNING) { return new PluginResult(status, i);
int r = this.start(); }
if (r == AccelListener.ERROR_FAILED_TO_START) { else if (action.equals("start")) {
return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START); int i = this.start();
} return new PluginResult(status, i);
// Wait until running }
long timeout = 2000; else if (action.equals("stop")) {
while ((this.status == STARTING) && (timeout > 0)) { this.stop();
timeout = timeout - 100; return new PluginResult(status, 0);
try { }
Thread.sleep(100); else if (action.equals("getAcceleration")) {
} catch (InterruptedException e) { // If not running, then this is an async call, so don't worry about waiting
e.printStackTrace(); if (this.status != AccelListener.RUNNING) {
} int r = this.start();
} if (r == AccelListener.ERROR_FAILED_TO_START) {
if (timeout == 0) { return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START);
return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START); }
} // Wait until running
} long timeout = 2000;
this.lastAccessTime = System.currentTimeMillis(); while ((this.status == STARTING) && (timeout > 0)) {
JSONObject r = new JSONObject(); timeout = timeout - 100;
r.put("x", this.x); try {
r.put("y", this.y); Thread.sleep(100);
r.put("z", this.z); } catch (InterruptedException e) {
// TODO: Should timestamp be sent? e.printStackTrace();
r.put("timestamp", this.timestamp); }
return new PluginResult(status, r); }
} if (timeout == 0) {
else if (action.equals("setTimeout")) { return new PluginResult(PluginResult.Status.IO_EXCEPTION, AccelListener.ERROR_FAILED_TO_START);
try { }
float timeout = Float.parseFloat(args.getString(0)); }
this.setTimeout(timeout); this.lastAccessTime = System.currentTimeMillis();
return new PluginResult(status, 0); JSONObject r = new JSONObject();
} catch (NumberFormatException e) { r.put("x", this.x);
status = PluginResult.Status.INVALID_ACTION; r.put("y", this.y);
e.printStackTrace(); r.put("z", this.z);
} catch (JSONException e) { // TODO: Should timestamp be sent?
status = PluginResult.Status.JSON_EXCEPTION; r.put("timestamp", this.timestamp);
e.printStackTrace(); return new PluginResult(status, r);
} }
} else if (action.equals("setTimeout")) {
else if (action.equals("getTimeout")) { try {
float f = this.getTimeout(); float timeout = Float.parseFloat(args.getString(0));
return new PluginResult(status, f); this.setTimeout(timeout);
} else { return new PluginResult(status, 0);
// Unsupported action } catch (NumberFormatException e) {
return new PluginResult(PluginResult.Status.INVALID_ACTION); status = PluginResult.Status.INVALID_ACTION;
} e.printStackTrace();
return new PluginResult(status, result); } catch (JSONException e) {
} catch (JSONException e) { status = PluginResult.Status.JSON_EXCEPTION;
return new PluginResult(PluginResult.Status.JSON_EXCEPTION); e.printStackTrace();
} }
} }
else if (action.equals("getTimeout")) {
float f = this.getTimeout();
return new PluginResult(status, f);
} else {
// Unsupported action
return new PluginResult(PluginResult.Status.INVALID_ACTION);
}
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
/**
* Identifies if action to be executed returns a value and should be run synchronously.
*
* @param action The action to execute
* @return T=returns value
*/
public boolean isSynch(String action) {
if (action.equals("getStatus")) {
return true;
}
else if (action.equals("getAcceleration")) {
// Can only return value if RUNNING
if (this.status == AccelListener.RUNNING) {
return true;
}
}
else if (action.equals("getTimeout")) {
return true;
}
return false;
}
/**
* Identifies if action to be executed returns a value and should be run synchronously.
*
* @param action The action to execute
* @return T=returns value
*/
public boolean isSynch(String action) {
if (action.equals("getStatus")) {
return true;
}
else if (action.equals("getAcceleration")) {
// Can only return value if RUNNING
if (this.status == AccelListener.RUNNING) {
return true;
}
}
else if (action.equals("getTimeout")) {
return true;
}
return false;
}
/** /**
* Called by AccelBroker when listener is to be shut down. * Called by AccelBroker when listener is to be shut down.
* Stop listener. * Stop listener.
*/ */
public void onDestroy() { public void onDestroy() {
this.stop(); this.stop();
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -199,14 +199,14 @@ public class AccelListener extends Plugin implements SensorEventListener {
*/ */
public int start() { public int start() {
// If already starting or running, then just return // If already starting or running, then just return
if ((this.status == AccelListener.RUNNING) || (this.status == AccelListener.STARTING)) { if ((this.status == AccelListener.RUNNING) || (this.status == AccelListener.STARTING)) {
return this.status; return this.status;
} }
// Get accelerometer from sensor manager // Get accelerometer from sensor manager
List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER); List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
// If found, then register as listener // If found, then register as listener
if ((list != null) && (list.size() > 0)) { if ((list != null) && (list.size() > 0)) {
this.mSensor = list.get(0); this.mSensor = list.get(0);
@ -214,12 +214,12 @@ public class AccelListener extends Plugin implements SensorEventListener {
this.setStatus(AccelListener.STARTING); this.setStatus(AccelListener.STARTING);
this.lastAccessTime = System.currentTimeMillis(); this.lastAccessTime = System.currentTimeMillis();
} }
// If error, then set status to error // If error, then set status to error
else { else {
this.setStatus(AccelListener.ERROR_FAILED_TO_START); this.setStatus(AccelListener.ERROR_FAILED_TO_START);
} }
return this.status; return this.status;
} }
@ -228,7 +228,7 @@ public class AccelListener extends Plugin implements SensorEventListener {
*/ */
public void stop() { public void stop() {
if (this.status != AccelListener.STOPPED) { if (this.status != AccelListener.STOPPED) {
this.sensorManager.unregisterListener(this); this.sensorManager.unregisterListener(this);
} }
this.setStatus(AccelListener.STOPPED); this.setStatus(AccelListener.STOPPED);
} }
@ -248,29 +248,29 @@ public class AccelListener extends Plugin implements SensorEventListener {
* @param SensorEvent event * @param SensorEvent event
*/ */
public void onSensorChanged(SensorEvent event) { public void onSensorChanged(SensorEvent event) {
// Only look at accelerometer events // Only look at accelerometer events
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) { if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
return; return;
} }
// If not running, then just return // If not running, then just return
if (this.status == AccelListener.STOPPED) { if (this.status == AccelListener.STOPPED) {
return; return;
} }
// Save time that event was received // Save time that event was received
this.timestamp = System.currentTimeMillis(); this.timestamp = System.currentTimeMillis();
this.x = event.values[0]; this.x = event.values[0];
this.y = event.values[1]; this.y = event.values[1];
this.z = event.values[2]; this.z = event.values[2];
this.setStatus(AccelListener.RUNNING); this.setStatus(AccelListener.RUNNING);
// If values haven't been read for TIMEOUT time, then turn off accelerometer sensor to save power // If values haven't been read for TIMEOUT time, then turn off accelerometer sensor to save power
if ((this.timestamp - this.lastAccessTime) > this.TIMEOUT) { if ((this.timestamp - this.lastAccessTime) > this.TIMEOUT) {
this.stop(); this.stop();
} }
} }
/** /**
@ -278,34 +278,34 @@ public class AccelListener extends Plugin implements SensorEventListener {
* *
* @return status * @return status
*/ */
public int getStatus() { public int getStatus() {
return this.status; return this.status;
} }
/** /**
* Set the timeout to turn off accelerometer sensor if getX() hasn't been called. * Set the timeout to turn off accelerometer sensor if getX() hasn't been called.
* *
* @param timeout Timeout in msec. * @param timeout Timeout in msec.
*/ */
public void setTimeout(float timeout) { public void setTimeout(float timeout) {
this.TIMEOUT = timeout; this.TIMEOUT = timeout;
} }
/** /**
* Get the timeout to turn off accelerometer sensor if getX() hasn't been called. * Get the timeout to turn off accelerometer sensor if getX() hasn't been called.
* *
* @return timeout in msec * @return timeout in msec
*/ */
public float getTimeout() { public float getTimeout() {
return this.TIMEOUT; return this.TIMEOUT;
} }
/** /**
* Set the status and send it to JavaScript. * Set the status and send it to JavaScript.
* @param status * @param status
*/ */
private void setStatus(int status) { private void setStatus(int status) {
this.status = status; this.status = status;
} }
} }

View File

@ -26,7 +26,7 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.webkit.WebView; //import android.webkit.WebView;
import android.app.Activity; import android.app.Activity;
import android.view.View; import android.view.View;
@ -50,38 +50,43 @@ public class App extends Plugin {
String result = ""; String result = "";
try { try {
if (action.equals("clearCache")) { if (action.equals("clearCache")) {
this.clearCache(); this.clearCache();
}
else if (action.equals("show")) {
final CordovaWebView wv = this.webView;
((Activity)this.ctx).runOnUiThread(new Runnable() {
public void run() {
wv.setVisibility(View.VISIBLE);
}
});
}
else if (action.equals("loadUrl")) {
this.loadUrl(args.getString(0), args.optJSONObject(1));
} }
else if (action.equals("cancelLoadUrl")) { else if (action.equals("show")) { // TODO @bc - Not in master branch. When should this be called?
this.cancelLoadUrl(); ctx.getActivity().runOnUiThread(new Runnable() {
public void run() {
webView.postMessage("spinner", "stop");
}
});
// final CordovaWebView wv = this.webView;
// ((Activity) this.ctx).runOnUiThread(new Runnable() {
// public void run() {
// wv.setVisibility(View.VISIBLE);
// }
// });
} }
else if (action.equals("clearHistory")) { else if (action.equals("loadUrl")) {
this.clearHistory(); 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("backHistory")) { else if (action.equals("backHistory")) {
this.backHistory(); this.backHistory();
} }
else if (action.equals("overrideBackbutton")) { else if (action.equals("overrideBackbutton")) {
this.overrideBackbutton(args.getBoolean(0)); this.overrideBackbutton(args.getBoolean(0));
} }
else if (action.equals("isBackbuttonOverridden")) { else if (action.equals("isBackbuttonOverridden")) {
boolean b = this.isBackbuttonOverridden(); boolean b = this.isBackbuttonOverridden();
return new PluginResult(status, b); return new PluginResult(status, b);
} }
else if (action.equals("exitApp")) { else if (action.equals("exitApp")) {
this.exitApp(); this.exitApp();
} }
return new PluginResult(status, result); return new PluginResult(status, result);
} catch (JSONException e) { } catch (JSONException e) {
@ -93,93 +98,93 @@ public class App extends Plugin {
// LOCAL METHODS // LOCAL METHODS
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* Clear the resource cache. * Clear the resource cache.
*/ */
public void clearCache() { public void clearCache() {
webView.clearCache(true); this.webView.clearCache(true);
} }
/**
* 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 {
LOG.d("App", "App.loadUrl("+url+","+props+")");
int wait = 0;
boolean openExternal = false;
boolean clearHistory = false;
// If there are properties, then set them on the Activity /**
HashMap<String, Object> params = new HashMap<String, Object>(); * Load the url into the webview.
if (props != null) { *
JSONArray keys = props.names(); * @param url
for (int i=0; i<keys.length(); i++) { * @param props Properties that can be passed in to the DroidGap activity (i.e. loadingDialog, wait, ...)
String key = keys.getString(i); * @throws JSONException
if (key.equals("wait")) { */
wait = props.getInt(key); public void loadUrl(String url, JSONObject props) throws JSONException {
} LOG.d("App", "App.loadUrl(" + url + "," + props + ")");
else if (key.equalsIgnoreCase("openexternal")) { int wait = 0;
openExternal = props.getBoolean(key); boolean openExternal = false;
} boolean clearHistory = false;
else if (key.equalsIgnoreCase("clearhistory")) {
clearHistory = props.getBoolean(key);
}
else {
Object value = props.get(key);
if (value == null) {
} // If there are properties, then set them on the Activity
else if (value.getClass().equals(String.class)) { HashMap<String, Object> params = new HashMap<String, Object>();
params.put(key, (String)value); if (props != null) {
} JSONArray keys = props.names();
else if (value.getClass().equals(Boolean.class)) { for (int i = 0; i < keys.length(); i++) {
params.put(key, (Boolean)value); String key = keys.getString(i);
} if (key.equals("wait")) {
else if (value.getClass().equals(Integer.class)) { wait = props.getInt(key);
params.put(key, (Integer)value); }
} else if (key.equalsIgnoreCase("openexternal")) {
} openExternal = props.getBoolean(key);
} }
} else if (key.equalsIgnoreCase("clearhistory")) {
clearHistory = props.getBoolean(key);
}
else {
Object value = props.get(key);
if (value == null) {
// If wait property, then delay loading }
else if (value.getClass().equals(String.class)) {
params.put(key, (String) value);
}
else if (value.getClass().equals(Boolean.class)) {
params.put(key, (Boolean) value);
}
else if (value.getClass().equals(Integer.class)) {
params.put(key, (Integer) value);
}
}
}
}
if (wait > 0) { // If wait property, then delay loading
try {
synchronized(this) { if (wait > 0) {
this.wait(wait); try {
} synchronized (this) {
} catch (InterruptedException e) { this.wait(wait);
e.printStackTrace(); }
} } catch (InterruptedException e) {
} e.printStackTrace();
webView.showWebPage(url, openExternal, clearHistory, params); }
} }
this.webView.showWebPage(url, openExternal, clearHistory, params);
}
/**
* Cancel loadUrl before it has been loaded (Only works on a CordovaInterface class)
*/
public void cancelLoadUrl() {
this.ctx.cancelLoadUrl();
}
/**
* Cancel loadUrl before it has been loaded (Only works on a CordovaInterface class)
*/
public void cancelLoadUrl() {
((DroidGap)this.ctx).cancelLoadUrl();
}
/** /**
* Clear page history for the app. * Clear page history for the app.
*/ */
public void clearHistory() { public void clearHistory() {
webView.clearHistory(); this.webView.clearHistory();
} }
/** /**
* Go to previous page displayed. * Go to previous page displayed.
* This is the same as pressing the backbutton on Android device. * This is the same as pressing the backbutton on Android device.
*/ */
public void backHistory() { public void backHistory() {
webView.backHistory(); this.webView.backHistory();
} }
/** /**
@ -189,8 +194,8 @@ public class App extends Plugin {
* @param override T=override, F=cancel override * @param override T=override, F=cancel override
*/ */
public void overrideBackbutton(boolean override) { public void overrideBackbutton(boolean override) {
LOG.i("DroidGap", "WARNING: Back Button Default Behaviour will be overridden. The backbutton event will be fired!"); LOG.i("App", "WARNING: Back Button Default Behaviour will be overridden. The backbutton event will be fired!");
((DroidGap)this.ctx).bound = override; this.ctx.bindBackButton(override);
} }
/** /**
@ -199,14 +204,14 @@ public class App extends Plugin {
* @return boolean * @return boolean
*/ */
public boolean isBackbuttonOverridden() { public boolean isBackbuttonOverridden() {
return ((DroidGap)this.ctx).bound; return this.ctx.isBackButtonBound();
} }
/** /**
* Exit the Android application. * Exit the Android application.
*/ */
public void exitApp() { public void exitApp() {
((DroidGap)this.ctx).endActivity(); this.ctx.getActivity().finish();
} }
} }

View File

@ -29,7 +29,8 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map.Entry;
//import java.util.Map.Entry;
/** /**
* This class called by CordovaActivity to play and record audio. * This class called by CordovaActivity to play and record audio.
@ -45,98 +46,98 @@ import java.util.Map.Entry;
public class AudioHandler extends Plugin { public class AudioHandler extends Plugin {
public static String TAG = "AudioHandler"; public static String TAG = "AudioHandler";
HashMap<String,AudioPlayer> players; // Audio player object HashMap<String, AudioPlayer> players; // Audio player object
ArrayList<AudioPlayer> pausedForPhone; // Audio players that were paused when phone call came in ArrayList<AudioPlayer> pausedForPhone; // Audio players that were paused when phone call came in
/**
* Constructor.
*/
public AudioHandler() {
this.players = new HashMap<String,AudioPlayer>();
this.pausedForPhone = new ArrayList<AudioPlayer>();
}
/** /**
* Executes the request and returns PluginResult. * Constructor.
* */
* @param action The action to execute. public AudioHandler() {
* @param args JSONArry of arguments for the plugin. this.players = new HashMap<String, AudioPlayer>();
* @param callbackId The callback id used when calling back into JavaScript. this.pausedForPhone = new ArrayList<AudioPlayer>();
* @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("startRecordingAudio")) {
this.startRecordingAudio(args.getString(0), args.getString(1));
}
else if (action.equals("stopRecordingAudio")) {
this.stopRecordingAudio(args.getString(0));
}
else if (action.equals("startPlayingAudio")) {
this.startPlayingAudio(args.getString(0), args.getString(1));
}
else if (action.equals("seekToAudio")) {
this.seekToAudio(args.getString(0), args.getInt(1));
}
else if (action.equals("pausePlayingAudio")) {
this.pausePlayingAudio(args.getString(0));
}
else if (action.equals("stopPlayingAudio")) {
this.stopPlayingAudio(args.getString(0));
} else if (action.equals("setVolume")) {
try {
this.setVolume(args.getString(0), Float.parseFloat(args.getString(1)));
} catch (NumberFormatException nfe) {
//no-op
}
} else if (action.equals("getCurrentPositionAudio")) {
float f = this.getCurrentPositionAudio(args.getString(0));
return new PluginResult(status, f);
}
else if (action.equals("getDurationAudio")) {
float f = this.getDurationAudio(args.getString(0), args.getString(1));
return new PluginResult(status, f);
}
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. * Executes the request and returns PluginResult.
* *
* @param action The action to execute * @param action The action to execute.
* @return T=returns value * @param args JSONArry of arguments for the plugin.
*/ * @param callbackId The callback id used when calling back into JavaScript.
public boolean isSynch(String action) { * @return A PluginResult object with a status and message.
if (action.equals("getCurrentPositionAudio")) { */
return true; public PluginResult execute(String action, JSONArray args, String callbackId) {
} PluginResult.Status status = PluginResult.Status.OK;
else if (action.equals("getDurationAudio")) { String result = "";
return true;
}
return false;
}
/** try {
* Stop all audio players and recorders. if (action.equals("startRecordingAudio")) {
*/ this.startRecordingAudio(args.getString(0), args.getString(1));
public void onDestroy() { }
else if (action.equals("stopRecordingAudio")) {
this.stopRecordingAudio(args.getString(0));
}
else if (action.equals("startPlayingAudio")) {
this.startPlayingAudio(args.getString(0), args.getString(1));
}
else if (action.equals("seekToAudio")) {
this.seekToAudio(args.getString(0), args.getInt(1));
}
else if (action.equals("pausePlayingAudio")) {
this.pausePlayingAudio(args.getString(0));
}
else if (action.equals("stopPlayingAudio")) {
this.stopPlayingAudio(args.getString(0));
} else if (action.equals("setVolume")) {
try {
this.setVolume(args.getString(0), Float.parseFloat(args.getString(1)));
} catch (NumberFormatException nfe) {
//no-op
}
} else if (action.equals("getCurrentPositionAudio")) {
float f = this.getCurrentPositionAudio(args.getString(0));
return new PluginResult(status, f);
}
else if (action.equals("getDurationAudio")) {
float f = this.getDurationAudio(args.getString(0), args.getString(1));
return new PluginResult(status, f);
}
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.
*
* @param action The action to execute
* @return T=returns value
*/
public boolean isSynch(String action) {
if (action.equals("getCurrentPositionAudio")) {
return true;
}
else if (action.equals("getDurationAudio")) {
return true;
}
return false;
}
/**
* Stop all audio players and recorders.
*/
public void onDestroy() {
for (AudioPlayer audio : this.players.values()) { for (AudioPlayer audio : this.players.values()) {
audio.destroy(); audio.destroy();
} }
this.players.clear(); this.players.clear();
} }
/** /**
* Called when a message is sent to plugin. * Called when a message is sent to plugin.
* *
@ -144,13 +145,13 @@ public class AudioHandler extends Plugin {
* @param data The message data * @param data The message data
*/ */
public void onMessage(String id, Object data) { public void onMessage(String id, Object data) {
// If phone message // If phone message
if (id.equals("telephone")) { if (id.equals("telephone")) {
// If phone ringing, then pause playing // If phone ringing, then pause playing
if ("ringing".equals(data) || "offhook".equals(data)) { if ("ringing".equals(data) || "offhook".equals(data)) {
// Get all audio players and pause them // Get all audio players and pause them
for (AudioPlayer audio : this.players.values()) { for (AudioPlayer audio : this.players.values()) {
if (audio.getState() == AudioPlayer.MEDIA_RUNNING) { if (audio.getState() == AudioPlayer.MEDIA_RUNNING) {
@ -160,7 +161,7 @@ public class AudioHandler extends Plugin {
} }
} }
// If phone idle, then resume playing those players we paused // If phone idle, then resume playing those players we paused
else if ("idle".equals(data)) { else if ("idle".equals(data)) {
for (AudioPlayer audio : this.pausedForPhone) { for (AudioPlayer audio : this.pausedForPhone) {
@ -174,177 +175,179 @@ public class AudioHandler extends Plugin {
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// LOCAL METHODS // 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. * Release the audio player instance to save memory.
* *
* @param id The id of the audio player * @param id The id of the audio player
* @param file The name of the file */
*/ 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.
*
* @param id The id of the audio player
* @param file The name of the file
*/
public void startRecordingAudio(String id, String file) { public void startRecordingAudio(String id, String file) {
// If already recording, then just return; // If already recording, then just return;
if (this.players.containsKey(id)) { if (this.players.containsKey(id)) {
return; return;
} }
AudioPlayer audio = new AudioPlayer(this, id); AudioPlayer audio = new AudioPlayer(this, id);
this.players.put(id, audio); this.players.put(id, audio);
audio.startRecording(file); audio.startRecording(file);
} }
/** /**
* Stop recording and save to the file specified when recording started. * Stop recording and save to the file specified when recording started.
* *
* @param id The id of the audio player * @param id The id of the audio player
*/ */
public void stopRecordingAudio(String id) { public void stopRecordingAudio(String id) {
AudioPlayer audio = this.players.get(id); AudioPlayer audio = this.players.get(id);
if (audio != null) { if (audio != null) {
audio.stopRecording(); audio.stopRecording();
this.players.remove(id); this.players.remove(id);
} }
} }
/** /**
* Start or resume playing audio file. * Start or resume playing audio file.
* *
* @param id The id of the audio player * @param id The id of the audio player
* @param file The name of the audio file. * @param file The name of the audio file.
*/ */
public void startPlayingAudio(String id, String file) { public void startPlayingAudio(String id, String file) {
AudioPlayer audio = this.players.get(id); AudioPlayer audio = this.players.get(id);
if (audio == null) { if (audio == null) {
audio = new AudioPlayer(this, id); audio = new AudioPlayer(this, id);
this.players.put(id, audio); this.players.put(id, audio);
} }
audio.startPlaying(file); audio.startPlaying(file);
} }
/** /**
* Seek to a location. * Seek to a location.
* *
* *
* @param id The id of the audio player * @param id The id of the audio player
* @param miliseconds int: number of milliseconds to skip 1000 = 1 second * @param miliseconds int: number of milliseconds to skip 1000 = 1 second
*/ */
public void seekToAudio(String id, int milliseconds) { public void seekToAudio(String id, int milliseconds) {
AudioPlayer audio = this.players.get(id); AudioPlayer audio = this.players.get(id);
if (audio != null) { if (audio != null) {
audio.seekToPlaying(milliseconds); audio.seekToPlaying(milliseconds);
} }
} }
/** /**
* Pause playing. * Pause playing.
* *
* @param id The id of the audio player * @param id The id of the audio player
*/ */
public void pausePlayingAudio(String id) { public void pausePlayingAudio(String id) {
AudioPlayer audio = this.players.get(id); AudioPlayer audio = this.players.get(id);
if (audio != null) { if (audio != null) {
audio.pausePlaying(); audio.pausePlaying();
} }
} }
/** /**
* Stop playing the audio file. * Stop playing the audio file.
* *
* @param id The id of the audio player * @param id The id of the audio player
*/ */
public void stopPlayingAudio(String id) { public void stopPlayingAudio(String id) {
AudioPlayer audio = this.players.get(id); AudioPlayer audio = this.players.get(id);
if (audio != null) { if (audio != null) {
audio.stopPlaying(); audio.stopPlaying();
//audio.destroy(); //audio.destroy();
//this.players.remove(id); //this.players.remove(id);
} }
} }
/** /**
* Get current position of playback. * Get current position of playback.
* *
* @param id The id of the audio player * @param id The id of the audio player
* @return position in msec * @return position in msec
*/ */
public float getCurrentPositionAudio(String id) { public float getCurrentPositionAudio(String id) {
AudioPlayer audio = this.players.get(id); AudioPlayer audio = this.players.get(id);
if (audio != null) { if (audio != null) {
return(audio.getCurrentPosition()/1000.0f); return (audio.getCurrentPosition() / 1000.0f);
} }
return -1; return -1;
} }
/** /**
* Get the duration of the audio file. * Get the duration of the audio file.
* *
* @param id The id of the audio player * @param id The id of the audio player
* @param file The name of the audio file. * @param file The name of the audio file.
* @return The duration in msec. * @return The duration in msec.
*/ */
public float getDurationAudio(String id, String file) { public float getDurationAudio(String id, String file) {
// Get audio file // Get audio file
AudioPlayer audio = this.players.get(id); AudioPlayer audio = this.players.get(id);
if (audio != null) { if (audio != null) {
return(audio.getDuration(file)); return (audio.getDuration(file));
} }
// If not already open, then open the file // If not already open, then open the file
else { else {
audio = new AudioPlayer(this, id); audio = new AudioPlayer(this, id);
this.players.put(id, audio); this.players.put(id, audio);
return(audio.getDuration(file)); return (audio.getDuration(file));
} }
} }
/** /**
* Set the audio device to be used for playback. * Set the audio device to be used for playback.
* *
* @param output 1=earpiece, 2=speaker * @param output 1=earpiece, 2=speaker
*/ */
@SuppressWarnings("deprecation")
public void setAudioOutputDevice(int output) { public void setAudioOutputDevice(int output) {
AudioManager audiMgr = (AudioManager) this.ctx.getSystemService(Context.AUDIO_SERVICE); AudioManager audiMgr = (AudioManager) this.ctx.getActivity().getSystemService(Context.AUDIO_SERVICE);
if (output == 2) { if (output == 2) {
audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL); audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_SPEAKER, AudioManager.ROUTE_ALL);
} }
else if (output == 1) { else if (output == 1) {
audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL); audiMgr.setRouting(AudioManager.MODE_NORMAL, AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL);
} }
else { else {
System.out.println("AudioHandler.setAudioOutputDevice() Error: Unknown output device."); System.out.println("AudioHandler.setAudioOutputDevice() Error: Unknown output device.");
} }
} }
/** /**
* Get the audio device to be used for playback. * Get the audio device to be used for playback.
* *
* @return 1=earpiece, 2=speaker * @return 1=earpiece, 2=speaker
*/ */
@SuppressWarnings("deprecation")
public int getAudioOutputDevice() { public int getAudioOutputDevice() {
AudioManager audiMgr = (AudioManager) this.ctx.getSystemService(Context.AUDIO_SERVICE); AudioManager audiMgr = (AudioManager) this.ctx.getActivity().getSystemService(Context.AUDIO_SERVICE);
if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_EARPIECE) { if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_EARPIECE) {
return 1; return 1;
} }
else if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_SPEAKER) { else if (audiMgr.getRouting(AudioManager.MODE_NORMAL) == AudioManager.ROUTE_SPEAKER) {
return 2; return 2;
} }
else { else {
return -1; return -1;
} }
} }
/** /**

View File

@ -45,413 +45,411 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
private static final String LOG_TAG = "AudioPlayer"; private static final String LOG_TAG = "AudioPlayer";
// AudioPlayer states // AudioPlayer states
public static int MEDIA_NONE = 0; public static int MEDIA_NONE = 0;
public static int MEDIA_STARTING = 1; public static int MEDIA_STARTING = 1;
public static int MEDIA_RUNNING = 2; public static int MEDIA_RUNNING = 2;
public static int MEDIA_PAUSED = 3; public static int MEDIA_PAUSED = 3;
public static int MEDIA_STOPPED = 4; public static int MEDIA_STOPPED = 4;
// AudioPlayer message ids // AudioPlayer message ids
private static int MEDIA_STATE = 1; private static int MEDIA_STATE = 1;
private static int MEDIA_DURATION = 2; private static int MEDIA_DURATION = 2;
private static int MEDIA_POSITION = 3; private static int MEDIA_POSITION = 3;
private static int MEDIA_ERROR = 9; private static int MEDIA_ERROR = 9;
// Media error codes
private static int MEDIA_ERR_NONE_ACTIVE = 0;
private static int MEDIA_ERR_ABORTED = 1;
private static int MEDIA_ERR_NETWORK = 2;
private static int MEDIA_ERR_DECODE = 3;
private static int MEDIA_ERR_NONE_SUPPORTED = 4;
private AudioHandler handler; // The AudioHandler object
private String id; // The id of this player (used to identify Media object in JavaScript)
private int state = MEDIA_NONE; // State of recording or playback
private String audioFile = null; // File name to play or record to
private float duration = -1; // Duration of audio
private MediaRecorder recorder = null; // Audio recording object // Media error codes
private String tempFile = null; // Temporary recording file name private static int MEDIA_ERR_NONE_ACTIVE = 0;
private static int MEDIA_ERR_ABORTED = 1;
private MediaPlayer mPlayer = null; // Audio player object // private static int MEDIA_ERR_NETWORK = 2;
private boolean prepareOnly = false; // private static int MEDIA_ERR_DECODE = 3;
// private static int MEDIA_ERR_NONE_SUPPORTED = 4;
/** private AudioHandler handler; // The AudioHandler object
* Constructor. private String id; // The id of this player (used to identify Media object in JavaScript)
* private int state = MEDIA_NONE; // State of recording or playback
* @param handler The audio handler object private String audioFile = null; // File name to play or record to
* @param id The id of this audio player private float duration = -1; // Duration of audio
*/
public AudioPlayer(AudioHandler handler, String id) { private MediaRecorder recorder = null; // Audio recording object
this.handler = handler; private String tempFile = null; // Temporary recording file name
this.id = id;
private MediaPlayer mPlayer = null; // Audio player object
private boolean prepareOnly = false;
/**
* Constructor.
*
* @param handler The audio handler object
* @param id The id of this audio player
*/
public AudioPlayer(AudioHandler handler, String id) {
this.handler = handler;
this.id = id;
this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3"; this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3";
} }
/** /**
* Destroy player and stop audio playing or recording. * Destroy player and stop audio playing or recording.
*/ */
public void destroy() { public void destroy() {
// Stop any play or record // Stop any play or record
if (this.mPlayer != null) { if (this.mPlayer != null) {
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) { if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
this.mPlayer.stop(); this.mPlayer.stop();
this.setState(MEDIA_STOPPED); this.setState(MEDIA_STOPPED);
} }
this.mPlayer.release(); this.mPlayer.release();
this.mPlayer = null; this.mPlayer = null;
} }
if (this.recorder != null) { if (this.recorder != null) {
this.stopRecording(); this.stopRecording();
this.recorder.release(); this.recorder.release();
this.recorder = null; this.recorder = null;
} }
} }
/**
* Start recording the specified file.
*
* @param file The name of the file
*/
public void startRecording(String file) {
if (this.mPlayer != null) {
Log.d(LOG_TAG, "AudioPlayer Error: Can't record in play mode.");
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
}
// Make sure we're not already recording
else if (this.recorder == null) {
this.audioFile = file;
this.recorder = new MediaRecorder();
this.recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
this.recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // THREE_GPP);
this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); //AMR_NB);
this.recorder.setOutputFile(this.tempFile);
try {
this.recorder.prepare();
this.recorder.start();
this.setState(MEDIA_RUNNING);
return;
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
}
else {
Log.d(LOG_TAG, "AudioPlayer Error: Already recording.");
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
}
}
/**
* Save temporary recorded file to specified name
*
* @param file
*/
public void moveFile(String file) {
/* this is a hack to save the file as the specified name */
File f = new File(this.tempFile);
f.renameTo(new File("/sdcard/" + file));
}
/**
* Start recording the specified file.
*
* @param file The name of the file
*/
public void startRecording(String file) {
if (this.mPlayer != null) {
Log.d(LOG_TAG, "AudioPlayer Error: Can't record in play mode.");
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
}
// Make sure we're not already recording
else if (this.recorder == null) {
this.audioFile = file;
this.recorder = new MediaRecorder();
this.recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
this.recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); // THREE_GPP);
this.recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); //AMR_NB);
this.recorder.setOutputFile(this.tempFile);
try {
this.recorder.prepare();
this.recorder.start();
this.setState(MEDIA_RUNNING);
return;
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
}
else {
Log.d(LOG_TAG, "AudioPlayer Error: Already recording.");
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
}
}
/**
* Save temporary recorded file to specified name
*
* @param file
*/
public void moveFile(String file) {
/* this is a hack to save the file as the specified name */
File f = new File(this.tempFile);
f.renameTo(new File("/sdcard/" + file));
}
/** /**
* Stop recording and save to the file specified when recording started. * Stop recording and save to the file specified when recording started.
*/ */
public void stopRecording() { public void stopRecording() {
if (this.recorder != null) { if (this.recorder != null) {
try{ try {
if (this.state == MEDIA_RUNNING) { if (this.state == MEDIA_RUNNING) {
this.recorder.stop(); this.recorder.stop();
this.setState(MEDIA_STOPPED); this.setState(MEDIA_STOPPED);
} }
this.moveFile(this.audioFile); this.moveFile(this.audioFile);
} } catch (Exception e) {
catch (Exception e) { e.printStackTrace();
e.printStackTrace(); }
} }
} }
}
/** /**
* Start or resume playing audio file. * Start or resume playing audio file.
* *
* @param file The name of the audio file. * @param file The name of the audio file.
*/ */
public void startPlaying(String file) { public void startPlaying(String file) {
if (this.recorder != null) { if (this.recorder != null) {
Log.d(LOG_TAG, "AudioPlayer Error: Can't play in record mode."); Log.d(LOG_TAG, "AudioPlayer Error: Can't play in record mode.");
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});"); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
} }
// If this is a new request to play audio, or stopped // If this is a new request to play audio, or stopped
else if ((this.mPlayer == null) || (this.state == MEDIA_STOPPED)) { else if ((this.mPlayer == null) || (this.state == MEDIA_STOPPED)) {
try { try {
// If stopped, then reset player // If stopped, then reset player
if (this.mPlayer != null) { if (this.mPlayer != null) {
this.mPlayer.reset(); this.mPlayer.reset();
} }
// Otherwise, create a new one // Otherwise, create a new one
else { else {
this.mPlayer = new MediaPlayer(); this.mPlayer = new MediaPlayer();
} }
this.audioFile = file; this.audioFile = file;
// If streaming file // If streaming file
if (this.isStreaming(file)) { if (this.isStreaming(file)) {
this.mPlayer.setDataSource(file); this.mPlayer.setDataSource(file);
this.mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); this.mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
this.setState(MEDIA_STARTING); this.setState(MEDIA_STARTING);
this.mPlayer.setOnPreparedListener(this); this.mPlayer.setOnPreparedListener(this);
this.mPlayer.prepareAsync(); this.mPlayer.prepareAsync();
} }
// If local file // If local file
else { else {
if (file.startsWith("/android_asset/")) { if (file.startsWith("/android_asset/")) {
String f = file.substring(15); String f = file.substring(15);
android.content.res.AssetFileDescriptor fd = this.handler.ctx.getAssets().openFd(f); android.content.res.AssetFileDescriptor fd = this.handler.ctx.getActivity().getAssets().openFd(f);
this.mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength()); this.mPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
} }
else { else {
File fp = new File(file); File fp = new File(file);
if (fp.exists()) { if (fp.exists()) {
FileInputStream fileInputStream = new FileInputStream(file); FileInputStream fileInputStream = new FileInputStream(file);
this.mPlayer.setDataSource(fileInputStream.getFD()); this.mPlayer.setDataSource(fileInputStream.getFD());
} }
else { else {
this.mPlayer.setDataSource("/sdcard/" + file); this.mPlayer.setDataSource("/sdcard/" + file);
} }
} }
this.setState(MEDIA_STARTING); this.setState(MEDIA_STARTING);
this.mPlayer.setOnPreparedListener(this); this.mPlayer.setOnPreparedListener(this);
this.mPlayer.prepare(); this.mPlayer.prepare();
// Get duration // Get duration
this.duration = getDurationInSeconds(); this.duration = getDurationInSeconds();
} }
} } catch (Exception e) {
catch (Exception e) { e.printStackTrace();
e.printStackTrace(); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});"); }
} }
}
// If we have already have created an audio player // If we have already have created an audio player
else { else {
// If player has been paused, then resume playback
if ((this.state == MEDIA_PAUSED) || (this.state == MEDIA_STARTING)) {
this.mPlayer.start();
this.setState(MEDIA_RUNNING);
}
else {
Log.d(LOG_TAG, "AudioPlayer Error: startPlaying() called during invalid state: "+this.state);
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
}
}
}
/** // If player has been paused, then resume playback
* Seek or jump to a new time in the track. if ((this.state == MEDIA_PAUSED) || (this.state == MEDIA_STARTING)) {
*/ this.mPlayer.start();
public void seekToPlaying(int milliseconds) { this.setState(MEDIA_RUNNING);
if (this.mPlayer != null) { }
this.mPlayer.seekTo(milliseconds); else {
Log.d(LOG_TAG, "Send a onStatus update for the new seek"); Log.d(LOG_TAG, "AudioPlayer Error: startPlaying() called during invalid state: " + this.state);
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_POSITION+", "+milliseconds/1000.0f+");"); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
} }
} }
}
/**
* Pause playing. /**
*/ * Seek or jump to a new time in the track.
public void pausePlaying() { */
public void seekToPlaying(int milliseconds) {
// If playing, then pause if (this.mPlayer != null) {
if (this.state == MEDIA_RUNNING) { this.mPlayer.seekTo(milliseconds);
this.mPlayer.pause(); Log.d(LOG_TAG, "Send a onStatus update for the new seek");
this.setState(MEDIA_PAUSED); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + milliseconds / 1000.0f + ");");
} }
else { }
Log.d(LOG_TAG, "AudioPlayer Error: pausePlaying() called during invalid state: "+this.state);
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_NONE_ACTIVE+"});"); /**
} * Pause playing.
} */
public void pausePlaying() {
// If playing, then pause
if (this.state == MEDIA_RUNNING) {
this.mPlayer.pause();
this.setState(MEDIA_PAUSED);
}
else {
Log.d(LOG_TAG, "AudioPlayer Error: pausePlaying() called during invalid state: " + this.state);
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
}
}
/** /**
* Stop playing the audio file. * Stop playing the audio file.
*/ */
public void stopPlaying() { public void stopPlaying() {
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) { if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
this.mPlayer.stop(); this.mPlayer.stop();
this.setState(MEDIA_STOPPED); this.setState(MEDIA_STOPPED);
} }
else { else {
Log.d(LOG_TAG, "AudioPlayer Error: stopPlaying() called during invalid state: "+this.state); Log.d(LOG_TAG, "AudioPlayer Error: stopPlaying() called during invalid state: " + this.state);
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_NONE_ACTIVE+"});"); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
} }
} }
/** /**
* Callback to be invoked when playback of a media source has completed. * Callback to be invoked when playback of a media source has completed.
* *
* @param mPlayer The MediaPlayer that reached the end of the file * @param mPlayer The MediaPlayer that reached the end of the file
*/ */
public void onCompletion(MediaPlayer mPlayer) { public void onCompletion(MediaPlayer mPlayer) {
this.setState(MEDIA_STOPPED); this.setState(MEDIA_STOPPED);
} }
/** /**
* Get current position of playback. * Get current position of playback.
* *
* @return position in msec or -1 if not playing * @return position in msec or -1 if not playing
*/ */
public long getCurrentPosition() { public long getCurrentPosition() {
if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) { if ((this.state == MEDIA_RUNNING) || (this.state == MEDIA_PAUSED)) {
int curPos = this.mPlayer.getCurrentPosition(); int curPos = this.mPlayer.getCurrentPosition();
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_POSITION+", "+curPos/1000.0f+");"); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_POSITION + ", " + curPos / 1000.0f + ");");
return curPos; return curPos;
} }
else { else {
return -1; return -1;
} }
} }
/** /**
* Determine if playback file is streaming or local. * Determine if playback file is streaming or local.
* It is streaming if file name starts with "http://" * It is streaming if file name starts with "http://"
*
* @param file The file name
* @return T=streaming, F=local
*/
public boolean isStreaming(String file) {
if (file.contains("http://") || file.contains("https://")) {
return true;
}
else {
return false;
}
}
/**
* Get the duration of the audio file.
* *
* @param file The name of the audio file. * @param file The file name
* @return The duration in msec. * @return T=streaming, F=local
* -1=can't be determined
* -2=not allowed
*/ */
public float getDuration(String file) { public boolean isStreaming(String file) {
if (file.contains("http://") || file.contains("https://")) {
// Can't get duration of recording return true;
if (this.recorder != null) { }
return(-2); // not allowed else {
} return false;
}
// If audio file already loaded and started, then return duration }
if (this.mPlayer != null) {
return this.duration;
}
// If no player yet, then create one
else {
this.prepareOnly = true;
this.startPlaying(file);
// This will only return value for local, since streaming
// file hasn't been read yet.
return this.duration;
}
}
/** /**
* Callback to be invoked when the media source is ready for playback. * Get the duration of the audio file.
* *
* @param mPlayer The MediaPlayer that is ready for playback * @param file The name of the audio file.
*/ * @return The duration in msec.
public void onPrepared(MediaPlayer mPlayer) { * -1=can't be determined
// Listen for playback completion * -2=not allowed
this.mPlayer.setOnCompletionListener(this); */
public float getDuration(String file) {
// If start playing after prepared // Can't get duration of recording
if (!this.prepareOnly) { if (this.recorder != null) {
return (-2); // not allowed
// Start playing }
this.mPlayer.start();
// Set player init flag // If audio file already loaded and started, then return duration
this.setState(MEDIA_RUNNING); if (this.mPlayer != null) {
} return this.duration;
}
// Save off duration
this.duration = getDurationInSeconds();
this.prepareOnly = false;
// Send status notification to JavaScript // If no player yet, then create one
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_DURATION+","+this.duration+");"); else {
this.prepareOnly = true;
} this.startPlaying(file);
/** // This will only return value for local, since streaming
* By default Android returns the length of audio in mills but we want seconds // file hasn't been read yet.
* return this.duration;
* @return length of clip in seconds }
*/ }
private float getDurationInSeconds() {
return (this.mPlayer.getDuration() / 1000.0f);
}
/** /**
* Callback to be invoked when there has been an error during an asynchronous operation * Callback to be invoked when the media source is ready for playback.
* (other errors will throw exceptions at method call time). *
* * @param mPlayer The MediaPlayer that is ready for playback
* @param mPlayer the MediaPlayer the error pertains to */
* @param arg1 the type of error that has occurred: (MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_SERVER_DIED) public void onPrepared(MediaPlayer mPlayer) {
* @param arg2 an extra code, specific to the error. // Listen for playback completion
*/ this.mPlayer.setOnCompletionListener(this);
public boolean onError(MediaPlayer mPlayer, int arg1, int arg2) {
Log.d(LOG_TAG, "AudioPlayer.onError(" + arg1 + ", " + arg2+")");
// TODO: Not sure if this needs to be sent? // If start playing after prepared
this.mPlayer.stop(); if (!this.prepareOnly) {
this.mPlayer.release();
// Send error notification to JavaScript
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', { \"code\":"+arg1+"});");
return false;
}
/**
* Set the state and send it to JavaScript.
*
* @param state
*/
private void setState(int state) {
if (this.state != state) {
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_STATE+", "+state+");");
}
this.state = state;
}
/**
* Get the audio state.
*
* @return int
*/
public int getState() {
return this.state;
}
/** // Start playing
* Set the volume for audio player this.mPlayer.start();
*
* @param volume // Set player init flag
*/ this.setState(MEDIA_RUNNING);
}
// Save off duration
this.duration = getDurationInSeconds();
this.prepareOnly = false;
// Send status notification to JavaScript
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_DURATION + "," + this.duration + ");");
}
/**
* By default Android returns the length of audio in mills but we want seconds
*
* @return length of clip in seconds
*/
private float getDurationInSeconds() {
return (this.mPlayer.getDuration() / 1000.0f);
}
/**
* Callback to be invoked when there has been an error during an asynchronous operation
* (other errors will throw exceptions at method call time).
*
* @param mPlayer the MediaPlayer the error pertains to
* @param arg1 the type of error that has occurred: (MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_SERVER_DIED)
* @param arg2 an extra code, specific to the error.
*/
public boolean onError(MediaPlayer mPlayer, int arg1, int arg2) {
Log.d(LOG_TAG, "AudioPlayer.onError(" + arg1 + ", " + arg2 + ")");
// TODO: Not sure if this needs to be sent?
this.mPlayer.stop();
this.mPlayer.release();
// Send error notification to JavaScript
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', { \"code\":" + arg1 + "});");
return false;
}
/**
* Set the state and send it to JavaScript.
*
* @param state
*/
private void setState(int state) {
if (this.state != state) {
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_STATE + ", " + state + ");");
}
this.state = state;
}
/**
* Get the audio state.
*
* @return int
*/
public int getState() {
return this.state;
}
/**
* Set the volume for audio player
*
* @param volume
*/
public void setVolume(float volume) { public void setVolume(float volume) {
this.mPlayer.setVolume(volume, volume); this.mPlayer.setVolume(volume, volume);
} }

View File

@ -24,7 +24,6 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -32,20 +31,20 @@ import android.content.IntentFilter;
import android.util.Log; import android.util.Log;
public class BatteryListener extends Plugin { public class BatteryListener extends Plugin {
private static final String LOG_TAG = "BatteryManager"; private static final String LOG_TAG = "BatteryManager";
BroadcastReceiver receiver; BroadcastReceiver receiver;
private String batteryCallbackId = null; private String batteryCallbackId = null;
/** /**
* Constructor. * Constructor.
*/ */
public BatteryListener() { public BatteryListener() {
this.receiver = null; this.receiver = null;
} }
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
* *
@ -56,43 +55,43 @@ public class BatteryListener extends Plugin {
*/ */
public PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.INVALID_ACTION; PluginResult.Status status = PluginResult.Status.INVALID_ACTION;
String result = "Unsupported Operation: " + action; String result = "Unsupported Operation: " + action;
if (action.equals("start")) { if (action.equals("start")) {
if (this.batteryCallbackId != null) { if (this.batteryCallbackId != null) {
return new PluginResult(PluginResult.Status.ERROR, "Battery listener already running."); return new PluginResult(PluginResult.Status.ERROR, "Battery listener already running.");
} }
this.batteryCallbackId = callbackId; this.batteryCallbackId = callbackId;
// We need to listen to power events to update battery status // We need to listen to power events to update battery status
IntentFilter intentFilter = new IntentFilter() ; IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
if (this.receiver == null) { if (this.receiver == null) {
this.receiver = new BroadcastReceiver() { this.receiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
updateBatteryInfo(intent); updateBatteryInfo(intent);
} }
}; };
ctx.registerReceiver(this.receiver, intentFilter); ctx.getActivity().registerReceiver(this.receiver, intentFilter);
} }
// Don't return any result now, since status results will be sent when events come in from broadcast receiver // Don't return any result now, since status results will be sent when events come in from broadcast receiver
PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT); PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
pluginResult.setKeepCallback(true); pluginResult.setKeepCallback(true);
return pluginResult; return pluginResult;
} }
else if (action.equals("stop")) { else if (action.equals("stop")) {
removeBatteryListener(); removeBatteryListener();
this.sendUpdate(new JSONObject(), false); // release status callback in JS side this.sendUpdate(new JSONObject(), false); // release status callback in JS side
this.batteryCallbackId = null; this.batteryCallbackId = null;
return new PluginResult(PluginResult.Status.OK); return new PluginResult(PluginResult.Status.OK);
} }
return new PluginResult(status, result); return new PluginResult(status, result);
} }
/** /**
* Stop battery receiver. * Stop battery receiver.
*/ */
@ -106,7 +105,7 @@ public class BatteryListener extends Plugin {
private void removeBatteryListener() { private void removeBatteryListener() {
if (this.receiver != null) { if (this.receiver != null) {
try { try {
this.ctx.unregisterReceiver(this.receiver); this.ctx.getActivity().unregisterReceiver(this.receiver);
this.receiver = null; this.receiver = null;
} catch (Exception e) { } catch (Exception e) {
Log.e(LOG_TAG, "Error unregistering battery receiver: " + e.getMessage(), e); Log.e(LOG_TAG, "Error unregistering battery receiver: " + e.getMessage(), e);
@ -137,20 +136,20 @@ public class BatteryListener extends Plugin {
* @param batteryIntent the current battery information * @param batteryIntent the current battery information
* @return * @return
*/ */
private void updateBatteryInfo(Intent batteryIntent) { private void updateBatteryInfo(Intent batteryIntent) {
sendUpdate(this.getBatteryInfo(batteryIntent), true); sendUpdate(this.getBatteryInfo(batteryIntent), true);
} }
/** /**
* Create a new plugin result and send it back to JavaScript * Create a new plugin result and send it back to JavaScript
* *
* @param connection the network info to set as navigator.connection * @param connection the network info to set as navigator.connection
*/ */
private void sendUpdate(JSONObject info, boolean keepCallback) { private void sendUpdate(JSONObject info, boolean keepCallback) {
if (this.batteryCallbackId != null) { if (this.batteryCallbackId != null) {
PluginResult result = new PluginResult(PluginResult.Status.OK, info); PluginResult result = new PluginResult(PluginResult.Status.OK, info);
result.setKeepCallback(keepCallback); result.setKeepCallback(keepCallback);
this.success(result, this.batteryCallbackId); this.success(result, this.batteryCallbackId);
} }
} }
} }

View File

@ -26,7 +26,7 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.cordova.api.CordovaInterface; //import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import org.apache.cordova.api.Plugin; import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult; import org.apache.cordova.api.PluginResult;
@ -35,7 +35,7 @@ import org.json.JSONException;
import android.app.Activity; import android.app.Activity;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; //import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -53,50 +53,50 @@ public class CameraLauncher extends Plugin {
private static final int DATA_URL = 0; // Return base64 encoded string private static final int DATA_URL = 0; // Return base64 encoded string
private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android) private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android)
private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android) private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android)
private static final int CAMERA = 1; // Take picture from camera private static final int CAMERA = 1; // Take picture from camera
private static final int SAVEDPHOTOALBUM = 2; // Choose image from picture library (same as PHOTOLIBRARY for Android) private static final int SAVEDPHOTOALBUM = 2; // Choose image from picture library (same as PHOTOLIBRARY for Android)
private static final int PICTURE = 0; // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType private static final int PICTURE = 0; // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType
private static final int VIDEO = 1; // allow selection of video only, ONLY RETURNS URL private static final int VIDEO = 1; // allow selection of video only, ONLY RETURNS URL
private static final int ALLMEDIA = 2; // allow selection from all media types private static final int ALLMEDIA = 2; // allow selection from all media types
private static final int JPEG = 0; // Take a picture of type JPEG private static final int JPEG = 0; // Take a picture of type JPEG
private static final int PNG = 1; // Take a picture of type PNG private static final int PNG = 1; // Take a picture of type PNG
private static final String GET_PICTURE = "Get Picture"; private static final String GET_PICTURE = "Get Picture";
private static final String GET_VIDEO = "Get Video"; private static final String GET_VIDEO = "Get Video";
private static final String GET_All = "Get All"; private static final String GET_All = "Get All";
private static final String LOG_TAG = "CameraLauncher"; private static final String LOG_TAG = "CameraLauncher";
private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality) private int mQuality; // Compression quality hint (0-100: 0=low quality & high compression, 100=compress of max quality)
private int targetWidth; // desired width of the image private int targetWidth; // desired width of the image
private int targetHeight; // desired height of the image private int targetHeight; // desired height of the image
private Uri imageUri; // Uri of captured image private Uri imageUri; // Uri of captured image
private int encodingType; // Type of encoding to use private int encodingType; // Type of encoding to use
private int mediaType; // What type of media to retrieve private int mediaType; // What type of media to retrieve
public String callbackId; public String callbackId;
private int numPics; private int numPics;
//This should never be null! //This should never be null!
private CordovaInterface cordova; //private CordovaInterface cordova;
/** /**
* Constructor. * Constructor.
*/ */
public CameraLauncher() { public CameraLauncher() {
} }
public void setContext(Context mCtx) { // public void setContext(CordovaInterface mCtx) {
super.setContext(mCtx); // super.setContext(mCtx);
if(CordovaInterface.class.isInstance(mCtx)) // if (CordovaInterface.class.isInstance(mCtx))
cordova = (CordovaInterface) mCtx; // cordova = (CordovaInterface) mCtx;
else // else
LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity"); // LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
} // }
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
* *
@ -107,9 +107,9 @@ public class CameraLauncher extends Plugin {
*/ */
public PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.OK; PluginResult.Status status = PluginResult.Status.OK;
String result = ""; String result = "";
this.callbackId = callbackId; this.callbackId = callbackId;
try { try {
if (action.equals("takePicture")) { if (action.equals("takePicture")) {
int srcType = CAMERA; int srcType = CAMERA;
@ -127,7 +127,7 @@ public class CameraLauncher extends Plugin {
this.targetHeight = args.getInt(4); this.targetHeight = args.getInt(4);
this.encodingType = args.getInt(5); this.encodingType = args.getInt(5);
this.mediaType = args.getInt(6); this.mediaType = args.getInt(6);
if (srcType == CAMERA) { if (srcType == CAMERA) {
this.takePicture(destType, encodingType); this.takePicture(destType, encodingType);
} }
@ -144,11 +144,11 @@ public class CameraLauncher extends Plugin {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION); return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
} }
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// LOCAL METHODS // LOCAL METHODS
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* Take a picture with the camera. * Take a picture with the camera.
* When an image is captured or the camera view is cancelled, the result is returned * When an image is captured or the camera view is cancelled, the result is returned
@ -166,20 +166,21 @@ public class CameraLauncher extends Plugin {
public void takePicture(int returnType, int encodingType) { public void takePicture(int returnType, int encodingType) {
// Save the number of images currently on disk for later // Save the number of images currently on disk for later
this.numPics = queryImgDB().getCount(); this.numPics = queryImgDB().getCount();
// Display camera // Display camera
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
// Specify file so that large image is captured and returned // Specify file so that large image is captured and returned
// TODO: What if there isn't any external storage? // TODO: What if there isn't any external storage?
File photo = createCaptureFile(encodingType); File photo = createCaptureFile(encodingType);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo)); intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
this.imageUri = Uri.fromFile(photo); this.imageUri = Uri.fromFile(photo);
if(cordova != null) if (this.ctx != null) {
cordova.startActivityForResult((Plugin) this, intent, (CAMERA+1)*16 + returnType+1); this.ctx.startActivityForResult((Plugin) this, intent, (CAMERA + 1) * 16 + returnType + 1);
else }
LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity"); // else
// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
} }
/** /**
@ -191,9 +192,9 @@ public class CameraLauncher extends Plugin {
private File createCaptureFile(int encodingType) { private File createCaptureFile(int encodingType) {
File photo = null; File photo = null;
if (encodingType == JPEG) { if (encodingType == JPEG) {
photo = new File(DirectoryManager.getTempDirectoryPath(ctx), "Pic.jpg"); photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Pic.jpg");
} else if (encodingType == PNG) { } else if (encodingType == PNG) {
photo = new File(DirectoryManager.getTempDirectoryPath(ctx), "Pic.png"); photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Pic.png");
} else { } else {
throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType); throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
} }
@ -212,23 +213,25 @@ public class CameraLauncher extends Plugin {
Intent intent = new Intent(); Intent intent = new Intent();
String title = GET_PICTURE; String title = GET_PICTURE;
if (this.mediaType == PICTURE) { if (this.mediaType == PICTURE) {
intent.setType("image/*"); intent.setType("image/*");
} }
else if (this.mediaType == VIDEO) { else if (this.mediaType == VIDEO) {
intent.setType("video/*"); intent.setType("video/*");
title = GET_VIDEO; title = GET_VIDEO;
} }
else if (this.mediaType == ALLMEDIA) { else if (this.mediaType == ALLMEDIA) {
// I wanted to make the type 'image/*, video/*' but this does not work on all versions // I wanted to make the type 'image/*, video/*' but this does not work on all versions
// of android so I had to go with the wildcard search. // of android so I had to go with the wildcard search.
intent.setType("*/*"); intent.setType("*/*");
title = GET_All; title = GET_All;
} }
intent.setAction(Intent.ACTION_GET_CONTENT); intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE); intent.addCategory(Intent.CATEGORY_OPENABLE);
cordova.startActivityForResult((Plugin) this, Intent.createChooser(intent, if (this.ctx != null) {
new String(title)), (srcType+1)*16 + returnType + 1); this.ctx.startActivityForResult((Plugin) this, Intent.createChooser(intent,
new String(title)), (srcType + 1) * 16 + returnType + 1);
}
} }
/** /**
@ -262,8 +265,8 @@ public class CameraLauncher extends Plugin {
// kept and Bitmap.SCALE_TO_FIT specified when scaling, but this // kept and Bitmap.SCALE_TO_FIT specified when scaling, but this
// would result in whitespace in the new image. // would result in whitespace in the new image.
else { else {
double newRatio = newWidth / (double)newHeight; double newRatio = newWidth / (double) newHeight;
double origRatio = origWidth / (double)origHeight; double origRatio = origWidth / (double) origHeight;
if (origRatio > newRatio) { if (origRatio > newRatio) {
newHeight = (newWidth * origHeight) / origWidth; newHeight = (newWidth * origHeight) / origWidth;
@ -271,10 +274,10 @@ public class CameraLauncher extends Plugin {
newWidth = (newHeight * origWidth) / origHeight; newWidth = (newHeight * origWidth) / origHeight;
} }
} }
return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true); return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
} }
/** /**
* Called when the camera view exits. * Called when the camera view exits.
* *
@ -284,22 +287,22 @@ public class CameraLauncher extends Plugin {
* @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/ */
public void onActivityResult(int requestCode, int resultCode, Intent intent) { public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// Get src and dest types from request code // Get src and dest types from request code
int srcType = (requestCode/16) - 1; int srcType = (requestCode / 16) - 1;
int destType = (requestCode % 16) - 1; int destType = (requestCode % 16) - 1;
int rotate = 0; int rotate = 0;
// Create an ExifHelper to save the exif data that is lost during compression // Create an ExifHelper to save the exif data that is lost during compression
ExifHelper exif = new ExifHelper(); ExifHelper exif = new ExifHelper();
try { try {
if (this.encodingType == JPEG) { if (this.encodingType == JPEG) {
exif.createInFile(DirectoryManager.getTempDirectoryPath(ctx) + "/Pic.jpg"); exif.createInFile(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/Pic.jpg");
exif.readExifData(); exif.readExifData();
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
// If CAMERA // If CAMERA
if (srcType == CAMERA) { if (srcType == CAMERA) {
@ -309,15 +312,15 @@ public class CameraLauncher extends Plugin {
// Read in bitmap of captured image // Read in bitmap of captured image
Bitmap bitmap; Bitmap bitmap;
try { try {
bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getContentResolver(), imageUri); bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getActivity().getContentResolver(), imageUri);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
Uri uri = intent.getData(); Uri uri = intent.getData();
android.content.ContentResolver resolver = this.ctx.getContentResolver(); android.content.ContentResolver resolver = this.ctx.getActivity().getContentResolver();
bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri)); bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
} }
bitmap = scaleBitmap(bitmap); bitmap = scaleBitmap(bitmap);
// If sending base64 image back // If sending base64 image back
if (destType == DATA_URL) { if (destType == DATA_URL) {
this.processPicture(bitmap); this.processPicture(bitmap);
@ -325,33 +328,33 @@ public class CameraLauncher extends Plugin {
} }
// If sending filename back // If sending filename back
else if (destType == FILE_URI){ else if (destType == FILE_URI) {
// Create entry in media store for image // Create entry in media store for image
// (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it)
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
Uri uri = null; Uri uri = null;
try { try {
uri = this.ctx.getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
LOG.d(LOG_TAG, "Can't write to external media storage."); LOG.d(LOG_TAG, "Can't write to external media storage.");
try { try {
uri = this.ctx.getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); uri = this.ctx.getActivity().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.failPicture("Error capturing image - no media storage found."); this.failPicture("Error capturing image - no media storage found.");
return; return;
} }
} }
// Add compressed version of captured image to returned media store Uri // Add compressed version of captured image to returned media store Uri
OutputStream os = this.ctx.getContentResolver().openOutputStream(uri); OutputStream os = this.ctx.getActivity().getContentResolver().openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
os.close(); os.close();
// Restore exif data to file // Restore exif data to file
if (this.encodingType == JPEG) { if (this.encodingType == JPEG) {
exif.createOutFile(FileUtils.getRealPathFromURI(uri, ((Activity) this.ctx))); exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
exif.writeExifData(); exif.writeExifData();
} }
@ -361,12 +364,12 @@ public class CameraLauncher extends Plugin {
bitmap.recycle(); bitmap.recycle();
bitmap = null; bitmap = null;
System.gc(); System.gc();
checkForDuplicateImage(FILE_URI); checkForDuplicateImage(FILE_URI);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
this.failPicture("Error capturing image."); this.failPicture("Error capturing image.");
} }
} }
// If cancelled // If cancelled
@ -379,37 +382,37 @@ public class CameraLauncher extends Plugin {
this.failPicture("Did not complete!"); this.failPicture("Did not complete!");
} }
} }
// If retrieving photo from library // If retrieving photo from library
else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) { else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
Uri uri = intent.getData(); Uri uri = intent.getData();
android.content.ContentResolver resolver = this.ctx.getContentResolver(); android.content.ContentResolver resolver = this.ctx.getActivity().getContentResolver();
// If you ask for video or all media type you will automatically get back a file URI // If you ask for video or all media type you will automatically get back a file URI
// and there will be no attempt to resize any returned data // and there will be no attempt to resize any returned data
if (this.mediaType != PICTURE) { if (this.mediaType != PICTURE) {
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
} }
else { else {
// If sending base64 image back // If sending base64 image back
if (destType == DATA_URL) { if (destType == DATA_URL) {
try { try {
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri)); Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
String[] cols = { MediaStore.Images.Media.ORIENTATION }; String[] cols = { MediaStore.Images.Media.ORIENTATION };
Cursor cursor = this.ctx.getContentResolver().query(intent.getData(), Cursor cursor = this.ctx.getActivity().getContentResolver().query(intent.getData(),
cols, cols,
null, null, null); null, null, null);
if (cursor != null) { if (cursor != null) {
cursor.moveToPosition(0); cursor.moveToPosition(0);
rotate = cursor.getInt(0); rotate = cursor.getInt(0);
cursor.close(); cursor.close();
} }
if (rotate != 0) { if (rotate != 0) {
Matrix matrix = new Matrix(); Matrix matrix = new Matrix();
matrix.setRotate(rotate); matrix.setRotate(rotate);
bitmap = bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
} }
bitmap = scaleBitmap(bitmap); bitmap = scaleBitmap(bitmap);
this.processPicture(bitmap); this.processPicture(bitmap);
bitmap.recycle(); bitmap.recycle();
@ -420,7 +423,7 @@ public class CameraLauncher extends Plugin {
this.failPicture("Error retrieving image."); this.failPicture("Error retrieving image.");
} }
} }
// If sending filename back // If sending filename back
else if (destType == FILE_URI) { else if (destType == FILE_URI) {
// Do we need to scale the returned file // Do we need to scale the returned file
@ -428,21 +431,21 @@ public class CameraLauncher extends Plugin {
try { try {
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri)); Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
bitmap = scaleBitmap(bitmap); bitmap = scaleBitmap(bitmap);
String fileName = DirectoryManager.getTempDirectoryPath(ctx) + "/resize.jpg"; String fileName = DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/resize.jpg";
OutputStream os = new FileOutputStream(fileName); OutputStream os = new FileOutputStream(fileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
os.close(); os.close();
// Restore exif data to file // Restore exif data to file
if (this.encodingType == JPEG) { if (this.encodingType == JPEG) {
exif.createOutFile(FileUtils.getRealPathFromURI(uri, ((Activity) ctx))); exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
exif.writeExifData(); exif.writeExifData();
} }
bitmap.recycle(); bitmap.recycle();
bitmap = null; bitmap = null;
// The resized image is cached by the app in order to get around this and not have to delete you // The resized image is cached by the app in order to get around this and not have to delete you
// application cache I'm adding the current system time to the end of the file url. // application cache I'm adding the current system time to the end of the file url.
this.success(new PluginResult(PluginResult.Status.OK, ("file://" + fileName + "?" + System.currentTimeMillis())), this.callbackId); this.success(new PluginResult(PluginResult.Status.OK, ("file://" + fileName + "?" + System.currentTimeMillis())), this.callbackId);
@ -453,16 +456,16 @@ public class CameraLauncher extends Plugin {
} }
} }
else { else {
this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId); this.success(new PluginResult(PluginResult.Status.OK, uri.toString()), this.callbackId);
} }
} }
} }
} }
else if (resultCode == Activity.RESULT_CANCELED) { else if (resultCode == Activity.RESULT_CANCELED) {
this.failPicture("Selection cancelled."); this.failPicture("Selection cancelled.");
} }
else { else {
this.failPicture("Selection did not complete!"); this.failPicture("Selection did not complete!");
} }
} }
} }
@ -473,14 +476,14 @@ public class CameraLauncher extends Plugin {
* @return a cursor * @return a cursor
*/ */
private Cursor queryImgDB() { private Cursor queryImgDB() {
return this.ctx.getContentResolver().query( return this.ctx.getActivity().getContentResolver().query(
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.Media._ID }, new String[] { MediaStore.Images.Media._ID },
null, null,
null, null,
null); null);
} }
/** /**
* Used to find out if we are in a situation where the Camera Intent adds to images * Used to find out if we are in a situation where the Camera Intent adds to images
* to the content store. If we are using a FILE_URI and the number of images in the DB * to the content store. If we are using a FILE_URI and the number of images in the DB
@ -492,17 +495,17 @@ public class CameraLauncher extends Plugin {
int diff = 1; int diff = 1;
Cursor cursor = queryImgDB(); Cursor cursor = queryImgDB();
int currentNumOfImages = cursor.getCount(); int currentNumOfImages = cursor.getCount();
if (type == FILE_URI) { if (type == FILE_URI) {
diff = 2; diff = 2;
} }
// delete the duplicate file if the difference is 2 for file URI or 1 for Data URL // delete the duplicate file if the difference is 2 for file URI or 1 for Data URL
if ((currentNumOfImages - numPics) == diff) { if ((currentNumOfImages - numPics) == diff) {
cursor.moveToLast(); cursor.moveToLast();
int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1; int id = Integer.valueOf(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media._ID))) - 1;
Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id); Uri uri = Uri.parse(MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + id);
this.ctx.getContentResolver().delete(uri, null, null); this.ctx.getActivity().getContentResolver().delete(uri, null, null);
} }
} }
@ -511,25 +514,24 @@ public class CameraLauncher extends Plugin {
* *
* @param bitmap * @param bitmap
*/ */
public void processPicture(Bitmap bitmap) { public void processPicture(Bitmap bitmap) {
ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream(); ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
try { try {
if (bitmap.compress(CompressFormat.JPEG, mQuality, jpeg_data)) { if (bitmap.compress(CompressFormat.JPEG, mQuality, jpeg_data)) {
byte[] code = jpeg_data.toByteArray(); byte[] code = jpeg_data.toByteArray();
byte[] output = Base64.encodeBase64(code); byte[] output = Base64.encodeBase64(code);
String js_out = new String(output); String js_out = new String(output);
this.success(new PluginResult(PluginResult.Status.OK, js_out), this.callbackId); this.success(new PluginResult(PluginResult.Status.OK, js_out), this.callbackId);
js_out = null; js_out = null;
output = null; output = null;
code = null; code = null;
} }
} } catch (Exception e) {
catch(Exception e) {
this.failPicture("Error compressing image."); this.failPicture("Error compressing image.");
} }
jpeg_data = null; jpeg_data = null;
} }
/** /**
* Send error message to JavaScript. * Send error message to JavaScript.
* *

View File

@ -32,7 +32,7 @@ import org.json.JSONObject;
import android.app.Activity; import android.app.Activity;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; //import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
@ -40,47 +40,47 @@ import android.media.MediaPlayer;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
public class Capture extends Plugin { public class Capture extends Plugin {
private static final String VIDEO_3GPP = "video/3gpp"; private static final String VIDEO_3GPP = "video/3gpp";
private static final String VIDEO_MP4 = "video/mp4"; private static final String VIDEO_MP4 = "video/mp4";
private static final String AUDIO_3GPP = "audio/3gpp"; private static final String AUDIO_3GPP = "audio/3gpp";
private static final String IMAGE_JPEG = "image/jpeg"; private static final String IMAGE_JPEG = "image/jpeg";
private static final int CAPTURE_AUDIO = 0; // Constant for capture audio private static final int CAPTURE_AUDIO = 0; // Constant for capture audio
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_INTERNAL_ERR = 0;
private static final int CAPTURE_APPLICATION_BUSY = 1; // private static final int CAPTURE_APPLICATION_BUSY = 1;
private static final int CAPTURE_INVALID_ARGUMENT = 2; // private static final int CAPTURE_INVALID_ARGUMENT = 2;
private static final int CAPTURE_NO_MEDIA_FILES = 3; private static final int CAPTURE_NO_MEDIA_FILES = 3;
private static final int CAPTURE_NOT_SUPPORTED = 20; // 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
private JSONArray results; // The array of results to be returned to the user private JSONArray results; // The array of results to be returned to the user
private Uri imageUri; // Uri of captured image private Uri imageUri; // Uri of captured image
private CordovaInterface cordova;
public void setContext(Context mCtx) //private CordovaInterface cordova;
{
if(CordovaInterface.class.isInstance(mCtx)) // public void setContext(Context mCtx)
cordova = (CordovaInterface) mCtx; // {
else // if (CordovaInterface.class.isInstance(mCtx))
LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity"); // cordova = (CordovaInterface) mCtx;
} // else
// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
// }
@Override @Override
public PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
this.callbackId = callbackId; this.callbackId = callbackId;
this.limit = 1; this.limit = 1;
this.duration = 0.0f; this.duration = 0.0f;
this.results = new JSONArray(); this.results = new JSONArray();
JSONObject options = args.optJSONObject(0); JSONObject options = args.optJSONObject(0);
if (options != null) { if (options != null) {
limit = options.optLong("limit", 1); limit = options.optLong("limit", 1);
@ -102,9 +102,9 @@ public class Capture extends Plugin {
this.captureImage(); this.captureImage();
} }
else if (action.equals("captureVideo")) { else if (action.equals("captureVideo")) {
this.captureVideo(duration); this.captureVideo(duration);
} }
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT); PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
r.setKeepCallback(true); r.setKeepCallback(true);
return r; return r;
@ -133,7 +133,7 @@ public class Capture extends Plugin {
mimeType = FileUtils.getMimeType(filePath); mimeType = FileUtils.getMimeType(filePath);
} }
Log.d(LOG_TAG, "Mime type = " + mimeType); Log.d(LOG_TAG, "Mime type = " + mimeType);
if (mimeType.equals(IMAGE_JPEG) || filePath.endsWith(".jpg")) { if (mimeType.equals(IMAGE_JPEG) || filePath.endsWith(".jpg")) {
obj = getImageData(filePath, obj); obj = getImageData(filePath, obj);
} }
@ -143,8 +143,7 @@ public class Capture extends Plugin {
else if (mimeType.equals(VIDEO_3GPP) || mimeType.equals(VIDEO_MP4)) { else if (mimeType.equals(VIDEO_3GPP) || mimeType.equals(VIDEO_MP4)) {
obj = getAudioVideoData(filePath, obj, true); obj = getAudioVideoData(filePath, obj, true);
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Error: setting media file data object"); Log.d(LOG_TAG, "Error: setting media file data object");
} }
return obj; return obj;
@ -179,15 +178,14 @@ public class Capture extends Plugin {
try { try {
player.setDataSource(filePath); player.setDataSource(filePath);
player.prepare(); player.prepare();
obj.put("duration", player.getDuration()/1000); obj.put("duration", player.getDuration() / 1000);
if (video) { if (video) {
obj.put("height", player.getVideoHeight()); obj.put("height", player.getVideoHeight());
obj.put("width", player.getVideoWidth()); obj.put("width", player.getVideoWidth());
} }
} } catch (IOException e) {
catch (IOException e) {
Log.d(LOG_TAG, "Error: loading video file"); Log.d(LOG_TAG, "Error: loading video file");
} }
return obj; return obj;
} }
@ -197,7 +195,7 @@ public class Capture extends Plugin {
private void captureAudio() { private void captureAudio() {
Intent intent = new Intent(android.provider.MediaStore.Audio.Media.RECORD_SOUND_ACTION); Intent intent = new Intent(android.provider.MediaStore.Audio.Media.RECORD_SOUND_ACTION);
cordova.startActivityForResult((Plugin) this, intent, CAPTURE_AUDIO); this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_AUDIO);
} }
/** /**
@ -207,11 +205,11 @@ public class Capture extends Plugin {
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
// Specify file so that large image is captured and returned // Specify file so that large image is captured and returned
File photo = new File(DirectoryManager.getTempDirectoryPath(ctx), "Capture.jpg"); File photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Capture.jpg");
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo)); intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
this.imageUri = Uri.fromFile(photo); this.imageUri = Uri.fromFile(photo);
cordova.startActivityForResult((Plugin) this, intent, CAPTURE_IMAGE); this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_IMAGE);
} }
/** /**
@ -221,10 +219,10 @@ public class Capture extends Plugin {
Intent intent = new Intent(android.provider.MediaStore.ACTION_VIDEO_CAPTURE); Intent intent = new Intent(android.provider.MediaStore.ACTION_VIDEO_CAPTURE);
// Introduced in API 8 // Introduced in API 8
//intent.putExtra(android.provider.MediaStore.EXTRA_DURATION_LIMIT, duration); //intent.putExtra(android.provider.MediaStore.EXTRA_DURATION_LIMIT, duration);
cordova.startActivityForResult((Plugin) this, intent, CAPTURE_VIDEO); this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_VIDEO);
} }
/** /**
* Called when the video view exits. * Called when the video view exits.
* *
@ -260,11 +258,11 @@ public class Capture extends Plugin {
try { try {
// Create an ExifHelper to save the exif data that is lost during compression // Create an ExifHelper to save the exif data that is lost during compression
ExifHelper exif = new ExifHelper(); ExifHelper exif = new ExifHelper();
exif.createInFile(DirectoryManager.getTempDirectoryPath(ctx) + "/Capture.jpg"); exif.createInFile(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/Capture.jpg");
exif.readExifData(); exif.readExifData();
// Read in bitmap of captured image // Read in bitmap of captured image
Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getContentResolver(), imageUri); Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getActivity().getContentResolver(), imageUri);
// Create entry in media store for image // Create entry in media store for image
// (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it)
@ -272,34 +270,34 @@ public class Capture extends Plugin {
values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, IMAGE_JPEG); values.put(android.provider.MediaStore.Images.Media.MIME_TYPE, IMAGE_JPEG);
Uri uri = null; Uri uri = null;
try { try {
uri = this.ctx.getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); uri = this.ctx.getActivity().getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
LOG.d(LOG_TAG, "Can't write to external media storage."); LOG.d(LOG_TAG, "Can't write to external media storage.");
try { try {
uri = this.ctx.getContentResolver().insert(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, values); uri = this.ctx.getActivity().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(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image - no media storage found.")); this.fail(createErrorObject(CAPTURE_INTERNAL_ERR, "Error capturing image - no media storage found."));
return; return;
} }
} }
// Add compressed version of captured image to returned media store Uri // Add compressed version of captured image to returned media store Uri
OutputStream os = this.ctx.getContentResolver().openOutputStream(uri); OutputStream os = this.ctx.getActivity().getContentResolver().openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
os.close(); os.close();
bitmap.recycle(); bitmap.recycle();
bitmap = null; bitmap = null;
System.gc(); System.gc();
// Restore exif data to file // Restore exif data to file
exif.createOutFile(FileUtils.getRealPathFromURI(uri, ((Activity) this.ctx))); exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
exif.writeExifData(); exif.writeExifData();
// Add image to results // Add image to results
results.put(createMediaFile(uri)); results.put(createMediaFile(uri));
if (results.length() >= limit) { if (results.length() >= limit) {
// Send Uri back to JavaScript for viewing image // Send Uri back to JavaScript for viewing image
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId); this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
@ -330,7 +328,7 @@ public class Capture extends Plugin {
else if (resultCode == Activity.RESULT_CANCELED) { else if (resultCode == Activity.RESULT_CANCELED) {
// If we have partial results send them back to the user // If we have partial results send them back to the user
if (results.length() > 0) { if (results.length() > 0) {
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId); this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
} }
// user canceled the action // user canceled the action
else { else {
@ -341,7 +339,7 @@ public class Capture extends Plugin {
else { else {
// If we have partial results send them back to the user // If we have partial results send them back to the user
if (results.length() > 0) { if (results.length() > 0) {
this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId); this.success(new PluginResult(PluginResult.Status.OK, results), this.callbackId);
} }
// something bad happened // something bad happened
else { else {
@ -357,38 +355,38 @@ public class Capture extends Plugin {
* @return a JSONObject that represents a File * @return a JSONObject that represents a File
* @throws IOException * @throws IOException
*/ */
private JSONObject createMediaFile(Uri data){ private JSONObject createMediaFile(Uri data) {
File fp = new File(FileUtils.getRealPathFromURI(data, ((Activity) this.ctx))); File fp = new File(FileUtils.getRealPathFromURI(data, this.ctx));
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
try { try {
// File properties // File properties
obj.put("name", fp.getName()); obj.put("name", fp.getName());
obj.put("fullPath", fp.getAbsolutePath()); obj.put("fullPath", fp.getAbsolutePath());
// Because of an issue with MimeTypeMap.getMimeTypeFromExtension() all .3gpp files // Because of an issue with MimeTypeMap.getMimeTypeFromExtension() all .3gpp files
// are reported as video/3gpp. I'm doing this hacky check of the URI to see if it // are reported as video/3gpp. I'm doing this hacky check of the URI to see if it
// is stored in the audio or video content store. // is stored in the audio or video content store.
if (fp.getAbsoluteFile().toString().endsWith(".3gp") || fp.getAbsoluteFile().toString().endsWith(".3gpp")) { if (fp.getAbsoluteFile().toString().endsWith(".3gp") || fp.getAbsoluteFile().toString().endsWith(".3gpp")) {
if (data.toString().contains("/audio/")) { if (data.toString().contains("/audio/")) {
obj.put("type", AUDIO_3GPP); obj.put("type", AUDIO_3GPP);
} else { } else {
obj.put("type", VIDEO_3GPP); obj.put("type", VIDEO_3GPP);
} }
} else { } else {
obj.put("type", FileUtils.getMimeType(fp.getAbsolutePath())); obj.put("type", FileUtils.getMimeType(fp.getAbsolutePath()));
} }
obj.put("lastModifiedDate", fp.lastModified()); obj.put("lastModifiedDate", fp.lastModified());
obj.put("size", fp.length()); obj.put("size", fp.length());
} catch (JSONException e) { } catch (JSONException e) {
// this will never happen // this will never happen
e.printStackTrace(); e.printStackTrace();
} }
return obj; return obj;
} }
private JSONObject createErrorObject(int code, String message) { private JSONObject createErrorObject(int code, String message) {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
try { try {

View File

@ -27,7 +27,6 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.hardware.Sensor; import android.hardware.Sensor;
import android.hardware.SensorEvent; import android.hardware.SensorEvent;
import android.hardware.SensorEventListener; import android.hardware.SensorEventListener;
@ -43,18 +42,18 @@ public class CompassListener extends Plugin implements SensorEventListener {
public static int STARTING = 1; public static int STARTING = 1;
public static int RUNNING = 2; public static int RUNNING = 2;
public static int ERROR_FAILED_TO_START = 3; public static int ERROR_FAILED_TO_START = 3;
public long TIMEOUT = 30000; // Timeout in msec to shut off listener public long TIMEOUT = 30000; // Timeout in msec to shut off listener
int status; // status of listener int status; // status of listener
float heading; // most recent heading value float heading; // most recent heading value
long timeStamp; // time of most recent value long timeStamp; // time of most recent value
long lastAccessTime; // time the value was last retrieved long lastAccessTime; // time the value was last retrieved
int accuracy; // accuracy of the sensor int accuracy; // accuracy of the sensor
private SensorManager sensorManager;// Sensor manager private SensorManager sensorManager;// Sensor manager
Sensor mSensor; // Compass sensor returned by sensor manager Sensor mSensor; // Compass sensor returned by sensor manager
/** /**
* Constructor. * Constructor.
*/ */
@ -70,9 +69,9 @@ public class CompassListener extends Plugin implements SensorEventListener {
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(Context ctx) { public void setContext(CordovaInterface ctx) {
super.setContext(ctx); super.setContext(ctx);
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE); this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE);
} }
/** /**
@ -85,8 +84,8 @@ public class CompassListener extends Plugin implements SensorEventListener {
*/ */
public PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.OK; PluginResult.Status status = PluginResult.Status.OK;
String result = ""; String result = "";
try { try {
if (action.equals("start")) { if (action.equals("start")) {
this.start(); this.start();
@ -116,7 +115,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
} }
} }
if (timeout == 0) { if (timeout == 0) {
return new PluginResult(PluginResult.Status.IO_EXCEPTION, CompassListener.ERROR_FAILED_TO_START); return new PluginResult(PluginResult.Status.IO_EXCEPTION, CompassListener.ERROR_FAILED_TO_START);
} }
} }
return new PluginResult(status, getCompassHeading()); return new PluginResult(status, getCompassHeading());
@ -159,7 +158,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
} }
return false; return false;
} }
/** /**
* Called when listener is to be shut down and object is being destroyed. * Called when listener is to be shut down and object is being destroyed.
*/ */
@ -177,13 +176,14 @@ public class CompassListener extends Plugin implements SensorEventListener {
* @return status of listener * @return status of listener
*/ */
public int start() { public int start() {
// If already starting or running, then just return // If already starting or running, then just return
if ((this.status == CompassListener.RUNNING) || (this.status == CompassListener.STARTING)) { if ((this.status == CompassListener.RUNNING) || (this.status == CompassListener.STARTING)) {
return this.status; return this.status;
} }
// Get compass sensor from sensor manager // Get compass sensor from sensor manager
@SuppressWarnings("deprecation")
List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ORIENTATION); List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
// If found, then register as listener // If found, then register as listener
@ -198,10 +198,10 @@ public class CompassListener extends Plugin implements SensorEventListener {
else { else {
this.setStatus(CompassListener.ERROR_FAILED_TO_START); this.setStatus(CompassListener.ERROR_FAILED_TO_START);
} }
return this.status; return this.status;
} }
/** /**
* Stop listening to compass sensor. * Stop listening to compass sensor.
*/ */
@ -211,8 +211,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
} }
this.setStatus(CompassListener.STOPPED); this.setStatus(CompassListener.STOPPED);
} }
public void onAccuracyChanged(Sensor sensor, int accuracy) { public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
@ -237,7 +236,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
this.stop(); this.stop();
} }
} }
/** /**
* Get status of compass sensor. * Get status of compass sensor.
* *
@ -246,7 +245,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
public int getStatus() { public int getStatus() {
return this.status; return this.status;
} }
/** /**
* Get the most recent compass heading. * Get the most recent compass heading.
* *
@ -256,7 +255,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
this.lastAccessTime = System.currentTimeMillis(); this.lastAccessTime = System.currentTimeMillis();
return this.heading; return this.heading;
} }
/** /**
* Set the timeout to turn off compass sensor if getHeading() hasn't been called. * Set the timeout to turn off compass sensor if getHeading() hasn't been called.
* *
@ -265,7 +264,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
public void setTimeout(long timeout) { public void setTimeout(long timeout) {
this.TIMEOUT = timeout; this.TIMEOUT = timeout;
} }
/** /**
* Get the timeout to turn off compass sensor if getHeading() hasn't been called. * Get the timeout to turn off compass sensor if getHeading() hasn't been called.
* *
@ -290,7 +289,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
*/ */
private JSONObject getCompassHeading() { private JSONObject getCompassHeading() {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
try { try {
obj.put("magneticHeading", this.getHeading()); obj.put("magneticHeading", this.getHeading());
obj.put("trueHeading", this.getHeading()); obj.put("trueHeading", this.getHeading());
@ -301,7 +300,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
} catch (JSONException e) { } catch (JSONException e) {
// Should never happen // Should never happen
} }
return obj; return obj;
} }

View File

@ -18,11 +18,12 @@ package org.apache.cordova;
import java.util.HashMap; import java.util.HashMap;
import android.app.Activity; //import android.app.Activity;
import android.content.Context; //import android.content.Context;
import android.util.Log; import android.util.Log;
import android.webkit.WebView; import android.webkit.WebView;
import org.apache.cordova.api.CordovaInterface;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -35,11 +36,11 @@ import org.json.JSONObject;
* Eclair or higher, we want to use {@link ContactAccessorSdk5}. * Eclair or higher, we want to use {@link ContactAccessorSdk5}.
*/ */
public abstract class ContactAccessor { public abstract class ContactAccessor {
protected final String LOG_TAG = "ContactsAccessor"; protected final String LOG_TAG = "ContactsAccessor";
protected Context mApp; protected CordovaInterface mApp;
protected WebView mView; protected WebView mView;
/** /**
* Check to see if the data associated with the key is required to * Check to see if the data associated with the key is required to
* be populated in the Contact object. * be populated in the Contact object.
@ -47,22 +48,22 @@ public abstract class ContactAccessor {
* @param map created by running buildPopulationSet. * @param map created by running buildPopulationSet.
* @return true if the key data is required * @return true if the key data is required
*/ */
protected boolean isRequired(String key, HashMap<String,Boolean> map) { protected boolean isRequired(String key, HashMap<String, Boolean> map) {
Boolean retVal = map.get(key); Boolean retVal = map.get(key);
return (retVal == null) ? false : retVal.booleanValue(); return (retVal == null) ? false : retVal.booleanValue();
} }
/** /**
* Create a hash map of what data needs to be populated in the Contact object * Create a hash map of what data needs to be populated in the Contact object
* @param fields the list of fields to populate * @param fields the list of fields to populate
* @return the hash map of required data * @return the hash map of required data
*/ */
protected HashMap<String,Boolean> buildPopulationSet(JSONArray fields) { protected HashMap<String, Boolean> buildPopulationSet(JSONArray fields) {
HashMap<String,Boolean> map = new HashMap<String,Boolean>(); HashMap<String, Boolean> map = new HashMap<String, Boolean>();
String key; String key;
try { try {
if (fields.length() == 1 && fields.getString(0).equals("*")) { if (fields.length() == 1 && fields.getString(0).equals("*")) {
map.put("displayName", true); map.put("displayName", true);
map.put("name", true); map.put("name", true);
map.put("nickname", true); map.put("nickname", true);
@ -76,90 +77,88 @@ public abstract class ContactAccessor {
map.put("urls", true); map.put("urls", true);
map.put("photos", true); map.put("photos", true);
map.put("categories", true); map.put("categories", true);
}
else {
for (int i=0; i<fields.length(); i++) {
key = fields.getString(i);
if (key.startsWith("displayName")) {
map.put("displayName", true);
}
else if (key.startsWith("name")) {
map.put("displayName", true);
map.put("name", true);
}
else if (key.startsWith("nickname")) {
map.put("nickname", true);
}
else if (key.startsWith("phoneNumbers")) {
map.put("phoneNumbers", true);
}
else if (key.startsWith("emails")) {
map.put("emails", true);
}
else if (key.startsWith("addresses")) {
map.put("addresses", true);
}
else if (key.startsWith("ims")) {
map.put("ims", true);
}
else if (key.startsWith("organizations")) {
map.put("organizations", true);
}
else if (key.startsWith("birthday")) {
map.put("birthday", true);
}
else if (key.startsWith("note")) {
map.put("note", true);
}
else if (key.startsWith("urls")) {
map.put("urls", true);
} }
else {
for (int i = 0; i < fields.length(); i++) {
key = fields.getString(i);
if (key.startsWith("displayName")) {
map.put("displayName", true);
}
else if (key.startsWith("name")) {
map.put("displayName", true);
map.put("name", true);
}
else if (key.startsWith("nickname")) {
map.put("nickname", true);
}
else if (key.startsWith("phoneNumbers")) {
map.put("phoneNumbers", true);
}
else if (key.startsWith("emails")) {
map.put("emails", true);
}
else if (key.startsWith("addresses")) {
map.put("addresses", true);
}
else if (key.startsWith("ims")) {
map.put("ims", true);
}
else if (key.startsWith("organizations")) {
map.put("organizations", true);
}
else if (key.startsWith("birthday")) {
map.put("birthday", true);
}
else if (key.startsWith("note")) {
map.put("note", true);
}
else if (key.startsWith("urls")) {
map.put("urls", true);
}
else if (key.startsWith("photos")) { else if (key.startsWith("photos")) {
map.put("photos", true); map.put("photos", true);
} }
else if (key.startsWith("categories")) { else if (key.startsWith("categories")) {
map.put("categories", true); map.put("categories", true);
} }
} }
}
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
} }
return map;
} }
catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e); /**
} * Convenience method to get a string from a JSON object. Saves a
return map; * lot of try/catch writing.
} * If the property is not found in the object null will be returned.
*
/** * @param obj contact object to search
* Convenience method to get a string from a JSON object. Saves a * @param property to be looked up
* lot of try/catch writing. * @return The value of the property
* If the property is not found in the object null will be returned. */
* protected String getJsonString(JSONObject obj, String property) {
* @param obj contact object to search String value = null;
* @param property to be looked up try {
* @return The value of the property if (obj != null) {
*/ value = obj.getString(property);
protected String getJsonString(JSONObject obj, String property) { if (value.equals("null")) {
String value = null; Log.d(LOG_TAG, property + " is string called 'null'");
try { value = null;
if (obj != null) { }
value = obj.getString(property); }
if (value.equals("null")) { } catch (JSONException e) {
Log.d(LOG_TAG, property + " is string called 'null'"); Log.d(LOG_TAG, "Could not get = " + e.getMessage());
value = null;
}
} }
return value;
} }
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get = " + e.getMessage());
}
return value;
}
/** /**
* Handles adding a JSON Contact object into the database. * Handles adding a JSON Contact object into the database.
* @return TODO * @return TODO
*/ */
public abstract String save(JSONObject contact); public abstract String save(JSONObject contact);
/** /**
* Handles searching through SDK-specific contacts API. * Handles searching through SDK-specific contacts API.
@ -175,25 +174,29 @@ public abstract class ContactAccessor {
/** /**
* Handles removing a contact from the database. * Handles removing a contact from the database.
*/ */
public abstract boolean remove(String id); public abstract boolean remove(String id);
/** /**
* A class that represents the where clause to be used in the database query * A class that represents the where clause to be used in the database query
*/ */
class WhereOptions { class WhereOptions {
private String where; private String where;
private String[] whereArgs; private String[] whereArgs;
public void setWhere(String where) {
this.where = where; public void setWhere(String where) {
this.where = where;
}
public String getWhere() {
return where;
}
public void setWhereArgs(String[] whereArgs) {
this.whereArgs = whereArgs;
}
public String[] getWhereArgs() {
return whereArgs;
}
} }
public String getWhere() {
return where;
}
public void setWhereArgs(String[] whereArgs) {
this.whereArgs = whereArgs;
}
public String[] getWhereArgs() {
return whereArgs;
}
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -17,17 +17,18 @@
under the License. under the License.
*/ */
package org.apache.cordova; package org.apache.cordova;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
//import android.app.Activity;
import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; //import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; //import android.view.View;
import android.webkit.ConsoleMessage; import android.webkit.ConsoleMessage;
import android.webkit.JsPromptResult; import android.webkit.JsPromptResult;
import android.webkit.JsResult; import android.webkit.JsResult;
@ -41,34 +42,41 @@ import android.widget.EditText;
* This class is the WebChromeClient that implements callbacks for our web view. * This class is the WebChromeClient that implements callbacks for our web view.
*/ */
public class CordovaChromeClient extends WebChromeClient { public class CordovaChromeClient extends WebChromeClient {
private String TAG = "CordovaLog"; private String TAG = "CordovaLog";
private long MAX_QUOTA = 100 * 1024 * 1024; private long MAX_QUOTA = 100 * 1024 * 1024;
private Activity ctx; private CordovaInterface ctx;
private CordovaWebView appView; private CordovaWebView appView;
/** /**
* Constructor. * Constructor.
* *
* @param ctx * @param ctx
*/ */
public CordovaChromeClient(Context ctx) { public CordovaChromeClient(CordovaInterface ctx) {
this.ctx = (Activity) ctx; this.ctx = ctx;
//appView = this.ctx.appView;
}
public CordovaChromeClient(Context ctx, CordovaWebView app)
{
this.ctx = (Activity) ctx;
appView = app;
} }
public void setWebView(CordovaWebView view) /**
{ * Constructor.
appView = view; *
* @param ctx
* @param app
*/
public CordovaChromeClient(CordovaInterface ctx, CordovaWebView app) {
this.ctx = ctx;
this.appView = app;
} }
/**
* Constructor.
*
* @param view
*/
public void setWebView(CordovaWebView view) {
this.appView = view;
}
/** /**
* Tell the client to display a javascript alert dialog. * Tell the client to display a javascript alert dialog.
* *
@ -79,39 +87,39 @@ public class CordovaChromeClient extends WebChromeClient {
*/ */
@Override @Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) { public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx); AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx.getActivity());
dlg.setMessage(message); dlg.setMessage(message);
dlg.setTitle("Alert"); dlg.setTitle("Alert");
//Don't let alerts break the back button //Don't let alerts break the back button
dlg.setCancelable(true); dlg.setCancelable(true);
dlg.setPositiveButton(android.R.string.ok, dlg.setPositiveButton(android.R.string.ok,
new AlertDialog.OnClickListener() { new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
result.confirm(); result.confirm();
} }
}); });
dlg.setOnCancelListener( dlg.setOnCancelListener(
new DialogInterface.OnCancelListener() { new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
result.confirm(); result.confirm();
} }
}); });
dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
//DO NOTHING //DO NOTHING
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) if (keyCode == KeyEvent.KEYCODE_BACK)
{ {
result.confirm(); result.confirm();
return false; return false;
} }
else else
return true; return true;
} }
}); });
dlg.create(); dlg.create();
dlg.show(); dlg.show();
return true; return true;
} }
/** /**
* Tell the client to display a confirm dialog to the user. * Tell the client to display a confirm dialog to the user.
@ -123,40 +131,40 @@ public class CordovaChromeClient extends WebChromeClient {
*/ */
@Override @Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) { public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx); AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx.getActivity());
dlg.setMessage(message); dlg.setMessage(message);
dlg.setTitle("Confirm"); dlg.setTitle("Confirm");
dlg.setCancelable(true); dlg.setCancelable(true);
dlg.setPositiveButton(android.R.string.ok, dlg.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
result.confirm(); result.confirm();
} }
}); });
dlg.setNegativeButton(android.R.string.cancel, dlg.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
result.cancel(); result.cancel();
} }
}); });
dlg.setOnCancelListener( dlg.setOnCancelListener(
new DialogInterface.OnCancelListener() { new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
result.cancel(); result.cancel();
} }
}); });
dlg.setOnKeyListener(new DialogInterface.OnKeyListener() { dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
//DO NOTHING //DO NOTHING
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) if (keyCode == KeyEvent.KEYCODE_BACK)
{ {
result.cancel(); result.cancel();
return false; return false;
} }
else else
return true; return true;
} }
}); });
dlg.create(); dlg.create();
dlg.show(); dlg.show();
return true; return true;
@ -178,14 +186,14 @@ public class CordovaChromeClient extends WebChromeClient {
*/ */
@Override @Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) { public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
// Security check to make sure any requests are coming from the page initially // Security check to make sure any requests are coming from the page initially
// loaded in webview and not another loaded in an iframe. // loaded in webview and not another loaded in an iframe.
boolean reqOk = false; boolean reqOk = false;
if (url.startsWith("file://") || url.indexOf(appView.baseUrl) == 0 || appView.isUrlWhiteListed(url)) { if (url.startsWith("file://") || url.indexOf(this.appView.baseUrl) == 0 || this.appView.isUrlWhiteListed(url)) {
reqOk = true; reqOk = true;
} }
// Calling PluginManager.exec() to call a native service using // Calling PluginManager.exec() to call a native service using
// prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true])); // prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) { if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
@ -196,67 +204,72 @@ public class CordovaChromeClient extends WebChromeClient {
String action = array.getString(1); String action = array.getString(1);
String callbackId = array.getString(2); String callbackId = array.getString(2);
boolean async = array.getBoolean(3); boolean async = array.getBoolean(3);
String r = appView.pluginManager.exec(service, action, callbackId, message, async); String r = this.appView.pluginManager.exec(service, action, callbackId, message, async);
result.confirm(r); result.confirm(r);
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
// Polling for JavaScript messages // Polling for JavaScript messages
else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) { else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
String r = appView.callbackServer.getJavascript(); String r = this.appView.callbackServer.getJavascript();
result.confirm(r); result.confirm(r);
} }
// Do NO-OP so older code doesn't display dialog
else if (defaultValue.equals("gap_init:")) {
result.confirm("OK");
}
// Calling into CallbackServer // Calling into CallbackServer
else if (reqOk && defaultValue != null && defaultValue.equals("gap_callbackServer:")) { else if (reqOk && defaultValue != null && defaultValue.equals("gap_callbackServer:")) {
String r = ""; String r = "";
if (message.equals("usePolling")) { if (message.equals("usePolling")) {
r = ""+ appView.callbackServer.usePolling(); r = "" + this.appView.callbackServer.usePolling();
} }
else if (message.equals("restartServer")) { else if (message.equals("restartServer")) {
appView.callbackServer.restartServer(); this.appView.callbackServer.restartServer();
} }
else if (message.equals("getPort")) { else if (message.equals("getPort")) {
r = Integer.toString(appView.callbackServer.getPort()); r = Integer.toString(this.appView.callbackServer.getPort());
} }
else if (message.equals("getToken")) { else if (message.equals("getToken")) {
r = appView.callbackServer.getToken(); r = this.appView.callbackServer.getToken();
} }
result.confirm(r); result.confirm(r);
} }
// Show dialog // Show dialog
else { else {
final JsPromptResult res = result; final JsPromptResult res = result;
AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx); AlertDialog.Builder dlg = new AlertDialog.Builder(this.ctx.getActivity());
dlg.setMessage(message); dlg.setMessage(message);
final EditText input = new EditText(this.ctx); final EditText input = new EditText(this.ctx.getActivity());
if (defaultValue != null) { if (defaultValue != null) {
input.setText(defaultValue); input.setText(defaultValue);
} }
dlg.setView(input); dlg.setView(input);
dlg.setCancelable(false); dlg.setCancelable(false);
dlg.setPositiveButton(android.R.string.ok, dlg.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
String usertext = input.getText().toString(); String usertext = input.getText().toString();
res.confirm(usertext); res.confirm(usertext);
} }
}); });
dlg.setNegativeButton(android.R.string.cancel, dlg.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
res.cancel(); res.cancel();
} }
}); });
dlg.create(); dlg.create();
dlg.show(); dlg.show();
} }
return true; return true;
} }
/** /**
* Handle database quota exceeded notification. * Handle database quota exceeded notification.
* *
@ -273,7 +286,7 @@ public class CordovaChromeClient extends WebChromeClient {
{ {
LOG.d(TAG, "DroidGap: onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota); LOG.d(TAG, "DroidGap: onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
if( estimatedSize < MAX_QUOTA) if (estimatedSize < MAX_QUOTA)
{ {
//increase for 1Mb //increase for 1Mb
long newQuota = estimatedSize; long newQuota = estimatedSize;
@ -289,17 +302,18 @@ public class CordovaChromeClient extends WebChromeClient {
} }
// console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html // console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html
@SuppressWarnings("deprecation")
@Override @Override
public void onConsoleMessage(String message, int lineNumber, String sourceID) public void onConsoleMessage(String message, int lineNumber, String sourceID)
{ {
LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message); LOG.d(TAG, "%s: Line %d : %s", sourceID, lineNumber, message);
super.onConsoleMessage(message, lineNumber, sourceID); super.onConsoleMessage(message, lineNumber, sourceID);
} }
@Override @Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) public boolean onConsoleMessage(ConsoleMessage consoleMessage)
{ {
if(consoleMessage.message() != null) if (consoleMessage.message() != null)
LOG.d(TAG, consoleMessage.message()); LOG.d(TAG, consoleMessage.message());
return super.onConsoleMessage(consoleMessage); return super.onConsoleMessage(consoleMessage);
} }
@ -315,6 +329,4 @@ public class CordovaChromeClient extends WebChromeClient {
super.onGeolocationPermissionsShowPrompt(origin, callback); super.onGeolocationPermissionsShowPrompt(origin, callback);
callback.invoke(origin, true, false); callback.invoke(origin, true, false);
} }
} }

1
framework/src/org/apache/cordova/CordovaException.java Normal file → Executable file
View File

@ -20,5 +20,4 @@
package org.apache.cordova; package org.apache.cordova;
public class CordovaException extends Exception { public class CordovaException extends Exception {
} }

File diff suppressed because it is too large Load Diff

View File

@ -18,10 +18,15 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import org.apache.cordova.api.LOG; import java.util.Hashtable;
import android.app.Activity; import org.apache.cordova.api.CordovaInterface;
import android.content.Context; import org.apache.cordova.api.LOG;
import org.json.JSONException;
import org.json.JSONObject;
//import android.app.Activity;
//import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -29,7 +34,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.net.http.SslError; import android.net.http.SslError;
import android.util.Log; //import android.util.Log;
import android.view.View; import android.view.View;
import android.webkit.HttpAuthHandler; import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler; import android.webkit.SslErrorHandler;
@ -40,32 +45,44 @@ import android.webkit.WebViewClient;
* This class is the WebViewClient that implements callbacks for our web view. * This class is the WebViewClient that implements callbacks for our web view.
*/ */
public class CordovaWebViewClient extends WebViewClient { public class CordovaWebViewClient extends WebViewClient {
private static final String TAG = "Cordova"; private static final String TAG = "Cordova";
Activity ctx; CordovaInterface ctx;
CordovaWebView appView; CordovaWebView appView;
private boolean doClearHistory = false; private boolean doClearHistory = false;
/** The authorization tokens. */
private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
/** /**
* Constructor. * Constructor.
* *
* @param ctx * @param ctx
*/ */
public CordovaWebViewClient(Activity ctx) { public CordovaWebViewClient(CordovaInterface ctx) {
this.ctx = ctx; this.ctx = ctx;
} }
public CordovaWebViewClient(Context ctx, CordovaWebView view) /**
{ * Constructor.
this.ctx = (Activity) ctx; *
appView = view; * @param ctx
* @param view
*/
public CordovaWebViewClient(CordovaInterface ctx, CordovaWebView view) {
this.ctx = ctx;
this.appView = view;
} }
public void setWebView(CordovaWebView view) /**
{ * Constructor.
appView = view; *
* @param view
*/
public void setWebView(CordovaWebView view) {
this.appView = view;
} }
/** /**
* Give the host application a chance to take over the control when a new url * Give the host application a chance to take over the control when a new url
* is about to be loaded in the current WebView. * is about to be loaded in the current WebView.
@ -76,19 +93,19 @@ public class CordovaWebViewClient extends WebViewClient {
*/ */
@Override @Override
public boolean shouldOverrideUrlLoading(WebView view, String url) { public boolean shouldOverrideUrlLoading(WebView view, String url) {
// First give any plugins the chance to handle the url themselves // First give any plugins the chance to handle the url themselves
if ((appView.pluginManager != null) && appView.pluginManager.onOverrideUrlLoading(url)) { if ((this.appView.pluginManager != null) && this.appView.pluginManager.onOverrideUrlLoading(url)) {
} }
// If dialing phone (tel:5551212) // If dialing phone (tel:5551212)
else if (url.startsWith(WebView.SCHEME_TEL)) { else if (url.startsWith(WebView.SCHEME_TEL)) {
try { try {
Intent intent = new Intent(Intent.ACTION_DIAL); Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse(url)); intent.setData(Uri.parse(url));
ctx.startActivity(intent); this.ctx.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error dialing "+url+": "+ e.toString()); LOG.e(TAG, "Error dialing " + url + ": " + e.toString());
} }
} }
@ -97,9 +114,9 @@ public class CordovaWebViewClient extends WebViewClient {
try { try {
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url)); intent.setData(Uri.parse(url));
ctx.startActivity(intent); this.ctx.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error showing map "+url+": "+ e.toString()); LOG.e(TAG, "Error showing map " + url + ": " + e.toString());
} }
} }
@ -108,9 +125,9 @@ public class CordovaWebViewClient extends WebViewClient {
try { try {
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url)); intent.setData(Uri.parse(url));
ctx.startActivity(intent); this.ctx.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error sending email "+url+": "+ e.toString()); LOG.e(TAG, "Error sending email " + url + ": " + e.toString());
} }
} }
@ -137,12 +154,12 @@ public class CordovaWebViewClient extends WebViewClient {
} }
} }
} }
intent.setData(Uri.parse("sms:"+address)); intent.setData(Uri.parse("sms:" + address));
intent.putExtra("address", address); intent.putExtra("address", address);
intent.setType("vnd.android-dir/mms-sms"); intent.setType("vnd.android-dir/mms-sms");
ctx.startActivity(intent); this.ctx.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error sending sms "+url+":"+ e.toString()); LOG.e(TAG, "Error sending sms " + url + ":" + e.toString());
} }
} }
@ -151,12 +168,12 @@ public class CordovaWebViewClient extends WebViewClient {
// If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity. // If our app or file:, then load into a new Cordova webview container by starting a new instance of our activity.
// Our app continues to run. When BACK is pressed, our app is redisplayed. // Our app continues to run. When BACK is pressed, our app is redisplayed.
if (url.startsWith("file://") || url.indexOf(appView.baseUrl) == 0 || appView.isUrlWhiteListed(url)) { if (url.startsWith("file://") || url.indexOf(this.appView.baseUrl) == 0 || this.appView.isUrlWhiteListed(url)) {
//This will fix iFrames //This will fix iFrames
if(appView.useBrowserHistory) if (appView.useBrowserHistory)
return false; return false;
else else
appView.loadUrl(url); this.appView.loadUrl(url);
} }
// If not our application, let default viewer handle // If not our application, let default viewer handle
@ -164,61 +181,56 @@ public class CordovaWebViewClient extends WebViewClient {
try { try {
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url)); intent.setData(Uri.parse(url));
ctx.startActivity(intent); this.ctx.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error loading url "+url, e); LOG.e(TAG, "Error loading url " + url, e);
} }
} }
} }
return true; return true;
} }
/** /**
* On received http auth request. * On received http auth request.
* The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination * The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination
* *
* @param view * @param view
* the view
* @param handler * @param handler
* the handler
* @param host * @param host
* the host
* @param realm * @param realm
* the realm
*/ */
@Override @Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
String realm) {
// Get the authentication token
// get the authentication token AuthenticationToken token = this.getAuthenticationToken(host, realm);
// Note: The WebView MUST be a CordoaWebView if (token != null) {
AuthenticationToken token = ((CordovaWebView) view).getAuthenticationToken(host,realm);
if(token != null) {
handler.proceed(token.getUserName(), token.getPassword()); handler.proceed(token.getUserName(), token.getPassword());
} }
} }
@Override @Override
public void onPageStarted(WebView view, String url, Bitmap favicon) { public void onPageStarted(WebView view, String url, Bitmap favicon) {
// Clear history so history.back() doesn't do anything. // Clear history so history.back() doesn't do anything.
// So we can reinit() native side CallbackServer & PluginManager.\ // So we can reinit() native side CallbackServer & PluginManager.
if(!appView.useBrowserHistory) if (!this.appView.useBrowserHistory) {
{ view.clearHistory();
view.clearHistory(); this.doClearHistory = true;
this.doClearHistory = true;
} }
// Create callback server and plugin manager // Create callback server and plugin manager
if (appView.callbackServer == null) { if (this.appView.callbackServer == null) {
appView.callbackServer = new CallbackServer(); this.appView.callbackServer = new CallbackServer();
appView.callbackServer.init(url); this.appView.callbackServer.init(url);
} }
else { else {
appView.callbackServer.reinit(url); this.appView.callbackServer.reinit(url);
} }
// Broadcast message that page has loaded
this.appView.postMessage("onPageStarted", url);
} }
/** /**
* Notify the host application that a page has finished loading. * Notify the host application that a page has finished loading.
* *
@ -241,26 +253,29 @@ public class CordovaWebViewClient extends WebViewClient {
} }
// Clear timeout flag // Clear timeout flag
appView.loadUrlTimeout++; this.appView.loadUrlTimeout++;
// Try firing the onNativeReady event in JS. If it fails because the JS is // Try firing the onNativeReady event in JS. If it fails because the JS is
// not loaded yet then just set a flag so that the onNativeReady can be fired // not loaded yet then just set a flag so that the onNativeReady can be fired
// from the JS side when the JS gets to that code. // from the JS side when the JS gets to that code.
if (!url.equals("about:blank")) { if (!url.equals("about:blank")) {
appView.loadUrl("javascript:try{ cordova.require('cordova/channel').onNativeReady.fire();}catch(e){_nativeReady = true;}"); this.appView.loadUrl("javascript:try{ cordova.require('cordova/channel').onNativeReady.fire();}catch(e){_nativeReady = true;}");
appView.postMessage("onNativeReady", null); this.appView.postMessage("onNativeReady", null);
} }
// Broadcast message that page has loaded
this.appView.postMessage("onPageFinished", url);
// Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly // Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly
if (appView.getVisibility() == View.INVISIBLE) { if (this.appView.getVisibility() == View.INVISIBLE) {
Thread t = new Thread(new Runnable() { Thread t = new Thread(new Runnable() {
public void run() { public void run() {
try { try {
Thread.sleep(2000); Thread.sleep(2000);
ctx.runOnUiThread(new Runnable() { ctx.getActivity().runOnUiThread(new Runnable() {
public void run() { public void run() {
appView.setVisibility(View.VISIBLE); //appView.setVisibility(View.VISIBLE);
//ctx.spinnerStop(); appView.postMessage("spinner", "stop");
} }
}); });
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -270,17 +285,16 @@ public class CordovaWebViewClient extends WebViewClient {
t.start(); t.start();
} }
// Shutdown if blank loaded // Shutdown if blank loaded
if (url.equals("about:blank")) { if (url.equals("about:blank")) {
if (appView.callbackServer != null) { if (this.appView.callbackServer != null) {
appView.callbackServer.destroy(); this.appView.callbackServer.destroy();
} }
//this.ctx.endActivity(); //this.ctx.endActivity();
this.ctx.finish(); this.ctx.getActivity().finish();
} }
} }
/** /**
* Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable). * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
* The errorCode parameter corresponds to one of the ERROR_* constants. * The errorCode parameter corresponds to one of the ERROR_* constants.
@ -292,22 +306,32 @@ public class CordovaWebViewClient extends WebViewClient {
*/ */
@Override @Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
LOG.d(TAG, "DroidGap: GapViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl); LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
// Clear timeout flag // Clear timeout flag
//this.ctx.loadUrlTimeout++; this.appView.loadUrlTimeout++;
// Stop "app loading" spinner if showing // Stop "app loading" spinner if showing
//this.ctx.spinnerStop(); //this.ctx.spinnerStop();
// Handle error // Handle error
//this.ctx.onReceivedError(errorCode, description, failingUrl); //this.ctx.onReceivedError(errorCode, description, failingUrl);
JSONObject data = new JSONObject();
try {
data.put("errorCode", errorCode);
data.put("description", description);
data.put("url", failingUrl);
} catch (JSONException e) {
e.printStackTrace();
}
this.appView.postMessage("onReceivedError", data);
} }
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final String packageName = this.ctx.getPackageName(); final String packageName = this.ctx.getActivity().getPackageName();
final PackageManager pm = this.ctx.getPackageManager(); final PackageManager pm = this.ctx.getActivity().getPackageManager();
ApplicationInfo appInfo; ApplicationInfo appInfo;
try { try {
appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA); appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
@ -317,7 +341,7 @@ public class CordovaWebViewClient extends WebViewClient {
return; return;
} else { } else {
// debug = false // debug = false
super.onReceivedSslError(view, handler, error); super.onReceivedSslError(view, handler, error);
} }
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {
// When it doubt, lock it out! // When it doubt, lock it out!
@ -331,8 +355,81 @@ public class CordovaWebViewClient extends WebViewClient {
* If you do a document.location.href the url does not get pushed on the stack * If you do a document.location.href the url does not get pushed on the stack
* so we do a check here to see if the url should be pushed. * so we do a check here to see if the url should be pushed.
*/ */
if (!appView.peekAtUrlStack().equals(url)) { if (!this.appView.peekAtUrlStack().equals(url)) {
appView.pushUrl(url); this.appView.pushUrl(url);
} }
} }
/**
* Sets the authentication token.
*
* @param authenticationToken
* @param host
* @param realm
*/
public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
if (host == null) {
host = "";
}
if (realm == null) {
realm = "";
}
this.authenticationTokens.put(host.concat(realm), authenticationToken);
}
/**
* Removes the authentication token.
*
* @param host
* @param realm
*
* @return the authentication token or null if did not exist
*/
public AuthenticationToken removeAuthenticationToken(String host, String realm) {
return this.authenticationTokens.remove(host.concat(realm));
}
/**
* Gets the authentication token.
*
* In order it tries:
* 1- host + realm
* 2- host
* 3- realm
* 4- no host, no realm
*
* @param host
* @param realm
*
* @return the authentication token
*/
public AuthenticationToken getAuthenticationToken(String host, String realm) {
AuthenticationToken token = null;
token = this.authenticationTokens.get(host.concat(realm));
if (token == null) {
// try with just the host
token = this.authenticationTokens.get(host);
// Try the realm
if (token == null) {
token = this.authenticationTokens.get(realm);
}
// if no host found, just query for default
if (token == null) {
token = this.authenticationTokens.get("");
}
}
return token;
}
/**
* Clear all authentication tokens.
*/
public void clearAuthenticationTokens() {
this.authenticationTokens.clear();
}
} }

View File

@ -41,7 +41,7 @@ public class Device extends Plugin {
public static String cordovaVersion = "1.7.0"; // Cordova version public static String cordovaVersion = "1.7.0"; // Cordova 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
BroadcastReceiver telephonyReceiver = null; BroadcastReceiver telephonyReceiver = null;
/** /**
@ -49,14 +49,14 @@ public class Device extends Plugin {
*/ */
public Device() { public Device() {
} }
/** /**
* Sets the context of the Command. This can then be used to do things like * Sets the context of the Command. This can then be used to do things like
* get file paths associated with the Activity. * get file paths associated with the Activity.
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(Context ctx) { public void setContext(CordovaInterface ctx) {
super.setContext(ctx); super.setContext(ctx);
Device.uuid = getUuid(); Device.uuid = getUuid();
this.initTelephonyReceiver(); this.initTelephonyReceiver();
@ -72,8 +72,8 @@ public class Device extends Plugin {
*/ */
public PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.OK; PluginResult.Status status = PluginResult.Status.OK;
String result = ""; String result = "";
try { try {
if (action.equals("getDeviceInfo")) { if (action.equals("getDeviceInfo")) {
JSONObject r = new JSONObject(); JSONObject r = new JSONObject();
@ -105,32 +105,32 @@ public class Device extends Plugin {
} }
return false; return false;
} }
/** /**
* Unregister receiver. * Unregister receiver.
*/ */
public void onDestroy() { public void onDestroy() {
this.ctx.unregisterReceiver(this.telephonyReceiver); this.ctx.getActivity().unregisterReceiver(this.telephonyReceiver);
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// LOCAL METHODS // LOCAL METHODS
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* Listen for telephony events: RINGING, OFFHOOK and IDLE * Listen for telephony events: RINGING, OFFHOOK and IDLE
* Send these events to all plugins using * Send these events to all plugins using
* DroidGap.onMessage("telephone", "ringing" | "offhook" | "idle") * DroidGap.onMessage("telephone", "ringing" | "offhook" | "idle")
*/ */
private void initTelephonyReceiver() { private void initTelephonyReceiver() {
IntentFilter intentFilter = new IntentFilter() ; IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
final Context myctx = this.ctx; //final CordovaInterface myctx = this.ctx;
this.telephonyReceiver = new BroadcastReceiver() { this.telephonyReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
// If state has changed // If state has changed
if ((intent != null) && intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) { if ((intent != null) && intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
if (intent.hasExtra(TelephonyManager.EXTRA_STATE)) { if (intent.hasExtra(TelephonyManager.EXTRA_STATE)) {
@ -151,9 +151,9 @@ public class Device extends Plugin {
} }
} }
}; };
// Register the receiver // Register the receiver
this.ctx.registerReceiver(this.telephonyReceiver, intentFilter); this.ctx.getActivity().registerReceiver(this.telephonyReceiver, intentFilter);
} }
/** /**
@ -164,14 +164,14 @@ public class Device extends Plugin {
public String getPlatform() { public String getPlatform() {
return Device.platform; return Device.platform;
} }
/** /**
* Get the device's Universally Unique Identifier (UUID). * Get the device's Universally Unique Identifier (UUID).
* *
* @return * @return
*/ */
public String getUuid() { public String getUuid() {
String uuid = Settings.Secure.getString(this.ctx.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID); String uuid = Settings.Secure.getString(this.ctx.getActivity().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
return uuid; return uuid;
} }
@ -182,18 +182,18 @@ public class Device extends Plugin {
*/ */
public String getCordovaVersion() { public String getCordovaVersion() {
return Device.cordovaVersion; return Device.cordovaVersion;
} }
public String getModel() { public String getModel() {
String model = android.os.Build.MODEL; String model = android.os.Build.MODEL;
return model; return model;
} }
public String getProductName() { public String getProductName() {
String productname = android.os.Build.PRODUCT; String productname = android.os.Build.PRODUCT;
return productname; return productname;
} }
/** /**
* Get the OS version. * Get the OS version.
* *
@ -203,17 +203,16 @@ public class Device extends Plugin {
String osversion = android.os.Build.VERSION.RELEASE; String osversion = android.os.Build.VERSION.RELEASE;
return osversion; return osversion;
} }
public String getSDKVersion() { public String getSDKVersion() {
@SuppressWarnings("deprecation")
String sdkversion = android.os.Build.VERSION.SDK; String sdkversion = android.os.Build.VERSION.SDK;
return sdkversion; return sdkversion;
} }
public String getTimeZoneID() {
TimeZone tz = TimeZone.getDefault();
return(tz.getID());
}
}
public String getTimeZoneID() {
TimeZone tz = TimeZone.getDefault();
return (tz.getID());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -51,13 +51,12 @@ import android.net.Uri;
import android.util.Log; import android.util.Log;
import android.webkit.CookieManager; import android.webkit.CookieManager;
public class FileTransfer extends Plugin { public class FileTransfer extends Plugin {
private static final String LOG_TAG = "FileTransfer"; private static final String LOG_TAG = "FileTransfer";
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;
@ -76,8 +75,7 @@ public class FileTransfer extends Plugin {
try { try {
source = args.getString(0); source = args.getString(0);
target = args.getString(1); target = args.getString(1);
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Missing source or target"); Log.d(LOG_TAG, "Missing source or target");
return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing source or target"); return new PluginResult(PluginResult.Status.JSON_EXCEPTION, "Missing source or target");
} }
@ -151,11 +149,11 @@ public class FileTransfer extends Plugin {
} }
public void checkClientTrusted(X509Certificate[] chain, public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException { String authType) throws CertificateException {
} }
public void checkServerTrusted(X509Certificate[] chain, public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException { String authType) throws CertificateException {
} }
} }; } };
@ -199,7 +197,7 @@ public class FileTransfer extends Plugin {
*/ */
private String getArgument(JSONArray args, int position, String defaultString) { private String getArgument(JSONArray args, int position, String defaultString) {
String arg = defaultString; String arg = defaultString;
if(args.length() >= position) { if (args.length() >= position) {
arg = args.optString(position); arg = args.optString(position);
if (arg == null || "null".equals(arg)) { if (arg == null || "null".equals(arg)) {
arg = defaultString; arg = defaultString;
@ -275,26 +273,26 @@ public class FileTransfer extends Plugin {
// Use a post method. // Use a post method.
conn.setRequestMethod("POST"); conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+BOUNDRY); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDRY);
// Handle the other headers // Handle the other headers
try { try {
JSONObject headers = params.getJSONObject("headers"); JSONObject headers = params.getJSONObject("headers");
for (Iterator iter = headers.keys(); iter.hasNext();) for (@SuppressWarnings("rawtypes")
{ Iterator iter = headers.keys(); iter.hasNext();)
String headerKey = iter.next().toString(); {
conn.setRequestProperty(headerKey, headers.getString(headerKey)); String headerKey = iter.next().toString();
} conn.setRequestProperty(headerKey, headers.getString(headerKey));
}
} catch (JSONException e1) { } catch (JSONException e1) {
// No headers to be manipulated! // No headers to be manipulated!
} }
// Set the cookies on the response // Set the cookies on the response
String cookie = CookieManager.getInstance().getCookie(server); String cookie = CookieManager.getInstance().getCookie(server);
if (cookie != null) { if (cookie != null) {
conn.setRequestProperty("Cookie", cookie); conn.setRequestProperty("Cookie", cookie);
} }
/* /*
* Store the non-file portions of the multipart data as a string, so that we can add it * Store the non-file portions of the multipart data as a string, so that we can add it
@ -302,42 +300,42 @@ public class FileTransfer extends Plugin {
*/ */
String extraParams = ""; String extraParams = "";
try { try {
for (Iterator iter = params.keys(); iter.hasNext();) { for (@SuppressWarnings("rawtypes")
Iterator iter = params.keys(); iter.hasNext();) {
Object key = iter.next(); Object key = iter.next();
if(key.toString() != "headers") if (key.toString() != "headers")
{ {
extraParams += LINE_START + BOUNDRY + LINE_END; extraParams += LINE_START + BOUNDRY + LINE_END;
extraParams += "Content-Disposition: form-data; name=\"" + key.toString() + "\";"; extraParams += "Content-Disposition: form-data; name=\"" + key.toString() + "\";";
extraParams += LINE_END + LINE_END; extraParams += LINE_END + LINE_END;
extraParams += params.getString(key.toString()); extraParams += params.getString(key.toString());
extraParams += LINE_END; extraParams += LINE_END;
} }
} }
} catch (JSONException e) { } catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e); Log.e(LOG_TAG, e.getMessage(), e);
} }
extraParams += LINE_START + BOUNDRY + LINE_END; extraParams += LINE_START + BOUNDRY + LINE_END;
extraParams += "Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\""; extraParams += "Content-Disposition: form-data; name=\"" + fileKey + "\";" + " filename=\"";
String midParams = "\"" + LINE_END + "Content-Type: " + mimeType + LINE_END + LINE_END; String midParams = "\"" + LINE_END + "Content-Type: " + mimeType + LINE_END + LINE_END;
String tailParams = LINE_END + LINE_START + BOUNDRY + LINE_START + LINE_END; String tailParams = LINE_END + LINE_START + BOUNDRY + LINE_START + LINE_END;
// Should set this up as an option // Should set this up as an option
if (chunkedMode) { if (chunkedMode) {
conn.setChunkedStreamingMode(maxBufferSize); conn.setChunkedStreamingMode(maxBufferSize);
} }
else else
{ {
int stringLength = extraParams.length() + midParams.length() + tailParams.length() + fileName.getBytes("UTF-8").length; int stringLength = extraParams.length() + midParams.length() + tailParams.length() + fileName.getBytes("UTF-8").length;
Log.d(LOG_TAG, "String Length: " + stringLength); Log.d(LOG_TAG, "String Length: " + stringLength);
int fixedLength = (int) fileInputStream.getChannel().size() + stringLength; int fixedLength = (int) fileInputStream.getChannel().size() + stringLength;
Log.d(LOG_TAG, "Content Length: " + fixedLength); Log.d(LOG_TAG, "Content Length: " + fixedLength);
conn.setFixedLengthStreamingMode(fixedLength); conn.setFixedLengthStreamingMode(fixedLength);
} }
dos = new DataOutputStream( conn.getOutputStream() ); dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(extraParams); dos.writeBytes(extraParams);
//We don't want to chagne encoding, we just want this to write for all Unicode. //We don't want to chagne encoding, we just want this to write for all Unicode.
dos.write(fileName.getBytes("UTF-8")); dos.write(fileName.getBytes("UTF-8"));
@ -373,13 +371,13 @@ public class FileTransfer extends Plugin {
StringBuffer responseString = new StringBuffer(""); StringBuffer responseString = new StringBuffer("");
DataInputStream inStream; DataInputStream inStream;
try { try {
inStream = new DataInputStream ( conn.getInputStream() ); inStream = new DataInputStream(conn.getInputStream());
} catch(FileNotFoundException e) { } catch (FileNotFoundException e) {
throw new IOException("Received error from server"); throw new IOException("Received error from server");
} }
String line; String line;
while (( line = inStream.readLine()) != null) { while ((line = inStream.readLine()) != null) {
responseString.append(line); responseString.append(line);
} }
Log.d(LOG_TAG, "got response from server"); Log.d(LOG_TAG, "got response from server");
@ -394,7 +392,7 @@ public class FileTransfer extends Plugin {
// 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);
} }
@ -416,46 +414,46 @@ public class FileTransfer extends Plugin {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
// connect to server // connect to server
if(webView.isUrlWhiteListed(source)) if (webView.isUrlWhiteListed(source))
{ {
URL url = new URL(source); URL url = new URL(source);
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET"); connection.setRequestMethod("GET");
//Add cookie support
String cookie = CookieManager.getInstance().getCookie(source);
if(cookie != null)
{
connection.setRequestProperty("cookie", cookie);
}
connection.connect();
Log.d(LOG_TAG, "Download file:" + url); //Add cookie support
String cookie = CookieManager.getInstance().getCookie(source);
if (cookie != null)
{
connection.setRequestProperty("cookie", cookie);
}
InputStream inputStream = connection.getInputStream(); connection.connect();
byte[] buffer = new byte[1024];
int bytesRead = 0;
FileOutputStream outputStream = new FileOutputStream(file); Log.d(LOG_TAG, "Download file:" + url);
// write bytes to file InputStream inputStream = connection.getInputStream();
while ( (bytesRead = inputStream.read(buffer)) > 0 ) { byte[] buffer = new byte[1024];
outputStream.write(buffer,0, bytesRead); int bytesRead = 0;
}
outputStream.close(); FileOutputStream outputStream = new FileOutputStream(file);
Log.d(LOG_TAG, "Saved file: " + target); // write bytes to file
while ((bytesRead = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, bytesRead);
}
// create FileEntry object outputStream.close();
FileUtils fileUtil = new FileUtils();
return fileUtil.getEntry(file); Log.d(LOG_TAG, "Saved file: " + target);
// create FileEntry object
FileUtils fileUtil = new FileUtils();
return fileUtil.getEntry(file);
} }
else else
{ {
throw new IOException("Error: Unable to connect to domain"); throw new IOException("Error: Unable to connect to domain");
} }
} catch (Exception e) { } catch (Exception e) {
Log.d(LOG_TAG, e.getMessage(), e); Log.d(LOG_TAG, e.getMessage(), e);
@ -473,7 +471,7 @@ public class FileTransfer extends Plugin {
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.getActivity().getContentResolver().openInputStream(uri);
} }
else if (path.startsWith("file://")) { else if (path.startsWith("file://")) {
int question = path.indexOf("?"); int question = path.indexOf("?");

View File

@ -37,15 +37,15 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.content.Context; //import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Environment; import android.os.Environment;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.util.Log; //import android.util.Log;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import android.app.Activity;
//import android.app.Activity;
/** /**
* This class provides SD card file and directory services to JavaScript. * This class provides SD card file and directory services to JavaScript.
@ -132,7 +132,7 @@ public class FileUtils extends Plugin {
else if (action.equals("requestFileSystem")) { else if (action.equals("requestFileSystem")) {
long size = args.optLong(1); long size = args.optLong(1);
if (size != 0) { if (size != 0) {
if (size > (DirectoryManager.getFreeDiskSpace(true)*1024)) { if (size > (DirectoryManager.getFreeDiskSpace(true) * 1024)) {
return new PluginResult(PluginResult.Status.ERROR, FileUtils.QUOTA_EXCEEDED_ERR); return new PluginResult(PluginResult.Status.ERROR, FileUtils.QUOTA_EXCEEDED_ERR);
} }
} }
@ -222,9 +222,9 @@ public class FileUtils extends Plugin {
* @param filePath the path to check * @param filePath the path to check
*/ */
private void notifyDelete(String filePath) { private void notifyDelete(String filePath) {
int result = this.ctx.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, int result = this.ctx.getActivity().getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
MediaStore.Images.Media.DATA + " = ?", MediaStore.Images.Media.DATA + " = ?",
new String[] {filePath}); new String[] { filePath });
} }
/** /**
@ -244,7 +244,7 @@ public class FileUtils extends Plugin {
// Handle the special case where you get an Android content:// uri. // Handle the special case where you get an Android content:// uri.
if (decoded.startsWith("content:")) { if (decoded.startsWith("content:")) {
Cursor cursor = ((Activity) this.ctx).managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null); Cursor cursor = this.ctx.getActivity().managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null);
// Note: MediaStore.Images/Audio/Video.Media.DATA is always "_data" // Note: MediaStore.Images/Audio/Video.Media.DATA is always "_data"
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst(); cursor.moveToFirst();
@ -295,7 +295,7 @@ public class FileUtils extends Plugin {
if (fp.isDirectory()) { if (fp.isDirectory()) {
File[] files = fp.listFiles(); File[] files = fp.listFiles();
for (int i=0; i<files.length; i++) { for (int i = 0; i < files.length; i++) {
entries.put(getEntry(files[i])); entries.put(getEntry(files[i]));
} }
} }
@ -321,7 +321,6 @@ public class FileUtils extends Plugin {
fileName = stripFileProtocol(fileName); fileName = stripFileProtocol(fileName);
newParent = stripFileProtocol(newParent); newParent = stripFileProtocol(newParent);
// Check for invalid file name // Check for invalid file name
if (newName != null && newName.contains(":")) { if (newName != null && newName.contains(":")) {
throw new EncodingException("Bad file name"); throw new EncodingException("Bad file name");
@ -378,7 +377,7 @@ public class FileUtils extends Plugin {
File destFile = null; File destFile = null;
// I know this looks weird but it is to work around a JSON bug. // I know this looks weird but it is to work around a JSON bug.
if ("null".equals(newName) || "".equals(newName) ) { if ("null".equals(newName) || "".equals(newName)) {
newName = null; newName = null;
} }
@ -400,7 +399,7 @@ public class FileUtils extends Plugin {
* @throws InvalidModificationException * @throws InvalidModificationException
* @throws JSONException * @throws JSONException
*/ */
private JSONObject copyFile(File srcFile, File destFile) throws IOException, InvalidModificationException, JSONException { private JSONObject copyFile(File srcFile, File destFile) throws IOException, InvalidModificationException, JSONException {
// Renaming a file to an existing directory should fail // Renaming a file to an existing directory should fail
if (destFile.exists() && destFile.isDirectory()) { if (destFile.exists() && destFile.isDirectory()) {
throw new InvalidModificationException("Can't rename a file to a directory"); throw new InvalidModificationException("Can't rename a file to a directory");
@ -478,7 +477,7 @@ public class FileUtils extends Plugin {
// This weird test is to determine if we are copying or moving a directory into itself. // This weird test is to determine if we are copying or moving a directory into itself.
// Copy /sdcard/myDir to /sdcard/myDir-backup is okay but // Copy /sdcard/myDir to /sdcard/myDir-backup is okay but
// Copy /sdcard/myDir to /sdcard/myDir/backup should thow an INVALID_MODIFICATION_ERR // Copy /sdcard/myDir to /sdcard/myDir/backup should thow an INVALID_MODIFICATION_ERR
if (dest.startsWith(src) && dest.indexOf(File.separator, src.length()-1) != -1) { if (dest.startsWith(src) && dest.indexOf(File.separator, src.length() - 1) != -1) {
return true; return true;
} }
@ -727,9 +726,9 @@ public class FileUtils extends Plugin {
private boolean atRootDirectory(String filePath) { private boolean atRootDirectory(String filePath) {
filePath = stripFileProtocol(filePath); filePath = stripFileProtocol(filePath);
if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + ctx.getPackageName() + "/cache") || if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + ctx.getActivity().getPackageName() + "/cache") ||
filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath()) || filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath()) ||
filePath.equals("/data/data/" + ctx.getPackageName())) { filePath.equals("/data/data/" + ctx.getActivity().getPackageName())) {
return true; return true;
} }
return false; return false;
@ -747,7 +746,7 @@ public class FileUtils extends Plugin {
} }
return filePath; return filePath;
} }
/** /**
* Create a File object from the passed in path * Create a File object from the passed in path
* *
@ -793,7 +792,7 @@ public class FileUtils extends Plugin {
throw new FileNotFoundException("File: " + filePath + " does not exist."); throw new FileNotFoundException("File: " + filePath + " does not exist.");
} }
JSONObject metadata = new JSONObject(); JSONObject metadata = new JSONObject();
metadata.put("size", file.length()); metadata.put("size", file.length());
metadata.put("type", getMimeType(filePath)); metadata.put("type", getMimeType(filePath));
metadata.put("name", file.getName()); metadata.put("name", file.getName());
@ -818,16 +817,16 @@ public class FileUtils extends Plugin {
fs.put("name", "temporary"); fs.put("name", "temporary");
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/"); "/Android/data/" + ctx.getActivity().getPackageName() + "/cache/");
// Create the cache dir if it doesn't exist. // Create the cache dir if it doesn't exist.
fp.mkdirs(); fp.mkdirs();
fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() + fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/")); "/Android/data/" + ctx.getActivity().getPackageName() + "/cache/"));
} else { } else {
fp = new File("/data/data/" + ctx.getPackageName() + "/cache/"); fp = new File("/data/data/" + ctx.getActivity().getPackageName() + "/cache/");
// Create the cache dir if it doesn't exist. // Create the cache dir if it doesn't exist.
fp.mkdirs(); fp.mkdirs();
fs.put("root", getEntry("/data/data/" + ctx.getPackageName() + "/cache/")); fs.put("root", getEntry("/data/data/" + ctx.getActivity().getPackageName() + "/cache/"));
} }
} }
else if (type == PERSISTENT) { else if (type == PERSISTENT) {
@ -835,13 +834,13 @@ public class FileUtils extends Plugin {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
fs.put("root", getEntry(Environment.getExternalStorageDirectory())); fs.put("root", getEntry(Environment.getExternalStorageDirectory()));
} else { } else {
fs.put("root", getEntry("/data/data/" + ctx.getPackageName())); fs.put("root", getEntry("/data/data/" + ctx.getActivity().getPackageName()));
} }
} }
else { else {
throw new IOException("No filesystem of type requested"); throw new IOException("No filesystem of type requested");
} }
return fs; return fs;
} }
@ -942,7 +941,7 @@ public class FileUtils extends Plugin {
String contentType = null; String contentType = null;
if (filename.startsWith("content:")) { if (filename.startsWith("content:")) {
Uri fileUri = Uri.parse(filename); Uri fileUri = Uri.parse(filename);
contentType = this.ctx.getContentResolver().getType(fileUri); contentType = this.ctx.getActivity().getContentResolver().getType(fileUri);
} }
else { else {
contentType = getMimeType(filename); contentType = getMimeType(filename);
@ -961,7 +960,7 @@ public class FileUtils extends Plugin {
*/ */
public static String getMimeType(String filename) { public static String getMimeType(String filename) {
MimeTypeMap map = MimeTypeMap.getSingleton(); MimeTypeMap map = MimeTypeMap.getSingleton();
return map.getMimeTypeFromExtension(map.getFileExtensionFromUrl(filename)); return map.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(filename));
} }
/** /**
@ -975,14 +974,14 @@ public class FileUtils extends Plugin {
/**/ /**/
public long write(String filename, String data, int offset) throws FileNotFoundException, IOException { public long write(String filename, String data, int offset) throws FileNotFoundException, IOException {
filename = stripFileProtocol(filename); filename = stripFileProtocol(filename);
boolean append = false; boolean append = false;
if (offset > 0) { if (offset > 0) {
this.truncateFile(filename, offset); this.truncateFile(filename, offset);
append = true; append = true;
} }
byte [] rawData = data.getBytes(); byte[] rawData = data.getBytes();
ByteArrayInputStream in = new ByteArrayInputStream(rawData); ByteArrayInputStream in = new ByteArrayInputStream(rawData);
FileOutputStream out = new FileOutputStream(filename, append); FileOutputStream out = new FileOutputStream(filename, append);
byte buff[] = new byte[rawData.length]; byte buff[] = new byte[rawData.length];
@ -1007,9 +1006,9 @@ public class FileUtils extends Plugin {
RandomAccessFile raf = new RandomAccessFile(filename, "rw"); RandomAccessFile raf = new RandomAccessFile(filename, "rw");
if (raf.length() >= size) { if (raf.length() >= size) {
FileChannel channel = raf.getChannel(); FileChannel channel = raf.getChannel();
channel.truncate(size); channel.truncate(size);
return size; return size;
} }
return raf.length(); return raf.length();
@ -1025,7 +1024,7 @@ public class FileUtils extends Plugin {
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.getActivity().getContentResolver().openInputStream(uri);
} }
else { else {
path = stripFileProtocol(path); path = stripFileProtocol(path);
@ -1040,9 +1039,9 @@ public class FileUtils extends Plugin {
* @param ctx) the current applicaiton context * @param ctx) the current applicaiton context
* @return the full path to the file * @return the full path to the file
*/ */
protected static String getRealPathFromURI(Uri contentUri, Activity ctx) { protected static String getRealPathFromURI(Uri contentUri, CordovaInterface ctx) {
String[] proj = { _DATA }; String[] proj = { _DATA };
Cursor cursor = ctx.managedQuery(contentUri, proj, null, null, null); Cursor cursor = ctx.getActivity().managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(_DATA); int column_index = cursor.getColumnIndexOrThrow(_DATA);
cursor.moveToFirst(); cursor.moveToFirst();
return cursor.getString(column_index); return cursor.getString(column_index);

View File

@ -21,113 +21,114 @@ package org.apache.cordova;
import android.content.Context; import android.content.Context;
import android.location.Location; import android.location.Location;
import android.location.LocationManager; import android.location.LocationManager;
import android.webkit.WebView;
//import android.webkit.WebView;
public class GeoListener { public class GeoListener {
public static int PERMISSION_DENIED = 1; public static int PERMISSION_DENIED = 1;
public static int POSITION_UNAVAILABLE = 2; public static int POSITION_UNAVAILABLE = 2;
public static int TIMEOUT = 3; public static int TIMEOUT = 3;
String id; // Listener ID String id; // Listener ID
String successCallback; // String successCallback; //
String failCallback; String failCallback;
GpsListener mGps; // GPS listener GpsListener mGps; // GPS listener
NetworkListener mNetwork; // Network listener NetworkListener mNetwork; // Network listener
LocationManager mLocMan; // Location manager LocationManager mLocMan; // Location manager
private GeoBroker broker; // GeoBroker object
int interval;
/**
* Constructor.
*
* @param id Listener id
* @param ctx
* @param time Sampling period in msec
* @param appView
*/
GeoListener(GeoBroker broker, String id, int time) {
this.id = id;
this.interval = time;
this.broker = broker;
this.mGps = null;
this.mNetwork = null;
this.mLocMan = (LocationManager) broker.ctx.getSystemService(Context.LOCATION_SERVICE);
// If GPS provider, then create and start GPS listener private GeoBroker broker; // GeoBroker object
if (this.mLocMan.getProvider(LocationManager.GPS_PROVIDER) != null) {
this.mGps = new GpsListener(broker.ctx, time, this); int interval;
}
/**
// If network provider, then create and start network listener * Constructor.
if (this.mLocMan.getProvider(LocationManager.NETWORK_PROVIDER) != null) { *
this.mNetwork = new NetworkListener(broker.ctx, time, this); * @param id Listener id
} * @param ctx
} * @param time Sampling period in msec
* @param appView
/** */
* Destroy listener. GeoListener(GeoBroker broker, String id, int time) {
*/ this.id = id;
public void destroy() { this.interval = time;
this.stop(); this.broker = broker;
} this.mGps = null;
this.mNetwork = null;
/** this.mLocMan = (LocationManager) broker.ctx.getActivity().getSystemService(Context.LOCATION_SERVICE);
* Location found. Send location back to JavaScript.
* // If GPS provider, then create and start GPS listener
* @param loc if (this.mLocMan.getProvider(LocationManager.GPS_PROVIDER) != null) {
*/ this.mGps = new GpsListener(broker.ctx, time, this);
void success(Location loc) { }
String params = loc.getLatitude() + "," + loc.getLongitude() + ", " + loc.getAltitude() + // If network provider, then create and start network listener
"," + loc.getAccuracy() + "," + loc.getBearing() + if (this.mLocMan.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
"," + loc.getSpeed() + "," + loc.getTime(); this.mNetwork = new NetworkListener(broker.ctx, time, this);
}
if (id == "global") { }
this.stop();
} /**
this.broker.sendJavascript("navigator._geo.success('" + id + "'," + params + ");"); * Destroy listener.
} */
public void destroy() {
/** this.stop();
* Location failed. Send error back to JavaScript. }
*
* @param code The error code /**
* @param msg The error message * Location found. Send location back to JavaScript.
*/ *
void fail(int code, String msg) { * @param loc
this.broker.sendJavascript("navigator._geo.fail('" + this.id + "', '" + code + "', '" + msg + "');"); */
this.stop(); void success(Location loc) {
}
String params = loc.getLatitude() + "," + loc.getLongitude() + ", " + loc.getAltitude() +
/** "," + loc.getAccuracy() + "," + loc.getBearing() +
* Start retrieving location. "," + loc.getSpeed() + "," + loc.getTime();
*
* @param interval if (id == "global") {
*/ this.stop();
void start(int interval) { }
if (this.mGps != null) { this.broker.sendJavascript("navigator._geo.success('" + id + "'," + params + ");");
this.mGps.start(interval); }
}
if (this.mNetwork != null) { /**
this.mNetwork.start(interval); * Location failed. Send error back to JavaScript.
} *
if (this.mNetwork == null && this.mGps == null) { * @param code The error code
this.fail(POSITION_UNAVAILABLE, "No location providers available."); * @param msg The error message
} */
} void fail(int code, String msg) {
this.broker.sendJavascript("navigator._geo.fail('" + this.id + "', '" + code + "', '" + msg + "');");
/** this.stop();
* Stop listening for location. }
*/
void stop() { /**
if (this.mGps != null) { * Start retrieving location.
this.mGps.stop(); *
} * @param interval
if (this.mNetwork != null) { */
this.mNetwork.stop(); void start(int interval) {
} if (this.mGps != null) {
} this.mGps.start(interval);
}
if (this.mNetwork != null) {
this.mNetwork.start(interval);
}
if (this.mNetwork == null && this.mGps == null) {
this.fail(POSITION_UNAVAILABLE, "No location providers available.");
}
}
/**
* Stop listening for location.
*/
void stop() {
if (this.mGps != null) {
this.mGps.stop();
}
if (this.mNetwork != null) {
this.mNetwork.stop();
}
}
} }

View File

@ -32,132 +32,132 @@ import android.os.Bundle;
* *
*/ */
public class GpsListener implements LocationListener { public class GpsListener implements LocationListener {
private Context mCtx; // CordovaActivity object
private LocationManager mLocMan; // Location manager object
private GeoListener owner; // Geolistener object (parent)
private boolean hasData = false; // Flag indicates if location data is available in cLoc
private Location cLoc; // Last recieved location
private boolean running = false; // Flag indicates if listener is running
/**
* Constructor.
* Automatically starts listening.
*
* @param ctx
* @param interval
* @param m
*/
public GpsListener(Context ctx, int interval, GeoListener m) {
this.owner = m;
this.mCtx = ctx;
this.mLocMan = (LocationManager) this.mCtx.getSystemService(Context.LOCATION_SERVICE);
this.running = false;
this.start(interval);
}
/**
* Get last location.
*
* @return Location object
*/
public Location getLocation() {
this.cLoc = this.mLocMan.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (this.cLoc != null) {
this.hasData = true;
}
return this.cLoc;
}
/**
* Called when the provider is disabled by the user.
*
* @param provider
*/
public void onProviderDisabled(String provider) {
this.owner.fail(GeoListener.POSITION_UNAVAILABLE, "GPS provider disabled.");
}
/** private CordovaInterface mCtx; // CordovaActivity object
* Called when the provider is enabled by the user.
*
* @param provider
*/
public void onProviderEnabled(String provider) {
System.out.println("GpsListener: The provider "+ provider + " is enabled");
}
/** private LocationManager mLocMan; // Location manager object
* Called when the provider status changes. This method is called when a private GeoListener owner; // Geolistener object (parent)
* provider is unable to fetch a location or if the provider has recently private boolean hasData = false; // Flag indicates if location data is available in cLoc
* become available after a period of unavailability. private Location cLoc; // Last recieved location
* private boolean running = false; // Flag indicates if listener is running
* @param provider
* @param status
* @param extras
*/
public void onStatusChanged(String provider, int status, Bundle extras) {
System.out.println("GpsListener: The status of the provider " + provider + " has changed");
if (status == 0) {
System.out.println("GpsListener: " + provider + " is OUT OF SERVICE");
this.owner.fail(GeoListener.POSITION_UNAVAILABLE, "GPS out of service.");
}
else if (status == 1) {
System.out.println("GpsListener: " + provider + " is TEMPORARILY_UNAVAILABLE");
}
else {
System.out.println("GpsListener: " + provider + " is Available");
}
}
/** /**
* Called when the location has changed. * Constructor.
* * Automatically starts listening.
* @param location *
*/ * @param ctx
public void onLocationChanged(Location location) { * @param interval
System.out.println("GpsListener: The location has been updated!"); * @param m
this.hasData = true; */
this.cLoc = location; public GpsListener(CordovaInterface ctx, int interval, GeoListener m) {
this.owner.success(location); this.owner = m;
} this.mCtx = ctx;
this.mLocMan = (LocationManager) this.mCtx.getActivity().getSystemService(Context.LOCATION_SERVICE);
this.running = false;
this.start(interval);
}
/** /**
* Determine if location data is available. * Get last location.
* *
* @return * @return Location object
*/ */
public boolean hasLocation() { public Location getLocation() {
return this.hasData; this.cLoc = this.mLocMan.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} if (this.cLoc != null) {
this.hasData = true;
/** }
* Start requesting location updates. return this.cLoc;
* }
* @param interval
*/
public void start(int interval) {
if (!this.running) {
this.running = true;
this.mLocMan.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval, 0, this);
this.getLocation();
// If GPS provider has data, then send now /**
if (this.hasData) { * Called when the provider is disabled by the user.
this.owner.success(this.cLoc); *
} * @param provider
} */
} public void onProviderDisabled(String provider) {
this.owner.fail(GeoListener.POSITION_UNAVAILABLE, "GPS provider disabled.");
}
/**
* Called when the provider is enabled by the user.
*
* @param provider
*/
public void onProviderEnabled(String provider) {
System.out.println("GpsListener: The provider " + provider + " is enabled");
}
/**
* Called when the provider status changes. This method is called when a
* provider is unable to fetch a location or if the provider has recently
* become available after a period of unavailability.
*
* @param provider
* @param status
* @param extras
*/
public void onStatusChanged(String provider, int status, Bundle extras) {
System.out.println("GpsListener: The status of the provider " + provider + " has changed");
if (status == 0) {
System.out.println("GpsListener: " + provider + " is OUT OF SERVICE");
this.owner.fail(GeoListener.POSITION_UNAVAILABLE, "GPS out of service.");
}
else if (status == 1) {
System.out.println("GpsListener: " + provider + " is TEMPORARILY_UNAVAILABLE");
}
else {
System.out.println("GpsListener: " + provider + " is Available");
}
}
/**
* Called when the location has changed.
*
* @param location
*/
public void onLocationChanged(Location location) {
System.out.println("GpsListener: The location has been updated!");
this.hasData = true;
this.cLoc = location;
this.owner.success(location);
}
/**
* Determine if location data is available.
*
* @return
*/
public boolean hasLocation() {
return this.hasData;
}
/**
* Start requesting location updates.
*
* @param interval
*/
public void start(int interval) {
if (!this.running) {
this.running = true;
this.mLocMan.requestLocationUpdates(LocationManager.GPS_PROVIDER, interval, 0, this);
this.getLocation();
// If GPS provider has data, then send now
if (this.hasData) {
this.owner.success(this.cLoc);
}
}
}
/**
* Stop receiving location updates.
*/
public void stop() {
if (this.running) {
this.mLocMan.removeUpdates(this);
}
this.running = false;
}
/**
* Stop receiving location updates.
*/
public void stop() {
if (this.running) {
this.mLocMan.removeUpdates(this);
}
this.running = false;
}
} }

View File

@ -29,52 +29,61 @@ import org.apache.http.impl.client.DefaultHttpClient;
public class HttpHandler { public class HttpHandler {
protected Boolean get(String url, String file) protected Boolean get(String url, String file)
{ {
HttpEntity entity = getHttpEntity(url); HttpEntity entity = getHttpEntity(url);
try { try {
writeToDisk(entity, file); writeToDisk(entity, file);
} catch (Exception e) { e.printStackTrace(); return false; } } catch (Exception e) {
try { e.printStackTrace();
entity.consumeContent(); return false;
} catch (Exception e) { e.printStackTrace(); return false; } }
return true; try {
} entity.consumeContent();
} catch (Exception e) {
private HttpEntity getHttpEntity(String url) e.printStackTrace();
/** return false;
* get the http entity at a given url }
*/ return true;
{ }
HttpEntity entity=null;
try { private HttpEntity getHttpEntity(String url)
DefaultHttpClient httpclient = new DefaultHttpClient(); /**
HttpGet httpget = new HttpGet(url); * get the http entity at a given url
HttpResponse response = httpclient.execute(httpget); */
entity = response.getEntity(); {
} catch (Exception e) { e.printStackTrace(); return null; } HttpEntity entity = null;
return entity; try {
} DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
private void writeToDisk(HttpEntity entity, String file) throws IllegalStateException, IOException HttpResponse response = httpclient.execute(httpget);
/** entity = response.getEntity();
* writes a HTTP entity to the specified filename and location on disk } catch (Exception e) {
*/ e.printStackTrace();
{ return null;
int i=0; }
String FilePath="/sdcard/" + file; return entity;
InputStream in = entity.getContent(); }
byte buff[] = new byte[1024];
FileOutputStream out= private void writeToDisk(HttpEntity entity, String file) throws IllegalStateException, IOException
new FileOutputStream(FilePath); /**
do { * writes a HTTP entity to the specified filename and location on disk
int numread = in.read(buff); */
if (numread <= 0) {
break; int i = 0;
out.write(buff, 0, numread); String FilePath = "/sdcard/" + file;
i++; InputStream in = entity.getContent();
} while (true); byte buff[] = new byte[1024];
out.flush(); FileOutputStream out =
out.close(); new FileOutputStream(FilePath);
} do {
int numread = in.read(buff);
if (numread <= 0)
break;
out.write(buff, 0, numread);
i++;
} while (true);
out.flush();
out.close();
}
} }

View File

@ -17,10 +17,11 @@
under the License. under the License.
*/ */
package org.apache.cordova; package org.apache.cordova;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import android.content.Context; import android.content.Context;
import android.view.View.MeasureSpec; //import android.view.View.MeasureSpec;
import android.widget.LinearLayout; import android.widget.LinearLayout;
/** /**
@ -29,15 +30,15 @@ import android.widget.LinearLayout;
public class LinearLayoutSoftKeyboardDetect extends LinearLayout { public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
private static final String TAG = "SoftKeyboardDetect"; private static final String TAG = "SoftKeyboardDetect";
private int oldHeight = 0; // Need to save the old height as not to send redundant events private int oldHeight = 0; // Need to save the old height as not to send redundant events
private int oldWidth = 0; // Need to save old width for orientation change private int oldWidth = 0; // Need to save old width for orientation change
private int screenWidth = 0; private int screenWidth = 0;
private int screenHeight = 0; private int screenHeight = 0;
private DroidGap app = null; private DroidGap app = null;
public LinearLayoutSoftKeyboardDetect(Context context, int width, int height) { public LinearLayoutSoftKeyboardDetect(Context context, int width, int height) {
super(context); super(context);
screenWidth = width; screenWidth = width;
screenHeight = height; screenHeight = height;
app = (DroidGap) context; app = (DroidGap) context;
@ -55,8 +56,8 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
* @param heightMeasureSpec * @param heightMeasureSpec
*/ */
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
LOG.v(TAG, "We are in our onMeasure method"); LOG.v(TAG, "We are in our onMeasure method");
// Get the current height of the visible part of the screen. // Get the current height of the visible part of the screen.
@ -66,7 +67,7 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
height = MeasureSpec.getSize(heightMeasureSpec); height = MeasureSpec.getSize(heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec); width = MeasureSpec.getSize(widthMeasureSpec);
LOG.v(TAG, "Old Height = %d", oldHeight); LOG.v(TAG, "Old Height = %d", oldHeight);
LOG.v(TAG, "Height = %d", height); LOG.v(TAG, "Height = %d", height);
LOG.v(TAG, "Old Width = %d", oldWidth); LOG.v(TAG, "Old Width = %d", oldWidth);
LOG.v(TAG, "Width = %d", width); LOG.v(TAG, "Width = %d", width);
@ -76,7 +77,7 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
LOG.d(TAG, "Ignore this event"); LOG.d(TAG, "Ignore this event");
} }
// Account for orientation change and ignore this event/Fire orientation change // Account for orientation change and ignore this event/Fire orientation change
else if(screenHeight == width) else if (screenHeight == width)
{ {
int tmp_var = screenHeight; int tmp_var = screenHeight;
screenHeight = screenWidth; screenHeight = screenWidth;
@ -86,14 +87,14 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
// 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) {
if(app != null) if (app != null)
app.sendJavascript("cordova.fireDocumentEvent('hidekeyboard');"); app.appView.sendJavascript("cordova.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) {
if(app != null) if (app != null)
app.sendJavascript("cordova.fireDocumentEvent('showkeyboard');"); app.appView.sendJavascript("cordova.fireDocumentEvent('showkeyboard');");
} }
// Update the old height for the next event // Update the old height for the next event

View File

@ -27,127 +27,127 @@ import android.location.LocationListener;
import android.os.Bundle; import android.os.Bundle;
public class NetworkListener implements LocationListener { public class NetworkListener implements LocationListener {
private Context mCtx; // CordovaActivity object
private LocationManager mLocMan; // Location manager object
private GeoListener owner; // Geolistener object (parent)
private boolean hasData = false; // Flag indicates if location data is available in cLoc
private Location cLoc; // Last recieved location
private boolean running = false; // Flag indicates if listener is running
/** private CordovaInterface mCtx; // CordovaActivity object
* Constructor.
* Automatically starts listening.
*
* @param ctx
* @param interval
* @param m
*/
public NetworkListener(Context ctx, int interval, GeoListener m) {
this.owner = m;
this.mCtx = ctx;
this.mLocMan = (LocationManager) this.mCtx.getSystemService(Context.LOCATION_SERVICE);
this.running = false;
this.start(interval);
}
/**
* Get last location.
*
* @return Location object
*/
public Location getLocation() {
this.cLoc = this.mLocMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (this.cLoc != null) {
this.hasData = true;
}
return this.cLoc;
}
/** private LocationManager mLocMan; // Location manager object
* Called when the provider is disabled by the user. private GeoListener owner; // Geolistener object (parent)
* private boolean hasData = false; // Flag indicates if location data is available in cLoc
* @param provider private Location cLoc; // Last recieved location
*/ private boolean running = false; // Flag indicates if listener is running
public void onProviderDisabled(String provider) {
System.out.println("NetworkListener: The provider " + provider + " is disabled");
}
/** /**
* Called when the provider is enabled by the user. * Constructor.
* * Automatically starts listening.
* @param provider *
*/ * @param ctx
public void onProviderEnabled(String provider) { * @param interval
System.out.println("NetworkListener: The provider "+ provider + " is enabled"); * @param m
} */
public NetworkListener(CordovaInterface ctx, int interval, GeoListener m) {
this.owner = m;
this.mCtx = ctx;
this.mLocMan = (LocationManager) this.mCtx.getActivity().getSystemService(Context.LOCATION_SERVICE);
this.running = false;
this.start(interval);
}
/** /**
* Called when the provider status changes. This method is called when a * Get last location.
* provider is unable to fetch a location or if the provider has recently *
* become available after a period of unavailability. * @return Location object
* */
* @param provider public Location getLocation() {
* @param status this.cLoc = this.mLocMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
* @param extras if (this.cLoc != null) {
*/ this.hasData = true;
public void onStatusChanged(String provider, int status, Bundle extras) { }
System.out.println("NetworkListener: The status of the provider " + provider + " has changed"); return this.cLoc;
if (status == 0) { }
System.out.println("NetworkListener: " + provider + " is OUT OF SERVICE");
} /**
else if (status == 1) { * Called when the provider is disabled by the user.
System.out.println("NetworkListener: " + provider + " is TEMPORARILY_UNAVAILABLE"); *
} * @param provider
else { */
System.out.println("NetworkListener: " + provider + " is Available"); public void onProviderDisabled(String provider) {
} System.out.println("NetworkListener: The provider " + provider + " is disabled");
} }
/**
* Called when the provider is enabled by the user.
*
* @param provider
*/
public void onProviderEnabled(String provider) {
System.out.println("NetworkListener: The provider " + provider + " is enabled");
}
/**
* Called when the provider status changes. This method is called when a
* provider is unable to fetch a location or if the provider has recently
* become available after a period of unavailability.
*
* @param provider
* @param status
* @param extras
*/
public void onStatusChanged(String provider, int status, Bundle extras) {
System.out.println("NetworkListener: The status of the provider " + provider + " has changed");
if (status == 0) {
System.out.println("NetworkListener: " + provider + " is OUT OF SERVICE");
}
else if (status == 1) {
System.out.println("NetworkListener: " + provider + " is TEMPORARILY_UNAVAILABLE");
}
else {
System.out.println("NetworkListener: " + provider + " is Available");
}
}
/**
* Called when the location has changed.
*
* @param location
*/
public void onLocationChanged(Location location) {
System.out.println("NetworkListener: The location has been updated!");
this.hasData = true;
this.cLoc = location;
// The GPS is the primary form of Geolocation in Cordova.
// Only fire the success variables if the GPS is down for some reason.
if (!this.owner.mGps.hasLocation()) {
this.owner.success(location);
}
}
/**
* Start requesting location updates.
*
* @param interval
*/
public void start(int interval) {
if (!this.running) {
this.running = true;
this.mLocMan.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, interval, 0, this);
this.getLocation();
// If Network provider has data but GPS provider doesn't, then send ours
if (this.hasData && !this.owner.mGps.hasLocation()) {
this.owner.success(this.cLoc);
}
}
}
/**
* Stop receiving location updates.
*/
public void stop() {
if (this.running) {
this.mLocMan.removeUpdates(this);
}
this.running = false;
}
/**
* Called when the location has changed.
*
* @param location
*/
public void onLocationChanged(Location location) {
System.out.println("NetworkListener: The location has been updated!");
this.hasData = true;
this.cLoc = location;
// The GPS is the primary form of Geolocation in Cordova.
// Only fire the success variables if the GPS is down for some reason.
if (!this.owner.mGps.hasLocation()) {
this.owner.success(location);
}
}
/**
* Start requesting location updates.
*
* @param interval
*/
public void start(int interval) {
if (!this.running) {
this.running = true;
this.mLocMan.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, interval, 0, this);
this.getLocation();
// If Network provider has data but GPS provider doesn't, then send ours
if (this.hasData && !this.owner.mGps.hasLocation()) {
this.owner.success(this.cLoc);
}
}
}
/**
* Stop receiving location updates.
*/
public void stop() {
if (this.running) {
this.mLocMan.removeUpdates(this);
}
this.running = false;
}
} }

View File

@ -23,7 +23,6 @@ import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult; import org.apache.cordova.api.PluginResult;
import org.json.JSONArray; import org.json.JSONArray;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -33,7 +32,7 @@ import android.net.NetworkInfo;
import android.util.Log; import android.util.Log;
public class NetworkManager extends Plugin { public class NetworkManager extends Plugin {
public static int NOT_REACHABLE = 0; public static int NOT_REACHABLE = 0;
public static int REACHABLE_VIA_CARRIER_DATA_NETWORK = 1; public static int REACHABLE_VIA_CARRIER_DATA_NETWORK = 1;
public static int REACHABLE_VIA_WIFI_NETWORK = 2; public static int REACHABLE_VIA_WIFI_NETWORK = 2;
@ -66,18 +65,18 @@ public class NetworkManager extends Plugin {
public static final String TYPE_3G = "3g"; public static final String TYPE_3G = "3g";
public static final String TYPE_4G = "4g"; public static final String TYPE_4G = "4g";
public static final String TYPE_NONE = "none"; public static final String TYPE_NONE = "none";
private static final String LOG_TAG = "NetworkManager"; private static final String LOG_TAG = "NetworkManager";
private String connectionCallbackId; private String connectionCallbackId;
ConnectivityManager sockMan; ConnectivityManager sockMan;
BroadcastReceiver receiver; BroadcastReceiver receiver;
/** /**
* Constructor. * Constructor.
*/ */
public NetworkManager() { public NetworkManager() {
this.receiver = null; this.receiver = null;
} }
@ -87,26 +86,27 @@ public class NetworkManager extends Plugin {
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(Context ctx) { public void setContext(CordovaInterface ctx) {
super.setContext(ctx); super.setContext(ctx);
this.sockMan = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); this.sockMan = (ConnectivityManager) ctx.getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
this.connectionCallbackId = null; this.connectionCallbackId = null;
// We need to listen to connectivity events to update navigator.connection // We need to listen to connectivity events to update navigator.connection
IntentFilter intentFilter = new IntentFilter() ; IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
if (this.receiver == null) { if (this.receiver == null) {
this.receiver = new BroadcastReceiver() { this.receiver = new BroadcastReceiver() {
@SuppressWarnings("deprecation")
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO)); updateConnectionInfo((NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
} }
}; };
ctx.registerReceiver(this.receiver, intentFilter); ctx.getActivity().registerReceiver(this.receiver, intentFilter);
} }
} }
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
* *
@ -118,7 +118,7 @@ public class NetworkManager extends Plugin {
public PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.INVALID_ACTION; PluginResult.Status status = PluginResult.Status.INVALID_ACTION;
String result = "Unsupported Operation: " + action; String result = "Unsupported Operation: " + action;
if (action.equals("getConnectionInfo")) { if (action.equals("getConnectionInfo")) {
this.connectionCallbackId = callbackId; this.connectionCallbackId = callbackId;
NetworkInfo info = sockMan.getActiveNetworkInfo(); NetworkInfo info = sockMan.getActiveNetworkInfo();
@ -126,7 +126,7 @@ public class NetworkManager extends Plugin {
pluginResult.setKeepCallback(true); pluginResult.setKeepCallback(true);
return pluginResult; return pluginResult;
} }
return new PluginResult(status, result); return new PluginResult(status, result);
} }
@ -139,14 +139,14 @@ public class NetworkManager extends Plugin {
public boolean isSynch(String action) { public boolean isSynch(String action) {
return true; return true;
} }
/** /**
* Stop network receiver. * Stop network receiver.
*/ */
public void onDestroy() { public void onDestroy() {
if (this.receiver != null) { if (this.receiver != null) {
try { try {
this.ctx.unregisterReceiver(this.receiver); this.ctx.getActivity().unregisterReceiver(this.receiver);
} catch (Exception e) { } catch (Exception e) {
Log.e(LOG_TAG, "Error unregistering network receiver: " + e.getMessage(), e); Log.e(LOG_TAG, "Error unregistering network receiver: " + e.getMessage(), e);
} }
@ -157,14 +157,13 @@ public class NetworkManager extends Plugin {
// LOCAL METHODS // LOCAL METHODS
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* Updates the JavaScript side whenever the connection changes * Updates the JavaScript side whenever the connection changes
* *
* @param info the current active network info * @param info the current active network info
* @return * @return
*/ */
private void updateConnectionInfo(NetworkInfo info) { private void updateConnectionInfo(NetworkInfo info) {
// send update to javascript "navigator.network.connection" // send update to javascript "navigator.network.connection"
sendUpdate(this.getConnectionInfo(info)); sendUpdate(this.getConnectionInfo(info));
} }
@ -188,7 +187,7 @@ public class NetworkManager extends Plugin {
} }
return type; return type;
} }
/** /**
* Create a new plugin result and send it back to JavaScript * Create a new plugin result and send it back to JavaScript
* *
@ -198,11 +197,11 @@ public class NetworkManager extends Plugin {
PluginResult result = new PluginResult(PluginResult.Status.OK, type); PluginResult result = new PluginResult(PluginResult.Status.OK, type);
result.setKeepCallback(true); result.setKeepCallback(true);
this.success(result, this.connectionCallbackId); this.success(result, this.connectionCallbackId);
// Send to all plugins // Send to all plugins
webView.postMessage("networkconnection", type); webView.postMessage("networkconnection", type);
} }
/** /**
* Determine the type of connection * Determine the type of connection
* *
@ -218,13 +217,13 @@ public class NetworkManager extends Plugin {
} }
else if (type.toLowerCase().equals(MOBILE)) { else if (type.toLowerCase().equals(MOBILE)) {
type = info.getSubtypeName(); type = info.getSubtypeName();
if (type.toLowerCase().equals(GSM) || if (type.toLowerCase().equals(GSM) ||
type.toLowerCase().equals(GPRS) || type.toLowerCase().equals(GPRS) ||
type.toLowerCase().equals(EDGE)) { type.toLowerCase().equals(EDGE)) {
return TYPE_2G; return TYPE_2G;
} }
else if (type.toLowerCase().startsWith(CDMA) || else if (type.toLowerCase().startsWith(CDMA) ||
type.toLowerCase().equals(UMTS) || type.toLowerCase().equals(UMTS) ||
type.toLowerCase().equals(ONEXRTT) || type.toLowerCase().equals(ONEXRTT) ||
type.toLowerCase().equals(EHRPD) || type.toLowerCase().equals(EHRPD) ||
type.toLowerCase().equals(HSUPA) || type.toLowerCase().equals(HSUPA) ||
@ -232,13 +231,13 @@ public class NetworkManager extends Plugin {
type.toLowerCase().equals(HSPA)) { type.toLowerCase().equals(HSPA)) {
return TYPE_3G; return TYPE_3G;
} }
else if (type.toLowerCase().equals(LTE) || else if (type.toLowerCase().equals(LTE) ||
type.toLowerCase().equals(UMB) || type.toLowerCase().equals(UMB) ||
type.toLowerCase().equals(HSPA_PLUS)) { type.toLowerCase().equals(HSPA_PLUS)) {
return TYPE_4G; return TYPE_4G;
} }
} }
} }
else { else {
return TYPE_NONE; return TYPE_NONE;
} }

View File

@ -31,337 +31,336 @@ import android.media.Ringtone;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.net.Uri; import android.net.Uri;
import android.os.Vibrator; import android.os.Vibrator;
import android.app.Activity;
/** /**
* This class provides access to notifications on the device. * This class provides access to notifications on the device.
*/ */
public class Notification extends Plugin { public class Notification extends Plugin {
public int confirmResult = -1;
public ProgressDialog spinnerDialog = null;
public ProgressDialog progressDialog = null;
/**
* Constructor.
*/
public Notification() {
}
/** public int confirmResult = -1;
* Executes the request and returns PluginResult. public ProgressDialog spinnerDialog = null;
* public ProgressDialog progressDialog = null;
* @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("beep")) {
this.beep(args.getLong(0));
}
else if (action.equals("vibrate")) {
this.vibrate(args.getLong(0));
}
else if (action.equals("alert")) {
this.alert(args.getString(0),args.getString(1),args.getString(2), callbackId);
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
r.setKeepCallback(true);
return r;
}
else if (action.equals("confirm")) {
this.confirm(args.getString(0),args.getString(1),args.getString(2), callbackId);
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
r.setKeepCallback(true);
return r;
}
else if (action.equals("activityStart")) {
this.activityStart(args.getString(0),args.getString(1));
}
else if (action.equals("activityStop")) {
this.activityStop();
}
else if (action.equals("progressStart")) {
this.progressStart(args.getString(0),args.getString(1));
}
else if (action.equals("progressValue")) {
this.progressValue(args.getInt(0));
}
else if (action.equals("progressStop")) {
this.progressStop();
}
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
/** /**
* Identifies if action to be executed returns a value and should be run synchronously. * Constructor.
* */
* @param action The action to execute public Notification() {
* @return T=returns value
*/
public boolean isSynch(String action) {
if (action.equals("alert")) {
return true;
} }
else if (action.equals("confirm")) {
return true; /**
* 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("beep")) {
this.beep(args.getLong(0));
}
else if (action.equals("vibrate")) {
this.vibrate(args.getLong(0));
}
else if (action.equals("alert")) {
this.alert(args.getString(0), args.getString(1), args.getString(2), callbackId);
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
r.setKeepCallback(true);
return r;
}
else if (action.equals("confirm")) {
this.confirm(args.getString(0), args.getString(1), args.getString(2), callbackId);
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
r.setKeepCallback(true);
return r;
}
else if (action.equals("activityStart")) {
this.activityStart(args.getString(0), args.getString(1));
}
else if (action.equals("activityStop")) {
this.activityStop();
}
else if (action.equals("progressStart")) {
this.progressStart(args.getString(0), args.getString(1));
}
else if (action.equals("progressValue")) {
this.progressValue(args.getInt(0));
}
else if (action.equals("progressStop")) {
this.progressStop();
}
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
} }
else if (action.equals("activityStart")) {
return true; /**
* Identifies if action to be executed returns a value and should be run synchronously.
*
* @param action The action to execute
* @return T=returns value
*/
public boolean isSynch(String action) {
if (action.equals("alert")) {
return true;
}
else if (action.equals("confirm")) {
return true;
}
else if (action.equals("activityStart")) {
return true;
}
else if (action.equals("activityStop")) {
return true;
}
else if (action.equals("progressStart")) {
return true;
}
else if (action.equals("progressValue")) {
return true;
}
else if (action.equals("progressStop")) {
return true;
}
else {
return false;
}
} }
else if (action.equals("activityStop")) {
return true;
}
else if (action.equals("progressStart")) {
return true;
}
else if (action.equals("progressValue")) {
return true;
}
else if (action.equals("progressStop")) {
return true;
}
else {
return false;
}
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// LOCAL METHODS // LOCAL METHODS
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* Beep plays the default notification ringtone. * Beep plays the default notification ringtone.
* *
* @param count Number of times to play notification * @param count Number of times to play notification
*/ */
public void beep(long count) { public void beep(long count) {
Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone notification = RingtoneManager.getRingtone(this.ctx, ringtone); Ringtone notification = RingtoneManager.getRingtone(this.ctx.getActivity().getBaseContext(), ringtone);
// If phone is not set to silent mode // If phone is not set to silent mode
if (notification != null) { if (notification != null) {
for (long i = 0; i < count; ++i) { for (long i = 0; i < count; ++i) {
notification.play(); notification.play();
long timeout = 5000; long timeout = 5000;
while (notification.isPlaying() && (timeout > 0)) { while (notification.isPlaying() && (timeout > 0)) {
timeout = timeout - 100; timeout = timeout - 100;
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
} }
}
}
} }
}
} }
}
/**
/** * Vibrates the device for the specified amount of time.
* Vibrates the device for the specified amount of time. *
* * @param time Time to vibrate in ms.
* @param time Time to vibrate in ms. */
*/ public void vibrate(long time) {
public void vibrate(long time){
// Start the vibration, 0 defaults to half a second. // Start the vibration, 0 defaults to half a second.
if (time == 0) { if (time == 0) {
time = 500; time = 500;
} }
Vibrator vibrator = (Vibrator) this.ctx.getSystemService(Context.VIBRATOR_SERVICE); Vibrator vibrator = (Vibrator) this.ctx.getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(time); vibrator.vibrate(time);
}
/**
* Builds and shows a native Android alert with given Strings
* @param message The message the alert should display
* @param title The title of the alert
* @param buttonLabel The label of the button
* @param callbackId The callback id
*/
public synchronized void alert(final String message, final String title, final String buttonLabel, final String callbackId) {
final Context ctx = this.ctx;
final Notification notification = this;
Runnable runnable = new Runnable() {
public void run() {
AlertDialog.Builder dlg = new AlertDialog.Builder(ctx);
dlg.setMessage(message);
dlg.setTitle(title);
dlg.setCancelable(false);
dlg.setPositiveButton(buttonLabel,
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 0), callbackId);
}
});
dlg.create();
dlg.show();
};
};
((Activity) this.ctx).runOnUiThread(runnable);
}
/**
* Builds and shows a native Android confirm dialog with given title, message, buttons.
* This dialog only shows up to 3 buttons. Any labels after that will be ignored.
* The index of the button pressed will be returned to the JavaScript callback identified by callbackId.
*
* @param message The message the dialog should display
* @param title The title of the dialog
* @param buttonLabels A comma separated list of button labels (Up to 3 buttons)
* @param callbackId The callback id
*/
public synchronized void confirm(final String message, final String title, String buttonLabels, final String callbackId) {
final Context ctx = this.ctx;
final Notification notification = this;
final String[] fButtons = buttonLabels.split(",");
Runnable runnable = new Runnable() {
public void run() {
AlertDialog.Builder dlg = new AlertDialog.Builder(ctx);
dlg.setMessage(message);
dlg.setTitle(title);
dlg.setCancelable(false);
// First button
if (fButtons.length > 0) {
dlg.setNegativeButton(fButtons[0],
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 1), callbackId);
}
});
}
// Second button
if (fButtons.length > 1) {
dlg.setNeutralButton(fButtons[1],
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 2), callbackId);
}
});
}
// Third button
if (fButtons.length > 2) {
dlg.setPositiveButton(fButtons[2],
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 3), callbackId);
}
}
);
}
dlg.create();
dlg.show();
};
};
((Activity) this.ctx).runOnUiThread(runnable);
}
/**
* Show the spinner.
*
* @param title Title of the dialog
* @param message The message of the dialog
*/
public synchronized void activityStart(final String title, final String message) {
if (this.spinnerDialog != null) {
this.spinnerDialog.dismiss();
this.spinnerDialog = null;
} }
final Notification notification = this;
final Activity ctx = (Activity) this.ctx;
Runnable runnable = new Runnable() {
public void run() {
notification.spinnerDialog = ProgressDialog.show(ctx, title , message, true, true,
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
notification.spinnerDialog = null;
}
});
}
};
ctx.runOnUiThread(runnable);
}
/**
* Stop spinner.
*/
public synchronized void activityStop() {
if (this.spinnerDialog != null) {
this.spinnerDialog.dismiss();
this.spinnerDialog = null;
}
}
/** /**
* Show the progress dialog. * Builds and shows a native Android alert with given Strings
* * @param message The message the alert should display
* @param title Title of the dialog * @param title The title of the alert
* @param message The message of the dialog * @param buttonLabel The label of the button
*/ * @param callbackId The callback id
public synchronized void progressStart(final String title, final String message) { */
if (this.progressDialog != null) { public synchronized void alert(final String message, final String title, final String buttonLabel, final String callbackId) {
this.progressDialog.dismiss();
this.progressDialog = null; final CordovaInterface ctx = this.ctx;
final Notification notification = this;
Runnable runnable = new Runnable() {
public void run() {
AlertDialog.Builder dlg = new AlertDialog.Builder(ctx.getActivity());
dlg.setMessage(message);
dlg.setTitle(title);
dlg.setCancelable(false);
dlg.setPositiveButton(buttonLabel,
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 0), callbackId);
}
});
dlg.create();
dlg.show();
};
};
this.ctx.getActivity().runOnUiThread(runnable);
} }
final Notification notification = this;
final Activity ctx = (Activity) this.ctx; /**
Runnable runnable = new Runnable() { * Builds and shows a native Android confirm dialog with given title, message, buttons.
public void run() { * This dialog only shows up to 3 buttons. Any labels after that will be ignored.
notification.progressDialog = new ProgressDialog(ctx); * The index of the button pressed will be returned to the JavaScript callback identified by callbackId.
notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); *
notification.progressDialog.setTitle(title); * @param message The message the dialog should display
notification.progressDialog.setMessage(message); * @param title The title of the dialog
notification.progressDialog.setCancelable(true); * @param buttonLabels A comma separated list of button labels (Up to 3 buttons)
notification.progressDialog.setMax(100); * @param callbackId The callback id
notification.progressDialog.setProgress(0); */
notification.progressDialog.setOnCancelListener( public synchronized void confirm(final String message, final String title, String buttonLabels, final String callbackId) {
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) { final CordovaInterface ctx = this.ctx;
notification.progressDialog = null; final Notification notification = this;
final String[] fButtons = buttonLabels.split(",");
Runnable runnable = new Runnable() {
public void run() {
AlertDialog.Builder dlg = new AlertDialog.Builder(ctx.getActivity());
dlg.setMessage(message);
dlg.setTitle(title);
dlg.setCancelable(false);
// First button
if (fButtons.length > 0) {
dlg.setNegativeButton(fButtons[0],
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 1), callbackId);
}
});
}
// Second button
if (fButtons.length > 1) {
dlg.setNeutralButton(fButtons[1],
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 2), callbackId);
}
});
}
// Third button
if (fButtons.length > 2) {
dlg.setPositiveButton(fButtons[2],
new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 3), callbackId);
}
}
);
}
dlg.create();
dlg.show();
};
};
this.ctx.getActivity().runOnUiThread(runnable);
}
/**
* Show the spinner.
*
* @param title Title of the dialog
* @param message The message of the dialog
*/
public synchronized void activityStart(final String title, final String message) {
if (this.spinnerDialog != null) {
this.spinnerDialog.dismiss();
this.spinnerDialog = null;
}
final Notification notification = this;
final CordovaInterface ctx = this.ctx;
Runnable runnable = new Runnable() {
public void run() {
notification.spinnerDialog = ProgressDialog.show(ctx.getActivity(), title, message, true, true,
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
notification.spinnerDialog = null;
}
});
} }
}); };
notification.progressDialog.show(); this.ctx.getActivity().runOnUiThread(runnable);
} }
};
ctx.runOnUiThread(runnable); /**
} * Stop spinner.
*/
/** public synchronized void activityStop() {
* Set value of progress bar. if (this.spinnerDialog != null) {
* this.spinnerDialog.dismiss();
* @param value 0-100 this.spinnerDialog = null;
*/ }
public synchronized void progressValue(int value) { }
if (this.progressDialog != null) {
this.progressDialog.setProgress(value); /**
} * Show the progress dialog.
} *
* @param title Title of the dialog
/** * @param message The message of the dialog
* Stop progress dialog. */
*/ public synchronized void progressStart(final String title, final String message) {
public synchronized void progressStop() { if (this.progressDialog != null) {
if (this.progressDialog != null) { this.progressDialog.dismiss();
this.progressDialog.dismiss(); this.progressDialog = null;
this.progressDialog = null; }
final Notification notification = this;
final CordovaInterface ctx = this.ctx;
Runnable runnable = new Runnable() {
public void run() {
notification.progressDialog = new ProgressDialog(ctx.getActivity());
notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
notification.progressDialog.setTitle(title);
notification.progressDialog.setMessage(message);
notification.progressDialog.setCancelable(true);
notification.progressDialog.setMax(100);
notification.progressDialog.setProgress(0);
notification.progressDialog.setOnCancelListener(
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
notification.progressDialog = null;
}
});
notification.progressDialog.show();
}
};
this.ctx.getActivity().runOnUiThread(runnable);
}
/**
* Set value of progress bar.
*
* @param value 0-100
*/
public synchronized void progressValue(int value) {
if (this.progressDialog != null) {
this.progressDialog.setProgress(value);
}
}
/**
* Stop progress dialog.
*/
public synchronized void progressStop() {
if (this.progressDialog != null) {
this.progressDialog.dismiss();
this.progressDialog = null;
}
} }
}
} }

View File

@ -31,7 +31,8 @@ public class SplashScreen extends Plugin {
String result = ""; String result = "";
if (action.equals("hide")) { if (action.equals("hide")) {
((DroidGap)this.ctx).removeSplashScreen(); //((DroidGap)this.ctx).removeSplashScreen();
this.webView.postMessage("splashscreen", "hide");
} }
else { else {
status = PluginResult.Status.INVALID_ACTION; status = PluginResult.Status.INVALID_ACTION;

View File

@ -18,18 +18,18 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import java.lang.reflect.Field; //import java.lang.reflect.Field;
import android.app.Activity; //import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
public class StandAlone extends DroidGap { public class StandAlone extends DroidGap {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
super.loadUrl("file:///android_asset/www/index.html"); super.loadUrl("file:///android_asset/www/index.html");
} }
} }

View File

@ -37,203 +37,202 @@ import android.database.sqlite.*;
*/ */
public class Storage extends Plugin { public class Storage extends Plugin {
// Data Definition Language // Data Definition Language
private static final String ALTER = "alter"; private static final String ALTER = "alter";
private static final String CREATE = "create"; private static final String CREATE = "create";
private static final String DROP = "drop"; private static final String DROP = "drop";
private static final String TRUNCATE = "truncate"; private static final String TRUNCATE = "truncate";
SQLiteDatabase myDb = null; // Database object
String path = null; // Database path
String dbName = null; // Database name
/** SQLiteDatabase myDb = null; // Database object
* Constructor. String path = null; // Database path
*/ String dbName = null; // Database name
public Storage() {
}
/** /**
* Executes the request and returns PluginResult. * Constructor.
* */
* @param action public Storage() {
* 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("openDatabase")) { * Executes the request and returns PluginResult.
this.openDatabase(args.getString(0), args.getString(1), *
args.getString(2), args.getLong(3)); * @param action
} else if (action.equals("executeSql")) { * The action to execute.
String[] s = null; * @param args
if (args.isNull(1)) { * JSONArry of arguments for the plugin.
s = new String[0]; * @param callbackId
} else { * The callback id used when calling back into JavaScript.
JSONArray a = args.getJSONArray(1); * @return A PluginResult object with a status and message.
int len = a.length(); */
s = new String[len]; public PluginResult execute(String action, JSONArray args, String callbackId) {
for (int i = 0; i < len; i++) { PluginResult.Status status = PluginResult.Status.OK;
s[i] = a.getString(i); String result = "";
}
}
this.executeSql(args.getString(0), s, args.getString(2));
}
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
/** try {
* Identifies if action to be executed returns a value and should be run if (action.equals("openDatabase")) {
* synchronously. this.openDatabase(args.getString(0), args.getString(1),
* args.getString(2), args.getLong(3));
* @param action } else if (action.equals("executeSql")) {
* The action to execute String[] s = null;
* @return T=returns value if (args.isNull(1)) {
*/ s = new String[0];
public boolean isSynch(String action) { } else {
return true; JSONArray a = args.getJSONArray(1);
} int len = a.length();
s = new String[len];
for (int i = 0; i < len; i++) {
s[i] = a.getString(i);
}
}
this.executeSql(args.getString(0), s, args.getString(2));
}
return new PluginResult(status, result);
} catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
}
/** /**
* Clean up and close database. * Identifies if action to be executed returns a value and should be run
*/ * synchronously.
@Override *
public void onDestroy() { * @param action
if (this.myDb != null) { * The action to execute
this.myDb.close(); * @return T=returns value
this.myDb = null; */
} public boolean isSynch(String action) {
} return true;
}
// -------------------------------------------------------------------------- /**
// LOCAL METHODS * Clean up and close database.
// -------------------------------------------------------------------------- */
@Override
public void onDestroy() {
if (this.myDb != null) {
this.myDb.close();
this.myDb = null;
}
}
/** // --------------------------------------------------------------------------
* Open database. // LOCAL METHODS
* // --------------------------------------------------------------------------
* @param db
* The name of the database
* @param version
* The version
* @param display_name
* The display name
* @param size
* The size in bytes
*/
public void openDatabase(String db, String version, String display_name,
long size) {
// If database is open, then close it /**
if (this.myDb != null) { * Open database.
this.myDb.close(); *
} * @param db
* The name of the database
* @param version
* The version
* @param display_name
* The display name
* @param size
* The size in bytes
*/
public void openDatabase(String db, String version, String display_name,
long size) {
// If no database path, generate from application package // If database is open, then close it
if (this.path == null) { if (this.myDb != null) {
this.path = this.ctx.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); this.myDb.close();
} }
this.dbName = this.path + File.pathSeparator + db + ".db"; // If no database path, generate from application package
this.myDb = SQLiteDatabase.openOrCreateDatabase(this.dbName, null); if (this.path == null) {
} this.path = this.ctx.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
}
/** this.dbName = this.path + File.pathSeparator + db + ".db";
* Execute SQL statement. this.myDb = SQLiteDatabase.openOrCreateDatabase(this.dbName, null);
* }
* @param query
* The SQL query
* @param params
* Parameters for the query
* @param tx_id
* Transaction id
*/
public void executeSql(String query, String[] params, String tx_id) {
try {
if (isDDL(query)) {
this.myDb.execSQL(query);
this.sendJavascript("cordova.require('cordova/plugin/android/storage').completeQuery('" + tx_id + "', '');");
}
else {
Cursor myCursor = this.myDb.rawQuery(query, params);
this.processResults(myCursor, tx_id);
myCursor.close();
}
}
catch (SQLiteException ex) {
ex.printStackTrace();
System.out.println("Storage.executeSql(): Error=" + ex.getMessage());
// Send error message back to JavaScript
this.sendJavascript("cordova.require('cordova/plugin/android/storage').fail('" + ex.getMessage() + "','" + tx_id + "');");
}
}
/** /**
* Checks to see the the query is a Data Definintion command * Execute SQL statement.
* *
* @param query to be executed * @param query
* @return true if it is a DDL command, false otherwise * The SQL query
*/ * @param params
private boolean isDDL(String query) { * Parameters for the query
String cmd = query.toLowerCase(); * @param tx_id
if (cmd.startsWith(DROP) || cmd.startsWith(CREATE) || cmd.startsWith(ALTER) || cmd.startsWith(TRUNCATE)) { * Transaction id
return true; */
} public void executeSql(String query, String[] params, String tx_id) {
return false; try {
} if (isDDL(query)) {
this.myDb.execSQL(query);
this.sendJavascript("cordova.require('cordova/plugin/android/storage').completeQuery('" + tx_id + "', '');");
}
else {
Cursor myCursor = this.myDb.rawQuery(query, params);
this.processResults(myCursor, tx_id);
myCursor.close();
}
} catch (SQLiteException ex) {
ex.printStackTrace();
System.out.println("Storage.executeSql(): Error=" + ex.getMessage());
/** // Send error message back to JavaScript
* Process query results. this.sendJavascript("cordova.require('cordova/plugin/android/storage').fail('" + ex.getMessage() + "','" + tx_id + "');");
* }
* @param cur }
* Cursor into query results
* @param tx_id
* Transaction id
*/
public void processResults(Cursor cur, String tx_id) {
String result = "[]"; /**
// If query result has rows * Checks to see the the query is a Data Definintion command
*
* @param query to be executed
* @return true if it is a DDL command, false otherwise
*/
private boolean isDDL(String query) {
String cmd = query.toLowerCase();
if (cmd.startsWith(DROP) || cmd.startsWith(CREATE) || cmd.startsWith(ALTER) || cmd.startsWith(TRUNCATE)) {
return true;
}
return false;
}
if (cur.moveToFirst()) { /**
JSONArray fullresult = new JSONArray(); * Process query results.
String key = ""; *
String value = ""; * @param cur
int colCount = cur.getColumnCount(); * Cursor into query results
* @param tx_id
* Transaction id
*/
public void processResults(Cursor cur, String tx_id) {
// Build up JSON result object for each row String result = "[]";
do { // If query result has rows
JSONObject row = new JSONObject();
try {
for (int i = 0; i < colCount; ++i) {
key = cur.getColumnName(i);
value = cur.getString(i);
row.put(key, value);
}
fullresult.put(row);
} catch (JSONException e) { if (cur.moveToFirst()) {
e.printStackTrace(); JSONArray fullresult = new JSONArray();
} String key = "";
String value = "";
int colCount = cur.getColumnCount();
} while (cur.moveToNext()); // Build up JSON result object for each row
do {
JSONObject row = new JSONObject();
try {
for (int i = 0; i < colCount; ++i) {
key = cur.getColumnName(i);
value = cur.getString(i);
row.put(key, value);
}
fullresult.put(row);
result = fullresult.toString(); } catch (JSONException e) {
} e.printStackTrace();
}
// Let JavaScript know that there are no more rows } while (cur.moveToNext());
this.sendJavascript("cordova.require('cordova/plugin/android/storage').completeQuery('" + tx_id + "', " + result + ");");
} result = fullresult.toString();
}
// Let JavaScript know that there are no more rows
this.sendJavascript("cordova.require('cordova/plugin/android/storage').completeQuery('" + tx_id + "', " + result + ");");
}
} }

View File

@ -25,7 +25,6 @@ import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult; import org.apache.cordova.api.PluginResult;
import org.json.JSONArray; import org.json.JSONArray;
import android.hardware.Sensor; import android.hardware.Sensor;
import android.hardware.SensorEvent; import android.hardware.SensorEvent;
import android.hardware.SensorEventListener; import android.hardware.SensorEventListener;
@ -33,80 +32,81 @@ import android.hardware.SensorManager;
import android.content.Context; import android.content.Context;
public class TempListener extends Plugin implements SensorEventListener { public class TempListener extends Plugin implements SensorEventListener {
Sensor mSensor;
private SensorManager sensorManager;
/**
* Constructor.
*/
public TempListener() {
}
/** Sensor mSensor;
* Sets the context of the Command. This can then be used to do things like private SensorManager sensorManager;
* get file paths associated with the Activity.
* /**
* @param ctx The context of the main Activity. * Constructor.
*/ */
public void setContext(Context ctx) { public TempListener() {
super.setContext(ctx); }
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE);
} /**
* Sets the context of the Command. This can then be used to do things like
* get file paths associated with the Activity.
*
* @param ctx The context of the main Activity.
*/
public void setContext(CordovaInterface ctx) {
super.setContext(ctx);
this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE);
}
/**
* 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 = "";
if (action.equals("start")) {
this.start();
}
else if (action.equals("stop")) {
this.stop();
}
return new PluginResult(status, result);
}
/**
* 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 = "";
if (action.equals("start")) {
this.start();
}
else if (action.equals("stop")) {
this.stop();
}
return new PluginResult(status, result);
}
/** /**
* Called by AccelBroker when listener is to be shut down. * Called by AccelBroker when listener is to be shut down.
* Stop listener. * Stop listener.
*/ */
public void onDestroy() { public void onDestroy() {
this.stop(); this.stop();
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// LOCAL METHODS // LOCAL METHODS
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
public void start() { public void start() {
List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_TEMPERATURE); @SuppressWarnings("deprecation")
if (list.size() > 0) { List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_TEMPERATURE);
this.mSensor = list.get(0); if (list.size() > 0) {
this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_NORMAL); this.mSensor = list.get(0);
} this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_NORMAL);
} }
}
public void stop() {
this.sensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
public void onSensorChanged(SensorEvent event) { public void stop() {
// We want to know what temp this is. this.sensorManager.unregisterListener(this);
float temp = event.values[0]; }
this.sendJavascript("gotTemp(" + temp + ");");
} public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
public void onSensorChanged(SensorEvent event) {
// We want to know what temp this is.
float temp = event.values[0];
this.sendJavascript("gotTemp(" + temp + ");");
}
} }

View File

@ -18,23 +18,22 @@
*/ */
package org.apache.cordova.api; package org.apache.cordova.api;
import java.util.HashMap; //import java.util.HashMap;
import android.app.Activity; import android.app.Activity;
import android.app.Service; //import android.app.Service;
import android.content.BroadcastReceiver; //import android.content.BroadcastReceiver;
import android.content.ContentResolver; //import android.content.ContentResolver;
import android.content.Context; //import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; //import android.content.IntentFilter;
import android.content.res.AssetManager; //import android.content.res.AssetManager;
import android.content.res.Resources; //import android.content.res.Resources;
import android.database.Cursor; //import android.database.Cursor;
import android.hardware.SensorManager; //import android.hardware.SensorManager;
import android.net.Uri; //import android.net.Uri;
import android.view.Menu; //import android.view.Menu;
import android.view.MenuItem; //import android.view.MenuItem;
/** /**
* The Cordova activity abstract class that is extended by DroidGap. * The Cordova activity abstract class that is extended by DroidGap.
@ -42,7 +41,6 @@ import android.view.MenuItem;
*/ */
public interface CordovaInterface { public interface CordovaInterface {
/** /**
* Launch an activity for which you would like a result when it finished. When this activity exits, * Launch an activity for which you would like a result when it finished. When this activity exits,
* your onActivityResult() method will be called. * your onActivityResult() method will be called.
@ -52,22 +50,24 @@ public interface CordovaInterface {
* @param requestCode The request code that is passed to callback to identify the activity * @param requestCode The request code that is passed to callback to identify the activity
*/ */
abstract public void startActivityForResult(IPlugin command, Intent intent, int requestCode); abstract public void startActivityForResult(IPlugin command, Intent intent, int requestCode);
/** /**
* Set the plugin to be called when a sub-activity exits. * Set the plugin to be called when a sub-activity exits.
* *
* @param plugin The plugin on which onActivityResult is to be called * @param plugin The plugin on which onActivityResult is to be called
*/ */
abstract public void setActivityResultCallback(IPlugin plugin); abstract public void setActivityResultCallback(IPlugin plugin);
/** /**
* Causes the Activity to override the back button behaviour * Causes the Activity to override the back button behavior.
*
* @param override * @param override
*/ */
public abstract void bindBackButton(boolean override); public abstract void bindBackButton(boolean override);
/** /**
* A hook required to check if the Back Button is bound * A hook required to check if the Back Button is bound.
*
* @return * @return
*/ */
public abstract boolean isBackButtonBound(); public abstract boolean isBackButtonBound();
@ -76,16 +76,20 @@ public interface CordovaInterface {
* Hook in DroidGap for menu plugins * Hook in DroidGap for menu plugins
* (This is in the Android SDK, do we need this on the Interface?) * (This is in the Android SDK, do we need this on the Interface?)
*/ */
public abstract boolean onCreateOptionsMenu(Menu menu); //public abstract boolean onCreateOptionsMenu(Menu menu);
public abstract boolean onPrepareOptionsMenu(Menu menu); //public abstract boolean onPrepareOptionsMenu(Menu menu);
public abstract boolean onOptionsItemSelected(MenuItem item); //public abstract boolean onOptionsItemSelected(MenuItem item);
/**
* Get the Android activity.
*
* @return
*/
public abstract Activity getActivity();
/** /**
* @deprecated * @deprecated
* Add services to res/xml/plugins.xml instead. * Add services to res/xml/plugins.xml instead.
@ -95,17 +99,17 @@ public interface CordovaInterface {
* @param serviceType * @param serviceType
* @param className * @param className
*/ */
@Deprecated // @Deprecated
abstract public void addService(String serviceType, String className); // abstract public void addService(String serviceType, String className);
/** /**
* @deprecated * @deprecated
* Send JavaScript statement back to JavaScript. * Send JavaScript statement back to JavaScript.
* *
* @param message * @param message
*/ */
@Deprecated // @Deprecated
abstract public void sendJavascript(String statement); // abstract public void sendJavascript(String statement);
/** /**
* @deprecated * @deprecated
@ -113,9 +117,8 @@ public interface CordovaInterface {
* *
* @param intent The intent to start * @param intent The intent to start
*/ */
@Deprecated // @Deprecated
abstract public void startActivity(Intent intent); // abstract public void startActivity(Intent intent);
/** /**
* @deprecated * @deprecated
@ -123,9 +126,9 @@ public interface CordovaInterface {
* *
* @param url The URL to load. * @param url The URL to load.
*/ */
@Deprecated // @Deprecated
abstract public void loadUrl(String url); // abstract public void loadUrl(String url);
/** /**
* @deprecated * @deprecated
* Send a message to all plugins. * Send a message to all plugins.
@ -133,66 +136,84 @@ public interface CordovaInterface {
* @param id The message id * @param id The message id
* @param data The message data * @param data The message data
*/ */
@Deprecated // @Deprecated
abstract public void postMessage(String id, Object data); // abstract public void postMessage(String id, Object data);
@Deprecated
public abstract Resources getResources();
@Deprecated // @Deprecated
public abstract String getPackageName(); // public abstract Resources getResources();
@Deprecated // @Deprecated
public abstract Object getSystemService(String service); // public abstract String getPackageName();
@Deprecated // @Deprecated
public abstract Context getContext(); // public abstract Object getSystemService(String service);
@Deprecated
public abstract Context getBaseContext();
@Deprecated // @Deprecated
public abstract Intent registerReceiver(BroadcastReceiver receiver, // public abstract Context getContext();
IntentFilter intentFilter);
@Deprecated // @Deprecated
public abstract ContentResolver getContentResolver(); // public abstract Context getBaseContext();
@Deprecated // @Deprecated
public abstract void unregisterReceiver(BroadcastReceiver receiver); // public abstract Intent registerReceiver(BroadcastReceiver receiver,
// IntentFilter intentFilter);
@Deprecated // @Deprecated
public abstract Cursor managedQuery(Uri uri, String[] projection, String selection, // public abstract ContentResolver getContentResolver();
String[] selectionArgs, String sortOrder);
@Deprecated
public abstract void runOnUiThread(Runnable runnable);
@Deprecated // @Deprecated
public abstract AssetManager getAssets(); // public abstract void unregisterReceiver(BroadcastReceiver receiver);
@Deprecated // @Deprecated
public abstract void clearCache(); // public abstract Cursor managedQuery(Uri uri, String[] projection, String selection,
// String[] selectionArgs, String sortOrder);
@Deprecated // @Deprecated
public abstract void clearHistory(); // public abstract void runOnUiThread(Runnable runnable);
@Deprecated // @Deprecated
public abstract boolean backHistory(); // public abstract AssetManager getAssets();
// @Deprecated
// public abstract void clearCache();
// @Deprecated
// public abstract void clearHistory();
// @Deprecated
// public abstract boolean backHistory();
//public abstract void addWhiteListEntry(String origin, boolean subdomains); //public abstract void addWhiteListEntry(String origin, boolean subdomains);
@Deprecated @Deprecated
public abstract void cancelLoadUrl(); public abstract void cancelLoadUrl();
@Deprecated // @Deprecated
public abstract void showWebPage(String url, boolean openExternal, // public abstract void showWebPage(String url, boolean openExternal,
boolean clearHistory, HashMap<String, Object> params); // boolean clearHistory, HashMap<String, Object> params);
@Deprecated // @Deprecated
public abstract Context getApplicationContext(); // public abstract Context getApplicationContext();
// @Deprecated
// public abstract boolean isUrlWhiteListed(String source);
/**
* Called when a message is sent to plugin.
*
* @param id The message id
* @param data The message data
*/
public void onMessage(String id, Object data);
/**
* Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
* The errorCode parameter corresponds to one of the ERROR_* constants.
*
* @param errorCode The error code corresponding to an ERROR_* value.
* @param description A String describing the error.
* @param failingUrl The url that failed to load.
*/
//public void onReceivedError(final int errorCode, final String description, final String failingUrl);
@Deprecated
public abstract boolean isUrlWhiteListed(String source);
} }

View File

@ -21,9 +21,10 @@ package org.apache.cordova.api;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import org.json.JSONArray; import org.json.JSONArray;
import android.content.Context; //import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.webkit.WebView;
//import android.webkit.WebView;
/** /**
* Plugin interface must be implemented by any plugin classes. * Plugin interface must be implemented by any plugin classes.
@ -31,40 +32,40 @@ import android.webkit.WebView;
* The execute method is called by the PluginManager. * The execute method is called by the PluginManager.
*/ */
public interface IPlugin { public interface IPlugin {
/**
* 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.
*/
PluginResult execute(String action, JSONArray args, String callbackId);
/** /**
* Identifies if action to be executed returns a value and should be run synchronously. * Executes the request and returns PluginResult.
* *
* @param action The action to execute * @param action The action to execute.
* @return T=returns value * @param args JSONArry of arguments for the plugin.
*/ * @param callbackId The callback id used when calling back into JavaScript.
public boolean isSynch(String action); * @return A PluginResult object with a status and message.
*/
PluginResult execute(String action, JSONArray args, String callbackId);
/** /**
* Sets the context of the Plugin. This can then be used to do things like * Identifies if action to be executed returns a value and should be run synchronously.
* get file paths associated with the Activity. *
* * @param action The action to execute
* @param ctx The context of the main Activity. * @return T=returns value
*/ */
void setContext(Context ctx); public boolean isSynch(String action);
/** /**
* Sets the main View of the application, this is the WebView within which * Sets the context of the Plugin. This can then be used to do things like
* a Cordova app runs. * get file paths associated with the Activity.
* *
* @param webView The Cordova WebView * @param ctx The context of the main Activity.
*/ */
void setView(CordovaWebView webView); void setContext(CordovaInterface ctx);
/**
* Sets the main View of the application, this is the WebView within which
* a Cordova app runs.
*
* @param webView The Cordova WebView
*/
void setView(CordovaWebView webView);
/** /**
* Called when the system is about to start resuming a previous activity. * Called when the system is about to start resuming a previous activity.
@ -79,7 +80,7 @@ public interface IPlugin {
* @param multitasking Flag indicating if multitasking is turned on for app * @param multitasking Flag indicating if multitasking is turned on for app
*/ */
void onResume(boolean multitasking); void onResume(boolean multitasking);
/** /**
* Called when the activity receives a new intent. * Called when the activity receives a new intent.
*/ */
@ -89,7 +90,7 @@ public interface IPlugin {
* The final call you receive before your activity is destroyed. * The final call you receive before your activity is destroyed.
*/ */
void onDestroy(); void onDestroy();
/** /**
* Called when a message is sent to plugin. * Called when a message is sent to plugin.
* *

View File

@ -22,9 +22,10 @@ import org.apache.cordova.CordovaWebView;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import android.content.Context; //import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.webkit.WebView;
//import android.webkit.WebView;
/** /**
* Plugin interface must be implemented by any plugin classes. * Plugin interface must be implemented by any plugin classes.
@ -33,50 +34,50 @@ import android.webkit.WebView;
*/ */
public abstract class Plugin implements IPlugin { public abstract class Plugin implements IPlugin {
public String id; public String id;
public CordovaWebView webView; // WebView object public CordovaWebView webView; // WebView object
public Context ctx; // CordovaActivity object public CordovaInterface ctx; // CordovaActivity object
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
* *
* @param action The action to execute. * @param action The action to execute.
* @param args JSONArry of arguments for the plugin. * @param args JSONArry of arguments for the plugin.
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackId The callback id used when calling back into JavaScript.
* @return A PluginResult object with a status and message. * @return A PluginResult object with a status and message.
*/ */
public abstract PluginResult execute(String action, JSONArray args, String callbackId); public abstract PluginResult execute(String action, JSONArray args, String callbackId);
/** /**
* Identifies if action to be executed returns a value and should be run synchronously. * Identifies if action to be executed returns a value and should be run synchronously.
* *
* @param action The action to execute * @param action The action to execute
* @return T=returns value * @return T=returns value
*/ */
public boolean isSynch(String action) { public boolean isSynch(String action) {
return false; return false;
} }
/** /**
* Sets the context of the Plugin. This can then be used to do things like * Sets the context of the Plugin. This can then be used to do things like
* get file paths associated with the Activity. * get file paths associated with the Activity.
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(Context ctx) { public void setContext(CordovaInterface ctx) {
this.ctx = ctx; this.ctx = ctx;
} }
/**
* Sets the main View of the application, this is the WebView within which
* a Cordova app runs.
*
* @param webView The Cordova WebView
*/
public void setView(CordovaWebView webView) {
this.webView = webView;
}
/**
* Sets the main View of the application, this is the WebView within which
* a Cordova app runs.
*
* @param webView The Cordova WebView
*/
public void setView(CordovaWebView webView) {
this.webView = webView;
}
/** /**
* Called when the system is about to start resuming a previous activity. * Called when the system is about to start resuming a previous activity.
* *
@ -92,19 +93,19 @@ public abstract class Plugin implements IPlugin {
*/ */
public void onResume(boolean multitasking) { public void onResume(boolean multitasking) {
} }
/** /**
* Called when the activity receives a new intent. * Called when the activity receives a new intent.
*/ */
public void onNewIntent(Intent intent) { public void onNewIntent(Intent intent) {
} }
/** /**
* The final call you receive before your activity is destroyed. * The final call you receive before your activity is destroyed.
*/ */
public void onDestroy() { public void onDestroy() {
} }
/** /**
* Called when a message is sent to plugin. * Called when a message is sent to plugin.
* *
@ -133,7 +134,7 @@ public abstract class Plugin implements IPlugin {
* @return Return true to prevent the URL from loading. Default is false. * @return Return true to prevent the URL from loading. Default is false.
*/ */
public boolean onOverrideUrlLoading(String url) { public boolean onOverrideUrlLoading(String url) {
return false; return false;
} }
/** /**
@ -143,7 +144,7 @@ public abstract class Plugin implements IPlugin {
* @param statement * @param statement
*/ */
public void sendJavascript(String statement) { public void sendJavascript(String statement) {
webView.sendJavascript(statement); this.webView.sendJavascript(statement);
} }
/** /**
@ -154,10 +155,10 @@ public abstract class Plugin implements IPlugin {
* call success(...) or error(...) * call success(...) or error(...)
* *
* @param pluginResult The result to return. * @param pluginResult The result to return.
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackId The callback id used when calling back into JavaScript.
*/ */
public void success(PluginResult pluginResult, String callbackId) { public void success(PluginResult pluginResult, String callbackId) {
webView.sendJavascript(pluginResult.toSuccessCallbackString(callbackId)); this.webView.sendJavascript(pluginResult.toSuccessCallbackString(callbackId));
} }
/** /**
@ -167,7 +168,7 @@ public abstract class Plugin implements IPlugin {
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackId The callback id used when calling back into JavaScript.
*/ */
public void success(JSONObject message, String callbackId) { public void success(JSONObject message, String callbackId) {
webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId));
} }
/** /**
@ -177,17 +178,17 @@ public abstract class Plugin implements IPlugin {
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackId The callback id used when calling back into JavaScript.
*/ */
public void success(String message, String callbackId) { public void success(String message, String callbackId) {
webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId));
} }
/** /**
* Call the JavaScript error callback for this plugin. * Call the JavaScript error callback for this plugin.
* *
* @param pluginResult The result to return. * @param pluginResult The result to return.
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackId The callback id used when calling back into JavaScript.
*/ */
public void error(PluginResult pluginResult, String callbackId) { public void error(PluginResult pluginResult, String callbackId) {
webView.sendJavascript(pluginResult.toErrorCallbackString(callbackId)); this.webView.sendJavascript(pluginResult.toErrorCallbackString(callbackId));
} }
/** /**
@ -197,7 +198,7 @@ public abstract class Plugin implements IPlugin {
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackId The callback id used when calling back into JavaScript.
*/ */
public void error(JSONObject message, String callbackId) { public void error(JSONObject message, String callbackId) {
webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId));
} }
/** /**
@ -207,6 +208,6 @@ public abstract class Plugin implements IPlugin {
* @param callbackId The callback id used when calling back into JavaScript. * @param callbackId The callback id used when calling back into JavaScript.
*/ */
public void error(String message, String callbackId) { public void error(String message, String callbackId) {
webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId));
} }
} }

View File

@ -20,8 +20,8 @@ package org.apache.cordova.api;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import android.content.Context; //import android.content.Context;
import android.webkit.WebView; //import android.webkit.WebView;
/** /**
* This class represents a service entry object. * This class represents a service entry object.
@ -69,12 +69,12 @@ public class PluginEntry {
* *
* @return The plugin object * @return The plugin object
*/ */
@SuppressWarnings("unchecked") public IPlugin createPlugin(CordovaWebView webView, CordovaInterface ctx) {
public IPlugin createPlugin(CordovaWebView webView, Context ctx) {
if (this.plugin != null) { if (this.plugin != null) {
return this.plugin; return this.plugin;
} }
try { try {
@SuppressWarnings("rawtypes")
Class c = getClassByName(this.pluginClass); Class c = getClassByName(this.pluginClass);
if (isCordovaPlugin(c)) { if (isCordovaPlugin(c)) {
this.plugin = (IPlugin) c.newInstance(); this.plugin = (IPlugin) c.newInstance();
@ -96,7 +96,7 @@ public class PluginEntry {
* @return * @return
* @throws ClassNotFoundException * @throws ClassNotFoundException
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("rawtypes")
private Class getClassByName(final String clazz) throws ClassNotFoundException { private Class getClassByName(final String clazz) throws ClassNotFoundException {
Class c = null; Class c = null;
if (clazz != null) { if (clazz != null) {
@ -112,7 +112,7 @@ public class PluginEntry {
* @param c The class to check the interfaces of. * @param c The class to check the interfaces of.
* @return Boolean indicating if the class implements org.apache.cordova.api.Plugin * @return Boolean indicating if the class implements org.apache.cordova.api.Plugin
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("rawtypes")
private boolean isCordovaPlugin(Class c) { private boolean isCordovaPlugin(Class c) {
if (c != null) { if (c != null) {
return org.apache.cordova.api.Plugin.class.isAssignableFrom(c) || org.apache.cordova.api.IPlugin.class.isAssignableFrom(c); return org.apache.cordova.api.Plugin.class.isAssignableFrom(c) || org.apache.cordova.api.IPlugin.class.isAssignableFrom(c);

View File

@ -28,10 +28,8 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import android.webkit.WebView;
/** /**
* PluginManager is exposed to JavaScript in the Cordova WebView. * PluginManager is exposed to JavaScript in the Cordova WebView.
@ -45,7 +43,7 @@ public class PluginManager {
// List of service entries // List of service entries
private final HashMap<String, PluginEntry> entries = new HashMap<String, PluginEntry>(); private final HashMap<String, PluginEntry> entries = new HashMap<String, PluginEntry>();
private final Context ctx; private final CordovaInterface ctx;
private final CordovaWebView app; private final CordovaWebView app;
// Flag to track first time through // Flag to track first time through
@ -61,26 +59,25 @@ public class PluginManager {
* @param app * @param app
* @param ctx * @param ctx
*/ */
public PluginManager(CordovaWebView app, Context ctx) { public PluginManager(CordovaWebView app, CordovaInterface ctx) {
this.ctx = ctx; this.ctx = ctx;
this.app = app; this.app = app;
this.firstRun = true; this.firstRun = true;
} }
// Called by com.phonegap.api.PluginManager only
public PluginManager(WebView mApp, CordovaInterface mCtx) throws Exception { // public PluginManager(WebView mApp, CordovaInterface mCtx) throws Exception {
this.ctx = mCtx.getContext(); // this.ctx = mCtx; //mCtx.getContext();
if(CordovaWebView.class.isInstance(mApp)) // if (CordovaWebView.class.isInstance(mApp))
{ // {
this.app = (CordovaWebView) mApp; // this.app = (CordovaWebView) mApp;
} // }
else // else
{ // {
//Throw an exception here // //Throw an exception here
throw new Exception(); // throw new Exception();
} // }
} // }
/** /**
* Init when loading a new HTML page into webview. * Init when loading a new HTML page into webview.
@ -89,9 +86,9 @@ public class PluginManager {
LOG.d(TAG, "init()"); LOG.d(TAG, "init()");
// If first time, then load plugins from plugins.xml file // If first time, then load plugins from plugins.xml file
if (firstRun) { if (this.firstRun) {
this.loadPlugins(); this.loadPlugins();
firstRun = false; this.firstRun = false;
} }
// Stop plugins on current HTML page and discard plugin objects // Stop plugins on current HTML page and discard plugin objects
@ -109,11 +106,11 @@ public class PluginManager {
* Load plugins from res/xml/plugins.xml * Load plugins from res/xml/plugins.xml
*/ */
public void loadPlugins() { public void loadPlugins() {
int id = ctx.getResources().getIdentifier("plugins", "xml", ctx.getPackageName()); int id = this.ctx.getActivity().getResources().getIdentifier("plugins", "xml", this.ctx.getActivity().getPackageName());
if (id == 0) { if (id == 0) {
pluginConfigurationMissing(); this.pluginConfigurationMissing();
} }
XmlResourceParser xml = ctx.getResources().getXml(id); XmlResourceParser xml = this.ctx.getActivity().getResources().getXml(id);
int eventType = -1; int eventType = -1;
String service = "", pluginClass = ""; String service = "", pluginClass = "";
boolean onload = false; boolean onload = false;
@ -184,14 +181,13 @@ public class PluginManager {
* *
* @return JSON encoded string with a response message and status. * @return JSON encoded string with a response message and status.
*/ */
@SuppressWarnings("unchecked")
public String exec(final String service, final String action, final String callbackId, final String jsonArgs, final boolean async) { public String exec(final String service, final String action, final String callbackId, final String jsonArgs, final boolean async) {
PluginResult cr = null; PluginResult cr = null;
boolean runAsync = async; boolean runAsync = async;
try { try {
final JSONArray args = new JSONArray(jsonArgs); final JSONArray args = new JSONArray(jsonArgs);
final IPlugin plugin = this.getPlugin(service); final IPlugin plugin = this.getPlugin(service);
final Context ctx = this.ctx; //final CordovaInterface ctx = this.ctx;
if (plugin != null) { if (plugin != null) {
runAsync = async && !plugin.isSynch(action); runAsync = async && !plugin.isSynch(action);
if (runAsync) { if (runAsync) {
@ -257,7 +253,7 @@ public class PluginManager {
* @return IPlugin or null * @return IPlugin or null
*/ */
private IPlugin getPlugin(String service) { private IPlugin getPlugin(String service) {
PluginEntry entry = entries.get(service); PluginEntry entry = this.entries.get(service);
if (entry == null) { if (entry == null) {
return null; return null;
} }
@ -334,6 +330,7 @@ public class PluginManager {
* @param data The message data * @param data The message data
*/ */
public void postMessage(String id, Object data) { public void postMessage(String id, Object data) {
this.ctx.onMessage(id, data);
for (PluginEntry entry : this.entries.values()) { for (PluginEntry entry : this.entries.values()) {
if (entry.plugin != null) { if (entry.plugin != null) {
entry.plugin.onMessage(id, data); entry.plugin.onMessage(id, data);

View File

@ -21,99 +21,99 @@ package org.apache.cordova.api;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import android.util.Log; //import android.util.Log;
public class PluginResult { public class PluginResult {
private final int status; private final int status;
private final String message; private final String message;
private boolean keepCallback = false; private boolean keepCallback = false;
public PluginResult(Status status) {
this.status = status.ordinal();
this.message = "'" + PluginResult.StatusMessages[this.status] + "'";
}
public PluginResult(Status status, String message) {
this.status = status.ordinal();
this.message = JSONObject.quote(message);
}
public PluginResult(Status status, JSONArray message) { public PluginResult(Status status) {
this.status = status.ordinal(); this.status = status.ordinal();
this.message = message.toString(); this.message = "'" + PluginResult.StatusMessages[this.status] + "'";
} }
public PluginResult(Status status, JSONObject message) { public PluginResult(Status status, String message) {
this.status = status.ordinal(); this.status = status.ordinal();
this.message = message.toString(); this.message = JSONObject.quote(message);
} }
public PluginResult(Status status, int i) { public PluginResult(Status status, JSONArray message) {
this.status = status.ordinal(); this.status = status.ordinal();
this.message = ""+i; this.message = message.toString();
} }
public PluginResult(Status status, float f) { public PluginResult(Status status, JSONObject message) {
this.status = status.ordinal(); this.status = status.ordinal();
this.message = ""+f; this.message = message.toString();
} }
public PluginResult(Status status, boolean b) { public PluginResult(Status status, int i) {
this.status = status.ordinal(); this.status = status.ordinal();
this.message = ""+b; this.message = "" + i;
} }
public void setKeepCallback(boolean b) {
this.keepCallback = b;
}
public int getStatus() {
return status;
}
public String getMessage() { public PluginResult(Status status, float f) {
return message; this.status = status.ordinal();
} this.message = "" + f;
}
public boolean getKeepCallback() {
return this.keepCallback; public PluginResult(Status status, boolean b) {
} this.status = status.ordinal();
this.message = "" + b;
public String getJSONString() { }
return "{status:" + this.status + ",message:" + this.message + ",keepCallback:" + this.keepCallback + "}";
} public void setKeepCallback(boolean b) {
this.keepCallback = b;
public String toSuccessCallbackString(String callbackId) { }
return "cordova.callbackSuccess('"+callbackId+"',"+this.getJSONString()+");";
} public int getStatus() {
return status;
public String toErrorCallbackString(String callbackId) { }
return "cordova.callbackError('"+callbackId+"', " + this.getJSONString()+ ");";
} public String getMessage() {
return message;
public static String[] StatusMessages = new String[] { }
"No result",
"OK", public boolean getKeepCallback() {
"Class not found", return this.keepCallback;
"Illegal access", }
"Instantiation error",
"Malformed url", public String getJSONString() {
"IO error", return "{status:" + this.status + ",message:" + this.message + ",keepCallback:" + this.keepCallback + "}";
"Invalid action", }
"JSON error",
"Error" public String toSuccessCallbackString(String callbackId) {
}; return "cordova.callbackSuccess('" + callbackId + "'," + this.getJSONString() + ");";
}
public enum Status {
NO_RESULT, public String toErrorCallbackString(String callbackId) {
OK, return "cordova.callbackError('" + callbackId + "', " + this.getJSONString() + ");";
CLASS_NOT_FOUND_EXCEPTION, }
ILLEGAL_ACCESS_EXCEPTION,
INSTANTIATION_EXCEPTION, public static String[] StatusMessages = new String[] {
MALFORMED_URL_EXCEPTION, "No result",
IO_EXCEPTION, "OK",
INVALID_ACTION, "Class not found",
JSON_EXCEPTION, "Illegal access",
ERROR "Instantiation error",
} "Malformed url",
"IO error",
"Invalid action",
"JSON error",
"Error"
};
public enum Status {
NO_RESULT,
OK,
CLASS_NOT_FOUND_EXCEPTION,
ILLEGAL_ACCESS_EXCEPTION,
INSTANTIATION_EXCEPTION,
MALFORMED_URL_EXCEPTION,
IO_EXCEPTION,
INVALID_ACTION,
JSON_EXCEPTION,
ERROR
}
} }