You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2013/05/10 01:00:25 UTC
[23/43] 2.6.0rc1 used for libs now. Bumped npm version to 2.6.0.
added androids local.properties to gitignore.
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java b/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java
index 8b023eb..4751fc3 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/CordovaWebViewClient.java
@@ -18,6 +18,7 @@
*/
package org.apache.cordova;
+import java.io.ByteArrayInputStream;
import java.util.Hashtable;
import org.apache.cordova.api.CordovaInterface;
@@ -38,6 +39,7 @@ import android.util.Log;
import android.view.View;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
+import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
@@ -66,7 +68,7 @@ public class CordovaWebViewClient extends WebViewClient {
/**
* Constructor.
- *
+ *
* @param cordova
* @param view
*/
@@ -77,7 +79,7 @@ public class CordovaWebViewClient extends WebViewClient {
/**
* Constructor.
- *
+ *
* @param view
*/
public void setWebView(CordovaWebView view) {
@@ -101,8 +103,8 @@ public class CordovaWebViewClient extends WebViewClient {
String callbackId = url.substring(idx3 + 1, idx4);
String jsonArgs = url.substring(idx4 + 1);
appView.pluginManager.exec(service, action, callbackId, jsonArgs);
- }
-
+ }
+
/**
* Give the host application a chance to take over the control when a new url
* is about to be loaded in the current WebView.
@@ -192,12 +194,8 @@ 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.
// Our app continues to run. When BACK is pressed, our app is redisplayed.
- if (url.startsWith("file://") || url.startsWith("data:") || url.indexOf(this.appView.baseUrl) == 0 || Config.isUrlWhiteListed(url)) {
- //This will fix iFrames
- if (appView.useBrowserHistory || url.startsWith("data:"))
- return false;
- else
- this.appView.loadUrl(url);
+ if (url.startsWith("file://") || url.startsWith("data:") || Config.isUrlWhiteListed(url)) {
+ return false;
}
// If not our application, let default viewer handle
@@ -215,6 +213,34 @@ public class CordovaWebViewClient extends WebViewClient {
}
/**
+ * Check for intercepting any requests for resources.
+ * This includes images and scripts and so on, not just top-level pages.
+ * @param view The WebView.
+ * @param url The URL to be loaded.
+ * @return Either null to proceed as normal, or a WebResourceResponse.
+ */
+ @Override
+ public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
+ //If something isn't whitelisted, just send a blank response
+ if(!Config.isUrlWhiteListed(url) && (url.startsWith("http://") || url.startsWith("https://")))
+ {
+ return getWhitelistResponse();
+ }
+ if (this.appView.pluginManager != null) {
+ return this.appView.pluginManager.shouldInterceptRequest(url);
+ }
+ return null;
+ }
+
+ private WebResourceResponse getWhitelistResponse()
+ {
+ WebResourceResponse emptyResponse;
+ String empty = "";
+ ByteArrayInputStream data = new ByteArrayInputStream(empty.getBytes());
+ return new WebResourceResponse("text/plain", "UTF-8", data);
+ }
+
+ /**
* On received http auth request.
* The method reacts on all registered authentication tokens. There is one and only one authentication token for any host + realm combination
*
@@ -230,7 +256,7 @@ public class CordovaWebViewClient extends WebViewClient {
AuthenticationToken token = this.getAuthenticationToken(host, realm);
if (token != null) {
handler.proceed(token.getUserName(), token.getPassword());
- }
+ }
else {
// Handle 401 like we'd normally do!
super.onReceivedHttpAuthRequest(view, handler, host, realm);
@@ -238,22 +264,16 @@ public class CordovaWebViewClient extends WebViewClient {
}
/**
- * 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.
- *
+ * 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
public void onPageStarted(WebView view, String url, Bitmap favicon) {
- // Clear history so history.back() doesn't do anything.
- // So we can reinit() native side CallbackServer & PluginManager.
- if (!this.appView.useBrowserHistory) {
- view.clearHistory();
- this.doClearHistory = true;
- }
// Flush stale messages.
this.appView.jsMessageQueue.reset();
@@ -270,7 +290,7 @@ public class CordovaWebViewClient extends WebViewClient {
/**
* 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 url The url of the page.
@@ -359,11 +379,11 @@ public class CordovaWebViewClient extends WebViewClient {
}
/**
- * 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.
+ * 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.
@@ -392,27 +412,10 @@ 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
- 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
- * so we do a check here to see if the url should be pushed.
- */
- if (!this.appView.peekAtUrlStack().equals(url)) {
- this.appView.pushUrl(url);
- }
- }
/**
* Sets the authentication token.
- *
+ *
* @param authenticationToken
* @param host
* @param realm
@@ -429,10 +432,10 @@ public class CordovaWebViewClient extends WebViewClient {
/**
* 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) {
@@ -441,16 +444,16 @@ public class CordovaWebViewClient extends WebViewClient {
/**
* 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) {
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/Device.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/Device.java b/lib/cordova-android/framework/src/org/apache/cordova/Device.java
index 5b09c13..ad399f0 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/Device.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/Device.java
@@ -38,7 +38,7 @@ import android.telephony.TelephonyManager;
public class Device extends CordovaPlugin {
public static final String TAG = "Device";
- public static String cordovaVersion = "2.5.0"; // Cordova version
+ public static String cordovaVersion = "2.6.0rc1"; // Cordova version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java b/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java
index 9a7be4e..d4296cb 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/DroidGap.java
@@ -28,6 +28,7 @@ import org.apache.cordova.api.LOG;
import org.json.JSONException;
import org.json.JSONObject;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -332,6 +333,7 @@ public class DroidGap extends Activity implements CordovaInterface {
* @param webViewClient
* @param webChromeClient
*/
+ @SuppressLint("NewApi")
public void init(CordovaWebView webView, CordovaWebViewClient webViewClient, CordovaChromeClient webChromeClient) {
LOG.d(TAG, "DroidGap.init()");
@@ -349,6 +351,12 @@ public class DroidGap extends Activity implements CordovaInterface {
ViewGroup.LayoutParams.MATCH_PARENT,
1.0F));
+ if (this.getBooleanProperty("disallowOverscroll", false)) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
+ this.appView.setOverScrollMode(CordovaWebView.OVER_SCROLL_NEVER);
+ }
+ }
+
// Add web view but make it invisible while loading URL
this.appView.setVisibility(View.INVISIBLE);
this.root.addView(this.appView);
@@ -1054,7 +1062,8 @@ public class DroidGap extends Activity implements CordovaInterface {
{
//Get whatever has focus!
View childView = appView.getFocusedChild();
- if ((appView.isCustomViewShowing() || childView != null ) && keyCode == KeyEvent.KEYCODE_BACK) {
+ if ((appView.isCustomViewShowing() || childView != null ) &&
+ (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU)) {
return appView.onKeyUp(keyCode, event);
} else {
return super.onKeyUp(keyCode, event);
@@ -1074,7 +1083,7 @@ public class DroidGap extends Activity implements CordovaInterface {
//Get whatever has focus!
View childView = appView.getFocusedChild();
//Determine if the focus is on the current view or not
- if (childView != null && keyCode == KeyEvent.KEYCODE_BACK) {
+ if (childView != null && (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU)) {
return appView.onKeyDown(keyCode, event);
}
else
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/FileHelper.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/FileHelper.java b/lib/cordova-android/framework/src/org/apache/cordova/FileHelper.java
new file mode 100644
index 0000000..c10ed96
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/FileHelper.java
@@ -0,0 +1,142 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+package org.apache.cordova;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.webkit.MimeTypeMap;
+
+import org.apache.cordova.api.CordovaInterface;
+import org.apache.cordova.api.LOG;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class FileHelper {
+ private static final String LOG_TAG = "FileUtils";
+ private static final String _DATA = "_data";
+
+ /**
+ * Returns the real path of the given URI string.
+ * If the given URI string represents a content:// URI, the real path is retrieved from the media store.
+ *
+ * @param uriString the URI string of the audio/image/video
+ * @param cordova the current application context
+ * @return the full path to the file
+ */
+ @SuppressWarnings("deprecation")
+ public static String getRealPath(String uriString, CordovaInterface cordova) {
+ String realPath = null;
+
+ if (uriString.startsWith("content://")) {
+ String[] proj = { _DATA };
+ Cursor cursor = cordova.getActivity().managedQuery(Uri.parse(uriString), proj, null, null, null);
+ int column_index = cursor.getColumnIndexOrThrow(_DATA);
+ cursor.moveToFirst();
+ realPath = cursor.getString(column_index);
+ if (realPath == null) {
+ LOG.e(LOG_TAG, "Could get real path for URI string %s", uriString);
+ }
+ } else if (uriString.startsWith("file://")) {
+ realPath = uriString.substring(7);
+ if (realPath.startsWith("/android_asset/")) {
+ LOG.e(LOG_TAG, "Cannot get real path for URI string %s because it is a file:///android_asset/ URI.", uriString);
+ realPath = null;
+ }
+ } else {
+ realPath = uriString;
+ }
+
+ return realPath;
+ }
+
+ /**
+ * Returns the real path of the given URI.
+ * If the given URI is a content:// URI, the real path is retrieved from the media store.
+ *
+ * @param uri the URI of the audio/image/video
+ * @param cordova the current application context
+ * @return the full path to the file
+ */
+ public static String getRealPath(Uri uri, CordovaInterface cordova) {
+ return FileHelper.getRealPath(uri.toString(), cordova);
+ }
+
+ /**
+ * Returns an input stream based on given URI string.
+ *
+ * @param uriString the URI string from which to obtain the input stream
+ * @param cordova the current application context
+ * @return an input stream into the data at the given URI or null if given an invalid URI string
+ * @throws IOException
+ */
+ public static InputStream getInputStreamFromUriString(String uriString, CordovaInterface cordova) throws IOException {
+ if (uriString.startsWith("content")) {
+ Uri uri = Uri.parse(uriString);
+ return cordova.getActivity().getContentResolver().openInputStream(uri);
+ } else if (uriString.startsWith("file:///android_asset/")) {
+ String relativePath = uriString.substring(22);
+ return cordova.getActivity().getAssets().open(relativePath);
+ } else {
+ return new FileInputStream(getRealPath(uriString, cordova));
+ }
+ }
+
+ /**
+ * Removes the "file://" prefix from the given URI string, if applicable.
+ * If the given URI string doesn't have a "file://" prefix, it is returned unchanged.
+ *
+ * @param uriString the URI string to operate on
+ * @return a path without the "file://" prefix
+ */
+ public static String stripFileProtocol(String uriString) {
+ if (uriString.startsWith("file://")) {
+ uriString = uriString.substring(7);
+ }
+ return uriString;
+ }
+
+ /**
+ * Returns the mime type of the data specified by the given URI string.
+ *
+ * @param uriString the URI string of the data
+ * @return the mime type of the specified data
+ */
+ public static String getMimeType(String uriString, CordovaInterface cordova) {
+ String mimeType = null;
+
+ if (uriString.startsWith("content://")) {
+ Uri uri = Uri.parse(uriString);
+ mimeType = cordova.getActivity().getContentResolver().getType(uri);
+ } else {
+ // MimeTypeMap.getFileExtensionFromUrl has a bug that occurs when the filename has a space, so we encode it.
+ // We also convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
+ String encodedUriString = uriString.replace(" ", "%20").toLowerCase();
+ String extension = MimeTypeMap.getFileExtensionFromUrl(encodedUriString);
+ if (extension.equals("3ga")) {
+ mimeType = "audio/3gpp";
+ } else {
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+ }
+ }
+
+ return mimeType;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java b/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
index 623baf8..dba29af 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/FileTransfer.java
@@ -18,6 +18,7 @@
*/
package org.apache.cordova;
+import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
@@ -27,7 +28,9 @@ import java.io.FileOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
@@ -155,6 +158,25 @@ public class FileTransfer extends CordovaPlugin {
return false;
}
+ private static void addHeadersToRequest(URLConnection connection, JSONObject headers) {
+ try {
+ for (Iterator<?> iter = headers.keys(); iter.hasNext(); ) {
+ String headerKey = iter.next().toString();
+ JSONArray headerValues = headers.optJSONArray(headerKey);
+ if (headerValues == null) {
+ headerValues = new JSONArray();
+ headerValues.put(headers.getString(headerKey));
+ }
+ connection.setRequestProperty(headerKey, headerValues.getString(0));
+ for (int i = 1; i < headerValues.length(); ++i) {
+ connection.addRequestProperty(headerKey, headerValues.getString(i));
+ }
+ }
+ } catch (JSONException e1) {
+ // No headers to be manipulated!
+ }
+ }
+
/**
* Uploads the specified file to the server URL provided using an HTTP multipart request.
* @param source Full path of the file on the file system
@@ -196,7 +218,7 @@ public class FileTransfer extends CordovaPlugin {
try {
url = new URL(target);
} catch (MalformedURLException e) {
- JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, 0);
+ JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, null, 0);
Log.e(LOG_TAG, error.toString(), e);
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
return;
@@ -269,22 +291,7 @@ public class FileTransfer extends CordovaPlugin {
// Handle the other headers
if (headers != null) {
- try {
- for (Iterator<?> iter = headers.keys(); iter.hasNext(); ) {
- String headerKey = iter.next().toString();
- JSONArray headerValues = headers.optJSONArray(headerKey);
- if (headerValues == null) {
- headerValues = new JSONArray();
- headerValues.put(headers.getString(headerKey));
- }
- conn.setRequestProperty(headerKey, headerValues.getString(0));
- for (int i = 1; i < headerValues.length(); ++i) {
- conn.addRequestProperty(headerKey, headerValues.getString(i));
- }
- }
- } catch (JSONException e1) {
- // No headers to be manipulated!
- }
+ addHeadersToRequest(conn, headers);
}
/*
@@ -530,18 +537,33 @@ public class FileTransfer extends CordovaPlugin {
private static JSONObject createFileTransferError(int errorCode, String source, String target, URLConnection connection) {
int httpStatus = 0;
-
+ StringBuilder bodyBuilder = new StringBuilder();
+ String body = null;
if (connection != null) {
try {
if (connection instanceof HttpURLConnection) {
httpStatus = ((HttpURLConnection)connection).getResponseCode();
+ InputStream err = ((HttpURLConnection) connection).getErrorStream();
+ if(err != null)
+ {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(err, "UTF-8"));
+ String line = reader.readLine();
+ while(line != null)
+ {
+ bodyBuilder.append(line);
+ line = reader.readLine();
+ if(line != null)
+ bodyBuilder.append('\n');
+ }
+ body = bodyBuilder.toString();
+ }
}
} catch (IOException e) {
Log.w(LOG_TAG, "Error getting HTTP status code from connection.", e);
}
}
- return createFileTransferError(errorCode, source, target, httpStatus);
+ return createFileTransferError(errorCode, source, target, body, httpStatus);
}
/**
@@ -549,13 +571,17 @@ public class FileTransfer extends CordovaPlugin {
* @param errorCode the error
* @return JSONObject containing the error
*/
- private static JSONObject createFileTransferError(int errorCode, String source, String target, Integer httpStatus) {
+ private static JSONObject createFileTransferError(int errorCode, String source, String target, String body, Integer httpStatus) {
JSONObject error = null;
try {
error = new JSONObject();
error.put("code", errorCode);
error.put("source", source);
error.put("target", target);
+ if(body != null)
+ {
+ error.put("body", body);
+ }
if (httpStatus != null) {
error.put("http_status", httpStatus);
}
@@ -594,12 +620,13 @@ public class FileTransfer extends CordovaPlugin {
final boolean trustEveryone = args.optBoolean(2);
final String objectId = args.getString(3);
+ final JSONObject headers = args.optJSONObject(4);
final URL url;
try {
url = new URL(source);
} catch (MalformedURLException e) {
- JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, 0);
+ JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, null, 0);
Log.e(LOG_TAG, error.toString(), e);
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
return;
@@ -608,7 +635,7 @@ public class FileTransfer extends CordovaPlugin {
if (!Config.isUrlWhiteListed(source)) {
Log.w(LOG_TAG, "Source URL is not in white list: '" + source + "'");
- JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, 401);
+ JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, null, 401);
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
return;
}
@@ -671,6 +698,11 @@ public class FileTransfer extends CordovaPlugin {
{
connection.setRequestProperty("cookie", cookie);
}
+
+ // Handle the other headers
+ if (headers != null) {
+ addHeadersToRequest(connection, headers);
+ }
connection.connect();
@@ -718,8 +750,7 @@ public class FileTransfer extends CordovaPlugin {
Log.d(LOG_TAG, "Saved file: " + target);
// create FileEntry object
- FileUtils fileUtil = new FileUtils();
- JSONObject fileEntry = fileUtil.getEntry(file);
+ JSONObject fileEntry = FileUtils.getEntry(file);
result = new PluginResult(PluginResult.Status.OK, fileEntry);
} catch (FileNotFoundException e) {
@@ -826,7 +857,7 @@ public class FileTransfer extends CordovaPlugin {
file.delete();
}
// Trigger the abort callback immediately to minimize latency between it and abort() being called.
- JSONObject error = createFileTransferError(ABORTED_ERR, context.source, context.target, -1);
+ JSONObject error = createFileTransferError(ABORTED_ERR, context.source, context.target, null, -1);
synchronized (context) {
context.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, error));
context.aborted = true;
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java b/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java
index b461b02..2135be9 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/FileUtils.java
@@ -15,18 +15,17 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-*/
+ */
package org.apache.cordova;
-import java.io.*;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.nio.channels.FileChannel;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.util.Log;
import org.apache.commons.codec.binary.Base64;
import org.apache.cordova.api.CallbackContext;
-import org.apache.cordova.api.CordovaInterface;
import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.apache.cordova.file.EncodingException;
@@ -38,23 +37,25 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
-//import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.webkit.MimeTypeMap;
-
-//import android.app.Activity;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.nio.channels.FileChannel;
/**
* This class provides SD card file and directory services to JavaScript.
* Only files on the SD card can be accessed.
*/
public class FileUtils extends CordovaPlugin {
- @SuppressWarnings("unused")
private static final String LOG_TAG = "FileUtils";
- private static final String _DATA = "_data"; // The column name where the file path is stored
public static int NOT_FOUND_ERR = 1;
public static int SECURITY_ERR = 2;
@@ -75,9 +76,6 @@ public class FileUtils extends CordovaPlugin {
public static int RESOURCE = 2;
public static int APPLICATION = 3;
- FileReader f_in;
- FileWriter f_out;
-
/**
* Constructor.
*/
@@ -111,30 +109,29 @@ public class FileUtils extends CordovaPlugin {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
}
else if (action.equals("readAsText")) {
- int start = 0;
- int end = Integer.MAX_VALUE;
- if (args.length() >= 3) {
- start = args.getInt(2);
- }
- if (args.length() >= 4) {
- end = args.getInt(3);
- }
+ String encoding = args.getString(1);
+ int start = args.getInt(2);
+ int end = args.getInt(3);
- String s = this.readAsText(args.getString(0), args.getString(1), start, end);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, s));
+ this.readFileAs(args.getString(0), start, end, callbackContext, encoding, PluginResult.MESSAGE_TYPE_STRING);
}
else if (action.equals("readAsDataURL")) {
- int start = 0;
- int end = Integer.MAX_VALUE;
- if (args.length() >= 2) {
- start = args.getInt(1);
- }
- if (args.length() >= 3) {
- end = args.getInt(2);
- }
+ int start = args.getInt(1);
+ int end = args.getInt(2);
+
+ this.readFileAs(args.getString(0), start, end, callbackContext, null, -1);
+ }
+ else if (action.equals("readAsArrayBuffer")) {
+ int start = args.getInt(1);
+ int end = args.getInt(2);
- String s = this.readAsDataURL(args.getString(0), start, end);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, s));
+ this.readFileAs(args.getString(0), start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_ARRAYBUFFER);
+ }
+ else if (action.equals("readAsBinaryString")) {
+ int start = args.getInt(1);
+ int end = args.getInt(2);
+
+ this.readFileAs(args.getString(0), start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_BINARYSTRING);
}
else if (action.equals("write")) {
long fileSize = this.write(args.getString(0), args.getString(1), args.getInt(2));
@@ -237,11 +234,11 @@ public class FileUtils extends CordovaPlugin {
* @param filePath the path to check
*/
private void notifyDelete(String filePath) {
- String newFilePath = getRealPathFromURI(Uri.parse(filePath), cordova);
+ String newFilePath = FileHelper.getRealPath(filePath, cordova);
try {
this.cordova.getActivity().getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- MediaStore.Images.Media.DATA + " = ?",
- new String[] { newFilePath });
+ MediaStore.Images.Media.DATA + " = ?",
+ new String[] { newFilePath });
} catch (UnsupportedOperationException t) {
// Was seeing this on the File mobile-spec tests on 4.0.3 x86 emulator.
// The ContentResolver applies only when the file was registered in the
@@ -344,8 +341,8 @@ public class FileUtils extends CordovaPlugin {
* @throws FileExistsException
*/
private JSONObject transferTo(String fileName, String newParent, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
- String newFileName = getRealPathFromURI(Uri.parse(fileName), cordova);
- newParent = getRealPathFromURI(Uri.parse(newParent), cordova);
+ String newFileName = FileHelper.getRealPath(fileName, cordova);
+ newParent = FileHelper.getRealPath(newParent, cordova);
// Check for invalid file name
if (newName != null && newName.contains(":")) {
@@ -384,14 +381,14 @@ public class FileUtils extends CordovaPlugin {
}
} else {
if (move) {
- JSONObject newFileEntry = moveFile(source, destination);
+ JSONObject newFileEntry = moveFile(source, destination);
- // If we've moved a file given its content URI, we need to clean up.
- if (fileName.startsWith("content://")) {
- notifyDelete(fileName);
- }
+ // If we've moved a file given its content URI, we need to clean up.
+ if (fileName.startsWith("content://")) {
+ notifyDelete(fileName);
+ }
- return newFileEntry;
+ return newFileEntry;
} else {
return copyFile(source, destination);
}
@@ -748,7 +745,7 @@ public class FileUtils extends CordovaPlugin {
if (fileName.startsWith("/")) {
fp = new File(fileName);
} else {
- dirPath = getRealPathFromURI(Uri.parse(dirPath), cordova);
+ dirPath = FileHelper.getRealPath(dirPath, cordova);
fp = new File(dirPath + File.separator + fileName);
}
return fp;
@@ -763,7 +760,7 @@ public class FileUtils extends CordovaPlugin {
* @throws JSONException
*/
private JSONObject getParent(String filePath) throws JSONException {
- filePath = getRealPathFromURI(Uri.parse(filePath), cordova);
+ filePath = FileHelper.getRealPath(filePath, cordova);
if (atRootDirectory(filePath)) {
return getEntry(filePath);
@@ -779,7 +776,7 @@ public class FileUtils extends CordovaPlugin {
* @return true if we are at the root, false otherwise.
*/
private boolean atRootDirectory(String filePath) {
- filePath = getRealPathFromURI(Uri.parse(filePath), cordova);
+ filePath = FileHelper.getRealPath(filePath, cordova);
if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + cordova.getActivity().getPackageName() + "/cache") ||
filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath()) ||
@@ -790,26 +787,13 @@ public class FileUtils extends CordovaPlugin {
}
/**
- * This method removes the "file://" from the passed in filePath
- *
- * @param filePath to be checked.
- * @return
- */
- public static String stripFileProtocol(String filePath) {
- if (filePath.startsWith("file://")) {
- filePath = filePath.substring(7);
- }
- return filePath;
- }
-
- /**
* Create a File object from the passed in path
*
* @param filePath
* @return
*/
private File createFileObject(String filePath) {
- filePath = getRealPathFromURI(Uri.parse(filePath), cordova);
+ filePath = FileHelper.getRealPath(filePath, cordova);
File file = new File(filePath);
return file;
@@ -849,7 +833,7 @@ public class FileUtils extends CordovaPlugin {
JSONObject metadata = new JSONObject();
metadata.put("size", file.length());
- metadata.put("type", getMimeType(filePath));
+ metadata.put("type", FileHelper.getMimeType(filePath, cordova));
metadata.put("name", file.getName());
metadata.put("fullPath", filePath);
metadata.put("lastModifiedDate", file.lastModified());
@@ -900,21 +884,21 @@ public class FileUtils extends CordovaPlugin {
}
/**
- * Returns a JSON Object representing a directory on the device's file system
+ * Returns a JSON object representing the given File.
*
- * @param path to the directory
- * @return
+ * @param file the File to convert
+ * @return a JSON representation of the given File
* @throws JSONException
*/
- public JSONObject getEntry(File file) throws JSONException {
+ public static JSONObject getEntry(File file) throws JSONException {
JSONObject entry = new JSONObject();
entry.put("isFile", file.isFile());
entry.put("isDirectory", file.isDirectory());
entry.put("name", file.getName());
entry.put("fullPath", "file://" + file.getAbsolutePath());
- // I can't add the next thing it as it would be an infinite loop
- //entry.put("filesystem", null);
+ // The file system can't be specified, as it would lead to an infinite loop.
+ // entry.put("filesystem", null);
return entry;
}
@@ -930,123 +914,83 @@ public class FileUtils extends CordovaPlugin {
return getEntry(new File(path));
}
- /**
- * Identifies if action to be executed returns a value and should be run synchronously.
- *
- * @param action The action to execute
- * @return T=returns value
- */
- public boolean isSynch(String action) {
- if (action.equals("testSaveLocationExists")) {
- return true;
- }
- else if (action.equals("getFreeDiskSpace")) {
- return true;
- }
- else if (action.equals("testFileExists")) {
- return true;
- }
- else if (action.equals("testDirectoryExists")) {
- return true;
- }
- return false;
- }
//--------------------------------------------------------------------------
// LOCAL METHODS
//--------------------------------------------------------------------------
/**
- * Read content of text file.
+ * Read the contents of a file.
+ * This is done in a background thread; the result is sent to the callback.
*
- * @param filename The name of the file.
- * @param encoding The encoding to return contents as. Typical value is UTF-8.
- * (see http://www.iana.org/assignments/character-sets)
- * @param start Start position in the file.
- * @param end End position to stop at (exclusive).
- * @return Contents of file.
- * @throws FileNotFoundException, IOException
+ * @param filename The name of the file.
+ * @param start Start position in the file.
+ * @param end End position to stop at (exclusive).
+ * @param callbackContext The context through which to send the result.
+ * @param encoding The encoding to return contents as. Typical value is UTF-8. (see http://www.iana.org/assignments/character-sets)
+ * @param resultType The desired type of data to send to the callback.
+ * @return Contents of file.
*/
- public String readAsText(String filename, String encoding, int start, int end) throws FileNotFoundException, IOException {
- int diff = end - start;
- byte[] bytes = new byte[1000];
- BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- int numRead = 0;
-
- if (start > 0) {
- bis.skip(start);
- }
-
- while ( diff > 0 && (numRead = bis.read(bytes, 0, Math.min(1000, diff))) >= 0) {
- diff -= numRead;
- bos.write(bytes, 0, numRead);
- }
-
- return new String(bos.toByteArray(), encoding);
+ public void readFileAs(final String filename, final int start, final int end, final CallbackContext callbackContext, final String encoding, final int resultType) {
+ this.cordova.getThreadPool().execute(new Runnable() {
+ public void run() {
+ try {
+ byte[] bytes = readAsBinaryHelper(filename, start, end);
+
+ PluginResult result;
+ switch (resultType) {
+ case PluginResult.MESSAGE_TYPE_STRING:
+ result = new PluginResult(PluginResult.Status.OK, new String(bytes, encoding));
+ break;
+ case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
+ result = new PluginResult(PluginResult.Status.OK, bytes);
+ break;
+ case PluginResult.MESSAGE_TYPE_BINARYSTRING:
+ result = new PluginResult(PluginResult.Status.OK, bytes, true);
+ break;
+ default: // Base64.
+ String contentType = FileHelper.getMimeType(filename, cordova);
+ byte[] base64 = Base64.encodeBase64(bytes);
+ String s = "data:" + contentType + ";base64," + new String(base64, "US-ASCII");
+ result = new PluginResult(PluginResult.Status.OK, s);
+ }
+
+ callbackContext.sendPluginResult(result);
+ } catch (FileNotFoundException e) {
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_FOUND_ERR));
+ } catch (IOException e) {
+ Log.d(LOG_TAG, e.getLocalizedMessage());
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
+ }
+ }
+ });
}
/**
- * Read content of text file and return as base64 encoded data url.
+ * Read the contents of a file as binary.
+ * This is done synchronously; the result is returned.
*
- * @param filename The name of the file.
- * @return Contents of file = data:<media type>;base64,<data>
- * @throws FileNotFoundException, IOException
+ * @param filename The name of the file.
+ * @param start Start position in the file.
+ * @param end End position to stop at (exclusive).
+ * @return Contents of the file as a byte[].
+ * @throws IOException
*/
- public String readAsDataURL(String filename, int start, int end) throws FileNotFoundException, IOException {
- int diff = end - start;
- byte[] bytes = new byte[1000];
- BufferedInputStream bis = new BufferedInputStream(getPathFromUri(filename), 1024);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- int numRead = 0;
+ private byte[] readAsBinaryHelper(String filename, int start, int end) throws IOException {
+ int numBytesToRead = end - start;
+ byte[] bytes = new byte[numBytesToRead];
+ InputStream inputStream = FileHelper.getInputStreamFromUriString(filename, cordova);
+ int numBytesRead = 0;
if (start > 0) {
- bis.skip(start);
- }
-
- while (diff > 0 && (numRead = bis.read(bytes, 0, Math.min(1000, diff))) >= 0) {
- diff -= numRead;
- bos.write(bytes, 0, numRead);
+ inputStream.skip(start);
}
- // Determine content type from file name
- String contentType = null;
- if (filename.startsWith("content:")) {
- Uri fileUri = Uri.parse(filename);
- contentType = this.cordova.getActivity().getContentResolver().getType(fileUri);
- }
- else {
- contentType = getMimeType(filename);
+ while (numBytesToRead > 0 && (numBytesRead = inputStream.read(bytes, numBytesRead, numBytesToRead)) >= 0) {
+ numBytesToRead -= numBytesRead;
}
- byte[] base64 = Base64.encodeBase64(bos.toByteArray());
- String data = "data:" + contentType + ";base64," + new String(base64);
- return data;
- }
-
- /**
- * Looks up the mime type of a given file name.
- *
- * @param filename
- * @return a mime type
- */
- public static String getMimeType(String filename) {
- if (filename != null) {
- // Stupid bug in getFileExtensionFromUrl when the file name has a space
- // So we need to replace the space with a url encoded %20
-
- // CB-2185: Stupid bug not putting JPG extension in the mime-type map
- String url = filename.replace(" ", "%20").toLowerCase();
- MimeTypeMap map = MimeTypeMap.getSingleton();
- String extension = MimeTypeMap.getFileExtensionFromUrl(url);
- if (extension.toLowerCase().equals("3ga")) {
- return "audio/3gpp";
- } else {
- return map.getMimeTypeFromExtension(extension);
- }
- } else {
- return "";
- }
+ return bytes;
}
/**
@@ -1060,11 +1004,11 @@ public class FileUtils extends CordovaPlugin {
*/
/**/
public long write(String filename, String data, int offset) throws FileNotFoundException, IOException, NoModificationAllowedException {
- if (filename.startsWith("content://")) {
- throw new NoModificationAllowedException("Couldn't write to file given its content URI");
- }
+ if (filename.startsWith("content://")) {
+ throw new NoModificationAllowedException("Couldn't write to file given its content URI");
+ }
- filename = getRealPathFromURI(Uri.parse(filename), cordova);
+ filename = FileHelper.getRealPath(filename, cordova);
boolean append = false;
if (offset > 0) {
@@ -1093,11 +1037,11 @@ public class FileUtils extends CordovaPlugin {
* @throws NoModificationAllowedException
*/
private long truncateFile(String filename, long size) throws FileNotFoundException, IOException, NoModificationAllowedException {
- if (filename.startsWith("content://")) {
- throw new NoModificationAllowedException("Couldn't truncate file given its content URI");
- }
+ if (filename.startsWith("content://")) {
+ throw new NoModificationAllowedException("Couldn't truncate file given its content URI");
+ }
- filename = getRealPathFromURI(Uri.parse(filename), cordova);
+ filename = FileHelper.getRealPath(filename, cordova);
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
try {
@@ -1112,48 +1056,4 @@ public class FileUtils extends CordovaPlugin {
raf.close();
}
}
-
- /**
- * Get an input stream based on file path or content:// uri
- *
- * @param path
- * @return an input stream
- * @throws FileNotFoundException
- */
- private InputStream getPathFromUri(String path) throws FileNotFoundException {
- if (path.startsWith("content")) {
- Uri uri = Uri.parse(path);
- return cordova.getActivity().getContentResolver().openInputStream(uri);
- }
- else {
- path = getRealPathFromURI(Uri.parse(path), cordova);
- return new FileInputStream(path);
- }
- }
-
- /**
- * Queries the media store to find out what the file path is for the Uri we supply
- *
- * @param contentUri the Uri of the audio/image/video
- * @param cordova the current application context
- * @return the full path to the file
- */
- @SuppressWarnings("deprecation")
- protected static String getRealPathFromURI(Uri contentUri, CordovaInterface cordova) {
- final String scheme = contentUri.getScheme();
-
- if (scheme == null) {
- return contentUri.toString();
- } else if (scheme.compareTo("content") == 0) {
- String[] proj = { _DATA };
- Cursor cursor = cordova.getActivity().managedQuery(contentUri, proj, null, null, null);
- int column_index = cursor.getColumnIndexOrThrow(_DATA);
- cursor.moveToFirst();
- return cursor.getString(column_index);
- } else if (scheme.compareTo("file") == 0) {
- return contentUri.getPath();
- } else {
- return contentUri.toString();
- }
- }
}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java b/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java
index 86aa628..e7cdce0 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/GeoBroker.java
@@ -150,7 +150,7 @@ public class GeoBroker extends CordovaPlugin {
o.put("altitude", (loc.hasAltitude() ? loc.getAltitude() : null));
o.put("accuracy", loc.getAccuracy());
o.put("heading", (loc.hasBearing() ? (loc.hasSpeed() ? loc.getBearing() : null) : null));
- o.put("speed", loc.getSpeed());
+ o.put("velocity", loc.getSpeed());
o.put("timestamp", loc.getTime());
} catch (JSONException e) {
// TODO Auto-generated catch block
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java b/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
index a96b242..2142714 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/IceCreamCordovaWebViewClient.java
@@ -42,7 +42,7 @@ public class IceCreamCordovaWebViewClient extends CordovaWebViewClient {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
- if(url.contains("?") || url.contains("#")){
+ if(url.contains("?") || url.contains("#") || needsIceCreamSpaceInAssetUrlFix(url)){
return generateWebResourceResponse(url);
} else {
return super.shouldInterceptRequest(view, url);
@@ -80,4 +80,18 @@ public class IceCreamCordovaWebViewClient extends CordovaWebViewClient {
return null;
}
+ private static boolean needsIceCreamSpaceInAssetUrlFix(String url) {
+ if (!url.contains("%20")){
+ return false;
+ }
+
+ switch(android.os.Build.VERSION.SDK_INT){
+ case android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH:
+ case android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1:
+ return true;
+ default:
+ return false;
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/InAppBrowser.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/InAppBrowser.java b/lib/cordova-android/framework/src/org/apache/cordova/InAppBrowser.java
index 7e7f862..48e27c6 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/InAppBrowser.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/InAppBrowser.java
@@ -35,7 +35,9 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.Color;
import android.net.Uri;
+import android.os.Bundle;
import android.text.InputType;
import android.util.Log;
import android.util.TypedValue;
@@ -48,6 +50,7 @@ import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebChromeClient;
+import android.webkit.GeolocationPermissions.Callback;
import android.webkit.WebSettings;
import android.webkit.WebStorage;
import android.webkit.WebView;
@@ -69,6 +72,8 @@ public class InAppBrowser extends CordovaPlugin {
private static final String EXIT_EVENT = "exit";
private static final String LOAD_START_EVENT = "loadstart";
private static final String LOAD_STOP_EVENT = "loadstop";
+ private static final String LOAD_ERROR_EVENT = "loaderror";
+ private static final String CLOSE_BUTTON_CAPTION = "closebuttoncaption";
private long MAX_QUOTA = 100 * 1024 * 1024;
private Dialog dialog;
@@ -76,6 +81,7 @@ public class InAppBrowser extends CordovaPlugin {
private EditText edittext;
private boolean showLocationBar = true;
private CallbackContext callbackContext;
+ private String buttonLabel = "Done";
/**
* Executes the request and returns PluginResult.
@@ -174,8 +180,12 @@ public class InAppBrowser extends CordovaPlugin {
option = new StringTokenizer(features.nextToken(), "=");
if (option.hasMoreElements()) {
String key = option.nextToken();
- Boolean value = option.nextToken().equals("no") ? Boolean.FALSE : Boolean.TRUE;
- map.put(key, value);
+ if (key.equalsIgnoreCase(CLOSE_BUTTON_CAPTION)) {
+ this.buttonLabel = option.nextToken();
+ } else {
+ Boolean value = option.nextToken().equals("no") ? Boolean.FALSE : Boolean.TRUE;
+ map.put(key, value);
+ }
}
}
return map;
@@ -221,6 +231,7 @@ public class InAppBrowser extends CordovaPlugin {
*/
private void closeDialog() {
try {
+ this.inAppWebView.loadUrl("about:blank");
JSONObject obj = new JSONObject();
obj.put("type", EXIT_EVENT);
@@ -289,7 +300,10 @@ public class InAppBrowser extends CordovaPlugin {
// Determine if we should hide the location bar.
showLocationBar = true;
if (features != null) {
- showLocationBar = features.get(LOCATION).booleanValue();
+ Boolean show = features.get(LOCATION);
+ if (show != null) {
+ showLocationBar = show.booleanValue();
+ }
}
final CordovaWebView thatWebView = this.webView;
@@ -405,7 +419,7 @@ public class InAppBrowser extends CordovaPlugin {
close.setLayoutParams(closeLayoutParams);
forward.setContentDescription("Close Button");
close.setId(5);
- close.setText("Done");
+ close.setText(buttonLabel);
close.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
closeDialog();
@@ -428,10 +442,18 @@ public class InAppBrowser extends CordovaPlugin {
*/
// @TODO: replace with settings.setPluginState(android.webkit.WebSettings.PluginState.ON)
settings.setPluginsEnabled(true);
- settings.setDatabaseEnabled(true);
- String databasePath = cordova.getActivity().getApplicationContext().getDir("inAppBrowserDB", Context.MODE_PRIVATE).getPath();
- settings.setDatabasePath(databasePath);
+
+ //Toggle whether this is enabled or not!
+ Bundle appSettings = cordova.getActivity().getIntent().getExtras();
+ boolean enableDatabase = appSettings.getBoolean("InAppBrowserStorageEnabled", true);
+ if(enableDatabase)
+ {
+ String databasePath = cordova.getActivity().getApplicationContext().getDir("inAppBrowserDB", Context.MODE_PRIVATE).getPath();
+ settings.setDatabasePath(databasePath);
+ settings.setDatabaseEnabled(true);
+ }
settings.setDomStorageEnabled(true);
+
inAppWebView.loadUrl(url);
inAppWebView.setId(6);
inAppWebView.getSettings().setLoadWithOverviewMode(true);
@@ -472,16 +494,24 @@ public class InAppBrowser extends CordovaPlugin {
}
/**
- * Create a new plugin result and send it back to JavaScript
+ * Create a new plugin success result and send it back to JavaScript
*
* @param obj a JSONObject contain event payload information
*/
private void sendUpdate(JSONObject obj, boolean keepCallback) {
- PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
+ sendUpdate(obj, keepCallback, PluginResult.Status.OK);
+ }
+
+ /**
+ * Create a new plugin result and send it back to JavaScript
+ *
+ * @param obj a JSONObject contain event payload information
+ * @param status the status code to return to the JavaScript environment
+ */ private void sendUpdate(JSONObject obj, boolean keepCallback, PluginResult.Status status) {
+ PluginResult result = new PluginResult(status, obj);
result.setKeepCallback(keepCallback);
this.callbackContext.sendPluginResult(result);
}
-
public class InAppChromeClient extends WebChromeClient {
/**
@@ -514,6 +544,18 @@ public class InAppBrowser extends CordovaPlugin {
quotaUpdater.updateQuota(currentQuota);
}
}
+
+ /**
+ * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
+ *
+ * @param origin
+ * @param callback
+ */
+ @Override
+ public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
+ super.onGeolocationPermissionsShowPrompt(origin, callback);
+ callback.invoke(origin, true, false);
+ }
}
/**
@@ -543,10 +585,62 @@ public class InAppBrowser extends CordovaPlugin {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
- String newloc;
+ String newloc = "";
if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
newloc = url;
- } else {
+ }
+ // If dialing phone (tel:5551212)
+ else if (url.startsWith(WebView.SCHEME_TEL)) {
+ try {
+ Intent intent = new Intent(Intent.ACTION_DIAL);
+ intent.setData(Uri.parse(url));
+ cordova.getActivity().startActivity(intent);
+ } catch (android.content.ActivityNotFoundException e) {
+ LOG.e(LOG_TAG, "Error dialing " + url + ": " + e.toString());
+ }
+ }
+
+ else if (url.startsWith("geo:") || url.startsWith(WebView.SCHEME_MAILTO) || url.startsWith("market:")) {
+ try {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ cordova.getActivity().startActivity(intent);
+ } catch (android.content.ActivityNotFoundException e) {
+ LOG.e(LOG_TAG, "Error with " + url + ": " + e.toString());
+ }
+ }
+ // If sms:5551212?body=This is the message
+ else if (url.startsWith("sms:")) {
+ try {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+
+ // Get address
+ String address = null;
+ int parmIndex = url.indexOf('?');
+ if (parmIndex == -1) {
+ address = url.substring(4);
+ }
+ else {
+ address = url.substring(4, parmIndex);
+
+ // If body, then set sms body
+ Uri uri = Uri.parse(url);
+ String query = uri.getQuery();
+ if (query != null) {
+ if (query.startsWith("body=")) {
+ intent.putExtra("sms_body", query.substring(5));
+ }
+ }
+ }
+ intent.setData(Uri.parse("sms:" + address));
+ intent.putExtra("address", address);
+ intent.setType("vnd.android-dir/mms-sms");
+ cordova.getActivity().startActivity(intent);
+ } catch (android.content.ActivityNotFoundException e) {
+ LOG.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
+ }
+ }
+ else {
newloc = "http://" + url;
}
@@ -578,5 +672,22 @@ public class InAppBrowser extends CordovaPlugin {
Log.d(LOG_TAG, "Should never happen");
}
}
+
+ public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+ super.onReceivedError(view, errorCode, description, failingUrl);
+
+ try {
+ JSONObject obj = new JSONObject();
+ obj.put("type", LOAD_ERROR_EVENT);
+ obj.put("url", failingUrl);
+ obj.put("code", errorCode);
+ obj.put("message", description);
+
+ sendUpdate(obj, true, PluginResult.Status.ERROR);
+ } catch (JSONException ex) {
+ Log.d(LOG_TAG, "Should never happen");
+ }
+
+ }
}
}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/JSONUtils.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/JSONUtils.java b/lib/cordova-android/framework/src/org/apache/cordova/JSONUtils.java
new file mode 100644
index 0000000..77df876
--- /dev/null
+++ b/lib/cordova-android/framework/src/org/apache/cordova/JSONUtils.java
@@ -0,0 +1,24 @@
+package org.apache.cordova;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+
+public class JSONUtils {
+ public static List<String> toStringList(JSONArray array) throws JSONException {
+ if(array == null) {
+ return null;
+ }
+ else {
+ List<String> list = new ArrayList<String>();
+
+ for (int i = 0; i < array.length(); i++) {
+ list.add(array.get(i).toString());
+ }
+
+ return list;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/NativeToJsMessageQueue.java b/lib/cordova-android/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
index 83e1778..ea684a4 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/NativeToJsMessageQueue.java
@@ -409,6 +409,9 @@ public class NativeToJsMessageQueue {
case PluginResult.MESSAGE_TYPE_STRING: // s
ret += 1 + pluginResult.getStrMessage().length();
break;
+ case PluginResult.MESSAGE_TYPE_BINARYSTRING:
+ ret += 1 + pluginResult.getMessage().length();
+ break;
case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
ret += 1 + pluginResult.getMessage().length();
break;
@@ -451,7 +454,11 @@ public class NativeToJsMessageQueue {
sb.append('s');
sb.append(pluginResult.getStrMessage());
break;
- case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
+ case PluginResult.MESSAGE_TYPE_BINARYSTRING: // S
+ sb.append('S');
+ sb.append(pluginResult.getMessage());
+ break;
+ case PluginResult.MESSAGE_TYPE_ARRAYBUFFER: // A
sb.append('A');
sb.append(pluginResult.getMessage());
break;
@@ -473,9 +480,9 @@ public class NativeToJsMessageQueue {
.append(success)
.append(",")
.append(status)
- .append(",")
+ .append(",[")
.append(pluginResult.getMessage())
- .append(",")
+ .append("],")
.append(pluginResult.getKeepCallback())
.append(");");
}
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/Notification.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/Notification.java b/lib/cordova-android/framework/src/org/apache/cordova/Notification.java
index 958ab26..9d96062 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/Notification.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/Notification.java
@@ -24,6 +24,7 @@ import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
+import org.json.JSONObject;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
@@ -32,6 +33,7 @@ import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Vibrator;
+import android.widget.EditText;
/**
* This class provides access to notifications on the device.
@@ -68,7 +70,11 @@ public class Notification extends CordovaPlugin {
return true;
}
else if (action.equals("confirm")) {
- this.confirm(args.getString(0), args.getString(1), args.getString(2), callbackContext);
+ this.confirm(args.getString(0), args.getString(1), args.getJSONArray(2), callbackContext);
+ return true;
+ }
+ else if (action.equals("prompt")) {
+ this.prompt(args.getString(0), args.getString(1), args.getJSONArray(2), callbackContext);
return true;
}
else if (action.equals("activityStart")) {
@@ -170,7 +176,7 @@ public class Notification extends CordovaPlugin {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 0));
}
});
-
+
dlg.create();
dlg.show();
};
@@ -188,10 +194,9 @@ public class Notification extends CordovaPlugin {
* @param buttonLabels A comma separated list of button labels (Up to 3 buttons)
* @param callbackContext The callback context.
*/
- public synchronized void confirm(final String message, final String title, String buttonLabels, final CallbackContext callbackContext) {
+ public synchronized void confirm(final String message, final String title, final JSONArray buttonLabels, final CallbackContext callbackContext) {
final CordovaInterface cordova = this.cordova;
- final String[] fButtons = buttonLabels.split(",");
Runnable runnable = new Runnable() {
public void run() {
@@ -201,37 +206,43 @@ public class Notification extends CordovaPlugin {
dlg.setCancelable(true);
// First button
- if (fButtons.length > 0) {
- dlg.setNegativeButton(fButtons[0],
- new AlertDialog.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 1));
- }
- });
+ if (buttonLabels.length() > 0) {
+ try {
+ dlg.setNegativeButton(buttonLabels.getString(0),
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 1));
+ }
+ });
+ } catch (JSONException e) { }
}
// Second button
- if (fButtons.length > 1) {
- dlg.setNeutralButton(fButtons[1],
- new AlertDialog.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 2));
- }
- });
+ if (buttonLabels.length() > 1) {
+ try {
+ dlg.setNeutralButton(buttonLabels.getString(1),
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 2));
+ }
+ });
+ } catch (JSONException e) { }
}
// Third button
- if (fButtons.length > 2) {
- dlg.setPositiveButton(fButtons[2],
- new AlertDialog.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 3));
- }
- }
- );
+ if (buttonLabels.length() > 2) {
+ try {
+ dlg.setPositiveButton(buttonLabels.getString(2),
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, 3));
+ }
+ }
+ );
+ } catch (JSONException e) { }
}
dlg.setOnCancelListener(new AlertDialog.OnCancelListener() {
public void onCancel(DialogInterface dialog)
@@ -249,6 +260,104 @@ public class Notification extends CordovaPlugin {
}
/**
+ * Builds and shows a native Android prompt dialog with given title, message, buttons.
+ * This dialog only shows up to 3 buttons. Any labels after that will be ignored.
+ * The following results are returned to the JavaScript callback identified by callbackId:
+ * buttonIndex Index number of the button selected
+ * input1 The text entered in the prompt dialog box
+ *
+ * @param message The message the dialog should display
+ * @param title The title of the dialog
+ * @param buttonLabels A comma separated list of button labels (Up to 3 buttons)
+ * @param callbackContext The callback context.
+ */
+ public synchronized void prompt(final String message, final String title, final JSONArray buttonLabels, final CallbackContext callbackContext) {
+
+ final CordovaInterface cordova = this.cordova;
+ final EditText promptInput = new EditText(cordova.getActivity());
+
+ Runnable runnable = new Runnable() {
+ public void run() {
+ AlertDialog.Builder dlg = new AlertDialog.Builder(cordova.getActivity());
+ dlg.setMessage(message);
+ dlg.setTitle(title);
+ dlg.setCancelable(true);
+
+ dlg.setView(promptInput);
+
+ final JSONObject result = new JSONObject();
+
+ // First button
+ if (buttonLabels.length() > 0) {
+ try {
+ dlg.setNegativeButton(buttonLabels.getString(0),
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ try {
+ result.put("buttonIndex",1);
+ result.put("input1", promptInput.getText());
+ } catch (JSONException e) { e.printStackTrace(); }
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
+ }
+ });
+ } catch (JSONException e) { }
+ }
+
+ // Second button
+ if (buttonLabels.length() > 1) {
+ try {
+ dlg.setNeutralButton(buttonLabels.getString(1),
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ try {
+ result.put("buttonIndex",2);
+ result.put("input1", promptInput.getText());
+ } catch (JSONException e) { e.printStackTrace(); }
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
+ }
+ });
+ } catch (JSONException e) { }
+ }
+
+ // Third button
+ if (buttonLabels.length() > 2) {
+ try {
+ dlg.setPositiveButton(buttonLabels.getString(2),
+ new AlertDialog.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ try {
+ result.put("buttonIndex",3);
+ result.put("input1", promptInput.getText());
+ } catch (JSONException e) { e.printStackTrace(); }
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
+ }
+ }
+ );
+ } catch (JSONException e) { }
+ }
+ dlg.setOnCancelListener(new AlertDialog.OnCancelListener() {
+ public void onCancel(DialogInterface dialog)
+ {
+ dialog.dismiss();
+ try {
+ result.put("buttonIndex",0);
+ result.put("input1", promptInput.getText());
+ } catch (JSONException e) { e.printStackTrace(); }
+ callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, result));
+ }
+ });
+
+ dlg.create();
+ dlg.show();
+
+ };
+ };
+ this.cordova.getActivity().runOnUiThread(runnable);
+ }
+ /**
* Show the spinner.
*
* @param title Title of the dialog
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/api/CallbackContext.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/api/CallbackContext.java b/lib/cordova-android/framework/src/org/apache/cordova/api/CallbackContext.java
index 2f7b15f..a5d1255 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/api/CallbackContext.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/api/CallbackContext.java
@@ -79,6 +79,15 @@ public class CallbackContext {
public void success(byte[] message) {
sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
}
+
+ /**
+ * Helper for success callbacks that just returns the Status.OK by default
+ *
+ * @param message The message to add to the success result.
+ */
+ public void success(int message) {
+ sendPluginResult(new PluginResult(PluginResult.Status.OK, message));
+ }
/**
* Helper for success callbacks that just returns the Status.OK by default
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java b/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java
index f4c785e..2b225e6 100644
--- a/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/api/CordovaPlugin.java
@@ -22,7 +22,12 @@ import org.apache.cordova.CordovaArgs;
import org.apache.cordova.CordovaWebView;
import org.json.JSONArray;
import org.json.JSONException;
+
+import android.annotation.TargetApi;
import android.content.Intent;
+import android.os.Build;
+import android.util.Log;
+import android.webkit.WebResourceResponse;
/**
* Plugins must extend this class and override one of the execute methods.
@@ -150,7 +155,7 @@ public class CordovaPlugin {
}
/**
- * By specifying a <url-filter> in plugins.xml you can map a URL (using startsWith atm) to this method.
+ * By specifying a <url-filter> in config.xml you can map a URL (using startsWith atm) to this method.
*
* @param url The URL that is trying to be loaded in the Cordova webview.
* @return Return true to prevent the URL from loading. Default is false.
@@ -160,6 +165,17 @@ public class CordovaPlugin {
}
/**
+ * By specifying a <url-filter> in config.xml you can map a URL prefix to this method. It applies to all resources loaded in the WebView, not just top-level navigation.
+ *
+ * @param url The URL of the resource to be loaded.
+ * @return Return a WebResourceResponse for the resource, or null to let the WebView handle it normally.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public WebResourceResponse shouldInterceptRequest(String url) {
+ return null;
+ }
+
+ /**
* Called when the WebView does a top-level navigation or refreshes.
*
* Plugins should stop any long-running processes and clean up internal state.
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java b/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java
index d0e6aef..337ef12 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/api/PluginManager.java
@@ -30,6 +30,8 @@ import org.xmlpull.v1.XmlPullParserException;
import android.content.Intent;
import android.content.res.XmlResourceParser;
+import android.webkit.WebResourceResponse;
+
/**
* PluginManager is exposed to JavaScript in the Cordova WebView.
*
@@ -118,7 +120,7 @@ public class PluginManager {
// System.out.println("Plugin: "+name+" => "+value);
onload = "true".equals(xml.getAttributeValue(null, "onload"));
entry = new PluginEntry(service, pluginClass, onload);
- this.addService(entry);
+ this.addService(entry);
}
//What is this?
else if (strNode.equals("url-filter")) {
@@ -367,6 +369,25 @@ public class PluginManager {
}
/**
+ * Called when the WebView is loading any resource, top-level or not.
+ *
+ * Uses the same url-filter tag as onOverrideUrlLoading.
+ *
+ * @param url The URL of the resource to be loaded.
+ * @return Return a WebResourceResponse with the resource, or null if the WebView should handle it.
+ */
+ public WebResourceResponse shouldInterceptRequest(String url) {
+ Iterator<Entry<String, String>> it = this.urlMap.entrySet().iterator();
+ while (it.hasNext()) {
+ HashMap.Entry<String, String> pairs = it.next();
+ if (url.startsWith(pairs.getKey())) {
+ return this.getPlugin(pairs.getValue()).shouldInterceptRequest(url);
+ }
+ }
+ return null;
+ }
+
+ /**
* Called when the app navigates or refreshes.
*/
public void onReset() {
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-android/framework/src/org/apache/cordova/api/PluginResult.java
----------------------------------------------------------------------
diff --git a/lib/cordova-android/framework/src/org/apache/cordova/api/PluginResult.java b/lib/cordova-android/framework/src/org/apache/cordova/api/PluginResult.java
index 4c1d833..a642200 100755
--- a/lib/cordova-android/framework/src/org/apache/cordova/api/PluginResult.java
+++ b/lib/cordova-android/framework/src/org/apache/cordova/api/PluginResult.java
@@ -71,11 +71,15 @@ public class PluginResult {
}
public PluginResult(Status status, byte[] data) {
+ this(status, data, false);
+ }
+
+ public PluginResult(Status status, byte[] data, boolean binaryString) {
this.status = status.ordinal();
- this.messageType = MESSAGE_TYPE_ARRAYBUFFER;
+ this.messageType = binaryString ? MESSAGE_TYPE_BINARYSTRING : MESSAGE_TYPE_ARRAYBUFFER;
this.encodedMessage = Base64.encodeToString(data, Base64.NO_WRAP);
}
-
+
public void setKeepCallback(boolean b) {
this.keepCallback = b;
}
@@ -143,6 +147,9 @@ public class PluginResult {
public static final int MESSAGE_TYPE_BOOLEAN = 4;
public static final int MESSAGE_TYPE_NULL = 5;
public static final int MESSAGE_TYPE_ARRAYBUFFER = 6;
+ // Use BINARYSTRING when your string may contain null characters.
+ // This is required to work around a bug in the platform :(.
+ public static final int MESSAGE_TYPE_BINARYSTRING = 7;
public static String[] StatusMessages = new String[] {
"No result",
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-blackberry/bin/create
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/bin/create b/lib/cordova-blackberry/bin/create
index 870bad1..b7e719b 100755
--- a/lib/cordova-blackberry/bin/create
+++ b/lib/cordova-blackberry/bin/create
@@ -56,6 +56,19 @@ function on_error {
[ -d "$PROJECT_PATH" ] && rm -rf "$PROJECT_PATH"
}
+function replace {
+ local pattern=$1
+ local filename=$2
+ # Mac OS X requires -i argument
+ if [[ "$OSTYPE" =~ "darwin" ]]
+ then
+ /usr/bin/sed -i '' -e $pattern "$filename"
+ elif [[ "$OSTYPE" =~ "linux" ]]
+ then
+ /bin/sed -i -e $pattern "$filename"
+ fi
+}
+
# we do not want the script to silently fail
trap on_error ERR
trap on_exit EXIT
@@ -79,13 +92,13 @@ then
(cd "$BUILD_PATH" && "$ANT" create -Dproject.path="$PROJECT_PATH" &> /dev/null )
# interpolate the activity and package into config.xml
echo "Updating config.xml ..."
- sed -i '' -e "s/__NAME__/${NAME}/g" "$MANIFEST_PATH"
- sed -i '' -e "s/__PACKAGE__/${PACKAGE}/g" "$MANIFEST_PATH"
+ replace "s/__NAME__/${NAME}/g" "$MANIFEST_PATH"
+ replace "s/__PACKAGE__/${PACKAGE}/g" "$MANIFEST_PATH"
else
# copy project template if in distribution
echo "Copying assets and resources ..."
cp -r "$BUILD_PATH/sample/." "$PROJECT_PATH"
echo "Updating config.xml ..."
- sed -i '' -e "s/cordovaExample/${NAME}/g" "$MANIFEST_PATH"
- sed -i '' -e "s/org.apache.cordova.example/${PACKAGE}/g" "$MANIFEST_PATH"
+ replace "s/cordovaExample/${NAME}/g" "$MANIFEST_PATH"
+ replace "s/org.apache.cordova.example/${PACKAGE}/g" "$MANIFEST_PATH"
fi
http://git-wip-us.apache.org/repos/asf/cordova-cli/blob/1ed1ee2d/lib/cordova-blackberry/bin/templates/project/www/index.html
----------------------------------------------------------------------
diff --git a/lib/cordova-blackberry/bin/templates/project/www/index.html b/lib/cordova-blackberry/bin/templates/project/www/index.html
index f083790..6b53abc 100644
--- a/lib/cordova-blackberry/bin/templates/project/www/index.html
+++ b/lib/cordova-blackberry/bin/templates/project/www/index.html
@@ -18,8 +18,8 @@
under the License.
-->
<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <head>
+ <meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<link rel="stylesheet" type="text/css" href="css/index.css" />