diff --git a/framework/assets/js/cache.js b/framework/assets/js/cache.js
deleted file mode 100644
index 28d55ce2..00000000
--- a/framework/assets/js/cache.js
+++ /dev/null
@@ -1,18 +0,0 @@
-PhoneGap.addPlugin = function(name, obj) {
- if ( !window.plugins ) {
- window.plugins = {};
- }
-
- if ( !window.plugins[name] ) {
- window.plugins[name] = obj;
- }
-}
-
-function Cache() {
-}
-
-Cache.prototype.getCachedPathForURI = function(uri, success, fail) {
- PhoneGap.execAsync(success, fail, 'com.phonegap.api.impl.Cache', 'getCachedPathForURI', [uri]);
-};
-
-PhoneGap.addPlugin('cache', new Cache());
\ No newline at end of file
diff --git a/framework/assets/js/phonegap.js.base b/framework/assets/js/phonegap.js.base
index 0e24a82a..237a19ee 100755
--- a/framework/assets/js/phonegap.js.base
+++ b/framework/assets/js/phonegap.js.base
@@ -136,6 +136,19 @@ PhoneGap.addConstructor = function(func) {
});
};
+/**
+ * Adds a plugin object to window.plugins
+ */
+PhoneGap.addPlugin = function(name, obj) {
+ if ( !window.plugins ) {
+ window.plugins = {};
+ }
+
+ if ( !window.plugins[name] ) {
+ window.plugins[name] = obj;
+ }
+}
+
/**
* onDOMContentLoaded channel is fired when the DOM content
* of the page has been parsed.
@@ -216,23 +229,22 @@ PhoneGap.callbacks = {};
* @param {String[]} [args] Zero or more arguments to pass to the method
*/
PhoneGap.exec = function(clazz, action, args) {
- CommandManager.exec(clazz, action, callbackId, args.join('__PHONEGAP__'), false);
+ CommandManager.exec(clazz, action, callbackId, JSON.stringify(args), false);
};
PhoneGap.execAsync = function(success, fail, clazz, action, args) {
var callbackId = clazz + PhoneGap.callbackId++;
PhoneGap.callbacks[callbackId] = {success:success, fail:fail};
- CommandManager.exec(clazz, action, callbackId, args.join('__PHONEGAP__'), true);
- return callbackId;
+ return CommandManager.exec(clazz, action, callbackId, JSON.stringify(args), true);
};
PhoneGap.callbackSuccess = function(callbackId, args) {
- PhoneGap.callbacks[callbackId].success.apply(this, JSON.parse(args));
+ PhoneGap.callbacks[callbackId].success(args);
delete PhoneGap.callbacks[callbackId];
};
-PhoneGap.callbackFailure = function(callbackId, args) {
- PhoneGap.callbacks[callbackId].fail.apply(this, JSON.parse(args));
+PhoneGap.callbackError = function(callbackId, args) {
+ PhoneGap.callbacks[callbackId].fail(args);
delete PhoneGap.callbacks[callbackId];
};
@@ -353,7 +365,7 @@ PhoneGap.UUIDcreatePart = function(length) {
};
PhoneGap.close = function(context, func, params) {
- if (null == params) {
+ if (typeof params === 'undefined') {
return function() {
return func.apply(context, arguments);
}
diff --git a/framework/assets/js/splashscreen.js b/framework/assets/js/splashscreen.js
new file mode 100644
index 00000000..cf27f765
--- /dev/null
+++ b/framework/assets/js/splashscreen.js
@@ -0,0 +1,5 @@
+PhoneGap.addConstructor(function() {
+ if (typeof navigator.splashScreen == "undefined") {
+ navigator.splashScreen = SplashScreen; // SplashScreen object come from native side through addJavaScriptInterface
+ }
+});
\ No newline at end of file
diff --git a/framework/build.xml b/framework/build.xml
index ce0af6a5..285c1908 100644
--- a/framework/build.xml
+++ b/framework/build.xml
@@ -64,21 +64,53 @@
-->
-
-
+
+
+
+ var alert=function(){},device={},Element={},debug={};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
diff --git a/framework/gen/com/phonegap/R.java b/framework/gen/com/phonegap/R.java
index 81a21810..7db0ceb3 100644
--- a/framework/gen/com/phonegap/R.java
+++ b/framework/gen/com/phonegap/R.java
@@ -12,15 +12,13 @@ public final class R {
}
public static final class drawable {
public static final int icon=0x7f020000;
+ public static final int splash=0x7f020001;
}
public static final class id {
public static final int appView=0x7f050000;
- public static final int go=0x7f050002;
- public static final int surface=0x7f050001;
}
public static final class layout {
public static final int main=0x7f030000;
- public static final int preview=0x7f030001;
}
public static final class string {
public static final int app_name=0x7f040000;
diff --git a/framework/res/drawable/splash.png b/framework/res/drawable/splash.png
new file mode 100755
index 00000000..aa3cbc51
Binary files /dev/null and b/framework/res/drawable/splash.png differ
diff --git a/framework/res/layout/preview.xml b/framework/res/layout/preview.xml
deleted file mode 100644
index f7fe83aa..00000000
--- a/framework/res/layout/preview.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/framework/src/com/phonegap/DroidGap.java b/framework/src/com/phonegap/DroidGap.java
index ce9b7604..8771da3d 100755
--- a/framework/src/com/phonegap/DroidGap.java
+++ b/framework/src/com/phonegap/DroidGap.java
@@ -38,6 +38,7 @@ import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
@@ -53,6 +54,7 @@ import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.GeolocationPermissions.Callback;
import android.webkit.WebSettings.LayoutAlgorithm;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.os.Build.*;
import android.provider.MediaStore;
@@ -61,6 +63,7 @@ public class DroidGap extends Activity {
private static final String LOG_TAG = "DroidGap";
protected WebView appView;
+ protected ImageView splashScreen;
private LinearLayout root;
private Device gap;
@@ -77,39 +80,53 @@ public class DroidGap extends Activity {
private AudioHandler audio;
private CallbackServer callbackServer;
private CommandManager commandManager;
-
+
private Uri imageUri;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(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!
-
- LinearLayout.LayoutParams containerParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.FILL_PARENT, 0.0F);
-
- LinearLayout.LayoutParams webviewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.FILL_PARENT, 1.0F);
-
+
root = new LinearLayout(this);
root.setOrientation(LinearLayout.VERTICAL);
root.setBackgroundColor(Color.BLACK);
- root.setLayoutParams(containerParams);
-
- appView = new WebView(this);
- appView.setLayoutParams(webviewParams);
-
+ root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.FILL_PARENT, 0.0F));
+
+ splashScreen = new ImageView(this);
+ splashScreen.setLayoutParams(new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.FILL_PARENT,
+ 1.0F));
+ splashScreen.setImageResource(R.drawable.splash);
+
+ root.addView(splashScreen);
+
+ initWebView();
+
+ setContentView(root);
+ }
+
+ private void initWebView() {
+ appView = new WebView(DroidGap.this);
+
+ appView.setLayoutParams(new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.FILL_PARENT,
+ 1.0F));
+
WebViewReflect.checkCompatibility();
-
- if (android.os.Build.VERSION.RELEASE.startsWith("2."))
- appView.setWebChromeClient(new EclairClient(this));
- else
- {
- appView.setWebChromeClient(new GapClient(this));
+
+ if (android.os.Build.VERSION.RELEASE.startsWith("2.")) {
+ appView.setWebChromeClient(new EclairClient(DroidGap.this));
+ } else {
+ appView.setWebChromeClient(new GapClient(DroidGap.this));
}
appView.setWebViewClient(new GapViewClient(this));
@@ -131,23 +148,15 @@ public class DroidGap extends Activity {
WebViewReflect.setDomStorage(settings);
// Turn off native geolocation object in browser - we use our own :)
WebViewReflect.setGeolocationEnabled(settings, true);
- /* Bind the appView object to the gap class methods */
+ // Bind the appView object to the gap class methods
bindBrowser(appView);
if(cupcakeStorage != null)
cupcakeStorage.setStorage(appPackage);
-
- root.addView(appView);
// 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
// from the JS side when the JS gets to that code.
appView.loadUrl("javascript:try{PhoneGap.onNativeReady.fire();}catch(e){_nativeReady = true;}");
-
- setContentView(root);
- }
-
- public void invoke(String origin, boolean allow, boolean remember) {
-
}
@Override
@@ -260,6 +269,7 @@ public class DroidGap extends Activity {
appView.addJavascriptInterface(mKey, "BackButton");
appView.addJavascriptInterface(audio, "GapAudio");
appView.addJavascriptInterface(callbackServer, "CallbackServer");
+ //appView.addJavascriptInterface(new SplashScreen(this), "SplashScreen");
if (android.os.Build.VERSION.RELEASE.startsWith("1."))
{
@@ -272,7 +282,7 @@ public class DroidGap extends Activity {
public void loadUrl(String url)
{
- appView.loadUrl(url);
+ this.appView.loadUrl(url);
}
/**
@@ -411,33 +421,39 @@ public class DroidGap extends Activity {
public boolean onKeyDown(int keyCode, KeyEvent event)
{
-
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- if (mKey.isBound())
- {
- //We fire an event here!
- appView.loadUrl("javascript:document.keyEvent.backTrigger()");
- }
- else
- {
- String testUrl = appView.getUrl();
- appView.goBack();
- if(appView.getUrl().equals(testUrl))
- {
- return super.onKeyDown(keyCode, event);
- }
- }
- }
-
- if (keyCode == KeyEvent.KEYCODE_MENU)
- {
- // This is where we launch the menu
- appView.loadUrl("javascript:keyEvent.menuTrigger()");
- }
-
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ if (mKey.isBound())
+ {
+ //We fire an event here!
+ appView.loadUrl("javascript:document.keyEvent.backTrigger()");
+ }
+ else
+ {
+ String testUrl = appView.getUrl();
+ appView.goBack();
+ if(appView.getUrl().equals(testUrl))
+ {
+ return super.onKeyDown(keyCode, event);
+ }
+ }
+ }
+
+ if (keyCode == KeyEvent.KEYCODE_MENU)
+ {
+ // This is where we launch the menu
+ appView.loadUrl("javascript:keyEvent.menuTrigger()");
+ }
return false;
}
+ /**
+ * Removes the splash screen from root view and adds the WebView
+ */
+ public void hideSplashScreen() {
+ root.removeView(splashScreen);
+ root.addView(appView);
+ }
+
// This is required to start the camera activity! It has to come from the previous activity
public void startCamera()
{
@@ -469,11 +485,5 @@ public class DroidGap extends Activity {
{
launcher.failPicture("Did not complete!");
}
- }
-
- public WebView getView()
- {
- return this.appView;
- }
-
+ }
}
diff --git a/framework/src/com/phonegap/SplashScreen.java b/framework/src/com/phonegap/SplashScreen.java
new file mode 100644
index 00000000..98bfd60e
--- /dev/null
+++ b/framework/src/com/phonegap/SplashScreen.java
@@ -0,0 +1,15 @@
+package com.phonegap;
+
+public class SplashScreen {
+ private final DroidGap gap;
+ public SplashScreen(DroidGap gap) {
+ this.gap = gap;
+ }
+ public void hide() {
+ gap.runOnUiThread(new Runnable() {
+ public void run() {
+ gap.hideSplashScreen();
+ }
+ });
+ }
+}
diff --git a/framework/src/com/phonegap/api/Command.java b/framework/src/com/phonegap/api/Command.java
index 479a3535..5c28f43d 100644
--- a/framework/src/com/phonegap/api/Command.java
+++ b/framework/src/com/phonegap/api/Command.java
@@ -1,24 +1,41 @@
package com.phonegap.api;
-import android.content.Context;
+import org.json.JSONArray;
+import android.content.Context;
+import android.webkit.WebView;
+
+/**
+ * Command interface must be implemented by any plugin classes.
+ *
+ * The execute method is called by the CommandManager.
+ *
+ * @author davejohnson
+ *
+ */
public interface Command {
/**
- * Executes the request and returns JS code to change client state.
- *
- * @param action the command to execute
- * @return a string with JavaScript code or null
+ * Executes the request and returns CommandResult.
+ *
+ * @param action The command to execute.
+ * @param args JSONArry of arguments for the command.
+ * @return A CommandResult object with a status and message.
*/
- CommandResult execute(String action, String[] args);
+ CommandResult execute(String action, JSONArray args);
/**
- * Determines if this command can process a request.
- *
- * @param action the command to execute
- *
- * @return true if this command understands the petition
+ * Sets the context of the Command. This can then be used to do things like
+ * get file paths associated with the Activity.
+ *
+ * @param ctx The context of the main Activity.
*/
- boolean accept(String action);
-
void setContext(Context ctx);
+
+ /**
+ * Sets the main View of the application, this is the WebView within which
+ * a PhoneGap app runs.
+ *
+ * @param webView The PhoneGap WebView
+ */
+ void setView(WebView webView);
}
diff --git a/framework/src/com/phonegap/api/CommandManager.java b/framework/src/com/phonegap/api/CommandManager.java
index 58bb146d..9a53f592 100644
--- a/framework/src/com/phonegap/api/CommandManager.java
+++ b/framework/src/com/phonegap/api/CommandManager.java
@@ -1,12 +1,21 @@
package com.phonegap.api;
+import org.json.JSONArray;
+import org.json.JSONException;
+
import android.content.Context;
import android.webkit.WebView;
import com.phonegap.DroidGap;
/**
- * Given a execution request detects matching {@link Command} and executes it.
+ * CommandManager is exposed to JavaScript in the PhoneGap WebView.
+ *
+ * Calling native plugin code can be done by calling CommandManager.exec(...)
+ * from JavaScript.
+ *
+ * @author davejohnson
+ *
*/
public final class CommandManager {
private static final String EXCEPTION_PREFIX = "[PhoneGap] *ERROR* Exception executing command [";
@@ -23,42 +32,57 @@ public final class CommandManager {
}
/**
- * Receives a request for execution and fulfills it as long as one of
- * the configured {@link Command} can understand it. Command precedence
- * is important (just one of them will be executed).
- *
- * @param instruction any API command
- * @return JS code to execute by the client or null
+ * Receives a request for execution and fulfills it by finding the appropriate
+ * Java class and calling it's execute method.
+ *
+ * CommandManager.exec can be used either synchronously or async. In either case, a JSON encoded
+ * string is returned that will indicate if any errors have occurred when trying to find
+ * or execute the class denoted by the clazz argument.
+ *
+ * @param clazz String containing the fully qualified class name. e.g. com.phonegap.FooBar
+ * @param action String containt the action that the class is supposed to perform. This is
+ * passed to the plugin execute method and it is up to the plugin developer
+ * how to deal with it.
+ * @param callbackId String containing the id of the callback that is execute in JavaScript if
+ * this is an async plugin call.
+ * @param args An Array literal string containing any arguments needed in the
+ * plugin execute method.
+ * @param async Boolean indicating whether the calling JavaScript code is expecting an
+ * immediate return value. If true, either PhoneGap.callbackSuccess(...) or PhoneGap.callbackError(...)
+ * is called once the plugin code has executed.
+ * @return JSON encoded string with a response message and status.
*/
public String exec(final String clazz, final String action, final String callbackId,
- final String args, final boolean async) {
+ final String jsonArgs, final boolean async) {
CommandResult cr = null;
try {
- //final WebView wv = this.app;
- final String _callbackId = callbackId;
- final String[] aargs = args.split("__PHONEGAP__");
- Class c = Class.forName(clazz);
- Class[] interfaces = c.getInterfaces();
- for (int j=0; j