Fixing FileUtils change. We are using contexts now, not CordovaInterfaces. CordovaInterface is a SHOULD, not a MUST

This commit is contained in:
Joe Bowser 2012-05-15 08:55:42 -07:00
commit 79048a5a84
38 changed files with 5495 additions and 5487 deletions

View File

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

View File

@ -27,7 +27,6 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.hardware.Sensor; import android.hardware.Sensor;
import android.hardware.SensorEvent; import android.hardware.SensorEvent;
import android.hardware.SensorEventListener; import android.hardware.SensorEventListener;
@ -73,8 +72,9 @@ 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(Context ctx) { public void setContext(CordovaInterface ctx) {
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE); super.setContext(ctx);
this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE);
} }
/** /**

View File

@ -25,11 +25,6 @@ import org.apache.cordova.api.PluginResult;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.webkit.WebView;
import android.app.Activity;
import android.view.View;
import java.util.HashMap; import java.util.HashMap;
/** /**
@ -53,11 +48,10 @@ public class App extends Plugin {
if (action.equals("clearCache")) { if (action.equals("clearCache")) {
this.clearCache(); this.clearCache();
} }
else if (action.equals("show")) { else if (action.equals("show")) { // TODO @bc - Not in master branch. When should this be called?
final CordovaWebView wv = this.webView; ctx.getActivity().runOnUiThread(new Runnable() {
((Activity)this.ctx).runOnUiThread(new Runnable() {
public void run() { public void run() {
wv.setVisibility(View.VISIBLE); webView.postMessage("spinner", "stop");
} }
}); });
} }
@ -97,7 +91,7 @@ public class App extends Plugin {
* Clear the resource cache. * Clear the resource cache.
*/ */
public void clearCache() { public void clearCache() {
webView.clearCache(true); this.webView.clearCache(true);
} }
/** /**
@ -157,21 +151,22 @@ public class App extends Plugin {
e.printStackTrace(); e.printStackTrace();
} }
} }
webView.showWebPage(url, openExternal, clearHistory, params); this.webView.showWebPage(url, openExternal, clearHistory, params);
} }
/** /**
* Cancel loadUrl before it has been loaded (Only works on a CordovaInterface class) * 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() {
webView.clearHistory(); this.webView.clearHistory();
} }
/** /**
@ -179,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() {
webView.backHistory(); this.webView.backHistory();
} }
/** /**
@ -189,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);
} }
/** /**
@ -199,14 +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

@ -22,14 +22,12 @@ import android.content.Context;
import android.media.AudioManager; import android.media.AudioManager;
import java.util.ArrayList; import java.util.ArrayList;
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;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map.Entry;
/** /**
* This class called by CordovaActivity to play and record audio. * This class called by CordovaActivity to play and record audio.
@ -142,8 +140,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")) {
@ -169,6 +168,7 @@ public class AudioHandler extends Plugin {
this.pausedForPhone.clear(); this.pausedForPhone.clear();
} }
} }
return null;
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -316,8 +316,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);
} }
@ -334,8 +335,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

@ -60,9 +60,9 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
// Media error codes // Media error codes
private static int MEDIA_ERR_NONE_ACTIVE = 0; private static int MEDIA_ERR_NONE_ACTIVE = 0;
private static int MEDIA_ERR_ABORTED = 1; private static int MEDIA_ERR_ABORTED = 1;
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 AudioHandler handler; // The AudioHandler object
private String id; // The id of this player (used to identify Media object in JavaScript) private String id; // The id of this player (used to identify Media object in JavaScript)
@ -169,8 +169,7 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
this.setState(MEDIA_STOPPED); this.setState(MEDIA_STOPPED);
} }
this.moveFile(this.audioFile); this.moveFile(this.audioFile);
} } catch (Exception e) {
catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -213,7 +212,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.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 {
@ -233,8 +232,7 @@ 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 + "});");
} }

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;
@ -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

@ -25,11 +25,8 @@ import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.net.URLEncoder;
import java.util.LinkedList; import java.util.LinkedList;
import android.util.Log;
/** /**
* This class provides a way for Java to run JavaScript in the web page that has loaded Cordova. * This class provides a way for Java to run JavaScript in the web page that has loaded Cordova.
* The CallbackServer class implements an XHR server and a polling server with a list of JavaScript * The CallbackServer class implements an XHR server and a polling server with a list of JavaScript
@ -56,6 +53,7 @@ import android.util.Log;
*/ */
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";
/** /**
@ -112,6 +110,7 @@ public class CallbackServer implements Runnable {
* *
* @param url The URL of the Cordova app being loaded * @param url The URL of the Cordova app being loaded
*/ */
@SuppressWarnings("deprecation")
public void init(String url) { public void init(String url) {
//Log.d(LOG_TAG, "CallbackServer.start("+url+")"); //Log.d(LOG_TAG, "CallbackServer.start("+url+")");
this.active = false; this.active = false;
@ -237,8 +236,8 @@ public class CallbackServer implements Runnable {
this.wait(10000); // prevent timeout from happening this.wait(10000); // prevent timeout from happening
//Log.d(LOG_TAG, "CallbackServer>>> break <<<"); //Log.d(LOG_TAG, "CallbackServer>>> break <<<");
break; break;
} catch (Exception e) {
} }
catch (Exception e) { }
} }
} }

View File

