This commit is contained in:
macdonst 2012-06-08 13:03:44 -04:00
commit d87f404d6e
82 changed files with 4840 additions and 8354 deletions

4
NOTICE
View File

@ -1,5 +1,5 @@
Apache Callback Apache Cordova
Copyright 2011 The Apache Software Foundation Copyright 2012 The Apache Software Foundation
This product includes software developed by This product includes software developed by
The Apache Software Foundation (http://www.apache.org) The Apache Software Foundation (http://www.apache.org)

View File

@ -20,6 +20,10 @@ Requires
- Android SDK [http://developer.android.com](http://developer.android.com) - Android SDK [http://developer.android.com](http://developer.android.com)
- Apache Commons Codec [http://commons.apache.org/codec/](http://commons.apache.org/codec/) - Apache Commons Codec [http://commons.apache.org/codec/](http://commons.apache.org/codec/)
Test Requirements
---
- JUnit - [https://github.com/KentBeck/junit](https://github.com/KentBeck/junit)
Building Building
--- ---
@ -98,6 +102,9 @@ Importing a Cordova Android Project into Eclipse
5. Right click on the project root: Run as > Run Configurations 5. Right click on the project root: Run as > Run Configurations
6. Click on the Target tab and select Manual (this way you can choose the emulator or device to build to) 6. Click on the Target tab and select Manual (this way you can choose the emulator or device to build to)
Running Tests
----
Please see details under test/README.md.
Further Reading Further Reading
--- ---

View File

@ -5723,4 +5723,4 @@ window.cordova = require('cordova');
}(window)); }(window));
})(); })();

View File

@ -30,7 +30,7 @@
<!-- <access origin=".*"/> Allow all domains, suggested development use only --> <!-- <access origin=".*"/> Allow all domains, suggested development use only -->
<log level="DEBUG"/> <log level="DEBUG"/>
<preference name="classicRender" value="true" /> <preference name="useBrowserHistory" value="false" />
</cordova> </cordova>

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;
@ -30,7 +31,7 @@ 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) { public PluginManager(WebView app, CordovaInterface ctx) throws Exception {
super(app, ctx); super((CordovaWebView) app, ctx);
} }
} }

View File