@ -26,7 +26,7 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.cordova.api.CordovaInterface; //import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import org.apache.cordova.api.Plugin; import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult; import org.apache.cordova.api.PluginResult;
@ -35,7 +35,7 @@ import org.json.JSONException;
import android.app.Activity; import android.app.Activity;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; //import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -81,7 +81,7 @@ public class CameraLauncher extends Plugin {
private int numPics; private int numPics;
//This should never be null! //This should never be null!
private CordovaInterface cordova; //private CordovaInterface cordova;
/** /**
* Constructor. * Constructor.
@ -89,13 +89,13 @@ public class CameraLauncher extends Plugin {
public CameraLauncher() { public CameraLauncher() {
} }
public void setContext(Context mCtx) { // public void setContext(CordovaInterface mCtx) {
super.setContext(mCtx); // super.setContext(mCtx);
if(CordovaInterface.class.isInstance(mCtx)) // if (CordovaInterface.class.isInstance(mCtx))
cordova = (CordovaInterface) mCtx; // cordova = (CordovaInterface) mCtx;
else // else
LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity"); // LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
} // }
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
@ -176,10 +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);
if(cordova != null) if (this.ctx != null) {
cordova.startActivityForResult((Plugin) this, intent, (CAMERA+1)*16 + returnType+1); this.ctx.startActivityForResult((Plugin) this, intent, (CAMERA + 1) * 16 + returnType + 1);
else }
LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity"); // else
// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
} }
/** /**
@ -191,9 +192,9 @@ public class CameraLauncher extends Plugin {
private File createCaptureFile(int encodingType) { private File createCaptureFile(int encodingType) {
File photo = null; File photo = null;
if (encodingType == JPEG) { if (encodingType == JPEG) {
photo = new File(DirectoryManager.getTempDirectoryPath(ctx), "Pic.jpg"); photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Pic.jpg");
} else if (encodingType == PNG) { } else if (encodingType == PNG) {
photo = new File(DirectoryManager.getTempDirectoryPath(ctx), "Pic.png"); photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Pic.png");
} else { } else {
throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType); throw new IllegalArgumentException("Invalid Encoding Type: " + encodingType);
} }
@ -227,9 +228,11 @@ 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);
cordova.startActivityForResult((Plugin) this, Intent.createChooser(intent, if (this.ctx != null) {
this.ctx.startActivityForResult((Plugin) this, Intent.createChooser(intent,
new String(title)), (srcType + 1) * 16 + returnType + 1); new String(title)), (srcType + 1) * 16 + returnType + 1);
} }
}
/** /**
* Scales the bitmap according to the requested size. * Scales the bitmap according to the requested size.
@ -294,7 +297,7 @@ public class CameraLauncher extends Plugin {
ExifHelper exif = new ExifHelper(); ExifHelper exif = new ExifHelper();
try { try {
if (this.encodingType == JPEG) { if (this.encodingType == JPEG) {
exif.createInFile(DirectoryManager.getTempDirectoryPath(ctx) + "/Pic.jpg"); exif.createInFile(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/Pic.jpg");
exif.readExifData(); exif.readExifData();
} }
} catch (IOException e) { } catch (IOException e) {
@ -309,10 +312,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));
} }
@ -332,11 +335,11 @@ public class CameraLauncher 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.failPicture("Error capturing image - no media storage found."); this.failPicture("Error capturing image - no media storage found.");
@ -345,13 +348,13 @@ 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();
// Restore exif data to file // Restore exif data to file
if (this.encodingType == JPEG) { if (this.encodingType == JPEG) {
exif.createOutFile(FileUtils.getRealPathFromURI(uri, ((Activity) this.ctx))); exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
exif.writeExifData(); exif.writeExifData();
} }
@ -384,7 +387,7 @@ 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
@ -397,7 +400,7 @@ public class CameraLauncher extends Plugin {
try { try {
Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri)); Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(resolver.openInputStream(uri));
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) {
@ -408,7 +411,7 @@ public class CameraLauncher extends Plugin {
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);
@ -429,14 +432,14 @@ 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) + "/resize.jpg"; String fileName = DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/resize.jpg";
OutputStream os = new FileOutputStream(fileName); OutputStream os = new FileOutputStream(fileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os);
os.close(); os.close();
// Restore exif data to file // Restore exif data to file
if (this.encodingType == JPEG) { if (this.encodingType == JPEG) {
exif.createOutFile(FileUtils.getRealPathFromURI(uri, ((Activity) ctx))); exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
exif.writeExifData(); exif.writeExifData();
} }
@ -473,7 +476,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,
@ -502,7 +505,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);
} }
} }
@ -523,8 +526,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

@ -22,7 +22,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
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;
@ -32,7 +31,6 @@ import org.json.JSONObject;
import android.app.Activity; import android.app.Activity;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
@ -40,7 +38,6 @@ 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";
@ -54,25 +51,26 @@ 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;
private String callbackId; // The ID of the callback to be invoked with our result private String callbackId; // The ID of the callback to be invoked with our result
private long limit; // the number of pics/vids/clips to take private long limit; // the number of pics/vids/clips to take
private double duration; // optional duration parameter for video recording private double duration; // optional duration parameter for video recording
private JSONArray results; // The array of results to be returned to the user private JSONArray results; // The array of results to be returned to the user
private Uri imageUri; // Uri of captured image private Uri imageUri; // Uri of captured image
private CordovaInterface cordova;
public void setContext(Context mCtx) //private CordovaInterface cordova;
{
if(CordovaInterface.class.isInstance(mCtx)) // public void setContext(Context mCtx)
cordova = (CordovaInterface) mCtx; // {
else // if (CordovaInterface.class.isInstance(mCtx))
LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity"); // cordova = (CordovaInterface) mCtx;
} // else
// LOG.d(LOG_TAG, "ERROR: You must use the CordovaInterface for this to work correctly. Please implement it in your activity");
// }
@Override @Override
public PluginResult execute(String action, JSONArray args, String callbackId) { public PluginResult execute(String action, JSONArray args, String callbackId) {
@ -143,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;
@ -184,8 +181,7 @@ public class Capture extends Plugin {
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 +193,7 @@ public class Capture extends Plugin {
private void captureAudio() { private void captureAudio() {
Intent intent = new Intent(android.provider.MediaStore.Audio.Media.RECORD_SOUND_ACTION); Intent intent = new Intent(android.provider.MediaStore.Audio.Media.RECORD_SOUND_ACTION);
cordova.startActivityForResult((Plugin) this, intent, CAPTURE_AUDIO); this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_AUDIO);
} }
/** /**
@ -207,11 +203,11 @@ public class Capture extends Plugin {
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
// Specify file so that large image is captured and returned // Specify file so that large image is captured and returned
File photo = new File(DirectoryManager.getTempDirectoryPath(ctx), "Capture.jpg"); File photo = new File(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()), "Capture.jpg");
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo)); intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
this.imageUri = Uri.fromFile(photo); this.imageUri = Uri.fromFile(photo);
cordova.startActivityForResult((Plugin) this, intent, CAPTURE_IMAGE); this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_IMAGE);
} }
/** /**
@ -222,7 +218,7 @@ public class Capture extends Plugin {
// Introduced in API 8 // Introduced in API 8
//intent.putExtra(android.provider.MediaStore.EXTRA_DURATION_LIMIT, duration); //intent.putExtra(android.provider.MediaStore.EXTRA_DURATION_LIMIT, duration);
cordova.startActivityForResult((Plugin) this, intent, CAPTURE_VIDEO); this.ctx.startActivityForResult((Plugin) this, intent, CAPTURE_VIDEO);
} }
/** /**
@ -260,11 +256,11 @@ public class Capture extends Plugin {
try { try {
// Create an ExifHelper to save the exif data that is lost during compression // Create an ExifHelper to save the exif data that is lost during compression
ExifHelper exif = new ExifHelper(); ExifHelper exif = new ExifHelper();
exif.createInFile(DirectoryManager.getTempDirectoryPath(ctx) + "/Capture.jpg"); exif.createInFile(DirectoryManager.getTempDirectoryPath(this.ctx.getActivity()) + "/Capture.jpg");
exif.readExifData(); exif.readExifData();
// Read in bitmap of captured image // Read in bitmap of captured image
Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getContentResolver(), imageUri); Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(this.ctx.getActivity().getContentResolver(), imageUri);
// Create entry in media store for image // Create entry in media store for image
// (Don't use insertImage() because it uses default compression setting of 50 - no way to change it) // (Don't use insertImage() because it uses default compression setting of 50 - no way to change it)
@ -272,11 +268,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."));
@ -285,7 +281,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();
@ -294,7 +290,7 @@ public class Capture extends Plugin {
System.gc(); System.gc();
// Restore exif data to file // Restore exif data to file
exif.createOutFile(FileUtils.getRealPathFromURI(uri, ((Activity) this.ctx))); exif.createOutFile(FileUtils.getRealPathFromURI(uri, this.ctx));
exif.writeExifData(); exif.writeExifData();
// Add image to results // Add image to results
@ -358,7 +354,7 @@ public class Capture extends Plugin {
* @throws IOException * @throws IOException
*/ */
private JSONObject createMediaFile(Uri data) { private JSONObject createMediaFile(Uri data) {
File fp = new File(FileUtils.getRealPathFromURI(data, ((Activity) this.ctx))); File fp = new File(FileUtils.getRealPathFromURI(data, this.ctx));
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
try { try {

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;
@ -70,9 +69,9 @@ public class CompassListener extends Plugin implements SensorEventListener {
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(Context ctx) { public void setContext(CordovaInterface ctx) {
super.setContext(ctx); super.setContext(ctx);
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE); this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE);
} }
/** /**
@ -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

@ -18,11 +18,12 @@ package org.apache.cordova;
import java.util.HashMap; import java.util.HashMap;
import android.app.Activity; //import android.app.Activity;
import android.content.Context; //import android.content.Context;
import android.util.Log; import android.util.Log;
import android.webkit.WebView; import android.webkit.WebView;
import org.apache.cordova.api.CordovaInterface;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -37,7 +38,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;
/** /**
@ -122,8 +123,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);
} }
return map; return map;
@ -148,8 +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());
} }
return value; return value;
@ -183,15 +182,19 @@ public abstract class ContactAccessor {
class WhereOptions { class WhereOptions {
private String where; private String where;
private String[] whereArgs; private String[] whereArgs;
public void setWhere(String where) { public void setWhere(String where) {
this.where = where; this.where = where;
} }
public String getWhere() { public String getWhere() {
return where; return where;
} }
public void setWhereArgs(String[] whereArgs) { public void setWhereArgs(String[] whereArgs) {
this.whereArgs = whereArgs; this.whereArgs = whereArgs;
} }
public String[] getWhereArgs() { public String[] getWhereArgs() {
return whereArgs; return whereArgs;
} }

View File

@ -32,18 +32,19 @@ import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
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;
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.app.Activity; //import android.app.Activity;
import android.content.ContentProviderOperation; import android.content.ContentProviderOperation;
import android.content.ContentProviderResult; import android.content.ContentProviderResult;
import android.content.ContentUris; import android.content.ContentUris;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; //import android.content.Context;
import android.content.OperationApplicationException; import android.content.OperationApplicationException;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
@ -122,7 +123,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
/** /**
* Create an contact accessor. * Create an contact accessor.
*/ */
public ContactAccessorSdk5(WebView view, Context context) { public ContactAccessorSdk5(WebView view, CordovaInterface context) {
mApp = context; mApp = context;
mView = view; mView = view;
} }
@ -173,7 +174,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
WhereOptions whereOptions = buildWhereClause(fields, searchTerm); WhereOptions whereOptions = buildWhereClause(fields, searchTerm);
// Get all the id's where the search term matches the fields passed in. // Get all the id's where the search term matches the fields passed in.
Cursor idCursor = mApp.getContentResolver().query(ContactsContract.Data.CONTENT_URI, Cursor idCursor = mApp.getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
new String[] { ContactsContract.Data.CONTACT_ID }, new String[] { ContactsContract.Data.CONTACT_ID },
whereOptions.getWhere(), whereOptions.getWhere(),
whereOptions.getWhereArgs(), whereOptions.getWhereArgs(),
@ -191,7 +192,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
WhereOptions idOptions = buildIdClause(contactIds, searchTerm); WhereOptions idOptions = buildIdClause(contactIds, searchTerm);
// Do the id query // Do the id query
Cursor c = mApp.getContentResolver().query(ContactsContract.Data.CONTENT_URI, Cursor c = mApp.getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
null, null,
idOptions.getWhere(), idOptions.getWhere(),
idOptions.getWhereArgs(), idOptions.getWhereArgs(),
@ -210,7 +211,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
*/ */
public JSONObject getContactById(String id) throws JSONException { public JSONObject getContactById(String id) throws JSONException {
// Do the id query // Do the id query
Cursor c = mApp.getContentResolver().query(ContactsContract.Data.CONTENT_URI, Cursor c = mApp.getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
null, null,
ContactsContract.Data.CONTACT_ID + " = ? ", ContactsContract.Data.CONTACT_ID + " = ? ",
new String[] { id }, new String[] { id },
@ -350,8 +351,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
&& isRequired("photos", populate)) { && isRequired("photos", populate)) {
photos.put(photoQuery(c, contactId)); photos.put(photoQuery(c, contactId));
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e); Log.e(LOG_TAG, e.getMessage(), e);
} }
@ -442,8 +442,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
if (photos.length() > 0) { if (photos.length() > 0) {
contact.put("photos", photos); contact.put("photos", photos);
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e); Log.e(LOG_TAG, e.getMessage(), e);
} }
return contact; return contact;
@ -596,8 +595,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
whereArgs.add(ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE); whereArgs.add(ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE);
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e); Log.e(LOG_TAG, e.getMessage(), e);
} }
@ -700,11 +698,21 @@ public class ContactAccessorSdk5 extends ContactAccessor {
// Create the formatted name // Create the formatted name
StringBuffer formatted = new StringBuffer(""); StringBuffer formatted = new StringBuffer("");
if (honorificPrefix != null) { formatted.append(honorificPrefix + " "); } if (honorificPrefix != null) {
if (givenName != null) { formatted.append(givenName + " "); } formatted.append(honorificPrefix + " ");
if (middleName != null) { formatted.append(middleName + " "); } }
if (familyName != null) { formatted.append(familyName + " "); } if (givenName != null) {
if (honorificSuffix != null) { formatted.append(honorificSuffix + " "); } formatted.append(givenName + " ");
}
if (middleName != null) {
formatted.append(middleName + " ");
}
if (familyName != null) {
formatted.append(familyName + " ");
}
if (honorificSuffix != null) {
formatted.append(honorificSuffix + " ");
}
contactName.put("familyName", familyName); contactName.put("familyName", familyName);
contactName.put("givenName", givenName); contactName.put("givenName", givenName);
@ -732,8 +740,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
phoneNumber.put("type", getPhoneType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE)))); phoneNumber.put("type", getPhoneType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE))));
} catch (JSONException e) { } catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e); Log.e(LOG_TAG, e.getMessage(), e);
} } catch (Exception excp) {
catch (Exception excp) {
Log.e(LOG_TAG, excp.getMessage(), excp); Log.e(LOG_TAG, excp.getMessage(), excp);
} }
return phoneNumber; return phoneNumber;
@ -821,7 +828,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
* @returns the id if the contact is successfully saved, null otherwise. * @returns the id if the contact is successfully saved, null otherwise.
*/ */
public String save(JSONObject contact) { public String save(JSONObject contact) {
AccountManager mgr = AccountManager.get(mApp); AccountManager mgr = AccountManager.get(mApp.getActivity());
Account[] accounts = mgr.getAccounts(); Account[] accounts = mgr.getAccounts();
String accountName = null; String accountName = null;
String accountType = null; String accountType = null;
@ -963,8 +970,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
} }
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get phone numbers"); Log.d(LOG_TAG, "Could not get phone numbers");
} }
@ -999,8 +1005,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
} }
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get emails"); Log.d(LOG_TAG, "Could not get emails");
} }
@ -1045,8 +1050,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
} }
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get addresses"); Log.d(LOG_TAG, "Could not get addresses");
} }
@ -1085,8 +1089,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
} }
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get organizations"); Log.d(LOG_TAG, "Could not get organizations");
} }
@ -1121,8 +1124,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
} }
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get emails"); Log.d(LOG_TAG, "Could not get emails");
} }
@ -1177,8 +1179,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
} }
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get websites"); Log.d(LOG_TAG, "Could not get websites");
} }
@ -1227,8 +1228,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
} }
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get photos"); Log.d(LOG_TAG, "Could not get photos");
} }
@ -1236,7 +1236,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
//Modify contact //Modify contact
try { try {
mApp.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); mApp.getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(LOG_TAG, e.getMessage(), e); Log.e(LOG_TAG, e.getMessage(), e);
Log.e(LOG_TAG, Log.getStackTraceString(e), e); Log.e(LOG_TAG, Log.getStackTraceString(e), e);
@ -1403,6 +1403,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
} }
return buffer.toByteArray(); return buffer.toByteArray();
} }
/** /**
* Get an input stream based on file path or uri content://, http://, file:// * Get an input stream based on file path or uri content://, http://, file://
* *
@ -1413,7 +1414,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
private InputStream getPathFromUri(String path) throws IOException { private InputStream getPathFromUri(String path) throws IOException {
if (path.startsWith("content:")) { if (path.startsWith("content:")) {
Uri uri = Uri.parse(path); Uri uri = Uri.parse(path);
return mApp.getContentResolver().openInputStream(uri); return mApp.getActivity().getContentResolver().openInputStream(uri);
} }
if (path.startsWith("http:") || path.startsWith("file:")) { if (path.startsWith("http:") || path.startsWith("file:")) {
URL url = new URL(path); URL url = new URL(path);
@ -1456,8 +1457,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
.withValue(ContactsContract.CommonDataKinds.StructuredName.SUFFIX, getJsonString(name, "honorificSuffix")) .withValue(ContactsContract.CommonDataKinds.StructuredName.SUFFIX, getJsonString(name, "honorificSuffix"))
.build()); .build());
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get name object"); Log.d(LOG_TAG, "Could not get name object");
} }
@ -1471,8 +1471,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
insertPhone(ops, phone); insertPhone(ops, phone);
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get phone numbers"); Log.d(LOG_TAG, "Could not get phone numbers");
} }
@ -1486,8 +1485,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
insertEmail(ops, email); insertEmail(ops, email);
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get emails"); Log.d(LOG_TAG, "Could not get emails");
} }
@ -1501,8 +1499,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
insertAddress(ops, address); insertAddress(ops, address);
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get addresses"); Log.d(LOG_TAG, "Could not get addresses");
} }
@ -1516,8 +1513,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
insertOrganization(ops, org); insertOrganization(ops, org);
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get organizations"); Log.d(LOG_TAG, "Could not get organizations");
} }
@ -1531,8 +1527,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
insertIm(ops, im); insertIm(ops, im);
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get emails"); Log.d(LOG_TAG, "Could not get emails");
} }
@ -1566,8 +1561,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
insertWebsite(ops, website); insertWebsite(ops, website);
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get websites"); Log.d(LOG_TAG, "Could not get websites");
} }
@ -1592,15 +1586,14 @@ public class ContactAccessorSdk5 extends ContactAccessor {
insertPhoto(ops, photo); insertPhoto(ops, photo);
} }
} }
} } catch (JSONException e) {
catch (JSONException e) {
Log.d(LOG_TAG, "Could not get photos"); Log.d(LOG_TAG, "Could not get photos");
} }
String newId = null; String newId = null;
//Add contact //Add contact
try { try {
ContentProviderResult[] cpResults = mApp.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); ContentProviderResult[] cpResults = mApp.getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
if (cpResults.length >= 0) { if (cpResults.length >= 0) {
newId = cpResults[0].uri.getLastPathSegment(); newId = cpResults[0].uri.getLastPathSegment();
} }
@ -1619,7 +1612,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
*/ */
public boolean remove(String id) { public boolean remove(String id) {
int result = 0; int result = 0;
Cursor cursor = mApp.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, Cursor cursor = mApp.getActivity().getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
null, null,
ContactsContract.Contacts._ID + " = ?", ContactsContract.Contacts._ID + " = ?",
new String[] { id }, null); new String[] { id }, null);
@ -1627,7 +1620,7 @@ public class ContactAccessorSdk5 extends ContactAccessor {
cursor.moveToFirst(); cursor.moveToFirst();
String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey); Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
result = mApp.getContentResolver().delete(uri, null, null); result = mApp.getActivity().getContentResolver().delete(uri, null, null);
} else { } else {
Log.d(LOG_TAG, "Could not find contact with ID"); Log.d(LOG_TAG, "Could not find contact with ID");
} }

View File

@ -17,17 +17,18 @@
under the License. under the License.
*/ */
package org.apache.cordova; package org.apache.cordova;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
//import android.app.Activity;
import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; //import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; //import android.view.View;
import android.webkit.ConsoleMessage; import android.webkit.ConsoleMessage;
import android.webkit.JsPromptResult; import android.webkit.JsPromptResult;
import android.webkit.JsResult; import android.webkit.JsResult;
@ -42,10 +43,9 @@ 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 Activity ctx; private CordovaInterface ctx;
private CordovaWebView appView; private CordovaWebView appView;
/** /**
@ -53,20 +53,28 @@ public class CordovaChromeClient extends WebChromeClient {
* *
* @param ctx * @param ctx
*/ */
public CordovaChromeClient(Context ctx) { public CordovaChromeClient(CordovaInterface ctx) {
this.ctx = (Activity) ctx; this.ctx = ctx;
//appView = this.ctx.appView;
} }
public CordovaChromeClient(Context ctx, CordovaWebView app) /**
{ * Constructor.
this.ctx = (Activity) ctx; *
appView = app; * @param ctx
* @param app
*/
public CordovaChromeClient(CordovaInterface ctx, CordovaWebView app) {
this.ctx = ctx;
this.appView = app;
} }
public void setWebView(CordovaWebView view) /**
{ * Constructor.
appView = view; *
* @param view
*/
public void setWebView(CordovaWebView view) {
this.appView = view;
} }
/** /**
@ -79,7 +87,7 @@ 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
@ -123,7 +131,7 @@ 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);
@ -182,7 +190,7 @@ 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(appView.baseUrl) == 0 || appView.isUrlWhiteListed(url)) { if (url.startsWith("file://") || url.indexOf(this.appView.baseUrl) == 0 || this.appView.isUrlWhiteListed(url)) {
reqOk = true; reqOk = true;
} }
@ -196,7 +204,7 @@ public class CordovaChromeClient extends WebChromeClient {
String action = array.getString(1); String action = array.getString(1);
String callbackId = array.getString(2); String callbackId = array.getString(2);
boolean async = array.getBoolean(3); boolean async = array.getBoolean(3);
String r = appView.pluginManager.exec(service, action, callbackId, message, async); String r = this.appView.pluginManager.exec(service, action, callbackId, message, async);
result.confirm(r); result.confirm(r);
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
@ -205,24 +213,29 @@ public class CordovaChromeClient extends WebChromeClient {
// Polling for JavaScript messages // Polling for JavaScript messages
else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) { else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
String r = appView.callbackServer.getJavascript(); String r = this.appView.callbackServer.getJavascript();
result.confirm(r); result.confirm(r);
} }
// Do NO-OP so older code doesn't display dialog
else if (defaultValue.equals("gap_init:")) {
result.confirm("OK");
}
// Calling into CallbackServer // Calling into CallbackServer
else if (reqOk && defaultValue != null && defaultValue.equals("gap_callbackServer:")) { else if (reqOk && defaultValue != null && defaultValue.equals("gap_callbackServer:")) {
String r = ""; String r = "";
if (message.equals("usePolling")) { if (message.equals("usePolling")) {
r = ""+ appView.callbackServer.usePolling(); r = "" + this.appView.callbackServer.usePolling();
} }
else if (message.equals("restartServer")) { else if (message.equals("restartServer")) {
appView.callbackServer.restartServer(); this.appView.callbackServer.restartServer();
} }
else if (message.equals("getPort")) { else if (message.equals("getPort")) {
r = Integer.toString(appView.callbackServer.getPort()); r = Integer.toString(this.appView.callbackServer.getPort());
} }
else if (message.equals("getToken")) { else if (message.equals("getToken")) {
r = appView.callbackServer.getToken(); r = this.appView.callbackServer.getToken();
} }
result.confirm(r); result.confirm(r);
} }
@ -230,9 +243,9 @@ public class CordovaChromeClient extends WebChromeClient {
// 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);
} }
@ -289,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)
{ {
@ -315,6 +329,4 @@ public class CordovaChromeClient extends WebChromeClient {
super.onGeolocationPermissionsShowPrompt(origin, callback); super.onGeolocationPermissionsShowPrompt(origin, callback);
callback.invoke(origin, true, false); callback.invoke(origin, true, false);
} }
} }

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

@ -21,4 +21,8 @@ package org.apache.cordova;
public class CordovaException extends Exception { public class CordovaException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1373339564758328799L;
} }

View File

@ -22,12 +22,12 @@ package org.apache.cordova;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator; import java.util.Iterator;
import java.util.Stack; import java.util.Stack;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import org.apache.cordova.api.PluginManager; import org.apache.cordova.api.PluginManager;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
@ -36,29 +36,26 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebSettings.LayoutAlgorithm;
import android.app.Activity;
public class CordovaWebView extends WebView { public class CordovaWebView extends WebView {
public static final String TAG = "CordovaWebView"; public static final String TAG = "CordovaWebView";
/** The authorization tokens. */
private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
/** The whitelist **/ /** The whitelist **/
private ArrayList<Pattern> whiteList = new ArrayList<Pattern>(); private ArrayList<Pattern> whiteList = new ArrayList<Pattern>();
private HashMap<String, Boolean> whiteListCache = new HashMap<String, Boolean>(); private HashMap<String, Boolean> whiteListCache = new HashMap<String, Boolean>();
protected PluginManager pluginManager; public PluginManager pluginManager;
public CallbackServer callbackServer; public CallbackServer callbackServer;
/** Actvities and other important classes **/ /** Actvities and other important classes **/
private Context mCtx; private CordovaInterface mCtx;
CordovaWebViewClient viewClient; CordovaWebViewClient viewClient;
@SuppressWarnings("unused")
private CordovaChromeClient chromeClient; private CordovaChromeClient chromeClient;
//This is for the polyfil history //This is for the polyfil history
@ -68,46 +65,69 @@ public class CordovaWebView extends WebView {
boolean useBrowserHistory = false; boolean useBrowserHistory = false;
protected int loadUrlTimeout; // Flag to track that a loadUrl timeout occurred
int loadUrlTimeout = 0;
protected long loadUrlTimeoutValue; /**
* Constructor.
//preferences read from cordova.xml *
protected PreferenceSet preferences; * @param context
*/
public CordovaWebView(Context context) { public CordovaWebView(CordovaInterface context) {
super(context); super(context.getActivity());
mCtx = context; this.mCtx = context;
setup(); this.loadConfiguration();
this.setup();
} }
public CordovaWebView(Context context, AttributeSet attrs) { /**
super(context, attrs); * Constructor.
mCtx = context; *
preferences = new PreferenceSet(); * @param context
loadConfiguration(); * @param attrs
setup(); */
public CordovaWebView(CordovaInterface context, AttributeSet attrs) {
super(context.getActivity(), attrs);
this.mCtx = context;
this.loadConfiguration();
this.setup();
} }
public CordovaWebView(Context context, AttributeSet attrs, int defStyle) { /**
super(context, attrs, defStyle); * Constructor.
mCtx = context; *
preferences = new PreferenceSet(); * @param context
loadConfiguration(); * @param attrs
setup(); * @param defStyle
*/
public CordovaWebView(CordovaInterface context, AttributeSet attrs, int defStyle) {
super(context.getActivity(), attrs, defStyle);
this.mCtx = context;
this.loadConfiguration();
this.setup();
} }
public CordovaWebView(Context context, AttributeSet attrs, int defStyle, /**
boolean privateBrowsing) { * Constructor.
super(context, attrs, defStyle, privateBrowsing); *
mCtx = context; * @param context
preferences = new PreferenceSet(); * @param attrs
loadConfiguration(); * @param defStyle
setup(); * @param privateBrowsing
*/
public CordovaWebView(CordovaInterface context, AttributeSet attrs, int defStyle, boolean privateBrowsing) {
super(context.getActivity(), attrs, defStyle, privateBrowsing);
this.mCtx = context;
this.loadConfiguration();
this.setup();
} }
private void setup() /**
{ * Initialize webview.
*/
@SuppressWarnings("deprecation")
private void setup() {
this.setInitialScale(0); this.setInitialScale(0);
this.setVerticalScrollBarEnabled(false); this.setVerticalScrollBarEnabled(false);
this.requestFocusFromTouch(); this.requestFocusFromTouch();
@ -123,13 +143,9 @@ public class CordovaWebView extends WebView {
// Enable database // Enable database
settings.setDatabaseEnabled(true); settings.setDatabaseEnabled(true);
String databasePath = mCtx.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); String databasePath = this.mCtx.getActivity().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
settings.setDatabasePath(databasePath); settings.setDatabasePath(databasePath);
//Setup the WebChromeClient and WebViewClient
setWebViewClient(new CordovaWebViewClient(mCtx, this));
setWebChromeClient(new CordovaChromeClient(mCtx, this));
// Enable DOM storage // Enable DOM storage
settings.setDomStorageEnabled(true); settings.setDomStorageEnabled(true);
@ -137,104 +153,28 @@ public class CordovaWebView extends WebView {
settings.setGeolocationEnabled(true); settings.setGeolocationEnabled(true);
//Start up the plugin manager //Start up the plugin manager
this.pluginManager = new PluginManager(this, mCtx); this.pluginManager = new PluginManager(this, this.mCtx);
} }
/**
//This sets it up so that we can save copies of the clients that we might need later. * Set the WebViewClient.
public void setWebViewClient(CordovaWebViewClient client) *
{ * @param client
viewClient = client; */
public void setWebViewClient(CordovaWebViewClient client) {
this.viewClient = client;
super.setWebViewClient(client); super.setWebViewClient(client);
} }
/**
public void setWebChromeClient(CordovaChromeClient client) * Set the WebChromeClient.
{ *
chromeClient = client; * @param client
*/
public void setWebChromeClient(CordovaChromeClient client) {
this.chromeClient = client;
super.setWebChromeClient(client); super.setWebChromeClient(client);
} }
/**
* Sets the authentication token.
*
* @param authenticationToken
* the authentication token
* @param host
* the host
* @param realm
* the realm
*/
public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
if(host == null) {
host = "";
}
if(realm == null) {
realm = "";
}
authenticationTokens.put(host.concat(realm), authenticationToken);
}
/**
* Removes the authentication token.
*
* @param host
* the host
* @param realm
* the realm
* @return the authentication token or null if did not exist
*/
public AuthenticationToken removeAuthenticationToken(String host, String realm) {
return 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
* the host
* @param realm
* the realm
* @return the authentication token
*/
public AuthenticationToken getAuthenticationToken(String host, String realm) {
AuthenticationToken token = null;
token = authenticationTokens.get(host.concat(realm));
if(token == null) {
// try with just the host
token = authenticationTokens.get(host);
// Try the realm
if(token == null) {
token = authenticationTokens.get(realm);
}
// if no host found, just query for default
if(token == null) {
token = authenticationTokens.get("");
}
}
return token;
}
/**
* Clear all authentication tokens.
*/
public void clearAuthenticationTokens() {
authenticationTokens.clear();
}
/** /**
* Add entry to approved list of URLs (whitelist) * Add entry to approved list of URLs (whitelist)
@ -247,24 +187,24 @@ public class CordovaWebView extends WebView {
// Unlimited access to network resources // Unlimited access to network resources
if (origin.compareTo("*") == 0) { if (origin.compareTo("*") == 0) {
LOG.d(TAG, "Unlimited access to network resources"); LOG.d(TAG, "Unlimited access to network resources");
whiteList.add(Pattern.compile(".*")); this.whiteList.add(Pattern.compile(".*"));
} else { // specific access } else { // specific access
// check if subdomains should be included // check if subdomains should be included
// TODO: we should not add more domains if * has already been added // TODO: we should not add more domains if * has already been added
if (subdomains) { if (subdomains) {
// XXX making it stupid friendly for people who forget to include protocol/SSL // XXX making it stupid friendly for people who forget to include protocol/SSL
if (origin.startsWith("http")) { if (origin.startsWith("http")) {
whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://(.*\\.)?"))); this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://(.*\\.)?")));
} else { } else {
whiteList.add(Pattern.compile("^https?://(.*\\.)?"+origin)); this.whiteList.add(Pattern.compile("^https?://(.*\\.)?" + origin));
} }
LOG.d(TAG, "Origin to allow with subdomains: %s", origin); LOG.d(TAG, "Origin to allow with subdomains: %s", origin);
} else { } else {
// XXX making it stupid friendly for people who forget to include protocol/SSL // XXX making it stupid friendly for people who forget to include protocol/SSL
if (origin.startsWith("http")) { if (origin.startsWith("http")) {
whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://"))); this.whiteList.add(Pattern.compile(origin.replaceFirst("https?://", "^https?://")));
} else { } else {
whiteList.add(Pattern.compile("^https?://"+origin)); this.whiteList.add(Pattern.compile("^https?://" + origin));
} }
LOG.d(TAG, "Origin to allow: %s", origin); LOG.d(TAG, "Origin to allow: %s", origin);
} }
@ -283,19 +223,19 @@ public class CordovaWebView extends WebView {
public boolean isUrlWhiteListed(String url) { public boolean isUrlWhiteListed(String url) {
// Check to see if we have matched url previously // Check to see if we have matched url previously
if (whiteListCache.get(url) != null) { if (this.whiteListCache.get(url) != null) {
return true; return true;
} }
// Look for match in white list // Look for match in white list
Iterator<Pattern> pit = whiteList.iterator(); Iterator<Pattern> pit = this.whiteList.iterator();
while (pit.hasNext()) { while (pit.hasNext()) {
Pattern p = pit.next(); Pattern p = pit.next();
Matcher m = p.matcher(url); Matcher m = p.matcher(url);
// If match found, then cache it to speed up subsequent comparisons // If match found, then cache it to speed up subsequent comparisons
if (m.find()) { if (m.find()) {
whiteListCache.put(url, true); this.whiteListCache.put(url, true);
return true; return true;
} }
} }
@ -303,14 +243,53 @@ public class CordovaWebView extends WebView {
} }
/** /**
* We override loadUrl so that we can track the back history * Load the url into the webview.
* @see android.webkit.WebView#loadUrl(java.lang.String) *
* @param url
*/ */
@Override @Override
public void loadUrl(String url) public void loadUrl(String url) {
{ 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) {
if (!url.startsWith("javascript:")) { if (!url.startsWith("javascript:")) {
LOG.d(TAG, ">>> loadUrl(" + url + ")");
this.url = url; this.url = url;
if (this.baseUrl == null) { if (this.baseUrl == null) {
int i = url.lastIndexOf('/'); int i = url.lastIndexOf('/');
@ -321,53 +300,122 @@ public class CordovaWebView extends WebView {
this.baseUrl = this.url + "/"; this.baseUrl = this.url + "/";
} }
pluginManager.init(); this.pluginManager.init();
if(!useBrowserHistory) if (!this.useBrowserHistory) {
this.urls.push(url); this.urls.push(url);
} }
} }
super.loadUrl(url); // Create a timeout timer for loadUrl
}
public void loadUrl(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 (this.urls.size() > 0 || this.canGoBack()) {
this.loadUrl(url);
}
if (!url.startsWith("javascript:")) {
LOG.d(TAG, "DroidGap.loadUrl(%s, %d)", url, time);
}
final CordovaWebView me = this; final CordovaWebView me = this;
Runnable runnable = new Runnable() { 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() { public void run() {
try { try {
synchronized (this) { synchronized (this) {
this.wait(time); wait(loadUrlTimeoutValue);
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
//I'm pretty sure this has to be on the UI thread
me.loadUrl(url); // If timeout, then stop loading and handle error
if (me.loadUrlTimeout == currentLoadUrlTimeout) {
me.mCtx.getActivity().runOnUiThread(loadError);
}
} }
}; };
Thread thread = new Thread(runnable);
// Load url
this.mCtx.getActivity().runOnUiThread(new Runnable() {
public void run() {
Thread thread = new Thread(timeoutCheck);
thread.start(); thread.start();
me.loadUrlNow(url);
}
});
} }
// If Javascript, then just load it now
else {
super.loadUrl(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) { public void sendJavascript(String statement) {
callbackServer.sendJavascript(statement); if (this.callbackServer != null) {
this.callbackServer.sendJavascript(statement);
}
} }
public void postMessage(String id, String data) { /**
pluginManager.postMessage(id, data); * 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);
}
} }
/** /**
@ -375,8 +423,8 @@ public class CordovaWebView extends WebView {
* the stack. * the stack.
*/ */
public String peekAtUrlStack() { public String peekAtUrlStack() {
if (urls.size() > 0) { if (this.urls.size() > 0) {
return urls.peek(); return this.urls.peek();
} }
return ""; return "";
} }
@ -387,7 +435,7 @@ public class CordovaWebView extends WebView {
* @param url * @param url
*/ */
public void pushUrl(String url) { public void pushUrl(String url) {
urls.push(url); this.urls.push(url);
} }
/** /**
@ -399,8 +447,8 @@ public class CordovaWebView extends WebView {
// Check webview first to see if there is a history // 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) // This is needed to support curPage#diffLink, since they are added to appView's history, but not our history url array (JQMobile behavior)
if (this.canGoBack()) { if (super.canGoBack()) {
this.goBack(); super.goBack();
return true; return true;
} }
@ -408,13 +456,27 @@ public class CordovaWebView extends WebView {
if (this.urls.size() > 1) { if (this.urls.size() > 1) {
this.urls.pop(); // Pop current url 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() String url = this.urls.pop(); // Pop prev url that we want to load, since it will be added back by loadUrl()
loadUrl(url); this.loadUrl(url);
return true; return true;
} }
return false; 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. * Load the specified URL in the Cordova webview or a new browser instance.
@ -426,7 +488,7 @@ public class CordovaWebView extends WebView {
* @param clearHistory Clear the history stack, so new page becomes top of history * @param clearHistory Clear the history stack, so new page becomes top of history
* @param params DroidGap parameters for new app * @param params DroidGap parameters for new app
*/ */
public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) { //throws android.content.ActivityNotFoundException { public void showWebPage(String url, boolean openExternal, boolean clearHistory, HashMap<String, Object> params) {
LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory); LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap", url, openExternal, clearHistory);
// If clearing history // If clearing history
@ -455,7 +517,7 @@ public class CordovaWebView extends WebView {
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));
mCtx.startActivity(intent); mCtx.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);
} }
@ -467,7 +529,7 @@ public class CordovaWebView extends WebView {
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));
mCtx.startActivity(intent); mCtx.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);
} }
@ -482,7 +544,7 @@ public class CordovaWebView extends WebView {
* <log level="DEBUG" /> * <log level="DEBUG" />
*/ */
private void loadConfiguration() { private void loadConfiguration() {
int id = getResources().getIdentifier("cordova", "xml", mCtx.getPackageName()); int id = getResources().getIdentifier("cordova", "xml", this.mCtx.getActivity().getPackageName());
if (id == 0) { if (id == 0) {
LOG.i("CordovaLog", "cordova.xml missing. Ignoring..."); LOG.i("CordovaLog", "cordova.xml missing. Ignoring...");
return; return;
@ -496,7 +558,7 @@ public class CordovaWebView extends WebView {
String origin = xml.getAttributeValue(null, "origin"); String origin = xml.getAttributeValue(null, "origin");
String subdomains = xml.getAttributeValue(null, "subdomains"); String subdomains = xml.getAttributeValue(null, "subdomains");
if (origin != null) { if (origin != null) {
addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0)); this.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
} }
} }
else if (strNode.equals("log")) { else if (strNode.equals("log")) {
@ -509,14 +571,11 @@ public class CordovaWebView extends WebView {
else if (strNode.equals("preference")) { else if (strNode.equals("preference")) {
String name = xml.getAttributeValue(null, "name"); String name = xml.getAttributeValue(null, "name");
String value = xml.getAttributeValue(null, "value"); String value = xml.getAttributeValue(null, "value");
String readonlyString = xml.getAttributeValue(null, "readonly");
boolean readonly = (readonlyString != null && LOG.i("CordovaLog", "Found preference for %s=%s", name, value);
readonlyString.equals("true"));
LOG.i("CordovaLog", "Found preference for %s", name); // Save preferences in Intent
this.mCtx.getActivity().getIntent().putExtra(name, value);
preferences.add(new PreferenceNode(name, value, readonly));
} }
} }
try { try {
@ -527,6 +586,32 @@ public class CordovaWebView extends WebView {
e.printStackTrace(); e.printStackTrace();
} }
} }
// Init preferences
if ("true".equals(this.getProperty("useBrowserHistory", "true"))) {
this.useBrowserHistory = true;
}
else {
this.useBrowserHistory = false;
}
} }
/**
* 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,10 +18,13 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import org.apache.cordova.api.LOG; import java.util.Hashtable;
import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.LOG;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -29,7 +32,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.net.http.SslError; import android.net.http.SslError;
import android.util.Log;
import android.view.View; import android.view.View;
import android.webkit.HttpAuthHandler; import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler; import android.webkit.SslErrorHandler;
@ -42,28 +44,40 @@ 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";
Activity ctx; CordovaInterface ctx;
CordovaWebView appView; CordovaWebView appView;
private boolean doClearHistory = false; private boolean doClearHistory = false;
/** The authorization tokens. */
private Hashtable<String, AuthenticationToken> authenticationTokens = new Hashtable<String, AuthenticationToken>();
/** /**
* Constructor. * Constructor.
* *
* @param ctx * @param ctx
*/ */
public CordovaWebViewClient(Activity ctx) { public CordovaWebViewClient(CordovaInterface ctx) {
this.ctx = ctx; this.ctx = ctx;
} }
public CordovaWebViewClient(Context ctx, CordovaWebView view) /**
{ * Constructor.
this.ctx = (Activity) ctx; *
appView = view; * @param ctx
* @param view
*/
public CordovaWebViewClient(CordovaInterface ctx, CordovaWebView view) {
this.ctx = ctx;
this.appView = view;
} }
public void setWebView(CordovaWebView view) /**
{ * Constructor.
appView = view; *
* @param view
*/
public void setWebView(CordovaWebView view) {
this.appView = view;
} }
/** /**
@ -78,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 ((appView.pluginManager != null) && appView.pluginManager.onOverrideUrlLoading(url)) { if ((this.appView.pluginManager != null) && this.appView.pluginManager.onOverrideUrlLoading(url)) {
} }
// If dialing phone (tel:5551212) // If dialing phone (tel:5551212)
@ -86,7 +100,7 @@ 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());
} }
@ -97,7 +111,7 @@ public class CordovaWebViewClient extends WebViewClient {
try { try {
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url)); intent.setData(Uri.parse(url));
ctx.startActivity(intent); this.ctx.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error showing map " + url + ": " + e.toString()); LOG.e(TAG, "Error showing map " + url + ": " + e.toString());
} }
@ -108,7 +122,7 @@ 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());
} }
@ -140,7 +154,7 @@ public class CordovaWebViewClient extends WebViewClient {
intent.setData(Uri.parse("sms:" + address)); intent.setData(Uri.parse("sms:" + address));
intent.putExtra("address", address); intent.putExtra("address", address);
intent.setType("vnd.android-dir/mms-sms"); intent.setType("vnd.android-dir/mms-sms");
ctx.startActivity(intent); this.ctx.getActivity().startActivity(intent);
} catch (android.content.ActivityNotFoundException e) { } catch (android.content.ActivityNotFoundException e) {
LOG.e(TAG, "Error sending sms " + url + ":" + e.toString()); LOG.e(TAG, "Error sending sms " + url + ":" + e.toString());
} }
@ -151,12 +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(appView.baseUrl) == 0 || appView.isUrlWhiteListed(url)) { if (url.startsWith("file://") || url.indexOf(this.appView.baseUrl) == 0 || this.appView.isUrlWhiteListed(url)) {
//This will fix iFrames //This will fix iFrames
if (appView.useBrowserHistory) if (appView.useBrowserHistory)
return false; return false;
else else
appView.loadUrl(url); this.appView.loadUrl(url);
} }
// If not our application, let default viewer handle // If not our application, let default viewer handle
@ -164,7 +178,7 @@ 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);
} }
@ -178,49 +192,54 @@ 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
// Note: The WebView MUST be a CordoaWebView
AuthenticationToken token = ((CordovaWebView) view).getAuthenticationToken(host,realm);
// Get the authentication token
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.
if(!appView.useBrowserHistory) if (!this.appView.useBrowserHistory) {
{
view.clearHistory(); view.clearHistory();
this.doClearHistory = true; this.doClearHistory = true;
} }
// Create callback server and plugin manager // Create callback server and plugin manager
if (appView.callbackServer == null) { if (this.appView.callbackServer == null) {
appView.callbackServer = new CallbackServer(); this.appView.callbackServer = new CallbackServer();
appView.callbackServer.init(url); this.appView.callbackServer.init(url);
} }
else { else {
appView.callbackServer.reinit(url); this.appView.callbackServer.reinit(url);
} }
// Broadcast message that page has loaded
this.appView.postMessage("onPageStarted", url);
} }
/** /**
* Notify the host application that a page has finished loading. * Notify the host application that a page has finished loading.
* 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.
@ -228,6 +247,7 @@ public class CordovaWebViewClient extends WebViewClient {
@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
@ -241,26 +261,28 @@ public class CordovaWebViewClient extends WebViewClient {
} }
// Clear timeout flag // Clear timeout flag
appView.loadUrlTimeout++; this.appView.loadUrlTimeout++;
// Try firing the onNativeReady event in JS. If it fails because the JS is // Try firing the onNativeReady event in JS. If it fails because the JS is
// not loaded yet then just set a flag so that the onNativeReady can be fired // not loaded yet then just set a flag so that the onNativeReady can be fired
// from the JS side when the JS gets to that code. // from the JS side when the JS gets to that code.
if (!url.equals("about:blank")) { if (!url.equals("about:blank")) {
appView.loadUrl("javascript:try{ cordova.require('cordova/channel').onNativeReady.fire();}catch(e){_nativeReady = true;}"); this.appView.loadUrl("javascript:try{ cordova.require('cordova/channel').onNativeReady.fire();}catch(e){_nativeReady = true;}");
appView.postMessage("onNativeReady", null); this.appView.postMessage("onNativeReady", null);
} }
// Broadcast message that page has loaded
this.appView.postMessage("onPageFinished", url);
// Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly // Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly
if (appView.getVisibility() == View.INVISIBLE) { if (this.appView.getVisibility() == View.INVISIBLE) {
Thread t = new Thread(new Runnable() { Thread t = new Thread(new Runnable() {
public void run() { public void run() {
try { try {
Thread.sleep(2000); Thread.sleep(2000);
ctx.runOnUiThread(new Runnable() { ctx.getActivity().runOnUiThread(new Runnable() {
public void run() { public void run() {
appView.setVisibility(View.VISIBLE); appView.postMessage("spinner", "stop");
//ctx.spinnerStop();
} }
}); });
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -270,14 +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 (appView.callbackServer != null) { if (this.appView.callbackServer != null) {
appView.callbackServer.destroy(); this.appView.callbackServer.destroy();
} }
//this.ctx.endActivity(); appView.postMessage("exit", null);
this.ctx.finish();
} }
} }
@ -292,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);
@ -325,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 (!appView.peekAtUrlStack().equals(url)) { if (!this.appView.peekAtUrlStack().equals(url)) {
appView.pushUrl(url); this.appView.pushUrl(url);
} }
} }
/**
* Sets the authentication token.
*
* @param authenticationToken
* @param host
* @param realm
*/
public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
if (host == null) {
host = "";
}
if (realm == null) {
realm = "";
}
this.authenticationTokens.put(host.concat(realm), authenticationToken);
}
/**
* Removes the authentication token.
*
* @param host
* @param realm
*
* @return the authentication token or null if did not exist
*/
public AuthenticationToken removeAuthenticationToken(String host, String realm) {
return this.authenticationTokens.remove(host.concat(realm));
}
/**
* Gets the authentication token.
*
* In order it tries:
* 1- host + realm
* 2- host
* 3- realm
* 4- no host, no realm
*
* @param host
* @param realm
*
* @return the authentication token
*/
public AuthenticationToken getAuthenticationToken(String host, String realm) {
AuthenticationToken token = null;
token = this.authenticationTokens.get(host.concat(realm));
if (token == null) {
// try with just the host
token = this.authenticationTokens.get(host);
// Try the realm
if (token == null) {
token = this.authenticationTokens.get(realm);
}
// if no host found, just query for default
if (token == null) {
token = this.authenticationTokens.get("");
}
}
return token;
}
/**
* Clear all authentication tokens.
*/
public void clearAuthenticationTokens() {
this.authenticationTokens.clear();
}
} }