@ -26,7 +26,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,14 +42,14 @@ public class AccelListener 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;
private float x,y,z; // most recent acceleration values private float x,y,z; // most recent acceleration values
private long timestamp; // time of most recent value private long timestamp; // time of most recent value
private int status; // status of listener private int status; // status of listener
private int accuracy = SensorManager.SENSOR_STATUS_UNRELIABLE; private int accuracy = SensorManager.SENSOR_STATUS_UNRELIABLE;
private SensorManager sensorManager; // Sensor manager private SensorManager sensorManager; // Sensor manager
private Sensor mSensor; // Acceleration sensor returned by sensor manager private Sensor mSensor; // Acceleration sensor returned by sensor manager
private String callbackId; // Keeps track of the single "start" callback ID passed in from JS private String callbackId; // Keeps track of the single "start" callback ID passed in from JS
@ -71,18 +70,19 @@ public class AccelListener extends Plugin implements SensorEventListener {
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(CordovaInterface 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);
} }
/** /**
* 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 PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
PluginResult.Status status = PluginResult.Status.NO_RESULT; PluginResult.Status status = PluginResult.Status.NO_RESULT;
@ -123,9 +123,9 @@ public class AccelListener extends Plugin implements SensorEventListener {
// //
/** /**
* Start listening for acceleration sensor. * Start listening for acceleration sensor.
* *
* @return status of listener * @return status of listener
*/ */
private int start() { private 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)) {
@ -139,24 +139,24 @@ public class AccelListener extends Plugin implements SensorEventListener {
// 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);
this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_UI); this.sensorManager.registerListener(this, this.mSensor, SensorManager.SENSOR_DELAY_UI);
this.setStatus(AccelListener.STARTING); this.setStatus(AccelListener.STARTING);
} else { } else {
this.setStatus(AccelListener.ERROR_FAILED_TO_START); this.setStatus(AccelListener.ERROR_FAILED_TO_START);
this.fail(AccelListener.ERROR_FAILED_TO_START, "No sensors found to register accelerometer listening to."); this.fail(AccelListener.ERROR_FAILED_TO_START, "No sensors found to register accelerometer listening to.");
return this.status; return this.status;
} }
// Wait until running // Wait until running
long timeout = 2000; long timeout = 2000;
while ((this.status == STARTING) && (timeout > 0)) { while ((this.status == STARTING) && (timeout > 0)) {
timeout = timeout - 100; timeout = timeout - 100;
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
if (timeout == 0) { if (timeout == 0) {
this.setStatus(AccelListener.ERROR_FAILED_TO_START); this.setStatus(AccelListener.ERROR_FAILED_TO_START);
@ -210,7 +210,6 @@ public class AccelListener extends Plugin implements SensorEventListener {
if (this.status == AccelListener.STOPPED) { if (this.status == AccelListener.STOPPED) {
return; return;
} }
this.setStatus(AccelListener.RUNNING); this.setStatus(AccelListener.RUNNING);
if (this.accuracy >= SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM) { if (this.accuracy >= SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM) {
@ -252,7 +251,6 @@ public class AccelListener extends Plugin implements SensorEventListener {
private void setStatus(int status) { private void setStatus(int status) {
this.status = status; this.status = status;
} }
private JSONObject getAccelerationJSON() { private JSONObject getAccelerationJSON() {
JSONObject r = new JSONObject(); JSONObject r = new JSONObject();
try { try {

View File

@ -48,6 +48,13 @@ public class App extends Plugin {
if (action.equals("clearCache")) { if (action.equals("clearCache")) {
this.clearCache(); this.clearCache();
} }
else if (action.equals("show")) { // TODO @bc - Not in master branch. When should this be called?
ctx.getActivity().runOnUiThread(new Runnable() {
public void run() {
webView.postMessage("spinner", "stop");
}
});
}
else if (action.equals("loadUrl")) { else if (action.equals("loadUrl")) {
this.loadUrl(args.getString(0), args.optJSONObject(1)); this.loadUrl(args.getString(0), args.optJSONObject(1));
} }
@ -84,7 +91,7 @@ public class App extends Plugin {
* Clear the resource cache. * Clear the resource cache.
*/ */
public void clearCache() { public void clearCache() {
((DroidGap)this.ctx).clearCache(); this.webView.clearCache(true);
} }
/** /**
@ -104,7 +111,7 @@ public class App extends Plugin {
HashMap<String, Object> params = new HashMap<String, Object>(); HashMap<String, Object> params = new HashMap<String, Object>();
if (props != null) { if (props != null) {
JSONArray keys = props.names(); JSONArray keys = props.names();
for (int i=0; i<keys.length(); i++) { for (int i = 0; i < keys.length(); i++) {
String key = keys.getString(i); String key = keys.getString(i);
if (key.equals("wait")) { if (key.equals("wait")) {
wait = props.getInt(key); wait = props.getInt(key);
@ -144,21 +151,22 @@ public class App extends Plugin {
e.printStackTrace(); e.printStackTrace();
} }
} }
((DroidGap)this.ctx).showWebPage(url, openExternal, clearHistory, params); this.webView.showWebPage(url, openExternal, clearHistory, params);
} }
/** /**
* Cancel loadUrl before it has been loaded. * Cancel loadUrl before it has been loaded (Only works on a CordovaInterface class)
*/ */
@Deprecated
public void cancelLoadUrl() { public void cancelLoadUrl() {
((DroidGap)this.ctx).cancelLoadUrl(); this.ctx.cancelLoadUrl();
} }
/** /**
* Clear page history for the app. * Clear page history for the app.
*/ */
public void clearHistory() { public void clearHistory() {
((DroidGap)this.ctx).clearHistory(); this.webView.clearHistory();
} }
/** /**
@ -166,7 +174,7 @@ public class App extends Plugin {
* 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() {
((DroidGap)this.ctx).backHistory(); this.webView.backHistory();
} }
/** /**
@ -176,8 +184,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);
} }
/** /**
@ -186,13 +194,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.webView.postMessage("exit", null);
} }
} }

View File

@ -26,7 +26,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 org.json.JSONException; import org.json.JSONException;
import java.util.HashMap; import java.util.HashMap;
/** /**
@ -43,20 +42,19 @@ import java.util.HashMap;
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. * Constructor.
*/ */
public AudioHandler() { public AudioHandler() {
this.players = new HashMap<String,AudioPlayer>(); this.players = new HashMap<String, AudioPlayer>();
this.pausedForPhone = new ArrayList<AudioPlayer>(); this.pausedForPhone = new ArrayList<AudioPlayer>();
} }
/** /**
* 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.
@ -111,7 +109,6 @@ public class AudioHandler extends Plugin {
/** /**
* 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
*/ */
@ -140,8 +137,9 @@ public class AudioHandler extends Plugin {
* *
* @param id The message id * @param id The message id
* @param data The message data * @param data The message data
* @return Object to stop propagation or null
*/ */
public void onMessage(String id, Object data) { public Object onMessage(String id, Object data) {
// If phone message // If phone message
if (id.equals("telephone")) { if (id.equals("telephone")) {
@ -167,6 +165,7 @@ public class AudioHandler extends Plugin {
this.pausedForPhone.clear(); this.pausedForPhone.clear();
} }
} }
return null;
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -175,7 +174,6 @@ public class AudioHandler extends Plugin {
/** /**
* Release the audio player instance to save memory. * Release the audio player instance to save memory.
*
* @param id The id of the audio player * @param id The id of the audio player
*/ */
private boolean release(String id) { private boolean release(String id) {
@ -190,7 +188,6 @@ public class AudioHandler extends Plugin {
/** /**
* Start recording and save the specified file. * Start recording and save the specified file.
*
* @param id The id of the audio player * @param id The id of the audio player
* @param file The name of the file * @param file The name of the file
*/ */
@ -206,7 +203,6 @@ public class AudioHandler extends Plugin {
/** /**
* 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) {
@ -219,7 +215,6 @@ public class AudioHandler extends Plugin {
/** /**
* 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.
*/ */
@ -234,8 +229,6 @@ public class AudioHandler extends Plugin {
/** /**
* 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
*/ */
@ -248,7 +241,6 @@ public class AudioHandler extends Plugin {
/** /**
* 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) {
@ -260,7 +252,6 @@ public class AudioHandler extends Plugin {
/** /**
* 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) {
@ -274,21 +265,19 @@ public class AudioHandler extends Plugin {
/** /**
* 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.
@ -298,14 +287,14 @@ public class AudioHandler extends Plugin {
// 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));
} }
} }
@ -314,8 +303,9 @@ public class AudioHandler extends Plugin {
* *
* @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);
} }
@ -332,8 +322,9 @@ public class AudioHandler extends Plugin {
* *
* @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;
} }

View File

@ -37,8 +37,8 @@ import java.io.IOException;
* Only one file can be played or recorded per class instance. * Only one file can be played or recorded per class instance.
* *
* Local audio files must reside in one of two places: * Local audio files must reside in one of two places:
* android_asset: file name must start with /android_asset/sound.mp3 * android_asset: file name must start with /android_asset/sound.mp3
* sdcard: file name is just sound.mp3 * sdcard: file name is just sound.mp3
*/ */
public class AudioPlayer implements OnCompletionListener, OnPreparedListener, OnErrorListener { public class AudioPlayer implements OnCompletionListener, OnPreparedListener, OnErrorListener {
@ -63,24 +63,24 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
private static int MEDIA_ERR_NETWORK = 2; private static int MEDIA_ERR_NETWORK = 2;
private static int MEDIA_ERR_DECODE = 3; private static int MEDIA_ERR_DECODE = 3;
private static int MEDIA_ERR_NONE_SUPPORTED = 4; 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 AudioHandler handler; // The AudioHandler object private MediaRecorder recorder = null; // Audio recording object
private String id; // The id of this player (used to identify Media object in JavaScript) private String tempFile = null; // Temporary recording file name
private int state = MEDIA_NONE; // State of recording or playback
private String audioFile = null; // File name to play or record to private MediaPlayer mPlayer = null; // Audio player object
private float duration = -1; // Duration of audio private boolean prepareOnly = false;
private MediaRecorder recorder = null; // Audio recording object
private String tempFile = null; // Temporary recording file name
private MediaPlayer mPlayer = null; // Audio player object
private boolean prepareOnly = false;
/** /**
* Constructor. * Constructor.
* *
* @param handler The audio handler object * @param handler The audio handler object
* @param id The id of this audio player * @param id The id of this audio player
*/ */
public AudioPlayer(AudioHandler handler, String id) { public AudioPlayer(AudioHandler handler, String id) {
this.handler = handler; this.handler = handler;
@ -88,7 +88,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3"; this.tempFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/tmprecording.mp3";
} else { } else {
this.tempFile = "/data/data/" + handler.ctx.getPackageName() + "/cache/tmprecording.mp3"; this.tempFile = "/data/data/" + handler.ctx.getActivity().getPackageName() + "/cache/tmprecording.mp3";
} }
} }
@ -96,7 +96,6 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
* 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)) {
@ -115,15 +114,14 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
/** /**
* Start recording the specified file. * Start recording the specified file.
* *
* @param file The name of the file * @param file The name of the file
*/ */
public void startRecording(String file) { public void startRecording(String file) {
if (this.mPlayer != null) { if (this.mPlayer != null) {
Log.d(LOG_TAG, "AudioPlayer Error: Can't record in play mode."); 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+"});"); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_ERROR+", { \"code\":"+MEDIA_ERR_ABORTED+"});");
} }
// Make sure we're not already recording // Make sure we're not already recording
else if (this.recorder == null) { else if (this.recorder == null) {
this.audioFile = file; this.audioFile = file;
@ -162,7 +160,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
f.renameTo(new File(Environment.getExternalStorageDirectory().getAbsolutePath() f.renameTo(new File(Environment.getExternalStorageDirectory().getAbsolutePath()
+ File.separator + file)); + File.separator + file));
} else { } else {
f.renameTo(new File("/data/data/" + handler.ctx.getPackageName() + "/cache/" + file)); f.renameTo(new File("/data/data/" + handler.ctx.getActivity().getPackageName() + "/cache/" + file));
} }
} }
@ -187,13 +185,13 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
/** /**
* 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
@ -222,7 +220,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
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.getBaseContext().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 {
@ -242,10 +240,9 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
// 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 + "});");
} }
} }
@ -258,8 +255,8 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
this.setState(MEDIA_RUNNING); this.setState(MEDIA_RUNNING);
} }
else { else {
Log.d(LOG_TAG, "AudioPlayer Error: startPlaying() called during invalid state: "+this.state); 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+"});"); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_ABORTED + "});");
} }
} }
} }
@ -271,7 +268,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
if (this.mPlayer != null) { if (this.mPlayer != null) {
this.mPlayer.seekTo(milliseconds); this.mPlayer.seekTo(milliseconds);
Log.d(LOG_TAG, "Send a onStatus update for the new seek"); Log.d(LOG_TAG, "Send a onStatus update for the new seek");
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_POSITION + ", " + milliseconds / 1000.0f + ");");
} }
} }
@ -286,8 +283,8 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
this.setState(MEDIA_PAUSED); this.setState(MEDIA_PAUSED);
} }
else { else {
Log.d(LOG_TAG, "AudioPlayer Error: pausePlaying() called during invalid state: "+this.state); 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+"});"); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_ERROR + ", { \"code\":" + MEDIA_ERR_NONE_ACTIVE + "});");
} }
} }
@ -300,15 +297,15 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
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);
@ -316,13 +313,13 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
/** /**
* 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 {
@ -333,9 +330,9 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
/** /**
* 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 * @param file The file name
* @return T=streaming, F=local * @return T=streaming, F=local
*/ */
public boolean isStreaming(String file) { public boolean isStreaming(String file) {
if (file.contains("http://") || file.contains("https://")) { if (file.contains("http://") || file.contains("https://")) {
@ -346,19 +343,19 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
} }
} }
/** /**
* Get the duration of the audio file. * Get the duration of the audio file.
* *
* @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.
* -1=can't be determined * -1=can't be determined
* -2=not allowed * -2=not allowed
*/ */
public float getDuration(String file) { public float getDuration(String file) {
// Can't get duration of recording // Can't get duration of recording
if (this.recorder != null) { if (this.recorder != null) {
return(-2); // not allowed return (-2); // not allowed
} }
// If audio file already loaded and started, then return duration // If audio file already loaded and started, then return duration
@ -378,9 +375,9 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
} }
/** /**
* Callback to be invoked when the media source is ready for playback. * Callback to be invoked when the media source is ready for playback.
* *
* @param mPlayer The MediaPlayer that is ready for playback * @param mPlayer The MediaPlayer that is ready for playback
*/ */
public void onPrepared(MediaPlayer mPlayer) { public void onPrepared(MediaPlayer mPlayer) {
// Listen for playback completion // Listen for playback completion
@ -401,13 +398,13 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
this.prepareOnly = false; this.prepareOnly = false;
// Send status notification to JavaScript // Send status notification to JavaScript
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_DURATION+","+this.duration+");"); 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 * By default Android returns the length of audio in mills but we want seconds
* *
* @return length of clip in seconds * @return length of clip in seconds
*/ */
private float getDurationInSeconds() { private float getDurationInSeconds() {
@ -417,31 +414,31 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
/** /**
* Callback to be invoked when there has been an error during an asynchronous operation * Callback to be invoked when there has been an error during an asynchronous operation
* (other errors will throw exceptions at method call time). * (other errors will throw exceptions at method call time).
* *
* @param mPlayer the MediaPlayer the error pertains to * @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 arg1 the type of error that has occurred: (MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_SERVER_DIED)
* @param arg2 an extra code, specific to the error. * @param arg2 an extra code, specific to the error.
*/ */
public boolean onError(MediaPlayer mPlayer, int arg1, int arg2) { public boolean onError(MediaPlayer mPlayer, int arg1, int arg2) {
Log.d(LOG_TAG, "AudioPlayer.onError(" + arg1 + ", " + arg2+")"); Log.d(LOG_TAG, "AudioPlayer.onError(" + arg1 + ", " + arg2 + ")");
// TODO: Not sure if this needs to be sent? // TODO: Not sure if this needs to be sent?
this.mPlayer.stop(); this.mPlayer.stop();
this.mPlayer.release(); this.mPlayer.release();
// Send error notification to JavaScript // Send error notification to JavaScript
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', { \"code\":"+arg1+"});"); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', { \"code\":" + arg1 + "});");
return false; return false;
} }
/** /**
* Set the state and send it to JavaScript. * Set the state and send it to JavaScript.
* *
* @param state * @param state
*/ */
private void setState(int state) { private void setState(int state) {
if (this.state != state) { if (this.state != state) {
this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', "+MEDIA_STATE+", "+state+");"); this.handler.sendJavascript("cordova.require('cordova/plugin/Media').onStatus('" + this.id + "', " + MEDIA_STATE + ", " + state + ");");
} }
this.state = state; this.state = state;
@ -449,7 +446,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
/** /**
* Get the audio state. * Get the audio state.
* *
* @return int * @return int
*/ */
public int getState() { public int getState() {

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;
@ -65,7 +64,7 @@ public class BatteryListener extends Plugin {
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() {
@ -74,7 +73,7 @@ public class BatteryListener extends Plugin {
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
@ -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);

View File

@ -53,6 +53,7 @@ import java.util.LinkedList;
*/ */
public class CallbackServer implements Runnable { public class CallbackServer implements Runnable {
@SuppressWarnings("unused")
private static final String LOG_TAG = "CallbackServer"; private static final String LOG_TAG = "CallbackServer";
/** /**
@ -94,7 +95,7 @@ public class CallbackServer implements Runnable {
* Constructor. * Constructor.
*/ */
public CallbackServer() { public CallbackServer() {
//System.out.println("CallbackServer()"); //Log.d(LOG_TAG, "CallbackServer()");
this.active = false; this.active = false;
this.empty = true; this.empty = true;
this.port = 0; this.port = 0;
@ -103,7 +104,7 @@ public class CallbackServer implements Runnable {
/** /**
* Init callback server and start XHR if running local app. * Init callback server and start XHR if running local app.
* *
* If Cordova app is loaded from file://, then we can use XHR * If Cordova app is loaded from file://, then we can use XHR
* otherwise we have to use polling due to cross-domain security restrictions. * otherwise we have to use polling due to cross-domain security restrictions.
* *
@ -143,7 +144,6 @@ public class CallbackServer implements Runnable {
/** /**
* Return if polling is being used instead of XHR. * Return if polling is being used instead of XHR.
*
* @return * @return
*/ */
public boolean usePolling() { public boolean usePolling() {
@ -152,7 +152,6 @@ public class CallbackServer implements Runnable {
/** /**
* Get the port that this server is running on. * Get the port that this server is running on.
*
* @return * @return
*/ */
public int getPort() { public int getPort() {
@ -161,7 +160,6 @@ public class CallbackServer implements Runnable {
/** /**
* Get the security token that this server requires when calling getJavascript(). * Get the security token that this server requires when calling getJavascript().
*
* @return * @return
*/ */
public String getToken() { public String getToken() {
@ -172,7 +170,7 @@ public class CallbackServer implements Runnable {
* Start the server on a new thread. * Start the server on a new thread.
*/ */
public void startServer() { public void startServer() {
//System.out.println("CallbackServer.startServer()"); //Log.d(LOG_TAG, "CallbackServer.startServer()");
this.active = false; this.active = false;
// Start server on new thread // Start server on new thread
@ -193,7 +191,7 @@ public class CallbackServer implements Runnable {
} }
/** /**
* Start running the server. * Start running the server.
* This is called automatically when the server thread is started. * This is called automatically when the server thread is started.
*/ */
public void run() { public void run() {
@ -204,90 +202,90 @@ public class CallbackServer implements Runnable {
String request; String request;
ServerSocket waitSocket = new ServerSocket(0); ServerSocket waitSocket = new ServerSocket(0);
this.port = waitSocket.getLocalPort(); this.port = waitSocket.getLocalPort();
//System.out.println("CallbackServer -- using port " +this.port); //Log.d(LOG_TAG, "CallbackServer -- using port " +this.port);
this.token = java.util.UUID.randomUUID().toString(); this.token = java.util.UUID.randomUUID().toString();
//System.out.println("CallbackServer -- using token "+this.token); //Log.d(LOG_TAG, "CallbackServer -- using token "+this.token);
while (this.active) { while (this.active) {
//System.out.println("CallbackServer: Waiting for data on socket"); //Log.d(LOG_TAG, "CallbackServer: Waiting for data on socket");
Socket connection = waitSocket.accept(); Socket connection = waitSocket.accept();
BufferedReader xhrReader = new BufferedReader(new InputStreamReader(connection.getInputStream()),40); BufferedReader xhrReader = new BufferedReader(new InputStreamReader(connection.getInputStream()), 40);
DataOutputStream output = new DataOutputStream(connection.getOutputStream()); DataOutputStream output = new DataOutputStream(connection.getOutputStream());
request = xhrReader.readLine(); request = xhrReader.readLine();
String response = ""; String response = "";
//System.out.println("CallbackServerRequest="+request); //Log.d(LOG_TAG, "CallbackServerRequest="+request);
if (this.active && (request != null)) { if (this.active && (request != null)) {
if (request.contains("GET")) { if (request.contains("GET")) {
// Get requested file // Get requested file
String[] requestParts = request.split(" "); String[] requestParts = request.split(" ");
// Must have security token // Must have security token
if ((requestParts.length == 3) && (requestParts[1].substring(1).equals(this.token))) { if ((requestParts.length == 3) && (requestParts[1].substring(1).equals(this.token))) {
//System.out.println("CallbackServer -- Processing GET request"); //Log.d(LOG_TAG, "CallbackServer -- Processing GET request");
// Wait until there is some data to send, or send empty data every 10 sec // Wait until there is some data to send, or send empty data every 10 sec
// to prevent XHR timeout on the client // to prevent XHR timeout on the client
synchronized (this) { synchronized (this) {
while (this.empty) { while (this.empty) {
try { try {
this.wait(10000); // prevent timeout from happening this.wait(10000); // prevent timeout from happening
//System.out.println("CallbackServer>>> break <<<"); //Log.d(LOG_TAG, "CallbackServer>>> break <<<");
break; break;
} } catch (Exception e) {
catch (Exception e) { } }
} }
} }
// If server is still running // If server is still running
if (this.active) { if (this.active) {
// If no data, then send 404 back to client before it times out // If no data, then send 404 back to client before it times out
if (this.empty) { if (this.empty) {
//System.out.println("CallbackServer -- sending data 0"); //Log.d(LOG_TAG, "CallbackServer -- sending data 0");
response = "HTTP/1.1 404 NO DATA\r\n\r\n "; // need to send content otherwise some Android devices fail, so send space response = "HTTP/1.1 404 NO DATA\r\n\r\n "; // need to send content otherwise some Android devices fail, so send space
} }
else { else {
//System.out.println("CallbackServer -- sending item"); //Log.d(LOG_TAG, "CallbackServer -- sending item");
response = "HTTP/1.1 200 OK\r\n\r\n"; response = "HTTP/1.1 200 OK\r\n\r\n";
String js = this.getJavascript(); String js = this.getJavascript();
if (js != null) { if (js != null) {
response += encode(js, "UTF-8"); response += encode(js, "UTF-8");
} }
} }
} }
else { else {
response = "HTTP/1.1 503 Service Unavailable\r\n\r\n "; response = "HTTP/1.1 503 Service Unavailable\r\n\r\n ";
} }
} }
else { else {
response = "HTTP/1.1 403 Forbidden\r\n\r\n "; response = "HTTP/1.1 403 Forbidden\r\n\r\n ";
} }
} }
else { else {
response = "HTTP/1.1 400 Bad Request\r\n\r\n "; response = "HTTP/1.1 400 Bad Request\r\n\r\n ";
} }
//System.out.println("CallbackServer: response="+response); //Log.d(LOG_TAG, "CallbackServer: response="+response);
//System.out.println("CallbackServer: closing output"); //Log.d(LOG_TAG, "CallbackServer: closing output");
output.writeBytes(response); output.writeBytes(response);
output.flush(); output.flush();
} }
output.close(); output.close();
xhrReader.close(); xhrReader.close();
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
this.active = false; this.active = false;
//System.out.println("CallbackServer.startServer() - EXIT"); //Log.d(LOG_TAG, "CallbackServer.startServer() - EXIT");
} }
/** /**
* Stop server. * Stop server.
* This stops the thread that the server is running on. * This stops the thread that the server is running on.
*/ */
public void stopServer() { public void stopServer() {
//System.out.println("CallbackServer.stopServer()"); //Log.d(LOG_TAG, "CallbackServer.stopServer()");
if (this.active) { if (this.active) {
this.active = false; this.active = false;
@ -307,11 +305,11 @@ public class CallbackServer implements Runnable {
/** /**
* Get the number of JavaScript statements. * Get the number of JavaScript statements.
* *
* @return int * @return int
*/ */
public int getSize() { public int getSize() {
synchronized(this) { synchronized (this) {
int size = this.javascript.size(); int size = this.javascript.size();
return size; return size;
} }
@ -319,11 +317,11 @@ public class CallbackServer implements Runnable {
/** /**
* Get the next JavaScript statement and remove from list. * Get the next JavaScript statement and remove from list.
* *
* @return String * @return String
*/ */
public String getJavascript() { public String getJavascript() {
synchronized(this) { synchronized (this) {
if (this.javascript.size() == 0) { if (this.javascript.size() == 0) {
return null; return null;
} }
@ -337,7 +335,7 @@ public class CallbackServer implements Runnable {
/** /**
* Add a JavaScript statement to the list. * Add a JavaScript statement to the list.
* *
* @param statement * @param statement
*/ */
public void sendJavascript(String statement) { public void sendJavascript(String statement) {

View File

@ -26,6 +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.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;
@ -34,6 +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.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -78,12 +80,23 @@ public class CameraLauncher extends Plugin {
public String callbackId; public String callbackId;
private int numPics; private int numPics;
//This should never be null!
//private CordovaInterface cordova;
/** /**
* Constructor. * Constructor.
*/ */
public CameraLauncher() { public CameraLauncher() {
} }
// public void setContext(CordovaInterface mCtx) {
// super.setContext(mCtx);
// if (CordovaInterface.class.isInstance(mCtx))
// 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");
// }
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
* *
@ -163,7 +176,11 @@ public class CameraLauncher extends Plugin {
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);
this.ctx.startActivityForResult((Plugin) this, intent, (CAMERA+1)*16 + returnType+1); if (this.ctx != null) {
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");
} }
/** /**
@ -175,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.getContext()), "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.getContext()), "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);
} }
@ -211,8 +228,10 @@ public class CameraLauncher extends Plugin {
intent.setAction(Intent.ACTION_GET_CONTENT); intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE); intent.addCategory(Intent.CATEGORY_OPENABLE);
this.ctx.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);
}
} }
/** /**
@ -246,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;
@ -272,21 +291,20 @@ public class CameraLauncher extends Plugin {
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
ExifHelper exif = new ExifHelper();
try {
if (this.encodingType == JPEG) {
exif.createInFile(DirectoryManager.getTempDirectoryPath(ctx.getContext()) + "/Pic.jpg");
exif.readExifData();
}
} catch (IOException e) {
e.printStackTrace();
}
// Create an ExifHelper to save the exif data that is lost during compression
ExifHelper exif = new ExifHelper();
try {
if (this.encodingType == JPEG) {
exif.createInFile(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/Pic.jpg");
exif.readExifData();
}
} catch (IOException e) {
e.printStackTrace();
}
// If CAMERA // If CAMERA
if (srcType == CAMERA) { if (srcType == CAMERA) {
// If image available // If image available
@ -295,10 +313,10 @@ 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));
} }
@ -311,18 +329,18 @@ 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.");
@ -331,7 +349,7 @@ public class CameraLauncher extends Plugin {
} }
// 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();
@ -370,9 +388,9 @@ public class CameraLauncher extends Plugin {
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);
@ -382,21 +400,21 @@ public class CameraLauncher extends Plugin {
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();
bitmap = null; bitmap = null;
@ -415,7 +433,7 @@ public class CameraLauncher extends Plugin {
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.getContext()) + "/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();
@ -429,7 +447,7 @@ public class CameraLauncher extends Plugin {
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);
System.gc(); System.gc();
@ -459,7 +477,7 @@ 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,
@ -488,7 +506,7 @@ public class CameraLauncher extends Plugin {
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);
} }
} }
@ -501,7 +519,7 @@ public class CameraLauncher extends Plugin {
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);
@ -509,8 +527,7 @@ public class CameraLauncher extends Plugin {
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;

View File

@ -38,11 +38,10 @@ 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";
@ -52,8 +51,8 @@ public class Capture extends Plugin {
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;
@ -63,6 +62,16 @@ public class Capture extends Plugin {
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)
// {
// if (CordovaInterface.class.isInstance(mCtx))
// 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;
@ -132,8 +141,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;
@ -169,13 +177,12 @@ 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 +204,7 @@ 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.getContext()), "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);
@ -250,11 +257,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.getContext()) + "/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)
@ -262,11 +269,11 @@ 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."));
@ -275,7 +282,7 @@ public class Capture extends Plugin {
} }
// 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();
@ -347,7 +354,7 @@ 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, this.ctx)); File fp = new File(FileUtils.getRealPathFromURI(data, this.ctx));
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
@ -355,9 +362,8 @@ public class Capture extends Plugin {
// File properties // File properties
obj.put("name", fp.getName()); obj.put("name", fp.getName());
obj.put("fullPath", "file://" + fp.getAbsolutePath()); obj.put("fullPath", "file://" + 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/")) {

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;
@ -72,7 +71,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
*/ */
public void setContext(CordovaInterface 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);
} }
/** /**
@ -184,6 +183,7 @@ public class CompassListener extends Plugin implements SensorEventListener {
} }
// 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
@ -212,7 +212,6 @@ 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
} }

View File

@ -22,6 +22,7 @@ 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;
@ -36,7 +37,7 @@ import org.json.JSONObject;
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;
/** /**
@ -75,7 +76,7 @@ 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 { else {
for (int i=0; i<fields.length(); i++) { for (int i=0; i<fields.length(); i++) {
key = fields.getString(i); key = fields.getString(i);
@ -121,7 +122,7 @@ public abstract class ContactAccessor {
} }
} }
} }
} }
catch (JSONException e) { catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e); Log.e(LOG_TAG, e.getMessage(), e);
} }
@ -147,7 +148,7 @@ public abstract class ContactAccessor {
value = null; value = null;
} }
} }
} }
catch (JSONException e) { catch (JSONException e) {
Log.d(LOG_TAG, "Could not get = " + e.getMessage()); Log.d(LOG_TAG, "Could not get = " + e.getMessage());
} }
@ -176,8 +177,8 @@ public abstract class ContactAccessor {
*/ */
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;

File diff suppressed because it is too large Load Diff

View File

@ -69,7 +69,7 @@ public class ContactManager extends Plugin {
* older phones. * older phones.
*/ */
if (this.contactAccessor == null) { if (this.contactAccessor == null) {
this.contactAccessor = new ContactAccessorSdk5(this.webView, this.ctx.getContext()); this.contactAccessor = new ContactAccessorSdk5(this.webView, this.ctx);
} }
try { try {

View File

@ -17,16 +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.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,18 +43,38 @@ import android.widget.EditText;
*/ */
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 DroidGap ctx; private CordovaInterface ctx;
private CordovaWebView appView;
/** /**
* Constructor. * Constructor.
* *
* @param ctx * @param ctx
*/ */
public CordovaChromeClient(Context ctx) { public CordovaChromeClient(CordovaInterface ctx) {
this.ctx = (DroidGap) ctx; this.ctx = ctx;
}
/**
* Constructor.
*
* @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;
} }
/** /**
@ -65,35 +87,35 @@ 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;
@ -109,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;
@ -168,11 +190,11 @@ public class CordovaChromeClient extends WebChromeClient {
// 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(this.ctx.baseUrl) == 0 || ctx.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:")) {
JSONArray array; JSONArray array;
@ -182,72 +204,66 @@ 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 = ctx.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 = ctx.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 = ""+ ctx.callbackServer.usePolling(); r = "" + this.appView.callbackServer.usePolling();
} }
else if (message.equals("restartServer")) { else if (message.equals("restartServer")) {
ctx.callbackServer.restartServer(); this.appView.callbackServer.restartServer();
} }
else if (message.equals("getPort")) { else if (message.equals("getPort")) {
r = Integer.toString(ctx.callbackServer.getPort()); r = Integer.toString(this.appView.callbackServer.getPort());
} }
else if (message.equals("getToken")) { else if (message.equals("getToken")) {
r = ctx.callbackServer.getToken(); r = this.appView.callbackServer.getToken();
} }
result.confirm(r); result.confirm(r);
} }
// Cordova JS has initialized, so show webview
// (This solves white flash seen when rendering HTML)
else if (reqOk && defaultValue != null && defaultValue.equals("gap_init:")) {
if (ctx.splashscreen != 0) {
ctx.root.setBackgroundResource(0);
}
ctx.appView.setVisibility(View.VISIBLE);
ctx.spinnerStop();
result.confirm("OK");
}
// 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();
} }
@ -270,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;
@ -286,6 +302,7 @@ 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)
{ {
@ -296,7 +313,7 @@ public class CordovaChromeClient extends WebChromeClient {
@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);
} }
@ -312,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);
} }
} }

View File

@ -0,0 +1,663 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.LOG;
import org.apache.cordova.api.PluginManager;
import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
import android.content.Intent;
import android.content.res.XmlResourceParser;
import android.net.Uri;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.WindowManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebSettings.LayoutAlgorithm;
public class CordovaWebView extends WebView {
public static final String TAG = "CordovaWebView";
/** The whitelist **/
private ArrayList<Pattern> whiteList = new ArrayList<Pattern>();
private HashMap<String, Boolean> whiteListCache = new HashMap<String, Boolean>();
public PluginManager pluginManager;
public CallbackServer callbackServer;
/** Actvities and other important classes **/
private CordovaInterface mCtx;
CordovaWebViewClient viewClient;
@SuppressWarnings("unused")
private CordovaChromeClient chromeClient;
//This is for the polyfil history
private String url;
String baseUrl;
private Stack<String> urls = new Stack<String>();
boolean useBrowserHistory = false;
// Flag to track that a loadUrl timeout occurred
int loadUrlTimeout = 0;
/**
* Constructor.
*
* @param context
*/
public CordovaWebView(Context context) {
super(context);
if (CordovaInterface.class.isInstance(context))
{
this.mCtx = (CordovaInterface) context;
}
else
{
Log.d(TAG, "Your activity must implement CordovaInterface to work");
}
this.loadConfiguration();
this.setup();
}
/**
* Constructor.
*
* @param context
* @param attrs
*/
public CordovaWebView(Context context, AttributeSet attrs) {
super(context, attrs);
if (CordovaInterface.class.isInstance(context))
{
this.mCtx = (CordovaInterface) context;
}
else
{
Log.d(TAG, "Your activity must implement CordovaInterface to work");
}
this.setWebChromeClient(new CordovaChromeClient(this.mCtx, this));
this.setWebViewClient(new CordovaWebViewClient(this.mCtx, this));
this.loadConfiguration();
this.setup();
}
/**
* Constructor.
*
* @param context
* @param attrs
* @param defStyle
*
*/
public CordovaWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (CordovaInterface.class.isInstance(context))
{
this.mCtx = (CordovaInterface) context;
}
else
{
Log.d(TAG, "Your activity must implement CordovaInterface to work");
}
this.setWebChromeClient(new CordovaChromeClient(this.mCtx, this));
this.setWebViewClient(new CordovaWebViewClient(this.mCtx, this));
this.loadConfiguration();
this.setup();
}
/**
* Constructor.
*
* @param context
* @param attrs
* @param defStyle
* @param privateBrowsing
*/
public CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
super(context, attrs, defStyle, privateBrowsing);
if (CordovaInterface.class.isInstance(context))
{
this.mCtx = (CordovaInterface) context;
}
else
{
Log.d(TAG, "Your activity must implement CordovaInterface to work");
}
this.setWebChromeClient(new CordovaChromeClient(this.mCtx));
this.setWebViewClient(new CordovaWebViewClient(this.mCtx));
this.loadConfiguration();
this.setup();
}
/**
* Initialize webview.
*/
@SuppressWarnings("deprecation")
private void setup() {
this.setInitialScale(0);
this.setVerticalScrollBarEnabled(false);
this.requestFocusFromTouch();
// Enable JavaScript
WebSettings settings = this.getSettings();
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
//Set the nav dump for HTC
settings.setNavDump(true);
// Enable database
settings.setDatabaseEnabled(true);
String databasePath = this.mCtx.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
settings.setDatabasePath(databasePath);
// Enable DOM storage
settings.setDomStorageEnabled(true);
// Enable built-in geolocation
settings.setGeolocationEnabled(true);
//Start up the plugin manager
try {
this.pluginManager = new PluginManager(this, this.mCtx);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Set the WebViewClient.
*
* @param client
*/
public void setWebViewClient(CordovaWebViewClient client) {
this.viewClient = client;
super.setWebViewClient(client);
}
/**
* Set the WebChromeClient.
*
* @param client
*/
public void setWebChromeClient(CordovaChromeClient client) {
this.chromeClient = client;
super.setWebChromeClient(client);
}
/**
* Add entry to approved list of URLs (whitelist)
*
* @param origin URL regular expression to allow
* @param subdomains T=include all subdomains under origin
*/
public void addWhiteListEntry(String origin, boolean subdomains) {
try {
// Unlimited access to network resources
if (origin.compareTo("*") == 0) {
LOG.d(TAG, "Unlimited access to network resources");
this.whiteList.add(Pattern.compile(".*"));
} else { // specific access
// check if subdomains should be included
// TODO: we should not add more domains if * has already been added
if (subdomains) {
// XXX making it stupid friendly for people who forget to include protocol/SSL
if (origin.startsWith("http")) {
this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://(.*\\.)?")));
} else {
this.whiteList.add(Pattern.compile("^https?://(.*\\.)?" + origin));
}
LOG.d(TAG, "Origin to allow with subdomains: %s", origin);
} else {
// XXX making it stupid friendly for people who forget to include protocol/SSL
if (origin.startsWith("http")) {
this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://")));
} else {
this.whiteList.add(Pattern.compile("^https?://" + origin));
}
LOG.d(TAG, "Origin to allow: %s", origin);
}
}
} catch (Exception e) {
LOG.d(TAG, "Failed to add origin %s", origin);
}
}
/**
* Determine if URL is in approved list of URLs to load.
*
* @param url
* @return
*/
public boolean isUrlWhiteListed(String url) {
// Check to see if we have matched url previously
if (this.whiteListCache.get(url) != null) {
return true;
}
// Look for match in white list
Iterator<Pattern> pit = this.whiteList.iterator();
while (pit.hasNext()) {
Pattern p = pit.next();
Matcher m = p.matcher(url);
// If match found, then cache it to speed up subsequent comparisons
if (m.find()) {
this.whiteListCache.put(url, true);
return true;
}
}
return false;
}
/**
* Load the url into the webview.
*
* @param url
*/
@Override
public void loadUrl(String url) {
if (url.equals("about:blank") || url.startsWith("javascript:")) {
this.loadUrlNow(url);
}
else {
String initUrl = this.getProperty("url", null);
// If first page of app, then set URL to load to be the one passed in
if (initUrl == null || (this.urls.size() > 0)) {
this.loadUrlIntoView(url);
}
// Otherwise use the URL specified in the activity's extras bundle
else {
this.loadUrlIntoView(initUrl);
}
}
}
/**
* Load the url into the webview after waiting for period of time.
* This is used to display the splashscreen for certain amount of time.
*
* @param url
* @param time The number of ms to wait before loading webview
*/
public void loadUrl(final String url, int time) {
String initUrl = this.getProperty("url", null);
// If first page of app, then set URL to load to be the one passed in
if (initUrl == null || (this.urls.size() > 0)) {
this.loadUrlIntoView(url, time);
}
// Otherwise use the URL specified in the activity's extras bundle
else {
this.loadUrlIntoView(initUrl);
}
}
/**
* Load the url into the webview.
*
* @param url
*/
public void loadUrlIntoView(final String url) {
LOG.d(TAG, ">>> loadUrl(" + url + ")");
this.url = url;
if (this.baseUrl == null) {
int i = url.lastIndexOf('/');
if (i > 0) {
this.baseUrl = url.substring(0, i + 1);
}
else {
this.baseUrl = this.url + "/";
}
this.pluginManager.init();
if (!this.useBrowserHistory) {
this.urls.push(url);
}
}
// Create a timeout timer for loadUrl
final CordovaWebView me = this;
final int currentLoadUrlTimeout = me.loadUrlTimeout;
final int loadUrlTimeoutValue = Integer.parseInt(this.getProperty("loadUrlTimeoutValue", "20000"));
// Timeout error method
final Runnable loadError = new Runnable() {
public void run() {
me.stopLoading();
LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!");
if (viewClient != null) {
viewClient.onReceivedError(me, -6, "The connection to the server was unsuccessful.", url);
}
}
};
// Timeout timer method
final Runnable timeoutCheck = new Runnable() {
public void run() {
try {
synchronized (this) {
wait(loadUrlTimeoutValue);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// If timeout, then stop loading and handle error
if (me.loadUrlTimeout == currentLoadUrlTimeout) {
me.mCtx.getActivity().runOnUiThread(loadError);
}
}
};
// Load url
this.mCtx.getActivity().runOnUiThread(new Runnable() {
public void run() {
Thread thread = new Thread(timeoutCheck);
thread.start();
me.loadUrlNow(url);
}
});
}
/**
* Load URL in webview.
*
* @param url
*/
private void loadUrlNow(String url) {
LOG.d(TAG, ">>> loadUrlNow()");
super.loadUrl(url);
}
/**
* Load the url into the webview after waiting for period of time.
* This is used to display the splashscreen for certain amount of time.
*
* @param url
* @param time The number of ms to wait before loading webview
*/
public void loadUrlIntoView(final String url, final int time) {
// If not first page of app, then load immediately
// Add support for browser history if we use it.
if ((url.startsWith("javascript:")) || this.urls.size() > 0 || this.canGoBack()) {
}
// If first page, then show splashscreen
else {
LOG.d(TAG, "DroidGap.loadUrl(%s, %d)", url, time);
// Send message to show splashscreen now if desired
this.postMessage("splashscreen", "show");
}
// Load url
this.loadUrlIntoView(url);
}
/**
* Send JavaScript statement back to JavaScript.
* (This is a convenience method)
*
* @param message
*/
public void sendJavascript(String statement) {
if (this.callbackServer != null) {
this.callbackServer.sendJavascript(statement);
}
}
/**
* Send a message to all plugins.
*
* @param id The message id
* @param data The message data
*/
public void postMessage(String id, Object data) {
if (this.pluginManager != null) {
this.pluginManager.postMessage(id, data);
}
}
/**
* Returns the top url on the stack without removing it from
* the stack.
*/
public String peekAtUrlStack() {
if (this.urls.size() > 0) {
return this.urls.peek();
}
return "";
}
/**
* Add a url to the stack
*
* @param url
*/
public void pushUrl(String url) {
this.urls.push(url);
}
/**
* Go to previous page in history. (We manage our own history)
*
* @return true if we went back, false if we are already at top
*/
public boolean backHistory() {
// Check webview first to see if there is a history
// This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
if (super.canGoBack()) {
super.goBack();
return true;
}
// If our managed history has prev url
if (this.urls.size() > 1) {
this.urls.pop(); // Pop current url
String url = this.urls.pop(); // Pop prev url that we want to load, since it will be added back by loadUrl()
this.loadUrl(url);
return true;
}
return false;
}
/**
* Return true if there is a history item.
*
* @return
*/
public boolean canGoBack() {
if (super.canGoBack()) {
return true;
}
if (this.urls.size() > 1) {
return true;
}
return false;
}
/**
* Load the specified URL in the Cordova webview or a new browser instance.
*
* NOTE: If openExternal is false, only URLs listed in whitelist can be loaded.
*
* @param url The url to load.
* @param openExternal Load url in browser instead of Cordova webview.
* @param clearHistory Clear the history stack, so new page becomes top of history
* @param params DroidGap parameters for new app
*/
public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) {
LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory);
// If clearing history
if (clearHistory) {
this.clearHistory();
}
// If loading into our webview
if (!openExternal) {
// Make sure url is in whitelist
if (url.startsWith("file://") || url.indexOf(this.baseUrl) == 0 || isUrlWhiteListed(url)) {
// TODO: What about params?
// Clear out current url from history, since it will be replacing it
if (clearHistory) {
this.urls.clear();
}
// Load new URL
this.loadUrl(url);
}
// Load in default viewer if not
else {
LOG.w(TAG, "showWebPage: Cannot load URL into webview since it is not in white list. Loading into browser instead. (URL=" + url + ")");
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
mCtx.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error loading url " + url, e);
}
}
}
// Load in default view intent
else {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
mCtx.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error loading url " + url, e);
}
}
}
/**
* Load Cordova configuration from res/xml/cordova.xml.
* Approved list of URLs that can be loaded into DroidGap
* <access origin="http://server regexp" subdomains="true" />
* Log level: ERROR, WARN, INFO, DEBUG, VERBOSE (default=ERROR)
* <log level="DEBUG" />
*/
private void loadConfiguration() {
int id = getResources().getIdentifier("cordova", "xml", this.mCtx.getActivity().getPackageName());
if (id == 0) {
LOG.i("CordovaLog", "cordova.xml missing. Ignoring...");
return;
}
XmlResourceParser xml = getResources().getXml(id);
int eventType = -1;
while (eventType != XmlResourceParser.END_DOCUMENT) {
if (eventType == XmlResourceParser.START_TAG) {
String strNode = xml.getName();
if (strNode.equals("access")) {
String origin = xml.getAttributeValue(null, "origin");
String subdomains = xml.getAttributeValue(null, "subdomains");
if (origin != null) {
this.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
}
}
else if (strNode.equals("log")) {
String level = xml.getAttributeValue(null, "level");
LOG.i("CordovaLog", "Found log level %s", level);
if (level != null) {
LOG.setLogLevel(level);
}
}
else if (strNode.equals("preference")) {
String name = xml.getAttributeValue(null, "name");
String value = xml.getAttributeValue(null, "value");
LOG.i("CordovaLog", "Found preference for %s=%s", name, value);
// Save preferences in Intent
this.mCtx.getActivity().getIntent().putExtra(name, value);
}
}
try {
eventType = xml.next();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// Init preferences
if ("true".equals(this.getProperty("useBrowserHistory", "true"))) {
this.useBrowserHistory = true;
}
else {
this.useBrowserHistory = false;
}
if ("true".equals(this.getProperty("fullscreen", "false"))) {
this.mCtx.getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
this.mCtx.getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
/**
* Get string property for activity.
*
* @param name
* @param defaultValue
* @return
*/
public String getProperty(String name, String defaultValue) {
Bundle bundle = this.mCtx.getActivity().getIntent().getExtras();
if (bundle == null) {
return defaultValue;
}
Object p = bundle.get(name);
if (p == null) {
return defaultValue;
}
return p.toString();
}
}

View File

@ -18,7 +18,12 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import java.util.Hashtable;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@ -39,18 +44,42 @@ import android.webkit.WebViewClient;
public class CordovaWebViewClient extends WebViewClient { public class CordovaWebViewClient extends WebViewClient {
private static final String TAG = "Cordova"; private static final String TAG = "Cordova";
DroidGap ctx; CordovaInterface ctx;
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(DroidGap ctx) { public CordovaWebViewClient(CordovaInterface ctx) {
this.ctx = ctx; this.ctx = ctx;
} }
/**
* Constructor.
*
* @param ctx
* @param view
*/
public CordovaWebViewClient(CordovaInterface ctx, CordovaWebView view) {
this.ctx = ctx;
this.appView = view;
}
/**
* Constructor.
*
* @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.
@ -63,7 +92,7 @@ public class CordovaWebViewClient extends WebViewClient {
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 ((this.ctx.pluginManager != null) && this.ctx.pluginManager.onOverrideUrlLoading(url)) { if ((this.appView.pluginManager != null) && this.appView.pluginManager.onOverrideUrlLoading(url)) {
} }
// If dialing phone (tel:5551212) // If dialing phone (tel:5551212)
@ -71,9 +100,9 @@ public class CordovaWebViewClient extends WebViewClient {
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());
} }
} }
@ -82,9 +111,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());
} }
} }
@ -93,9 +122,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());
} }
} }
@ -122,12 +151,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());
} }
} }
@ -136,8 +165,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(this.ctx.baseUrl) == 0 || ctx.isUrlWhiteListed(url)) { if (url.startsWith("file://") || url.indexOf(this.appView.baseUrl) == 0 || this.appView.isUrlWhiteListed(url)) {
this.ctx.loadUrl(url); //This will fix iFrames
if (appView.useBrowserHistory)
return false;
else
this.appView.loadUrl(url);
} }
// If not our application, let default viewer handle // If not our application, let default viewer handle
@ -145,9 +178,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 loading url "+url, e); LOG.e(TAG, "Error loading url " + url, e);
} }
} }
} }
@ -159,44 +192,62 @@ public class CordovaWebViewClient extends WebViewClient {
* 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 = ctx.getAuthenticationToken(host,realm); AuthenticationToken token = this.getAuthenticationToken(host, realm);
if (token != null) {
if(token != null) {
handler.proceed(token.getUserName(), token.getPassword()); handler.proceed(token.getUserName(), token.getPassword());
} }
} }
/**
* Notify the host application that a page has started loading.
* This method is called once for each main frame load so a page with iframes or framesets will call onPageStarted
* one time for the main frame. This also means that onPageStarted will not be called when the contents of an
* embedded frame changes, i.e. clicking a link whose target is an iframe.
*
* @param view The webview initiating the callback.
* @param url The url of the page.
*/
@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.
view.clearHistory(); if (!this.appView.useBrowserHistory) {
this.doClearHistory = true; view.clearHistory();
this.doClearHistory = true;
}
// Create callback server and plugin manager
if (this.appView.callbackServer == null) {
this.appView.callbackServer = new CallbackServer();
this.appView.callbackServer.init(url);
}
else {
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.
* * This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet.
*
* @param view The webview initiating the callback. * @param view The webview initiating the callback.
* @param url The url of the page. * @param url The url of the page.
*/ */
@Override @Override
public void onPageFinished(WebView view, String url) { public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url); super.onPageFinished(view, url);
LOG.d(TAG, "onPageFinished(" + url + ")");
/** /**
* Because of a timing issue we need to clear this history in onPageFinished as well as * Because of a timing issue we need to clear this history in onPageFinished as well as
@ -210,29 +261,28 @@ public class CordovaWebViewClient extends WebViewClient {
} }
// Clear timeout flag // Clear timeout flag
this.ctx.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")) {
ctx.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;}");
this.ctx.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 (ctx.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() {
if (ctx.splashscreen != 0) { appView.postMessage("spinner", "stop");
ctx.root.setBackgroundResource(0);
}
ctx.appView.setVisibility(View.VISIBLE);
ctx.spinnerStop();
} }
}); });
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -242,13 +292,12 @@ 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 (this.ctx.callbackServer != null) { if (this.appView.callbackServer != null) {
this.ctx.callbackServer.destroy(); this.appView.callbackServer.destroy();
} }
this.ctx.endActivity(); appView.postMessage("exit", null);
} }
} }
@ -263,22 +312,38 @@ 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
this.ctx.spinnerStop();
// Handle error // Handle error
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);
} }
/**
* Notify the host application that an SSL error occurred while loading a resource.
* The host application must call either handler.cancel() or handler.proceed().
* Note that the decision may be retained for use in response to future SSL errors.
* The default behavior is to cancel the load.
*
* @param view The WebView that is initiating the callback.
* @param handler An SslErrorHandler object that will handle the user's response.
* @param error The SSL error object.
*/
@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);
@ -296,14 +361,94 @@ public class CordovaWebViewClient extends WebViewClient {
} }
} }
/**
* Notify the host application to update its visited links database.
*
* @param view The WebView that is initiating the callback.
* @param url The url being visited.
* @param isReload True if this url is being reloaded.
*/
@Override @Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
/* /*
* 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 (!this.ctx.peekAtUrlStack().equals(url)) { if (!this.appView.peekAtUrlStack().equals(url)) {
this.ctx.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

@ -110,7 +110,7 @@ public class Device extends Plugin {
* Unregister receiver. * Unregister receiver.
*/ */
public void onDestroy() { public void onDestroy() {
this.ctx.unregisterReceiver(this.telephonyReceiver); this.ctx.getActivity().unregisterReceiver(this.telephonyReceiver);
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -123,9 +123,9 @@ public class Device extends Plugin {
* 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 CordovaInterface myctx = this.ctx; //final CordovaInterface myctx = this.ctx;
this.telephonyReceiver = new BroadcastReceiver() { this.telephonyReceiver = new BroadcastReceiver() {
@Override @Override
@ -137,15 +137,15 @@ public class Device extends Plugin {
String extraData = intent.getStringExtra(TelephonyManager.EXTRA_STATE); String extraData = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (extraData.equals(TelephonyManager.EXTRA_STATE_RINGING)) { if (extraData.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
LOG.i(TAG, "Telephone RINGING"); LOG.i(TAG, "Telephone RINGING");
myctx.postMessage("telephone", "ringing"); webView.postMessage("telephone", "ringing");
} }
else if (extraData.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { else if (extraData.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
LOG.i(TAG, "Telephone OFFHOOK"); LOG.i(TAG, "Telephone OFFHOOK");
myctx.postMessage("telephone", "offhook"); webView.postMessage("telephone", "offhook");
} }
else if (extraData.equals(TelephonyManager.EXTRA_STATE_IDLE)) { else if (extraData.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
LOG.i(TAG, "Telephone IDLE"); LOG.i(TAG, "Telephone IDLE");
myctx.postMessage("telephone", "idle"); webView.postMessage("telephone", "idle");
} }
} }
} }
@ -153,7 +153,7 @@ public class Device extends Plugin {
}; };
// Register the receiver // Register the receiver
this.ctx.registerReceiver(this.telephonyReceiver, intentFilter); this.ctx.getActivity().registerReceiver(this.telephonyReceiver, intentFilter);
} }
/** /**
@ -171,7 +171,7 @@ public class Device extends Plugin {
* @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;
} }
@ -205,15 +205,14 @@ public class Device extends Plugin {
} }
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() { public String getTimeZoneID() {
TimeZone tz = TimeZone.getDefault(); TimeZone tz = TimeZone.getDefault();
return(tz.getID()); return (tz.getID());
} }
} }

View File

@ -32,11 +32,11 @@ import android.os.StatFs;
*/ */
public class DirectoryManager { public class DirectoryManager {
@SuppressWarnings("unused")
private static final String LOG_TAG = "DirectoryManager"; private static final String LOG_TAG = "DirectoryManager";
/** /**
* Determine if a file or directory exists. * Determine if a file or directory exists.
*
* @param name The name of the file to check. * @param name The name of the file to check.
* @return T=exists, F=not found * @return T=exists, F=not found
*/ */
@ -50,7 +50,7 @@ public class DirectoryManager {
status = newPath.exists(); status = newPath.exists();
} }
// If no SD card // If no SD card
else{ else {
status = false; status = false;
} }
return status; return status;
@ -58,7 +58,7 @@ public class DirectoryManager {
/** /**
* Get the free disk space * Get the free disk space
* *
* @return Size in KB or -1 if not available * @return Size in KB or -1 if not available
*/ */
protected static long getFreeDiskSpace(boolean checkInternal) { protected static long getFreeDiskSpace(boolean checkInternal) {
@ -82,7 +82,7 @@ public class DirectoryManager {
/** /**
* Given a path return the number of free KB * Given a path return the number of free KB
* *
* @param path to the file system * @param path to the file system
* @return free space in KB * @return free space in KB
*/ */
@ -90,12 +90,12 @@ public class DirectoryManager {
StatFs stat = new StatFs(path); StatFs stat = new StatFs(path);
long blockSize = stat.getBlockSize(); long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks(); long availableBlocks = stat.getAvailableBlocks();
return availableBlocks*blockSize/1024; return availableBlocks * blockSize / 1024;
} }
/** /**
* Determine if SD card exists. * Determine if SD card exists.
* *
* @return T=exists, F=not found * @return T=exists, F=not found
*/ */
protected static boolean testSaveLocationExists() { protected static boolean testSaveLocationExists() {
@ -127,7 +127,7 @@ public class DirectoryManager {
newPath = new File(file2); newPath = new File(file2);
} }
else { else {
newPath = new File(file1+"/"+file2); newPath = new File(file1 + "/" + file2);
} }
return newPath; return newPath;
} }

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,6 @@ 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";
@ -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");
} }
@ -353,11 +351,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 {
} }
} }; } };
@ -419,7 +417,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;
@ -428,7 +426,6 @@ public class FileTransfer extends Plugin {
return arg; return arg;
} }
/** /**
* Downloads a file form a given URL and saves it to the specified directory. * Downloads a file form a given URL and saves it to the specified directory.
* *
@ -447,7 +444,7 @@ public class FileTransfer extends Plugin {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();
// connect to server // connect to server
if(this.ctx.isUrlWhiteListed(source)) if (webView.isUrlWhiteListed(source))
{ {
URL url = new URL(source); URL url = new URL(source);
connection = (HttpURLConnection) url.openConnection(); connection = (HttpURLConnection) url.openConnection();
@ -464,20 +461,24 @@ public class FileTransfer extends Plugin {
Log.d(LOG_TAG, "Download file: " + url); Log.d(LOG_TAG, "Download file: " + url);
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);
}
outputStream.close();
Log.d(LOG_TAG, "Saved file: " + target);
// create FileEntry object // create FileEntry object
FileUtils fileUtil = new FileUtils(); FileUtils fileUtil = new FileUtils();
@ -521,7 +522,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,18 +37,21 @@ 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.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.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
//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.
* Only files on the SD card can be accessed. * Only files on the SD card can be accessed.
*/ */
public class FileUtils extends Plugin { public class FileUtils extends Plugin {
@SuppressWarnings("unused")
private static final String LOG_TAG = "FileUtils"; private static final String LOG_TAG = "FileUtils";
private static final String _DATA = "_data"; // The column name where the file path is stored private static final String _DATA = "_data"; // The column name where the file path is stored
@ -129,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);
} }
} }
@ -220,9 +223,9 @@ public class FileUtils extends Plugin {
*/ */
private void notifyDelete(String filePath) { private void notifyDelete(String filePath) {
String newFilePath = stripFileProtocol(filePath); String newFilePath = stripFileProtocol(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[] {newFilePath}); new String[] { filePath });
} }
/** /**
@ -235,6 +238,7 @@ public class FileUtils extends Plugin {
* @throws IOException if the user can't read the file * @throws IOException if the user can't read the file
* @throws JSONException * @throws JSONException
*/ */
@SuppressWarnings("deprecation")
private JSONObject resolveLocalFileSystemURI(String url) throws IOException, JSONException { private JSONObject resolveLocalFileSystemURI(String url) throws IOException, JSONException {
String decoded = URLDecoder.decode(url, "UTF-8"); String decoded = URLDecoder.decode(url, "UTF-8");
@ -242,7 +246,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 = 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();
@ -293,7 +297,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]));
} }
} }
@ -319,7 +323,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");
@ -376,7 +379,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;
} }
@ -398,7 +401,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");
@ -476,7 +479,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;
} }
@ -725,9 +728,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;
@ -791,7 +794,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());
@ -816,16 +819,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) {
@ -833,7 +836,7 @@ 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 {
@ -940,7 +943,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);
@ -959,7 +962,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));
} }
/** /**
@ -980,7 +983,7 @@ public class FileUtils extends Plugin {
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];
@ -1005,9 +1008,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();
@ -1023,7 +1026,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);
@ -1035,12 +1038,13 @@ public class FileUtils extends Plugin {
* Queries the media store to find out what the file path is for the Uri we supply * Queries the media store to find out what the file path is for the Uri we supply
* *
* @param contentUri the Uri of the audio/image/video * @param contentUri the Uri of the audio/image/video
* @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
*/ */
@SuppressWarnings("deprecation")
protected static String getRealPathFromURI(Uri contentUri, CordovaInterface 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

@ -55,7 +55,7 @@ public class GeoBroker extends Plugin {
*/ */
public PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
if (this.locationManager == null) { if (this.locationManager == null) {
this.locationManager = (LocationManager) this.ctx.getSystemService(Context.LOCATION_SERVICE); this.locationManager = (LocationManager) this.ctx.getActivity().getSystemService(Context.LOCATION_SERVICE);
this.networkListener = new NetworkListener(this.locationManager, this); this.networkListener = new NetworkListener(this.locationManager, this);
this.gpsListener = new GPSListener(this.locationManager, this); this.gpsListener = new GPSListener(this.locationManager, this);
} }
@ -141,46 +141,47 @@ public class GeoBroker extends Plugin {
o.put("latitude", loc.getLatitude()); o.put("latitude", loc.getLatitude());
o.put("longitude", loc.getLongitude()); o.put("longitude", loc.getLongitude());
o.put("altitude", (loc.hasAltitude() ? loc.getAltitude() : null)); o.put("altitude", (loc.hasAltitude() ? loc.getAltitude() : null));
o.put("accuracy", loc.getAccuracy()); o.put("accuracy", loc.getAccuracy());
o.put("heading", (loc.hasBearing() ? (loc.hasSpeed() ? loc.getBearing() : null) : null)); o.put("heading", (loc.hasBearing() ? (loc.hasSpeed() ? loc.getBearing() : null) : null));
o.put("speed", loc.getSpeed()); o.put("speed", loc.getSpeed());
o.put("timestamp", loc.getTime()); o.put("timestamp", loc.getTime());
} catch (JSONException e) { } catch (JSONException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
return o; return o;
} }
public void win(Location loc, String callbackId) {
PluginResult result = new PluginResult(PluginResult.Status.OK, this.returnLocationJSON(loc));
this.success(result, callbackId);
}
/**
* Location failed. Send error back to JavaScript.
*
* @param code The error code
* @param msg The error message
* @throws JSONException
*/
public void fail(int code, String msg, String callbackId) {
JSONObject obj = new JSONObject();
String backup = null;
try {
obj.put("code", code);
obj.put("message", msg);
} catch (JSONException e) {
obj = null;
backup = "{'code':" + code + ",'message':'" + msg.replaceAll("'", "\'") + "'}";
}
PluginResult result;
if (obj != null) {
result = new PluginResult(PluginResult.Status.ERROR, obj);
} else {
result = new PluginResult(PluginResult.Status.ERROR, backup);
}
this.error(result, callbackId); public void win(Location loc, String callbackId) {
} PluginResult result = new PluginResult(PluginResult.Status.OK, this.returnLocationJSON(loc));
this.success(result, callbackId);
}
/**
* Location failed. Send error back to JavaScript.
*
* @param code The error code
* @param msg The error message
* @throws JSONException
*/
public void fail(int code, String msg, String callbackId) {
JSONObject obj = new JSONObject();
String backup = null;
try {
obj.put("code", code);
obj.put("message", msg);
} catch (JSONException e) {
obj = null;
backup = "{'code':" + code + ",'message':'" + msg.replaceAll("'", "\'") + "'}";
}
PluginResult result;
if (obj != null) {
result = new PluginResult(PluginResult.Status.ERROR, obj);
} else {
result = new PluginResult(PluginResult.Status.ERROR, backup);
}
this.error(result, callbackId);
}
} }

View File

@ -34,10 +34,16 @@ public class HttpHandler {
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) {
e.printStackTrace();
return false;
}
try { try {
entity.consumeContent(); entity.consumeContent();
} catch (Exception e) { e.printStackTrace(); return false; } } catch (Exception e) {
e.printStackTrace();
return false;
}
return true; return true;
} }
@ -46,7 +52,7 @@ public class HttpHandler {
* get the http entity at a given url * get the http entity at a given url
*/ */
{ {
HttpEntity entity=null; HttpEntity entity = null;
try { try {
DefaultHttpClient httpclient = new DefaultHttpClient(); DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url); HttpGet httpget = new HttpGet(url);
@ -61,18 +67,18 @@ public class HttpHandler {
* writes a HTTP entity to the specified filename and location on disk * writes a HTTP entity to the specified filename and location on disk
*/ */
{ {
int i=0; //int i = 0;
String FilePath="/sdcard/" + file; String FilePath = "/sdcard/" + file;
InputStream in = entity.getContent(); InputStream in = entity.getContent();
byte buff[] = new byte[1024]; byte buff[] = new byte[1024];
FileOutputStream out= FileOutputStream out =
new FileOutputStream(FilePath); new FileOutputStream(FilePath);
do { do {
int numread = in.read(buff); int numread = in.read(buff);
if (numread <= 0) if (numread <= 0)
break; break;
out.write(buff, 0, numread); out.write(buff, 0, numread);
i++; //i++;
} while (true); } while (true);
out.flush(); out.flush();
out.close(); out.close();

View File

@ -17,9 +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.widget.LinearLayout; import android.widget.LinearLayout;
/** /**
@ -75,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;
@ -85,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

@ -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;
@ -77,7 +76,7 @@ public class NetworkManager extends Plugin {
/** /**
* Constructor. * Constructor.
*/ */
public NetworkManager() { public NetworkManager() {
this.receiver = null; this.receiver = null;
} }
@ -89,20 +88,21 @@ public class NetworkManager extends Plugin {
*/ */
public void setContext(CordovaInterface 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);
} }
} }
@ -146,7 +146,7 @@ public class NetworkManager extends Plugin {
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,7 +157,6 @@ 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
* *
@ -200,7 +199,7 @@ public class NetworkManager extends Plugin {
this.success(result, this.connectionCallbackId); this.success(result, this.connectionCallbackId);
// Send to all plugins // Send to all plugins
this.ctx.postMessage("networkconnection", type); webView.postMessage("networkconnection", type);
} }
/** /**
@ -224,7 +223,7 @@ public class NetworkManager extends Plugin {
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) ||

View File

@ -37,330 +37,330 @@ import android.os.Vibrator;
*/ */
public class Notification extends Plugin { public class Notification extends Plugin {
public int confirmResult = -1; public int confirmResult = -1;
public ProgressDialog spinnerDialog = null; public ProgressDialog spinnerDialog = null;
public ProgressDialog progressDialog = null; public ProgressDialog progressDialog = null;
/** /**
* Constructor. * Constructor.
*/ */
public Notification() { public Notification() {
} }
/** /**
* 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 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("beep")) { if (action.equals("beep")) {
this.beep(args.getLong(0)); this.beep(args.getLong(0));
} }
else if (action.equals("vibrate")) { else if (action.equals("vibrate")) {
this.vibrate(args.getLong(0)); this.vibrate(args.getLong(0));
} }
else if (action.equals("alert")) { else if (action.equals("alert")) {
this.alert(args.getString(0),args.getString(1),args.getString(2), callbackId); this.alert(args.getString(0), args.getString(1), args.getString(2), callbackId);
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;
} }
else if (action.equals("confirm")) { else if (action.equals("confirm")) {
this.confirm(args.getString(0),args.getString(1),args.getString(2), callbackId); this.confirm(args.getString(0), args.getString(1), args.getString(2), callbackId);
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;
} }
else if (action.equals("activityStart")) { else if (action.equals("activityStart")) {
this.activityStart(args.getString(0),args.getString(1)); this.activityStart(args.getString(0), args.getString(1));
} }
else if (action.equals("activityStop")) { else if (action.equals("activityStop")) {
this.activityStop(); this.activityStop();
} }
else if (action.equals("progressStart")) { else if (action.equals("progressStart")) {
this.progressStart(args.getString(0),args.getString(1)); this.progressStart(args.getString(0), args.getString(1));
} }
else if (action.equals("progressValue")) { else if (action.equals("progressValue")) {
this.progressValue(args.getInt(0)); this.progressValue(args.getInt(0));
} }
else if (action.equals("progressStop")) { else if (action.equals("progressStop")) {
this.progressStop(); this.progressStop();
} }
return new PluginResult(status, result); return new PluginResult(status, result);
} catch (JSONException e) { } catch (JSONException e) {
return new PluginResult(PluginResult.Status.JSON_EXCEPTION); return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
}
} }
}
/** /**
* 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) {
if (action.equals("alert")) { if (action.equals("alert")) {
return true; 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("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;
}
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// 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.getContext(), 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 * Builds and shows a native Android alert with given Strings
* @param message The message the alert should display * @param message The message the alert should display
* @param title The title of the alert * @param title The title of the alert
* @param buttonLabel The label of the button * @param buttonLabel The label of the button
* @param callbackId The callback id * @param callbackId The callback id
*/ */
public synchronized void alert(final String message, final String title, final String buttonLabel, final String callbackId) { public synchronized void alert(final String message, final String title, final String buttonLabel, final String callbackId) {
final CordovaInterface ctx = this.ctx; final CordovaInterface ctx = this.ctx;
final Notification notification = this; final Notification notification = this;
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
public void run() { public void run() {
AlertDialog.Builder dlg = new AlertDialog.Builder(ctx.getContext()); AlertDialog.Builder dlg = new AlertDialog.Builder(ctx.getActivity());
dlg.setMessage(message); dlg.setMessage(message);
dlg.setTitle(title); dlg.setTitle(title);
dlg.setCancelable(false); dlg.setCancelable(false);
dlg.setPositiveButton(buttonLabel, dlg.setPositiveButton(buttonLabel,
new AlertDialog.OnClickListener() { new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
dialog.dismiss(); dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 0), callbackId); notification.success(new PluginResult(PluginResult.Status.OK, 0), callbackId);
} }
}); });
dlg.create(); dlg.create();
dlg.show(); dlg.show();
}; };
}; };
this.ctx.runOnUiThread(runnable); this.ctx.getActivity().runOnUiThread(runnable);
} }
/** /**
* Builds and shows a native Android confirm dialog with given title, message, buttons. * 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. * 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. * 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 message The message the dialog should display
* @param title The title of the dialog * @param title The title of the dialog
* @param buttonLabels A comma separated list of button labels (Up to 3 buttons) * @param buttonLabels A comma separated list of button labels (Up to 3 buttons)
* @param callbackId The callback id * @param callbackId The callback id
*/ */
public synchronized void confirm(final String message, final String title, String buttonLabels, final String callbackId) { public synchronized void confirm(final String message, final String title, String buttonLabels, final String callbackId) {
final CordovaInterface ctx = this.ctx; final CordovaInterface ctx = this.ctx;
final Notification notification = this; final Notification notification = this;
final String[] fButtons = buttonLabels.split(","); final String[] fButtons = buttonLabels.split(",");
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
public void run() { public void run() {
AlertDialog.Builder dlg = new AlertDialog.Builder(ctx.getContext()); AlertDialog.Builder dlg = new AlertDialog.Builder(ctx.getActivity());
dlg.setMessage(message); dlg.setMessage(message);
dlg.setTitle(title); dlg.setTitle(title);
dlg.setCancelable(false); dlg.setCancelable(false);
// First button // First button
if (fButtons.length > 0) { if (fButtons.length > 0) {
dlg.setNegativeButton(fButtons[0], dlg.setNegativeButton(fButtons[0],
new AlertDialog.OnClickListener() { new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
dialog.dismiss(); dialog.dismiss();
notification.success(new PluginResult(PluginResult.Status.OK, 1), callbackId); 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;
// Second button final CordovaInterface ctx = this.ctx;
if (fButtons.length > 1) { Runnable runnable = new Runnable() {
dlg.setNeutralButton(fButtons[1], public void run() {
new AlertDialog.OnClickListener() { notification.spinnerDialog = ProgressDialog.show(ctx.getActivity(), title, message, true, true,
public void onClick(DialogInterface dialog, int which) { new DialogInterface.OnCancelListener() {
dialog.dismiss(); public void onCancel(DialogInterface dialog) {
notification.success(new PluginResult(PluginResult.Status.OK, 2), callbackId); notification.spinnerDialog = null;
}
});
} }
}); };
this.ctx.getActivity().runOnUiThread(runnable);
}
/**
* Stop spinner.
*/
public synchronized void activityStop() {
if (this.spinnerDialog != null) {
this.spinnerDialog.dismiss();
this.spinnerDialog = null;
} }
}
// Third button /**
if (fButtons.length > 2) { * Show the progress dialog.
dlg.setPositiveButton(fButtons[2], *
new AlertDialog.OnClickListener() { * @param title Title of the dialog
public void onClick(DialogInterface dialog, int which) { * @param message The message of the dialog
dialog.dismiss(); */
notification.success(new PluginResult(PluginResult.Status.OK, 3), callbackId); public synchronized void progressStart(final String title, final String message) {
} if (this.progressDialog != null) {
} this.progressDialog.dismiss();
); this.progressDialog = null;
} }
final Notification notification = this;
dlg.create(); final CordovaInterface ctx = this.ctx;
dlg.show(); Runnable runnable = new Runnable() {
}; public void run() {
}; notification.progressDialog = new ProgressDialog(ctx.getActivity());
this.ctx.runOnUiThread(runnable); notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
} notification.progressDialog.setTitle(title);
notification.progressDialog.setMessage(message);
/** notification.progressDialog.setCancelable(true);
* Show the spinner. notification.progressDialog.setMax(100);
* notification.progressDialog.setProgress(0);
* @param title Title of the dialog notification.progressDialog.setOnCancelListener(
* @param message The message of the dialog new DialogInterface.OnCancelListener() {
*/ public void onCancel(DialogInterface dialog) {
public synchronized void activityStart(final String title, final String message) { notification.progressDialog = null;
if (this.spinnerDialog != null) { }
this.spinnerDialog.dismiss(); });
this.spinnerDialog = null; notification.progressDialog.show();
}
final Notification notification = this;
final CordovaInterface ctx = this.ctx;
Runnable runnable = new Runnable() {
public void run() {
notification.spinnerDialog = ProgressDialog.show(ctx.getContext(), title , message, true, true,
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
notification.spinnerDialog = null;
} }
}); };
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);
} }
};
this.ctx.runOnUiThread(runnable);
}
/**
* Stop spinner.
*/
public synchronized void activityStop() {
if (this.spinnerDialog != null) {
this.spinnerDialog.dismiss();
this.spinnerDialog = null;
} }
}
/** /**
* Show the progress dialog. * Stop progress dialog.
* */
* @param title Title of the dialog public synchronized void progressStop() {
* @param message The message of the dialog if (this.progressDialog != null) {
*/ this.progressDialog.dismiss();
public synchronized void progressStart(final String title, final String message) { this.progressDialog = null;
if (this.progressDialog != null) { }
this.progressDialog.dismiss();
this.progressDialog = null;
} }
final Notification notification = this;
final CordovaInterface ctx = this.ctx;
Runnable runnable = new Runnable() {
public void run() {
notification.progressDialog = new ProgressDialog(ctx.getContext());
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.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

@ -1,62 +0,0 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova;
import java.util.HashSet;
import org.apache.cordova.PreferenceNode;
public class PreferenceSet {
private HashSet<PreferenceNode> innerSet;
public PreferenceSet() {
this.innerSet = new HashSet<PreferenceNode>();
}
public void add(PreferenceNode node) {
this.innerSet.add(node);
}
public int size() {
return this.innerSet.size();
}
public void clear() {
this.innerSet.clear();
}
public String pref(String prefName) {
for (PreferenceNode n : innerSet)
if (prefName.equals(n.name))
return n.value;
return null;
}
public boolean prefMatches(String prefName, String prefValue) {
String value = pref(prefName);
if (value == null) {
return false;
} else {
return value.equals(prefValue);
}
}
}

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

@ -141,7 +141,7 @@ public class Storage extends Plugin {
// If no database path, generate from application package // If no database path, generate from application package
if (this.path == null) { if (this.path == null) {
this.path = this.ctx.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); this.path = this.ctx.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
} }
this.dbName = this.path + File.pathSeparator + db + ".db"; this.dbName = this.path + File.pathSeparator + db + ".db";

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;
@ -51,12 +50,12 @@ public class TempListener extends Plugin implements SensorEventListener {
*/ */
public void setContext(CordovaInterface 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);
} }
/** /**
* 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.
@ -87,7 +86,8 @@ public class TempListener extends Plugin implements SensorEventListener {
// LOCAL METHODS // LOCAL METHODS
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
public void start() { public void start() {
@SuppressWarnings("deprecation")
List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_TEMPERATURE); List<Sensor> list = this.sensorManager.getSensorList(Sensor.TYPE_TEMPERATURE);
if (list.size() > 0) { if (list.size() > 0) {
this.mSensor = list.get(0); this.mSensor = list.get(0);

View File

@ -18,18 +18,8 @@
*/ */
package org.apache.cordova.api; package org.apache.cordova.api;
import java.util.HashMap; import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
/** /**
* The Cordova activity abstract class that is extended by DroidGap. * The Cordova activity abstract class that is extended by DroidGap.
@ -38,107 +28,53 @@ import android.net.Uri;
public interface CordovaInterface { public interface CordovaInterface {
/** /**
* @deprecated * Launch an activity for which you would like a result when it finished. When this activity exits,
* Add services to res/xml/plugins.xml instead.
*
* Add a class that implements a service.
*
* @param serviceType
* @param className
*/
@Deprecated
abstract public void addService(String serviceType, String className);
/**
* Send JavaScript statement back to JavaScript.
*
* @param message
*/
abstract public void sendJavascript(String statement);
/**
* Launch an activity for which you would like a result when it finished. When this activity exits,
* your onActivityResult() method will be called. * your onActivityResult() method will be called.
* *
* @param command The command object * @param command The command object
* @param intent The intent to start * @param intent The intent to start
* @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);
/**
* Launch an activity for which you would not like a result when it finished.
*
* @param intent The intent to start
*/
abstract public void startActivity(Intent intent);
/** /**
* 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);
/** /**
* Load the specified URL in the Cordova webview. * Causes the Activity to override the back button behavior.
* *
* @param url The URL to load. * @param override
*/ */
abstract public void loadUrl(String url);
/**
* Send a message to all plugins.
*
* @param id The message id
* @param data The message data
*/
abstract public void postMessage(String id, Object data);
public abstract Resources getResources();
public abstract String getPackageName();
public abstract Object getSystemService(String service);
public abstract Context getContext();
public abstract Context getBaseContext();
public abstract Intent registerReceiver(BroadcastReceiver receiver,
IntentFilter intentFilter);
public abstract ContentResolver getContentResolver();
public abstract void unregisterReceiver(BroadcastReceiver receiver);
public abstract Cursor managedQuery(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder);
public abstract void runOnUiThread(Runnable runnable);
public abstract AssetManager getAssets();
public abstract void clearCache();
public abstract void clearHistory();
public abstract boolean backHistory();
//public abstract void addWhiteListEntry(String origin, boolean subdomains);
public abstract void bindBackButton(boolean override); public abstract void bindBackButton(boolean override);
/**
* A hook required to check if the Back Button is bound.
*
* @return
*/
public abstract boolean isBackButtonBound(); public abstract boolean isBackButtonBound();
/**
* Get the Android activity.
*
* @return
*/
public abstract Activity getActivity();
@Deprecated
public abstract void cancelLoadUrl(); public abstract void cancelLoadUrl();
public abstract void showWebPage(String url, boolean openExternal, /**
boolean clearHistory, HashMap<String, Object> params); * Called when a message is sent to plugin.
*
public abstract Context getApplicationContext(); * @param id The message id
* @param data The message data
public abstract boolean isUrlWhiteListed(String source); * @return Object or null
*/
public Object onMessage(String id, Object data);
} }

View File

@ -18,9 +18,11 @@
*/ */
package org.apache.cordova.api; package org.apache.cordova.api;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray; import org.json.JSONArray;
//import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.webkit.WebView;
/** /**
* Plugin interface must be implemented by any plugin classes. * Plugin interface must be implemented by any plugin classes.
@ -50,18 +52,18 @@ public interface IPlugin {
/** /**
* 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.
*/ */
void setContext(CordovaInterface ctx); void setContext(CordovaInterface ctx);
/** /**
* Sets the main View of the application, this is the WebView within which * Sets the main View of the application, this is the WebView within which
* a Cordova app runs. * a Cordova app runs.
* *
* @param webView The Cordova WebView * @param webView The Cordova WebView
*/ */
void setView(WebView 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.
@ -92,8 +94,9 @@ public interface IPlugin {
* *
* @param id The message id * @param id The message id
* @param data The message data * @param data The message data
* @return Object to stop propagation or null
*/ */
public void onMessage(String id, Object data); public Object onMessage(String id, Object data);
/** /**
* Called when an activity you launched exits, giving you the requestCode you started it with, * Called when an activity you launched exits, giving you the requestCode you started it with,

View File

@ -18,11 +18,10 @@
*/ */
package org.apache.cordova.api; package org.apache.cordova.api;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import android.content.Intent; import android.content.Intent;
import android.webkit.WebView;
/** /**
* Plugin interface must be implemented by any plugin classes. * Plugin interface must be implemented by any plugin classes.
@ -32,12 +31,12 @@ import android.webkit.WebView;
public abstract class Plugin implements IPlugin { public abstract class Plugin implements IPlugin {
public String id; public String id;
public WebView webView; // WebView object public CordovaWebView webView; // WebView object
public CordovaInterface 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.
@ -66,18 +65,18 @@ public abstract class Plugin implements IPlugin {
} }
/** /**
* Sets the main View of the application, this is the WebView within which * Sets the main View of the application, this is the WebView within which
* a Cordova app runs. * a Cordova app runs.
* *
* @param webView The Cordova WebView * @param webView The Cordova WebView
*/ */
public void setView(WebView webView) { public void setView(CordovaWebView webView) {
this.webView = 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.
* *
* @param multitasking Flag indicating if multitasking is turned on for app * @param multitasking Flag indicating if multitasking is turned on for app
*/ */
public void onPause(boolean multitasking) { public void onPause(boolean multitasking) {
@ -108,8 +107,10 @@ public abstract class Plugin implements IPlugin {
* *
* @param id The message id * @param id The message id
* @param data The message data * @param data The message data
* @return Object to stop propagation or null
*/ */
public void onMessage(String id, Object data) { public Object onMessage(String id, Object data) {
return null;
} }
/** /**
@ -141,7 +142,7 @@ public abstract class Plugin implements IPlugin {
* @param statement * @param statement
*/ */
public void sendJavascript(String statement) { public void sendJavascript(String statement) {
this.ctx.sendJavascript(statement); this.webView.sendJavascript(statement);
} }
/** /**
@ -155,7 +156,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(PluginResult pluginResult, String callbackId) { public void success(PluginResult pluginResult, String callbackId) {
this.ctx.sendJavascript(pluginResult.toSuccessCallbackString(callbackId)); this.webView.sendJavascript(pluginResult.toSuccessCallbackString(callbackId));
} }
/** /**
@ -165,7 +166,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) {
this.ctx.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId));
} }
/** /**
@ -175,7 +176,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(String message, String callbackId) { public void success(String message, String callbackId) {
this.ctx.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId));
} }
/** /**
@ -185,7 +186,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(PluginResult pluginResult, String callbackId) { public void error(PluginResult pluginResult, String callbackId) {
this.ctx.sendJavascript(pluginResult.toErrorCallbackString(callbackId)); this.webView.sendJavascript(pluginResult.toErrorCallbackString(callbackId));
} }
/** /**
@ -195,7 +196,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) {
this.ctx.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId));
} }
/** /**
@ -205,6 +206,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) {
this.ctx.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId));
} }
} }

View File

@ -18,7 +18,10 @@
*/ */
package org.apache.cordova.api; package org.apache.cordova.api;
import android.webkit.WebView; import org.apache.cordova.CordovaWebView;
//import android.content.Context;
//import android.webkit.WebView;
/** /**
* This class represents a service entry object. * This class represents a service entry object.
@ -66,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(WebView webView, CordovaInterface 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();
@ -93,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) {
@ -109,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

@ -23,13 +23,13 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray; 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.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.
@ -44,7 +44,7 @@ public class PluginManager {
private final HashMap<String, PluginEntry> entries = new HashMap<String, PluginEntry>(); private final HashMap<String, PluginEntry> entries = new HashMap<String, PluginEntry>();
private final CordovaInterface ctx; private final CordovaInterface ctx;
private final WebView app; private final CordovaWebView app;
// Flag to track first time through // Flag to track first time through
private boolean firstRun; private boolean firstRun;
@ -59,7 +59,7 @@ public class PluginManager {
* @param app * @param app
* @param ctx * @param ctx
*/ */
public PluginManager(WebView app, CordovaInterface 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;
@ -72,9 +72,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
@ -92,11 +92,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;
@ -167,14 +167,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 CordovaInterface 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) {
@ -192,16 +191,16 @@ public class PluginManager {
// Check the success (OK, NO_RESULT & !KEEP_CALLBACK) // Check the success (OK, NO_RESULT & !KEEP_CALLBACK)
else if ((status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal())) { else if ((status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal())) {
ctx.sendJavascript(cr.toSuccessCallbackString(callbackId)); app.sendJavascript(cr.toSuccessCallbackString(callbackId));
} }
// If error // If error
else { else {
ctx.sendJavascript(cr.toErrorCallbackString(callbackId)); app.sendJavascript(cr.toErrorCallbackString(callbackId));
} }
} catch (Exception e) { } catch (Exception e) {
PluginResult cr = new PluginResult(PluginResult.Status.ERROR, e.getMessage()); PluginResult cr = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
ctx.sendJavascript(cr.toErrorCallbackString(callbackId)); app.sendJavascript(cr.toErrorCallbackString(callbackId));
} }
} }
}); });
@ -226,7 +225,7 @@ public class PluginManager {
if (cr == null) { if (cr == null) {
cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION); cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
} }
ctx.sendJavascript(cr.toErrorCallbackString(callbackId)); app.sendJavascript(cr.toErrorCallbackString(callbackId));
} }
return (cr != null ? cr.getJSONString() : "{ status: 0, message: 'all good' }"); return (cr != null ? cr.getJSONString() : "{ status: 0, message: 'all good' }");
} }
@ -240,7 +239,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;
} }
@ -315,13 +314,22 @@ public class PluginManager {
* *
* @param id The message id * @param id The message id
* @param data The message data * @param data The message data
* @return
*/ */
public void postMessage(String id, Object data) { public Object postMessage(String id, Object data) {
Object obj = this.ctx.onMessage(id, data);
if (obj != null) {
return obj;
}
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); obj = entry.plugin.onMessage(id, data);
if (obj != null) {
return obj;
}
} }
} }
return null;
} }
/** /**

View File

@ -25,12 +25,13 @@ 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) { public PluginResult(Status status) {
this.status = status.ordinal(); this.status = status.ordinal();
this.message = "'" + PluginResult.StatusMessages[this.status] + "'"; this.message = "'" + PluginResult.StatusMessages[this.status] + "'";
} }
public PluginResult(Status status, String message) { public PluginResult(Status status, String message) {
this.status = status.ordinal(); this.status = status.ordinal();
this.message = JSONObject.quote(message); this.message = JSONObject.quote(message);
@ -60,11 +61,11 @@ public class PluginResult {
this.status = status.ordinal(); this.status = status.ordinal();
this.message = ""+b; this.message = ""+b;
} }
public void setKeepCallback(boolean b) { public void setKeepCallback(boolean b) {
this.keepCallback = b; this.keepCallback = b;
} }
public int getStatus() { public int getStatus() {
return status; return status;
} }
@ -72,23 +73,23 @@ public class PluginResult {
public String getMessage() { public String getMessage() {
return message; return message;
} }
public boolean getKeepCallback() { public boolean getKeepCallback() {
return this.keepCallback; return this.keepCallback;
} }
public String getJSONString() { public String getJSONString() {
return "{\"status\":" + this.status + ",\"message\":" + this.message + ",\"keepCallback\":" + this.keepCallback + "}"; return "{\"status\":" + this.status + ",\"message\":" + this.message + ",\"keepCallback\":" + this.keepCallback + "}";
} }
public String toSuccessCallbackString(String callbackId) { public String toSuccessCallbackString(String callbackId) {
return "cordova.callbackSuccess('"+callbackId+"',"+this.getJSONString()+");"; return "cordova.callbackSuccess('"+callbackId+"',"+this.getJSONString()+");";
} }
public String toErrorCallbackString(String callbackId) { public String toErrorCallbackString(String callbackId) {
return "cordova.callbackError('"+callbackId+"', " + this.getJSONString()+ ");"; return "cordova.callbackError('"+callbackId+"', " + this.getJSONString()+ ");";
} }
public static String[] StatusMessages = new String[] { public static String[] StatusMessages = new String[] {
"No result", "No result",
"OK", "OK",
@ -101,7 +102,7 @@ public class PluginResult {
"JSON error", "JSON error",
"Error" "Error"
}; };
public enum Status { public enum Status {
NO_RESULT, NO_RESULT,
OK, OK,

View File

@ -0,0 +1,29 @@
# Cordova Upgrade Guide #
This document is for people who need to upgrade their Cordova versions from an older version to a current version of Cordova.
- To upgrade to 1.8.0, please go from 1.7.0
- To upgrade from 1.7.0, please go from 1.6.0
## Upgrade to 1.8.0 from 1.7.0 ##
1. Remove cordova-1.7.0.jar from the libs directory in your project
2. Add cordova-1.8.0.jar to the libs directory in your project
3. If you are using Eclipse, please refresh your eclipse project and do a clean
4. Copy the new cordova-1.7.0.js into your project
5. Update your HTML to sue the new cordova-1.7.0.js file
6. Update the res/xml/plugins.xml to be the same as the one found in framework/res/xml/plugins.xml
## Upgrade to 1.7.0 from 1.6.0 ##
1. Remove cordova-1.6.0.jar from the libs directory in your project
2. Add cordova-1.6.0.jar to the libs directory in your project
3. If you are using Eclipse, please refresh your eclipse project and do a clean
4. Copy the new cordova-1.6.0.js into your project
5. Update your HTML to sue the new cordova-1.6.0.js file
6. Update the res/xml/plugins.xml to be the same as the one found in framework/res/xml/plugins.xml

View File

@ -0,0 +1,53 @@
# How to use Cordova as a component #
Beginning in Cordova 1.8, with the assistance of the CordovaActivity, you can use Cordova as a component in your Android applications. This component is known in Android
as the CordovaWebView, and new Cordova-based applications from 1.8 and greater will be using the CordovaWebView as its main view, whether the legacy DroidGap approach is
used or not.
The pre-requisites are the same as the pre-requisites for Android application development. It is assumed that you are familiar with Android Development. If not, please
look at the Getting Started guide to developing an Cordova Application and start there before continuing with this approach. Since this is not the main method that people use
to run applications, the instructions are currently manual. In the future, we may try to further automate the project generation.
## Pre-requisites ##
1. **Cordova 1.8** or greater downloaded
2. Android SDK updated with 15
## Guide to using CordovaWebView in an Android Project ##
1. Use bin/create to fetch the commons-codec-1.6.jar
2. Go into framework and run ant jar to build the cordova jar (currently cordova-1.8.jar at the time of writing)
3. Copy the cordova jar into your Android project libs directory
4. Edit your main.xml to look similar the following. The layout_height, layout_width and ID can be modified to suit your application:
` <org.apache.cordova.CordovaWebView$
android:id="@+id/tutorialView"$
android:layout_width="match_parent"$
android:layout_height="match_parent" />$
`
5. Modify your activity so that it implements the CordovaInterface. It is recommended that you implement the methods that are included. You may wish to copy the methods from framework/src/org/apache/cordova/DroidGap.java, or you may wish to implement your own methods. Below is a fragment of code from a basic application that uses the interface:
`
public class CordovaViewTestActivity extends Activity implements CordovaInterface {$
CordovaWebView phoneGap;$
$
/** Called when the activity is first created. */$
@Override$
public void onCreate(Bundle savedInstanceState) {$
super.onCreate(savedInstanceState);$
setContentView(R.layout.main);$
$
phoneGap = (CordovaWebView) findViewById(R.id.phoneGapView);$
$
phoneGap.loadUrl("file:///android_asset/www/index.html");$
}$
`
6. Copy the HTML and Javascript used to the assets directory of your Android project
7. Copy cordova.xml and plugins.xml from framework/res/xml to the framework/res/xml in your project

0
test/.classpath Executable file → Normal file
View File

2
test/.project Executable file → Normal file
View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<projectDescription> <projectDescription>
<name>CordovaTest</name> <name>PhoneGapViewTestActivity</name>
<comment></comment> <comment></comment>
<projects> <projects>
</projects> </projects>

View File

@ -20,20 +20,20 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan" <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="org.apache.cordova.test" android:versionName="1.1" android:versionCode="5"> package="org.apache.cordova.test" android:versionName="1.1" android:versionCode="5">
<supports-screens <supports-screens
android:largeScreens="true" android:largeScreens="true"
android:normalScreens="true" android:normalScreens="true"
android:smallScreens="true" android:smallScreens="true"
android:xlargeScreens="true" android:xlargeScreens="true"
android:resizeable="true" android:resizeable="true"
android:anyDensity="true" android:anyDensity="true"
/> />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/> <uses-permission android:name="android.permission.RECORD_VIDEO"/>
@ -44,21 +44,66 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-sdk android:minSdkVersion="7" />
<uses-feature android:name="android.hardware.camera" /> <instrumentation
<uses-feature android:name="android.hardware.camera.autofocus" /> android:name="android.test.InstrumentationTestRunner"
android:targetPackage="org.apache.cordova.test" />
<application android:icon="@drawable/icon" android:label="@string/app_name" <application
android:debuggable="true"> android:icon="@drawable/icon"
<activity android:name="tests" android:label="@string/app_name" android:label="@string/app_name" >
android:configChanges="orientation|keyboardHidden"> <uses-library android:name="android.test.runner" />
<intent-filter> <activity
<action android:name="android.intent.action.MAIN" /> android:windowSoftInputMode="adjustPan"
<category android:name="android.intent.category.LAUNCHER" /> android:label="@string/app_name"
</intent-filter> android:configChanges="orientation|keyboardHidden"
android:name=".CordovaWebViewTestActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="tests" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".JailActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".CordovaDriverAction" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<activity
android:windowSoftInputMode="adjustPan"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"
android:name=".CordovaActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity> </activity>
<activity android:name="splashscreen" android:label="@string/app_name" <activity android:name="splashscreen" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"> android:configChanges="orientation|keyboardHidden">
</activity> </activity>
<activity android:name="timeout" android:label="@string/app_name" <activity android:name="timeout" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"> android:configChanges="orientation|keyboardHidden">
@ -99,7 +144,14 @@
<activity android:name="xhr" android:label="@string/app_name" <activity android:name="xhr" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden"> android:configChanges="orientation|keyboardHidden">
</activity> </activity>
<activity android:name="basicauth" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
</activity>
<activity android:name="fullscreen" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
</activity>
<activity android:name="backgroundcolor" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
</activity>
</application> </application>
<uses-sdk android:minSdkVersion="5" />
</manifest> </manifest>

View File

@ -1,23 +1,30 @@
## Android Native Tests ## # Android Native Tests #
These tests are designed to verify Android native features and other Android specific features. These tests are designed to verify Android native features and other Android specific features.
## Initial Setup ##
Before running the tests, they need to be set up. Before running the tests, they need to be set up.
1. Copy the version of cordova-x.y.z.js into assets/www directory 0. Copy cordova-x.y.z.jar into libs directory
2. Edit assets/www/cordova.js to reference the correct version
3. Copy cordova-x.y.z.jar into libs directory
To run from command line: To run from command line:
4. Build by entering "ant debug install" 0. Build by entering `ant debug install`
5. Run tests by clicking on "CordovaTest" icon on device 0. Run tests by clicking on "CordovaTest" icon on device
To run from Eclipse: To run from Eclipse:
4. Import Android project into Eclipse 0. Import Android project into Eclipse
5. Ensure Project properties "Java Build Path" includes the lib/cordova-x.y.z.jar 0. Ensure Project properties "Java Build Path" includes the lib/cordova-x.y.z.jar
6. Create run configuration if not already created 0. Create run configuration if not already created
7. Run tests 0. Run tests
## Automatic Runs ##
Once you have installed the test, you can launch and run the tests
automatically with the below command:
adb shell am instrument -w org.apache.cordova.test/android.test.InstrumentationTestRunner
(Optionally, you can also run in Eclipse)

View File

@ -0,0 +1,41 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320; user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Background Color Test</h1>
<div id="info">
<h4>Platform: <span id="platform"> &nbsp;</span>, Version: <span id="version">&nbsp;</span></h4>
<h4>UUID: <span id="uuid"> &nbsp;</span>, Name: <span id="name">&nbsp;</span></h4>
<h4>Width: <span id="width"> &nbsp;</span>, Height: <span id="height">&nbsp;
</span>, Color Depth: <span id="colorDepth"></span></h4>
</div>
<div id="info">
Before this page was show, you should have seen the background flash green.</br>
</div>
</body>
</html>

View File

@ -0,0 +1,42 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320; user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Basic Auth</h1>
<div id="info">
<h4>Platform: <span id="platform"> &nbsp;</span>, Version: <span id="version">&nbsp;</span></h4>
<h4>UUID: <span id="uuid"> &nbsp;</span>, Name: <span id="name">&nbsp;</span></h4>
<h4>Width: <span id="width"> &nbsp;</span>, Height: <span id="height">&nbsp;
</span>, Color Depth: <span id="colorDepth"></span></h4>
</div>
<div id="info">
Loading link below should be successful and show page indicating username=test & password=test. <br>
</div>
<a href="http://browserspy.dk/password-ok.php" class="btn large">Test password</a>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320; user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Cordova Tests</title>
<link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title">
<script type="text/javascript" charset="utf-8" src="../cordova.js"></script>
<script type="text/javascript" charset="utf-8" src="../main.js"></script>
</head>
<body onload="init();" id="stage" class="theme">
<h1>Full Screen Test</h1>
<div id="info">
<h4>Platform: <span id="platform"> &nbsp;</span>, Version: <span id="version">&nbsp;</span></h4>
<h4>UUID: <span id="uuid"> &nbsp;</span>, Name: <span id="name">&nbsp;</span></h4>
<h4>Width: <span id="width"> &nbsp;</span>, Height: <span id="height">&nbsp;
</span>, Color Depth: <span id="colorDepth"></span></h4>
</div>
<div id="info">
The app should take over the entire screen. <br>
The top Android status bar should not be shown.
</div>
</body>
</html>

View File

@ -1,20 +1,20 @@
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one$ Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file$ or more contributor license agreements. See the NOTICE file
distributed with this work for additional information$ distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file$ regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the$ to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance$ "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at$ with the License. You may obtain a copy of the License at
$
http://www.apache.org/licenses/LICENSE-2.0$ http://www.apache.org/licenses/LICENSE-2.0
$
Unless required by applicable law or agreed to in writing,$ Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an$ software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY$ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the$ KIND, either express or implied. See the License for the
specific language governing permissions and limitations$ specific language governing permissions and limitations
under the License.$ under the License.
--> -->
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
@ -49,7 +49,10 @@ $
</div> </div>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.jqmtabbackbutton');">Backbutton jQM tab</button> <button class="btn large" onclick="startActivity('org.apache.cordova.test.jqmtabbackbutton');">Backbutton jQM tab</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.backbuttonmultipage');">Backbutton with multiple pages</button> <button class="btn large" onclick="startActivity('org.apache.cordova.test.backbuttonmultipage');">Backbutton with multiple pages</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.backgroundcolor');">Background Color</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.basicauth');">Basic Authentication</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.errorurl');">Error URL</button> <button class="btn large" onclick="startActivity('org.apache.cordova.test.errorurl');">Error URL</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.fullscreen');">Full Screen</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.htmlnotfound');">HTML not found</button> <button class="btn large" onclick="startActivity('org.apache.cordova.test.htmlnotfound');">HTML not found</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.iframe');">IFrame</button> <button class="btn large" onclick="startActivity('org.apache.cordova.test.iframe');">IFrame</button>
<button class="btn large" onclick="startActivity('org.apache.cordova.test.lifecycle');">Lifecycle</button> <button class="btn large" onclick="startActivity('org.apache.cordova.test.lifecycle');">Lifecycle</button>

40
test/proguard.cfg Normal file
View File

@ -0,0 +1,40 @@
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

2
test/project.properties Executable file → Normal file
View File

@ -8,4 +8,4 @@
# project structure. # project structure.
# Project target. # Project target.
target=Google Inc.:Google APIs:14 target=Google Inc.:Google APIs:15

16
test/res/layout/main.xml Executable file → Normal file
View File

@ -18,14 +18,14 @@
under the License. under the License.
--> -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
> android:orientation="vertical" >
<TextView
android:layout_width="fill_parent" <org.apache.cordova.CordovaWebView
android:layout_height="wrap_content" android:id="@+id/phoneGapView"
android:text="Hello World, tests" android:layout_width="fill_parent"
/> android:layout_height="fill_parent" />
</LinearLayout>
</LinearLayout>

2
test/res/values/strings.xml Executable file → Normal file
View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">CordovaTests</string> <string name="app_name">CordovaTests</string>
</resources> </resources>

View File

@ -18,19 +18,19 @@
under the License. under the License.
--> -->
<cordova> <cordova>
<!-- <!--
access elements control the Android whitelist. access elements control the Android whitelist.
Domains are assumed blocked unless set otherwise Domains are assumed blocked unless set otherwise
--> -->
<access origin="http://127.0.0.1*"/> <!-- allow local pages --> <access origin="http://127.0.0.1*"/> <!-- allow local pages -->
<!-- <access origin="https://example.com" /> allow any secure requests to example.com --> <!-- <access origin="https://example.com" /> allow any secure requests to example.com -->
<!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www --> <!-- <access origin="https://example.com" subdomains="true" /> such as above, but including subdomains, such as www -->
<!-- <access origin=".*"/> Allow all domains, suggested development use only --> <!-- <access origin=".*"/> Allow all domains, suggested development use only -->
<log level="DEBUG"/> <log level="DEBUG"/>
<preference name="classicRender" value="true" /> <preference name="useBrowserHistory" value="true" />
</cordova> </cordova>

0
test/res/xml/plugins.xml Executable file → Normal file
View File

View File

@ -69,9 +69,9 @@ public class ActivityPlugin extends Plugin {
public void startActivity(String className) { public void startActivity(String className) {
try { try {
Intent intent = new Intent().setClass(this.ctx.getContext(), Class.forName(className)); Intent intent = new Intent().setClass(this.ctx.getActivity(), Class.forName(className));
LOG.d(TAG, "Starting activity %s", className); LOG.d(TAG, "Starting activity %s", className);
this.ctx.startActivity(intent); this.ctx.getActivity().startActivity(intent);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
LOG.e(TAG, "Error starting activity %s", className); LOG.e(TAG, "Error starting activity %s", className);

View File

@ -16,19 +16,18 @@
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
*/ */
package org.apache.cordova; package org.apache.cordova.test;
// represents the <preference> element from the W3C config.xml spec import org.apache.cordova.DroidGap;
// see http://www.w3.org/TR/widgets/#the-preference-element-and-its-attributes
public class PreferenceNode {
public String name;
public String value;
public boolean readonly;
// constructor import android.app.Activity;
public PreferenceNode(String name, String value, boolean readonly) { import android.os.Bundle;
this.name = name;
this.value = value; public class CordovaActivity extends DroidGap {
this.readonly = readonly; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.loadUrl("file:///android_asset/www/index.html");
} }
} }

View File

@ -0,0 +1,68 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import com.phonegap.api.PluginManager;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class CordovaActivityTest extends ActivityInstrumentationTestCase2<CordovaActivity> {
private CordovaActivity testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private CordovaWebView testView;
@SuppressWarnings("deprecation")
public CordovaActivityTest()
{
super("org.apache.cordova.test",CordovaActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = (CordovaWebView) innerContainer.getChildAt(0);
}
public void testPreconditions(){
assertNotNull(innerContainer);
assertNotNull(testView);
}
public void testForCordovaView() {
String className = testView.getClass().getSimpleName();
assertTrue(className.equals("CordovaWebView"));
}
public void testForLinearLayout() {
String className = innerContainer.getClass().getSimpleName();
assertTrue(className.equals("LinearLayoutSoftKeyboardDetect"));
}
}

View File

@ -0,0 +1,109 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import com.phonegap.api.PluginManager;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
public class CordovaTest extends
ActivityInstrumentationTestCase2<CordovaWebViewTestActivity> {
private static final long TIMEOUT = 1000;
private CordovaWebViewTestActivity testActivity;
private View testView;
private String rString;
public CordovaTest() {
super("com.phonegap.test.activities", CordovaWebViewTestActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
testActivity = this.getActivity();
testView = testActivity.findViewById(R.id.phoneGapView);
}
public void testPreconditions() {
assertNotNull(testView);
}
public void testForCordovaView() {
String className = testView.getClass().getSimpleName();
assertTrue(className.equals("CordovaWebView"));
}
/*
public void testForPluginManager() {
CordovaWebView v = (CordovaWebView) testView;
PluginManager p = v.getPluginManager();
assertNotNull(p);
String className = p.getClass().getSimpleName();
assertTrue(className.equals("PluginManager"));
}
public void testBackButton() {
CordovaWebView v = (CordovaWebView) testView;
assertFalse(v.checkBackKey());
}
public void testLoadUrl() {
CordovaWebView v = (CordovaWebView) testView;
v.loadUrlIntoView("file:///android_asset/www/index.html");
sleep();
String url = v.getUrl();
boolean result = url.equals("file:///android_asset/www/index.html");
assertTrue(result);
int visible = v.getVisibility();
assertTrue(visible == View.VISIBLE);
}
public void testBackHistoryFalse() {
CordovaWebView v = (CordovaWebView) testView;
// Move back in the history
boolean test = v.backHistory();
assertFalse(test);
}
// Make sure that we can go back
public void testBackHistoryTrue() {
this.testLoadUrl();
CordovaWebView v = (CordovaWebView) testView;
v.loadUrlIntoView("file:///android_asset/www/compass/index.html");
sleep();
String url = v.getUrl();
assertTrue(url.equals("file:///android_asset/www/compass/index.html"));
// Move back in the history
boolean test = v.backHistory();
assertTrue(test);
sleep();
url = v.getUrl();
assertTrue(url.equals("file:///android_asset/www/index.html"));
}
*/
private void sleep() {
try {
Thread.sleep(TIMEOUT);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@ -0,0 +1,96 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.IPlugin;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class CordovaWebViewTestActivity extends Activity implements CordovaInterface {
CordovaWebView phoneGap;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
phoneGap = (CordovaWebView) findViewById(R.id.phoneGapView);
phoneGap.loadUrl("file:///android_asset/www/index.html");
}
public void onDestroy()
{
super.onDestroy();
if (phoneGap.pluginManager != null) {
phoneGap.pluginManager.onDestroy();
}
}
@Override
public void startActivityForResult(IPlugin command, Intent intent, int requestCode) {
// TODO Auto-generated method stub
}
@Override
public void setActivityResultCallback(IPlugin plugin) {
// TODO Auto-generated method stub
}
@Override
public void bindBackButton(boolean override) {
// TODO Auto-generated method stub
}
@Override
public boolean isBackButtonBound() {
// TODO Auto-generated method stub
return false;
}
@Override
public Activity getActivity() {
// TODO Auto-generated method stub
return this;
}
@Override
public void cancelLoadUrl() {
// TODO Auto-generated method stub
}
@Override
public Object onMessage(String id, Object data) {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -0,0 +1,54 @@
package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class ErrorUrlTest extends ActivityInstrumentationTestCase2<errorurl> {
private int TIMEOUT = 1000;
errorurl testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private CordovaWebView testView;
public ErrorUrlTest() {
super("org.apache.cordova.test",errorurl.class);
}
protected void setUp() throws Exception {
super.setUp();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = (CordovaWebView) innerContainer.getChildAt(0);
}
public void testPreconditions(){
assertNotNull(innerContainer);
assertNotNull(testView);
}
public void testUrl()
{
sleep();
String good_url = "file:///android_asset/www/htmlnotfound/error.html";
String url = testView.getUrl();
assertNotNull(url);
assertTrue(url.equals(good_url));
}
private void sleep() {
try {
Thread.sleep(TIMEOUT);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@ -0,0 +1,67 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaChromeClient;
import org.apache.cordova.api.PluginManager;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class GapClientTest extends ActivityInstrumentationTestCase2<CordovaWebViewTestActivity> {
private CordovaWebViewTestActivity testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private View testView;
private String rString;
private CordovaChromeClient appCode;
public GapClientTest() {
super("com.phonegap.test.activities",CordovaWebViewTestActivity.class);
}
protected void setUp() throws Exception{
super.setUp();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = innerContainer.getChildAt(0);
}
public void testPreconditions(){
assertNotNull(innerContainer);
assertNotNull(testView);
}
public void testForCordovaView() {
String className = testView.getClass().getSimpleName();
assertTrue(className.equals("CordovaWebView"));
}
}

View File

@ -0,0 +1,52 @@
package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class HtmlNotFoundTest extends ActivityInstrumentationTestCase2<htmlnotfound> {
private int TIMEOUT = 1000;
private htmlnotfound testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private CordovaWebView testView;
public HtmlNotFoundTest() {
super("org.apache.cordova.test",htmlnotfound.class);
}
protected void setUp() throws Exception {
super.setUp();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = (CordovaWebView) innerContainer.getChildAt(0);
}
public void testPreconditions(){
assertNotNull(innerContainer);
assertNotNull(testView);
}
public void testUrl()
{
sleep();
String good_url = "file:///android_asset/www/htmlnotfound/error.html";
String url = testView.getUrl();
assertNotNull(url);
assertFalse(url.equals(good_url));
}
private void sleep() {
try {
Thread.sleep(TIMEOUT);
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@ -0,0 +1,11 @@
package org.apache.cordova.test;
import android.test.ActivityInstrumentationTestCase2;
public class IFrameTest extends ActivityInstrumentationTestCase2<iframe> {
public IFrameTest() {
super("org.apache.cordova.test",iframe.class);
}
}

View File

@ -0,0 +1,12 @@
package org.apache.cordova.test;
import android.test.ActivityInstrumentationTestCase2;
public class JQMTabTest extends ActivityInstrumentationTestCase2<jqmtabbackbutton> {
public JQMTabTest(Class<jqmtabbackbutton> activityClass) {
super(activityClass);
// TODO Auto-generated constructor stub
}
}

View File

@ -0,0 +1,11 @@
package org.apache.cordova.test;
import android.test.ActivityInstrumentationTestCase2;
public class LifecycleTest extends ActivityInstrumentationTestCase2<lifecycle> {
public LifecycleTest()
{
super("org.apache.cordova.test",lifecycle.class);
}
}

View File

@ -0,0 +1,50 @@
package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class LoadTimeoutTest extends ActivityInstrumentationTestCase2<loading> {
private loading testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private CordovaWebView testView;
private long TIMEOUT = 1000;
public LoadTimeoutTest()
{
super("org.apache.cordova.test",loading.class);
}
protected void setUp() throws Exception {
super.setUp();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = (CordovaWebView) innerContainer.getChildAt(0);
}
public void testPreconditions(){
assertNotNull(innerContainer);
assertNotNull(testView);
}
public void testUrl()
{
sleep();
String good_url = "http://www.google.com";
String url = testView.getUrl();
assertNotNull(url);
assertFalse(url.equals(good_url));
}
private void sleep() {
try {
Thread.sleep(TIMEOUT );
} catch (InterruptedException e) {
fail("Unexpected Timeout");
}
}
}

View File

@ -0,0 +1,69 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import com.phonegap.api.PluginManager;
import android.test.ActivityInstrumentationTestCase2;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class PluginManagerTest extends ActivityInstrumentationTestCase2<CordovaWebViewTestActivity> {
private CordovaWebViewTestActivity testActivity;
private FrameLayout containerView;
private LinearLayout innerContainer;
private View testView;
private String rString;
private PluginManager pMan;
public PluginManagerTest() {
super("com.phonegap.test.activities",CordovaWebViewTestActivity.class);
}
protected void setUp() throws Exception{
super.setUp();
testActivity = this.getActivity();
containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
innerContainer = (LinearLayout) containerView.getChildAt(0);
testView = innerContainer.getChildAt(0);
}
public void testPreconditions(){
assertNotNull(innerContainer);
assertNotNull(testView);
}
public void testForPluginManager() {
/*
CordovaWebView v = (CordovaWebView) testView;
pMan = v.getPluginManager();
assertNotNull(pMan);
String className = pMan.getClass().getSimpleName();
assertTrue(className.equals("PluginManager"));
*/
}
}

View File

@ -0,0 +1,27 @@
package org.apache.cordova.test;
import org.apache.cordova.CordovaWebView;
import android.app.Dialog;
import android.test.ActivityInstrumentationTestCase2;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class SplashscreenTest extends ActivityInstrumentationTestCase2<splashscreen> {
private splashscreen testActivity;
private Dialog containerView;
public SplashscreenTest()
{
super("org.apache.cordova.test",splashscreen.class);
}
protected void setUp() throws Exception {
super.setUp();
testActivity = this.getActivity();
//containerView = (FrameLayout) testActivity.findViewById(android.R.id.content);
//containerView = (Dialog) testActivity.findViewById(id);
}
}

View File

@ -0,0 +1,11 @@
package org.apache.cordova.test;
import android.test.ActivityInstrumentationTestCase2;
public class UserWebViewTest extends ActivityInstrumentationTestCase2<userwebview> {
public UserWebViewTest ()
{
super(userwebview.class);
}
}

View File

@ -0,0 +1,12 @@
package org.apache.cordova.test;
import android.test.ActivityInstrumentationTestCase2;
public class WhitelistTest extends ActivityInstrumentationTestCase2<whitelist> {
public WhitelistTest()
{
super(whitelist.class);
}
}

View File

@ -0,0 +1,11 @@
package org.apache.cordova.test;
import android.test.ActivityInstrumentationTestCase2;
public class XhrTest extends ActivityInstrumentationTestCase2<xhr> {
public XhrTest()
{
super(xhr.class);
}
}

View File

@ -19,7 +19,6 @@
package org.apache.cordova.test; package org.apache.cordova.test;
import android.os.Bundle; import android.os.Bundle;
import android.webkit.WebView;
import org.apache.cordova.*; import org.apache.cordova.*;

View File

@ -0,0 +1,40 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import android.graphics.Color;
import android.os.Bundle;
import org.apache.cordova.*;
public class backgroundcolor extends DroidGap {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Properties must be set before init() is called, since some are processed during init().
// backgroundColor can also be set in cordova.xml, but you must use the number equivalent of the color. For example, Color.RED is
// <preference name="backgroundColor" value="-65536" />
super.setIntegerProperty("backgroundColor", Color.GREEN);
super.init();
super.loadUrl("file:///android_asset/www/backgroundcolor/index.html");
}
}

View File

@ -0,0 +1,43 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import android.os.Bundle;
import org.apache.cordova.*;
public class basicauth extends DroidGap {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.init();
// LogCat: onReceivedHttpAuthRequest(browserspy.dk:80,BrowserSpy.dk - HTTP Password Test)
AuthenticationToken token = new AuthenticationToken();
token.setUserName("test");
token.setPassword("test");
super.setAuthenticationToken(token, "browserspy.dk:80", "BrowserSpy.dk - HTTP Password Test");
// Add web site to whitelist
super.appView.addWhiteListEntry("http://browserspy.dk*", true);
// Load test
super.loadUrl("file:///android_asset/www/basicauth/index.html");
}
}

View File

@ -29,4 +29,6 @@ public class errorurl extends DroidGap {
this.setStringProperty("errorUrl", "file:///android_asset/www/htmlnotfound/error.html"); this.setStringProperty("errorUrl", "file:///android_asset/www/htmlnotfound/error.html");
super.loadUrl("file:///android_asset/www/htmlnotfound/index.html"); super.loadUrl("file:///android_asset/www/htmlnotfound/index.html");
} }
} }

View File

@ -0,0 +1,39 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
package org.apache.cordova.test;
import android.os.Bundle;
import org.apache.cordova.*;
public class fullscreen extends DroidGap {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Properties must be set before init() is called, since some are processed during init().
// fullscreen can also be set in cordova.xml. For example,
// <preference name="fullscreen" value="true" />
super.setBooleanProperty("fullscreen", true);
super.init();
super.loadUrl("file:///android_asset/www/fullscreen/index.html");
}
}

View File

@ -26,7 +26,7 @@ public class tests extends DroidGap {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
super.init(); super.init();
super.pluginManager.addService("Activity", "org.apache.cordova.test.ActivityPlugin"); //super.pluginManager.addService("Activity", "org.apache.cordova.test.ActivityPlugin");
super.loadUrl("file:///android_asset/www/index.html"); super.loadUrl("file:///android_asset/www/index.html");
} }
} }

View File

@ -29,7 +29,7 @@ public class userwebview extends DroidGap {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
super.init(new WebView(this), new TestViewClient(this), new TestChromeClient(this)); super.init(new CordovaWebView(this), new TestViewClient(this), new TestChromeClient(this));
super.loadUrl("file:///android_asset/www/userwebview/index.html"); super.loadUrl("file:///android_asset/www/userwebview/index.html");
} }

View File

@ -28,7 +28,7 @@ public class whitelist extends DroidGap {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
super.init(new WebView(this), new TestViewClient(this), new CordovaChromeClient(this)); super.init(new CordovaWebView(this), new TestViewClient(this), new CordovaChromeClient(this));
super.loadUrl("file:///android_asset/www/whitelist/index.html"); super.loadUrl("file:///android_asset/www/whitelist/index.html");
} }