View File

@ -56,7 +56,7 @@ public class Device extends Plugin {
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(Context ctx) { public void setContext(CordovaInterface ctx) {
super.setContext(ctx); super.setContext(ctx);
Device.uuid = getUuid(); Device.uuid = getUuid();
this.initTelephonyReceiver(); this.initTelephonyReceiver();
@ -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);
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -125,7 +125,7 @@ public class Device extends Plugin {
private void initTelephonyReceiver() { private void initTelephonyReceiver() {
IntentFilter intentFilter = new IntentFilter(); IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
final Context myctx = this.ctx; //final CordovaInterface myctx = this.ctx;
this.telephonyReceiver = new BroadcastReceiver() { this.telephonyReceiver = new BroadcastReceiver() {
@Override @Override
@ -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,6 +32,7 @@ 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";
/** /**

View File

@ -18,22 +18,13 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.cordova.PreferenceNode;
import org.apache.cordova.PreferenceSet;
import org.apache.cordova.api.IPlugin; import org.apache.cordova.api.IPlugin;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import org.apache.cordova.api.CordovaInterface; import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.PluginManager; import org.json.JSONException;
import org.xmlpull.v1.XmlPullParserException; import org.json.JSONObject;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
@ -43,10 +34,8 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.XmlResourceParser;
import android.graphics.Color; import android.graphics.Color;
import android.media.AudioManager; import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.view.Display; import android.view.Display;
@ -57,15 +46,9 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.LinearLayout; import android.widget.LinearLayout;
/** /**
* This class is the main Android activity that represents the Cordova * This class is the main Android activity that represents the Cordova
* application. It should be extended by the user to load the specific * application. It should be extended by the user to load the specific
@ -152,7 +135,7 @@ public class DroidGap extends Activity implements CordovaInterface {
// The webview for our app // The webview for our app
protected CordovaWebView appView; protected CordovaWebView appView;
protected WebViewClient webViewClient; protected CordovaWebViewClient webViewClient;
protected LinearLayout root; protected LinearLayout root;
public boolean bound = false; public boolean bound = false;
@ -161,11 +144,7 @@ public class DroidGap extends Activity implements CordovaInterface {
// The initial URL for our app // The initial URL for our app
// ie http://server/path/index.html#abc?query // ie http://server/path/index.html#abc?query
private String url = null; //private String url = null;
private Stack<String> urls = new Stack<String>();
// Url was specified from extras (activity was started programmatically)
private String initUrl = null;
private static int ACTIVITY_STARTING = 0; private static int ACTIVITY_STARTING = 0;
private static int ACTIVITY_RUNNING = 1; private static int ACTIVITY_RUNNING = 1;
@ -181,9 +160,6 @@ public class DroidGap extends Activity implements CordovaInterface {
protected IPlugin activityResultCallback = null; protected IPlugin activityResultCallback = null;
protected boolean activityResultKeepRunning; protected boolean activityResultKeepRunning;
// Flag indicates that a loadUrl timeout occurred
int loadUrlTimeout = 0;
// Default background color for activity // Default background color for activity
// (this is not the color for the webview, which is set in HTML) // (this is not the color for the webview, which is set in HTML)
private int backgroundColor = Color.BLACK; private int backgroundColor = Color.BLACK;
@ -195,38 +171,94 @@ public class DroidGap extends Activity implements CordovaInterface {
// Draw a splash screen using an image located in the drawable resource directory. // Draw a splash screen using an image located in the drawable resource directory.
// This is not the same as calling super.loadSplashscreen(url) // This is not the same as calling super.loadSplashscreen(url)
protected int splashscreen = 0; protected int splashscreen = 0;
protected int splashscreenTime = 0;
// LoadUrl timeout value in msec (default of 20 sec)
protected int loadUrlTimeoutValue = 20000;
// Keep app running when pause is received. (default = true) // Keep app running when pause is received. (default = true)
// If true, then the JavaScript and native code continue to run in the background // If true, then the JavaScript and native code continue to run in the background
// when another application (activity) is started. // when another application (activity) is started.
protected boolean keepRunning = true; protected boolean keepRunning = true;
// Store the useBrowserHistory preference until we actually need it. /**
private boolean useBrowserHistory = false; * Sets the authentication token.
*
* @param authenticationToken
* @param host
* @param realm
*/
public void setAuthenticationToken(AuthenticationToken authenticationToken, String host, String realm) {
if (this.appView != null && this.appView.viewClient != null) {
this.appView.viewClient.setAuthenticationToken(authenticationToken, host, realm);
}
}
// preferences read from cordova.xml /**
protected PreferenceSet preferences; * 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) {
if (this.appView != null && this.appView.viewClient != null) {
return this.appView.viewClient.removeAuthenticationToken(host, realm);
}
return null;
}
/**
* 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) {
if (this.appView != null && this.appView.viewClient != null) {
return this.appView.viewClient.getAuthenticationToken(host, realm);
}
return null;
}
/**
* Clear all authentication tokens.
*/
public void clearAuthenticationTokens() {
if (this.appView != null && this.appView.viewClient != null) {
this.appView.viewClient.clearAuthenticationTokens();
}
}
/** /**
* Called when the activity is first created. * Called when the activity is first created.
* *
* @param savedInstanceState * @param savedInstanceState
*/ */
@SuppressWarnings("deprecation")
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
preferences = new PreferenceSet(); //preferences = new PreferenceSet();
LOG.d(TAG, "DroidGap.onCreate()"); LOG.d(TAG, "DroidGap.onCreate()");
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE); getWindow().requestFeature(Window.FEATURE_NO_TITLE);
// TODO @bc - What about fullscreen?
//if (preferences.prefMatches("fullscreen", "true")) {
// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
// WindowManager.LayoutParams.FLAG_FULLSCREEN);
//} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
//}
// This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket! // This builds the view. We could probably get away with NOT having a LinearLayout, but I like having a bucket!
Display display = getWindowManager().getDefaultDisplay(); Display display = getWindowManager().getDefaultDisplay();
@ -239,23 +271,25 @@ public class DroidGap extends Activity implements CordovaInterface {
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT, 0.0F)); ViewGroup.LayoutParams.MATCH_PARENT, 0.0F));
// If url was passed in to intent, then init webview, which will load the url
Bundle bundle = this.getIntent().getExtras();
if (bundle != null) {
String url = bundle.getString("url");
if (url != null) {
this.initUrl = url;
}
}
// Setup the hardware volume controls to handle volume control // Setup the hardware volume controls to handle volume control
setVolumeControlStream(AudioManager.STREAM_MUSIC); setVolumeControlStream(AudioManager.STREAM_MUSIC);
} }
/**
* Get the Android activity.
*
* @return
*/
public Activity getActivity() {
return this;
}
/** /**
* Create and initialize web container with default web view objects. * Create and initialize web container with default web view objects.
*/ */
public void init() { public void init() {
this.init(new CordovaWebView(DroidGap.this), new CordovaWebViewClient(this), new CordovaChromeClient(DroidGap.this)); CordovaWebView webView = new CordovaWebView(DroidGap.this);
this.init(webView, new CordovaWebViewClient(this, webView), new CordovaChromeClient(this, webView));
} }
/** /**
@ -265,21 +299,17 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param webViewClient * @param webViewClient
* @param webChromeClient * @param webChromeClient
*/ */
public void init(CordovaWebView webView, WebViewClient webViewClient, WebChromeClient webChromeClient) { public void init(CordovaWebView webView, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient) {
LOG.d(TAG, "DroidGap.init()"); LOG.d(TAG, "DroidGap.init()");
// Set up web container // Set up web container
this.appView = webView; this.appView = webView;
this.appView.setId(100); this.appView.setId(100);
// Load Cordova configuration: this.appView.setWebViewClient(webViewClient);
// white list of allowed URLs this.appView.setWebChromeClient(webChromeClient);
// debug setting webViewClient.setWebView(this.appView);
this.loadConfiguration(); webChromeClient.setWebView(this.appView);
//Now we can check the preference
appView.useBrowserHistory = preferences.prefMatches("useBrowserHistory", "true");
//
this.appView.setLayoutParams(new LinearLayout.LayoutParams( this.appView.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
@ -288,35 +318,11 @@ public class DroidGap extends Activity implements CordovaInterface {
// Add web view but make it invisible while loading URL // Add web view but make it invisible while loading URL
this.appView.setVisibility(View.INVISIBLE); this.appView.setVisibility(View.INVISIBLE);
root.addView(this.appView); this.root.addView(this.appView);
setContentView(root); setContentView(this.root);
// Clear cancel flag // Clear cancel flag
this.cancelLoadUrl = false; this.cancelLoadUrl = false;
}
/**
* Look at activity parameters and process them.
* This must be called from the main UI thread.
*/
private void handleActivityParameters() {
// If backgroundColor
this.backgroundColor = this.getIntegerProperty("backgroundColor", Color.BLACK);
this.root.setBackgroundColor(this.backgroundColor);
// If spashscreen
this.splashscreen = this.getIntegerProperty("splashscreen", 0);
// If loadUrlTimeoutValue
int timeout = this.getIntegerProperty("loadUrlTimeoutValue", 0);
if (timeout > 0) {
this.loadUrlTimeoutValue = timeout;
}
// If keepRunning
this.keepRunning = this.getBooleanProperty("keepRunning", true);
} }
/** /**
@ -326,26 +332,34 @@ public class DroidGap extends Activity implements CordovaInterface {
*/ */
public void loadUrl(String url) { public void loadUrl(String url) {
// If first page of app, then set URL to load to be the one passed in // Init web view if not already done
if (this.initUrl == null || (this.urls.size() > 0)) { if (this.appView == null) {
this.loadUrlIntoView(url); this.init();
}
// Otherwise use the URL specified in the activity's extras bundle
else {
this.loadUrlIntoView(this.initUrl);
} }
// TODO @bc - background color doesn't work
// If backgroundColor
this.backgroundColor = this.getIntegerProperty("backgroundColor", Color.BLACK);
LOG.e(TAG, "Setting background color=" + this.backgroundColor);
this.root.setBackgroundColor(this.backgroundColor);
// If keepRunning
this.keepRunning = this.getBooleanProperty("keepRunning", true);
// Then load the spinner
this.loadSpinner();
this.appView.loadUrl(url);
} }
/* /*
* Load the spinner * Load the spinner
*
*/ */
void loadSpinner() void loadSpinner() {
{
// If loadingDialog property, then show the App loading dialog for first page of app // If loadingDialog property, then show the App loading dialog for first page of app
// (This doesn't seem to actually do anything here)
String loading = null; String loading = null;
if (this.urls.size() == 1) { if ((this.appView == null) || !this.appView.canGoBack()) {
loading = this.getStringProperty("loadingDialog", null); loading = this.getStringProperty("loadingDialog", null);
} }
else { else {
@ -371,71 +385,6 @@ public class DroidGap extends Activity implements CordovaInterface {
} }
} }
/**
* Load the url into the webview.
*
* @param url
*/
private void loadUrlIntoView(final String url) {
if (!url.startsWith("javascript:")) {
LOG.d(TAG, "DroidGap.loadUrl(%s)", url);
}
if (!url.startsWith("javascript:")) {
LOG.d(TAG, "DroidGap: url=%s baseUrl=%s", url, baseUrl);
}
// Load URL on UI thread
final DroidGap me = this;
final Runnable loadError = new Runnable() {
public void run() {
me.appView.stopLoading();
LOG.e(TAG, "DroidGap: TIMEOUT ERROR! - calling webViewClient");
appView.viewClient.onReceivedError(me.appView, -6, "The connection to the server was unsuccessful.", url);
}
};
this.runOnUiThread(new Runnable() {
public void run() {
// Init web view if not already done
if (me.appView == null) {
me.init();
}
// Handle activity parameters (TODO: Somehow abstract this)
me.handleActivityParameters();
// Then load the spinner
me.loadSpinner();
// Create a timeout timer for loadUrl
final int currentLoadUrlTimeout = me.loadUrlTimeout;
Runnable runnable = new Runnable() {
public void run() {
try {
synchronized(this) {
wait(me.loadUrlTimeoutValue);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
// If timeout, then stop loading and handle error
if (me.loadUrlTimeout == currentLoadUrlTimeout) {
me.runOnUiThread(loadError);
}
}
};
Thread thread = new Thread(runnable);
thread.start();
me.appView.loadUrl(url);
}
});
}
/** /**
* Load the url into the webview after waiting for period of time. * Load the url into the webview after waiting for period of time.
* This is used to display the splashscreen for certain amount of time. * This is used to display the splashscreen for certain amount of time.
@ -445,47 +394,20 @@ public class DroidGap extends Activity implements CordovaInterface {
*/ */
public void loadUrl(final String url, int time) { public void loadUrl(final String url, int time) {
// If first page of app, then set URL to load to be the one passed in // Init web view if not already done
if (this.initUrl == null || (this.urls.size() > 0)) { if (this.appView == null) {
this.loadUrlIntoView(url, time); this.init();
}
// Otherwise use the URL specified in the activity's extras bundle
else {
this.loadUrlIntoView(this.initUrl);
}
} }
/** this.splashscreenTime = time;
* Load the url into the webview after waiting for period of time. this.appView.loadUrl(url, 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
*/
private void loadUrlIntoView(final String url, final int time) {
// Clear cancel flag
this.cancelLoadUrl = false;
// If not first page of app, then load immediately
if (this.urls.size() > 0) {
this.loadUrlIntoView(url);
}
if (!url.startsWith("javascript:")) {
LOG.d(TAG, "DroidGap.loadUrl(%s, %d)", url, time);
}
this.handleActivityParameters();
if (this.splashscreen != 0) {
this.showSplashScreen(time);
}
this.loadUrlIntoView(url);
} }
/** /**
* Cancel loadUrl before it has been loaded. * Cancel loadUrl before it has been loaded.
*/ */
// TODO NO-OP
@Deprecated
public void cancelLoadUrl() { public void cancelLoadUrl() {
this.cancelLoadUrl = true; this.cancelLoadUrl = true;
} }
@ -504,16 +426,20 @@ public class DroidGap extends Activity implements CordovaInterface {
* Clear web history in this web view. * Clear web history in this web view.
*/ */
public void clearHistory() { public void clearHistory() {
this.urls.clear();
this.appView.clearHistory(); this.appView.clearHistory();
// Leave current url on history stack
if (this.url != null) {
this.urls.push(this.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() {
if (this.appView != null) {
return appView.backHistory();
}
return false;
}
@Override @Override
/** /**
@ -662,7 +588,9 @@ public class DroidGap extends Activity implements CordovaInterface {
this.appView.loadUrl("javascript:try{cordova.fireDocumentEvent('pause');}catch(e){console.log('exception firing pause event from native');};"); this.appView.loadUrl("javascript:try{cordova.fireDocumentEvent('pause');}catch(e){console.log('exception firing pause event from native');};");
// Forward to plugins // Forward to plugins
appView.pluginManager.onPause(this.keepRunning); if (this.appView.pluginManager != null) {
this.appView.pluginManager.onPause(this.keepRunning);
}
// If app doesn't want to run in background // If app doesn't want to run in background
if (!this.keepRunning) { if (!this.keepRunning) {
@ -680,7 +608,9 @@ public class DroidGap extends Activity implements CordovaInterface {
super.onNewIntent(intent); super.onNewIntent(intent);
//Forward to plugins //Forward to plugins
appView.pluginManager.onNewIntent(intent); if ((this.appView != null) && (this.appView.pluginManager != null)) {
this.appView.pluginManager.onNewIntent(intent);
}
} }
@Override @Override
@ -703,7 +633,9 @@ public class DroidGap extends Activity implements CordovaInterface {
this.appView.loadUrl("javascript:try{cordova.fireDocumentEvent('resume');}catch(e){console.log('exception firing resume event from native');};"); this.appView.loadUrl("javascript:try{cordova.fireDocumentEvent('resume');}catch(e){console.log('exception firing resume event from native');};");
// Forward to plugins // Forward to plugins
appView.pluginManager.onResume(this.keepRunning || this.activityResultKeepRunning); if (this.appView.pluginManager != null) {
this.appView.pluginManager.onResume(this.keepRunning || this.activityResultKeepRunning);
}
// If app doesn't want to run in background // If app doesn't want to run in background
if (!this.keepRunning || this.activityResultKeepRunning) { if (!this.keepRunning || this.activityResultKeepRunning) {
@ -724,11 +656,11 @@ public class DroidGap extends Activity implements CordovaInterface {
* The final call you receive before your activity is destroyed. * The final call you receive before your activity is destroyed.
*/ */
public void onDestroy() { public void onDestroy() {
LOG.d(TAG, "onDestroy()");
super.onDestroy(); super.onDestroy();
if (this.appView != null) { if (this.appView != null) {
// Send destroy event to JavaScript // Send destroy event to JavaScript
this.appView.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};"); this.appView.loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};");
@ -736,7 +668,9 @@ public class DroidGap extends Activity implements CordovaInterface {
this.appView.loadUrl("about:blank"); this.appView.loadUrl("about:blank");
// Forward to plugins // Forward to plugins
appView.pluginManager.onDestroy(); if (this.appView.pluginManager != null) {
this.appView.pluginManager.onDestroy();
}
} }
else { else {
this.endActivity(); this.endActivity();
@ -750,9 +684,9 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param data The message data * @param data The message data
*/ */
public void postMessage(String id, Object data) { public void postMessage(String id, Object data) {
if (this.appView != null) {
// Forward to plugins this.appView.postMessage(id, data);
appView.pluginManager.postMessage(id, data); }
} }
/** /**
@ -764,9 +698,10 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param serviceType * @param serviceType
* @param className * @param className
*/ */
@Deprecated
public void addService(String serviceType, String className) { public void addService(String serviceType, String className) {
appView.pluginManager.addService(serviceType, className); if (this.appView != null && this.appView.pluginManager != null) {
this.appView.pluginManager.addService(serviceType, className);
}
} }
/** /**
@ -776,9 +711,10 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param message * @param message
*/ */
public void sendJavascript(String statement) { public void sendJavascript(String statement) {
//We need to check for the null case on the Kindle Fire beacuse it changes the width and height on load //We need to check for the null case on the Kindle Fire because it changes the width and height on load
if(this.appView.callbackServer != null) if (this.appView != null && this.appView.callbackServer != null) {
appView.callbackServer.sendJavascript(statement); this.appView.callbackServer.sendJavascript(statement);
}
} }
/** /**
@ -816,11 +752,11 @@ public class DroidGap extends Activity implements CordovaInterface {
*/ */
public void endActivity() { public void endActivity() {
this.activityState = ACTIVITY_EXITING; this.activityState = ACTIVITY_EXITING;
this.finish(); super.finish();
} }
/** /**
* Called when a key is de-pressed. (Key UP) * Called when a key is released. (Key UP)
* *
* @param keyCode * @param keyCode
* @param event * @param event
@ -866,23 +802,6 @@ public class DroidGap extends Activity implements CordovaInterface {
return false; return false;
} }
/**
* Any calls to Activity.startActivityForResult must use method below, so
* the result can be routed to them correctly.
*
* This is done to eliminate the need to modify DroidGap.java to receive activity results.
*
* @param intent The intent to start
* @param requestCode Identifies who to send the result to
*
* @throws RuntimeException
*/
@Override
public void startActivityForResult(Intent intent, int requestCode) throws RuntimeException {
LOG.d(TAG, "DroidGap.startActivityForResult(intent,%d)", requestCode);
super.startActivityForResult(intent, requestCode);
}
/** /**
* Launch an activity for which you would like a result when it finished. When this activity exits, * Launch an activity for which you would like a result when it finished. When this activity exits,
* your onActivityResult() method will be called. * your onActivityResult() method will be called.
@ -937,14 +856,17 @@ public class DroidGap extends Activity implements CordovaInterface {
public void onReceivedError(final int errorCode, final String description, final String failingUrl) { public void onReceivedError(final int errorCode, final String description, final String failingUrl) {
final DroidGap me = this; final DroidGap me = this;
// Stop "app loading" spinner if showing
this.spinnerStop();
// If errorUrl specified, then load it // If errorUrl specified, then load it
final String errorUrl = me.getStringProperty("errorUrl", null); final String errorUrl = me.getStringProperty("errorUrl", null);
if ((errorUrl != null) && (errorUrl.startsWith("file://") || errorUrl.indexOf(me.baseUrl) == 0 || isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) { if ((errorUrl != null) && (errorUrl.startsWith("file://") || errorUrl.indexOf(me.baseUrl) == 0 || this.appView.isUrlWhiteListed(errorUrl)) && (!failingUrl.equals(errorUrl))) {
// Load URL on UI thread // Load URL on UI thread
me.runOnUiThread(new Runnable() { me.runOnUiThread(new Runnable() {
public void run() { public void run() {
me.showWebPage(errorUrl, false, true, null); me.appView.showWebPage(errorUrl, false, true, null);
} }
}); });
} }
@ -975,6 +897,7 @@ public class DroidGap extends Activity implements CordovaInterface {
final DroidGap me = this; final DroidGap me = this;
me.runOnUiThread(new Runnable() { me.runOnUiThread(new Runnable() {
public void run() { public void run() {
try {
AlertDialog.Builder dlg = new AlertDialog.Builder(me); AlertDialog.Builder dlg = new AlertDialog.Builder(me);
dlg.setMessage(message); dlg.setMessage(message);
dlg.setTitle(title); dlg.setTitle(title);
@ -990,68 +913,13 @@ public class DroidGap extends Activity implements CordovaInterface {
}); });
dlg.create(); dlg.create();
dlg.show(); dlg.show();
} catch (Exception e) {
finish();
}
} }
}); });
} }
/**
* 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", 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) {
appView.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");
String readonlyString = xml.getAttributeValue(null, "readonly");
boolean readonly = (readonlyString != null &&
readonlyString.equals("true"));
LOG.i("CordovaLog", "Found preference for %s", name);
preferences.add(new PreferenceNode(name, value, readonly));
}
}
try {
eventType = xml.next();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** /**
* Determine if URL is in approved list of URLs to load. * Determine if URL is in approved list of URLs to load.
* *
@ -1060,63 +928,76 @@ public class DroidGap extends Activity implements CordovaInterface {
*/ */
public boolean isUrlWhiteListed(String url) { public boolean isUrlWhiteListed(String url) {
// Check to see if we have matched url previously // Check to see if we have matched url previously
if (this.appView != null) {
return this.appView.isUrlWhiteListed(url); return this.appView.isUrlWhiteListed(url);
} }
return false;
/* }
* URL stack manipulators
*/
/* /*
* Hook in DroidGap for menu plugins * Hook in DroidGap for menu plugins
* *
*/ */
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) public boolean onCreateOptionsMenu(Menu menu) {
{
this.postMessage("onCreateOptionsMenu", menu); this.postMessage("onCreateOptionsMenu", menu);
return super.onCreateOptionsMenu(menu); return super.onCreateOptionsMenu(menu);
} }
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) public boolean onPrepareOptionsMenu(Menu menu) {
{
this.postMessage("onPrepareOptionsMenu", menu); this.postMessage("onPrepareOptionsMenu", menu);
return super.onPrepareOptionsMenu(menu); return super.onPrepareOptionsMenu(menu);
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) public boolean onOptionsItemSelected(MenuItem item) {
{
this.postMessage("onOptionsItemSelected", item); this.postMessage("onOptionsItemSelected", item);
return true; return true;
} }
/**
* Get Activity context.
*
* @return
*/
public Context getContext() { public Context getContext() {
return this; return this.getContext();
} }
/**
* Override the backbutton.
*
* @param override
*/
public void bindBackButton(boolean override) { public void bindBackButton(boolean override) {
// TODO Auto-generated method stub
this.bound = override; this.bound = override;
} }
/**
* Determine of backbutton is overridden.
*
* @return
*/
public boolean isBackButtonBound() { public boolean isBackButtonBound() {
// TODO Auto-generated method stub
return this.bound; return this.bound;
} }
public boolean backHistory() { /**
return appView.backHistory(); * 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.
public void showWebPage(String url, boolean openExternal, *
boolean clearHistory, HashMap<String, Object> params) { * @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) {
if (this.appView != null) {
appView.showWebPage(url, openExternal, clearHistory, params); appView.showWebPage(url, openExternal, clearHistory, params);
} }
}
protected Dialog splashDialog; protected Dialog splashDialog;
@ -1133,7 +1014,9 @@ public class DroidGap extends Activity implements CordovaInterface {
/** /**
* Shows the splash screen over the full Activity * Shows the splash screen over the full Activity
*/ */
@SuppressWarnings("deprecation")
protected void showSplashScreen(int time) { protected void showSplashScreen(int time) {
// Get reference to display // Get reference to display
Display display = getWindowManager().getDefaultDisplay(); Display display = getWindowManager().getDefaultDisplay();
@ -1161,4 +1044,43 @@ public class DroidGap extends Activity implements CordovaInterface {
} }
}, time); }, time);
} }
/**
* Called when a message is sent to plugin.
*
* @param id The message id
* @param data The message data
* @return Object or null
*/
public Object onMessage(String id, Object data) {
LOG.d(TAG, "onMessage(" + id + "," + data + ")");
if ("splashscreen".equals(id)) {
if ("hide".equals(data.toString())) {
this.removeSplashScreen();
}
else {
this.splashscreen = this.getIntegerProperty("splashscreen", 0);
this.showSplashScreen(this.splashscreenTime);
}
}
else if ("spinner".equals(id)) {
if ("stop".equals(data.toString())) {
this.spinnerStop();
this.appView.setVisibility(View.VISIBLE);
}
}
else if ("onReceivedError".equals(id)) {
JSONObject d = (JSONObject) data;
try {
this.onReceivedError(d.getInt("errorCode"), d.getString("description"), d.getString("url"));
} catch (JSONException e) {
e.printStackTrace();
}
}
else if ("exit".equals(id)) {
this.endActivity();
}
return null;
}
} }

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");
} }
@ -219,6 +217,7 @@ public class FileTransfer extends Plugin {
* @param params key:value pairs of user-defined parameters * @param params key:value pairs of user-defined parameters
* @return FileUploadResult containing result of upload request * @return FileUploadResult containing result of upload request
*/ */
@SuppressWarnings("deprecation")
public FileUploadResult upload(String file, String server, final String fileKey, final String fileName, public FileUploadResult upload(String file, String server, final String fileKey, final String fileName,
final String mimeType, JSONObject params, boolean trustEveryone, boolean chunkedMode) throws IOException, SSLException { final String mimeType, JSONObject params, boolean trustEveryone, boolean chunkedMode) throws IOException, SSLException {
// Create return object // Create return object
@ -280,7 +279,8 @@ public class FileTransfer extends Plugin {
// Handle the other headers // Handle the other headers
try { try {
JSONObject headers = params.getJSONObject("headers"); JSONObject headers = params.getJSONObject("headers");
for (Iterator iter = headers.keys(); iter.hasNext();) for (@SuppressWarnings("rawtypes")
Iterator iter = headers.keys(); iter.hasNext();)
{ {
String headerKey = iter.next().toString(); String headerKey = iter.next().toString();
conn.setRequestProperty(headerKey, headers.getString(headerKey)); conn.setRequestProperty(headerKey, headers.getString(headerKey));
@ -295,14 +295,14 @@ public class FileTransfer extends Plugin {
conn.setRequestProperty("Cookie", cookie); conn.setRequestProperty("Cookie", cookie);
} }
/* /*
* Store the non-file portions of the multipart data as a string, so that we can add it * Store the non-file portions of the multipart data as a string, so that we can add it
* to the contentSize, since it is part of the body of the HTTP request. * to the contentSize, since it is part of the body of the HTTP request.
*/ */
String extraParams = ""; String extraParams = "";
try { try {
for (Iterator iter = params.keys(); iter.hasNext();) { for (@SuppressWarnings("rawtypes")
Iterator iter = params.keys(); iter.hasNext();) {
Object key = iter.next(); Object key = iter.next();
if (key.toString() != "headers") if (key.toString() != "headers")
{ {
@ -336,7 +336,6 @@ public class FileTransfer extends Plugin {
conn.setFixedLengthStreamingMode(fixedLength); conn.setFixedLengthStreamingMode(fixedLength);
} }
dos = new DataOutputStream(conn.getOutputStream()); dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(extraParams); dos.writeBytes(extraParams);
//We don't want to chagne encoding, we just want this to write for all Unicode. //We don't want to chagne encoding, we just want this to write for all Unicode.
@ -473,7 +472,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,21 +37,22 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.content.Context; //import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.os.Environment; import android.os.Environment;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.util.Log; //import android.util.Log;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import android.app.Activity;
//import android.app.Activity;
/** /**
* This class provides SD card file and directory services to JavaScript. * This class provides SD card file and directory services to JavaScript.
* 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
@ -225,7 +226,7 @@ public class FileUtils extends Plugin {
String newFilePath = stripFileProtocol(filePath); String newFilePath = stripFileProtocol(filePath);
int result = this.ctx.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, int result = this.ctx.getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
MediaStore.Images.Media.DATA + " = ?", MediaStore.Images.Media.DATA + " = ?",
new String[] {newFilePath}); new String[] { filePath });
} }
/** /**
@ -238,6 +239,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");
@ -245,7 +247,7 @@ public class FileUtils extends Plugin {
// Handle the special case where you get an Android content:// uri. // Handle the special case where you get an Android content:// uri.
if (decoded.startsWith("content:")) { if (decoded.startsWith("content:")) {
Cursor cursor = ((Activity) this.ctx).managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null); Cursor cursor = this.ctx.getActivity().managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null);
// Note: MediaStore.Images/Audio/Video.Media.DATA is always "_data" // Note: MediaStore.Images/Audio/Video.Media.DATA is always "_data"
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst(); cursor.moveToFirst();
@ -322,7 +324,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");
@ -728,9 +729,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;
@ -819,16 +820,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) {
@ -836,7 +837,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 {
@ -943,7 +944,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);
@ -962,7 +963,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));
} }
/** /**
@ -1026,7 +1027,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);
@ -1041,9 +1042,10 @@ public class FileUtils extends Plugin {
* @param ctx) the current applicaiton context * @param ctx) the current applicaiton context
* @return the full path to the file * @return the full path to the file
*/ */
protected static String getRealPathFromURI(Uri contentUri, Activity ctx) { @SuppressWarnings("deprecation")
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);
} }
@ -150,13 +150,14 @@ public class GeoBroker extends Plugin {
e.printStackTrace(); e.printStackTrace();
} }
return o; return o;
} }
public void win(Location loc, String callbackId) { public void win(Location loc, String callbackId) {
PluginResult result = new PluginResult(PluginResult.Status.OK, this.returnLocationJSON(loc)); PluginResult result = new PluginResult(PluginResult.Status.OK, this.returnLocationJSON(loc));
this.success(result, callbackId); this.success(result, callbackId);
} }
/** /**
* Location failed. Send error back to JavaScript. * Location failed. Send error back to JavaScript.
* *

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;
} }
@ -52,7 +58,10 @@ public class HttpHandler {
HttpGet httpget = new HttpGet(url); HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget); HttpResponse response = httpclient.execute(httpget);
entity = response.getEntity(); entity = response.getEntity();
} catch (Exception e) { e.printStackTrace(); return null; } } catch (Exception e) {
e.printStackTrace();
return null;
}
return entity; return entity;
} }
@ -61,7 +70,7 @@ 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];
@ -72,7 +81,7 @@ public class HttpHandler {
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,10 +17,11 @@
under the License. under the License.
*/ */
package org.apache.cordova; package org.apache.cordova;
import org.apache.cordova.api.LOG; import org.apache.cordova.api.LOG;
import android.content.Context; import android.content.Context;
import android.view.View.MeasureSpec; //import android.view.View.MeasureSpec;
import android.widget.LinearLayout; import android.widget.LinearLayout;
/** /**
@ -87,13 +88,13 @@ public class LinearLayoutSoftKeyboardDetect extends LinearLayout {
// 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;
@ -87,9 +86,9 @@ public class NetworkManager extends Plugin {
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(Context ctx) { public void setContext(CordovaInterface ctx) {
super.setContext(ctx); super.setContext(ctx);
this.sockMan = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); this.sockMan = (ConnectivityManager) ctx.getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
this.connectionCallbackId = null; this.connectionCallbackId = null;
// We need to listen to connectivity events to update navigator.connection // We need to listen to connectivity events to update navigator.connection
@ -97,12 +96,13 @@ public class NetworkManager extends Plugin {
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
* *

View File

@ -31,7 +31,6 @@ import android.media.Ringtone;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.net.Uri; import android.net.Uri;
import android.os.Vibrator; import android.os.Vibrator;
import android.app.Activity;
/** /**
* This class provides access to notifications on the device. * This class provides access to notifications on the device.
@ -144,7 +143,7 @@ public class Notification extends Plugin {
*/ */
public void beep(long count) { public void beep(long count) {
Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); Uri ringtone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone notification = RingtoneManager.getRingtone(this.ctx, ringtone); Ringtone notification = RingtoneManager.getRingtone(this.ctx.getActivity().getBaseContext(), ringtone);
// If phone is not set to silent mode // If phone is not set to silent mode
if (notification != null) { if (notification != null) {
@ -172,7 +171,7 @@ public class Notification extends Plugin {
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);
} }
@ -185,13 +184,13 @@ public class Notification extends Plugin {
*/ */
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 Context 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); 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);
@ -206,7 +205,7 @@ public class Notification extends Plugin {
dlg.show(); dlg.show();
}; };
}; };
((Activity) this.ctx).runOnUiThread(runnable); this.ctx.getActivity().runOnUiThread(runnable);
} }
/** /**
@ -221,13 +220,13 @@ public class Notification extends Plugin {
*/ */
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 Context 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); 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);
@ -270,7 +269,7 @@ public class Notification extends Plugin {
dlg.show(); dlg.show();
}; };
}; };
((Activity) this.ctx).runOnUiThread(runnable); this.ctx.getActivity().runOnUiThread(runnable);
} }
/** /**
@ -285,10 +284,10 @@ public class Notification extends Plugin {
this.spinnerDialog = null; this.spinnerDialog = null;
} }
final Notification notification = this; final Notification notification = this;
final Activity ctx = (Activity) this.ctx; final CordovaInterface ctx = this.ctx;
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
public void run() { public void run() {
notification.spinnerDialog = ProgressDialog.show(ctx, title , message, true, true, notification.spinnerDialog = ProgressDialog.show(ctx.getActivity(), title, message, true, true,
new DialogInterface.OnCancelListener() { new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
notification.spinnerDialog = null; notification.spinnerDialog = null;
@ -296,7 +295,7 @@ public class Notification extends Plugin {
}); });
} }
}; };
ctx.runOnUiThread(runnable); this.ctx.getActivity().runOnUiThread(runnable);
} }
/** /**
@ -321,10 +320,10 @@ public class Notification extends Plugin {
this.progressDialog = null; this.progressDialog = null;
} }
final Notification notification = this; final Notification notification = this;
final Activity ctx = (Activity) this.ctx; final CordovaInterface ctx = this.ctx;
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
public void run() { public void run() {
notification.progressDialog = new ProgressDialog(ctx); notification.progressDialog = new ProgressDialog(ctx.getActivity());
notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); notification.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
notification.progressDialog.setTitle(title); notification.progressDialog.setTitle(title);
notification.progressDialog.setMessage(message); notification.progressDialog.setMessage(message);
@ -340,7 +339,7 @@ public class Notification extends Plugin {
notification.progressDialog.show(); notification.progressDialog.show();
} }
}; };
ctx.runOnUiThread(runnable); this.ctx.getActivity().runOnUiThread(runnable);
} }
/** /**

View File

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

View File

@ -18,9 +18,9 @@
*/ */
package org.apache.cordova; package org.apache.cordova;
import java.lang.reflect.Field; //import java.lang.reflect.Field;
import android.app.Activity; //import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
public class StandAlone extends DroidGap { public class StandAlone extends DroidGap {

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";
@ -169,8 +169,7 @@ public class Storage extends Plugin {
this.processResults(myCursor, tx_id); this.processResults(myCursor, tx_id);
myCursor.close(); myCursor.close();
} }
} } catch (SQLiteException ex) {
catch (SQLiteException ex) {
ex.printStackTrace(); ex.printStackTrace();
System.out.println("Storage.executeSql(): Error=" + ex.getMessage()); System.out.println("Storage.executeSql(): Error=" + ex.getMessage());

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;
@ -49,9 +48,9 @@ public class TempListener extends Plugin implements SensorEventListener {
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(Context ctx) { public void setContext(CordovaInterface ctx) {
super.setContext(ctx); super.setContext(ctx);
this.sensorManager = (SensorManager) ctx.getSystemService(Context.SENSOR_SERVICE); this.sensorManager = (SensorManager) ctx.getActivity().getSystemService(Context.SENSOR_SERVICE);
} }
/** /**
@ -88,6 +87,7 @@ public class TempListener extends Plugin implements SensorEventListener {
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
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,23 +18,8 @@
*/ */
package org.apache.cordova.api; package org.apache.cordova.api;
import java.util.HashMap;
import android.app.Activity; import android.app.Activity;
import android.app.Service;
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.hardware.SensorManager;
import android.net.Uri;
import android.view.Menu;
import android.view.MenuItem;
/** /**
* The Cordova activity abstract class that is extended by DroidGap. * The Cordova activity abstract class that is extended by DroidGap.
@ -42,7 +27,6 @@ import android.view.MenuItem;
*/ */
public interface CordovaInterface { public interface CordovaInterface {
/** /**
* Launch an activity for which you would like a result when it finished. When this activity exits, * Launch an activity for which you would like a result when it finished. When this activity exits,
* your onActivityResult() method will be called. * your onActivityResult() method will be called.
@ -61,138 +45,36 @@ public interface CordovaInterface {
abstract public void setActivityResultCallback(IPlugin plugin); abstract public void setActivityResultCallback(IPlugin plugin);
/** /**
* Causes the Activity to override the back button behaviour * Causes the Activity to override the back button behavior.
*
* @param override * @param override
*/ */
public abstract void bindBackButton(boolean override); public abstract void bindBackButton(boolean override);
/** /**
* A hook required to check if the Back Button is bound * A hook required to check if the Back Button is bound.
*
* @return * @return
*/ */
public abstract boolean isBackButtonBound(); public abstract boolean isBackButtonBound();
/*
* Hook in DroidGap for menu plugins
* (This is in the Android SDK, do we need this on the Interface?)
*/
public abstract boolean onCreateOptionsMenu(Menu menu);
public abstract boolean onPrepareOptionsMenu(Menu menu);
public abstract boolean onOptionsItemSelected(MenuItem item);
/** /**
* @deprecated * Get the Android activity.
* Add services to res/xml/plugins.xml instead.
* *
* Add a class that implements a service. * @return
*
* @param serviceType
* @param className
*/ */
@Deprecated public abstract Activity getActivity();
abstract public void addService(String serviceType, String className);
/**
* @deprecated
* Send JavaScript statement back to JavaScript.
*
* @param message
*/
@Deprecated
abstract public void sendJavascript(String statement);
/**
* @deprecated
* Launch an activity for which you would not like a result when it finished.
*
* @param intent The intent to start
*/
@Deprecated
abstract public void startActivity(Intent intent);
/**
* @deprecated
* Load the specified URL in the Cordova webview.
*
* @param url The URL to load.
*/
@Deprecated
abstract public void loadUrl(String url);
/**
* @deprecated
* Send a message to all plugins.
*
* @param id The message id
* @param data The message data
*/
@Deprecated
abstract public void postMessage(String id, Object data);
@Deprecated
public abstract Resources getResources();
@Deprecated
public abstract String getPackageName();
@Deprecated
public abstract Object getSystemService(String service);
@Deprecated
public abstract Context getContext();
@Deprecated
public abstract Context getBaseContext();
@Deprecated
public abstract Intent registerReceiver(BroadcastReceiver receiver,
IntentFilter intentFilter);
@Deprecated
public abstract ContentResolver getContentResolver();
@Deprecated
public abstract void unregisterReceiver(BroadcastReceiver receiver);
@Deprecated
public abstract Cursor managedQuery(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder);
@Deprecated
public abstract void runOnUiThread(Runnable runnable);
@Deprecated
public abstract AssetManager getAssets();
@Deprecated
public abstract void clearCache();
@Deprecated
public abstract void clearHistory();
@Deprecated
public abstract boolean backHistory();
//public abstract void addWhiteListEntry(String origin, boolean subdomains);
@Deprecated @Deprecated
public abstract void cancelLoadUrl(); public abstract void cancelLoadUrl();
@Deprecated /**
public abstract void showWebPage(String url, boolean openExternal, * Called when a message is sent to plugin.
boolean clearHistory, HashMap<String, Object> params); *
* @param id The message id
@Deprecated * @param data The message data
public abstract Context getApplicationContext(); * @return Object or null
*/
@Deprecated public Object onMessage(String id, Object data);
public abstract boolean isUrlWhiteListed(String source);
} }

View File

@ -21,9 +21,8 @@ package org.apache.cordova.api;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import org.json.JSONArray; import org.json.JSONArray;
import android.content.Context; //import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.webkit.WebView;
/** /**
* Plugin interface must be implemented by any plugin classes. * Plugin interface must be implemented by any plugin classes.
@ -56,7 +55,7 @@ public interface IPlugin {
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
void setContext(Context 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
@ -95,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

@ -21,10 +21,7 @@ package org.apache.cordova.api;
import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaWebView;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import android.content.Context;
import android.content.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.
@ -35,7 +32,7 @@ public abstract class Plugin implements IPlugin {
public String id; public String id;
public CordovaWebView webView; // WebView object public CordovaWebView webView; // WebView object
public Context ctx; // CordovaActivity object public CordovaInterface ctx; // CordovaActivity object
/** /**
* Executes the request and returns PluginResult. * Executes the request and returns PluginResult.
@ -63,7 +60,7 @@ public abstract class Plugin implements IPlugin {
* *
* @param ctx The context of the main Activity. * @param ctx The context of the main Activity.
*/ */
public void setContext(Context ctx) { public void setContext(CordovaInterface ctx) {
this.ctx = ctx; this.ctx = ctx;
} }
@ -110,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;
} }
/** /**
@ -143,7 +142,7 @@ public abstract class Plugin implements IPlugin {
* @param statement * @param statement
*/ */
public void sendJavascript(String statement) { public void sendJavascript(String statement) {
webView.sendJavascript(statement); this.webView.sendJavascript(statement);
} }
/** /**
@ -157,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) {
webView.sendJavascript(pluginResult.toSuccessCallbackString(callbackId)); this.webView.sendJavascript(pluginResult.toSuccessCallbackString(callbackId));
} }
/** /**
@ -167,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) {
webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId));
} }
/** /**
@ -177,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) {
webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.OK, message).toSuccessCallbackString(callbackId));
} }
/** /**
@ -187,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) {
webView.sendJavascript(pluginResult.toErrorCallbackString(callbackId)); this.webView.sendJavascript(pluginResult.toErrorCallbackString(callbackId));
} }
/** /**
@ -197,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) {
webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId));
} }
/** /**
@ -207,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) {
webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId)); this.webView.sendJavascript(new PluginResult(PluginResult.Status.ERROR, message).toErrorCallbackString(callbackId));
} }
} }

View File

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

View File

@ -28,10 +28,8 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import android.webkit.WebView;
/** /**
* PluginManager is exposed to JavaScript in the Cordova WebView. * PluginManager is exposed to JavaScript in the Cordova WebView.
@ -45,7 +43,7 @@ public class PluginManager {
// List of service entries // List of service entries
private final HashMap<String, PluginEntry> entries = new HashMap<String, PluginEntry>(); private final HashMap<String, PluginEntry> entries = new HashMap<String, PluginEntry>();
private final Context ctx; private final CordovaInterface ctx;
private final CordovaWebView app; private final CordovaWebView app;
// Flag to track first time through // Flag to track first time through
@ -61,27 +59,12 @@ public class PluginManager {
* @param app * @param app
* @param ctx * @param ctx
*/ */
public PluginManager(CordovaWebView app, Context ctx) { public PluginManager(CordovaWebView app, CordovaInterface ctx) {
this.ctx = ctx; this.ctx = ctx;
this.app = app; this.app = app;
this.firstRun = true; this.firstRun = true;
} }
public PluginManager(WebView mApp, CordovaInterface mCtx) throws Exception {
this.ctx = mCtx.getContext();
if(CordovaWebView.class.isInstance(mApp))
{
this.app = (CordovaWebView) mApp;
}
else
{
//Throw an exception here
throw new Exception();
}
}
/** /**
* Init when loading a new HTML page into webview. * Init when loading a new HTML page into webview.
*/ */
@ -89,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
@ -109,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;
@ -184,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 Context ctx = this.ctx; //final CordovaInterface ctx = this.ctx;
if (plugin != null) { if (plugin != null) {
runAsync = async && !plugin.isSynch(action); runAsync = async && !plugin.isSynch(action);
if (runAsync) { if (runAsync) {
@ -257,7 +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;
} }
@ -332,14 +314,23 @@ 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;
}
/** /**
* Called when the activity receives a new intent. * Called when the activity receives a new intent.

View File

@ -21,7 +21,7 @@ package org.apache.cordova.api;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import android.util.Log; //import android.util.Log;
public class PluginResult { public class PluginResult {
private final int status; private final int status;

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, 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);