getPluginEntries() {
- return pluginEntries;
- }
-
- public String getLaunchUrl() {
- return launchUrl;
- }
-
- public void parse(Context action) {
- // First checking the class namespace for config.xml
- int id = action.getResources().getIdentifier("config", "xml", action.getClass().getPackage().getName());
- if (id == 0) {
- // If we couldn't find config.xml there, we'll look in the namespace from AndroidManifest.xml
- id = action.getResources().getIdentifier("config", "xml", action.getPackageName());
- if (id == 0) {
- LOG.e(TAG, "res/xml/config.xml is missing!");
- return;
- }
- }
- parse(action.getResources().getXml(id));
- }
-
- boolean insideFeature = false;
- String service = "", pluginClass = "", paramType = "";
- boolean onload = false;
-
- public void parse(XmlPullParser xml) {
- int eventType = -1;
-
- while (eventType != XmlPullParser.END_DOCUMENT) {
- if (eventType == XmlPullParser.START_TAG) {
- handleStartTag(xml);
- }
- else if (eventType == XmlPullParser.END_TAG)
- {
- handleEndTag(xml);
- }
- try {
- eventType = xml.next();
- } catch (XmlPullParserException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- public void handleStartTag(XmlPullParser xml) {
- String strNode = xml.getName();
- if (strNode.equals("feature")) {
- //Check for supported feature sets aka. plugins (Accelerometer, Geolocation, etc)
- //Set the bit for reading params
- insideFeature = true;
- service = xml.getAttributeValue(null, "name");
- }
- else if (insideFeature && strNode.equals("param")) {
- paramType = xml.getAttributeValue(null, "name");
- if (paramType.equals("service")) // check if it is using the older service param
- service = xml.getAttributeValue(null, "value");
- else if (paramType.equals("package") || paramType.equals("android-package"))
- pluginClass = xml.getAttributeValue(null,"value");
- else if (paramType.equals("onload"))
- onload = "true".equals(xml.getAttributeValue(null, "value"));
- }
- else if (strNode.equals("preference")) {
- String name = xml.getAttributeValue(null, "name").toLowerCase(Locale.ENGLISH);
- String value = xml.getAttributeValue(null, "value");
- prefs.set(name, value);
- }
- else if (strNode.equals("content")) {
- String src = xml.getAttributeValue(null, "src");
- if (src != null) {
- setStartUrl(src);
- }
- }
- }
-
- public void handleEndTag(XmlPullParser xml) {
- String strNode = xml.getName();
- if (strNode.equals("feature")) {
- pluginEntries.add(new PluginEntry(service, pluginClass, onload));
-
- service = "";
- pluginClass = "";
- insideFeature = false;
- onload = false;
- }
- }
-
- private void setStartUrl(String src) {
- Pattern schemeRegex = Pattern.compile("^[a-z-]+://");
- Matcher matcher = schemeRegex.matcher(src);
- if (matcher.find()) {
- launchUrl = src;
- } else {
- if (src.charAt(0) == '/') {
- src = src.substring(1);
- }
- launchUrl = "file:///android_asset/www/" + src;
- }
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaActivity.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaActivity.java
deleted file mode 100755
index dbbb48f..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaActivity.java
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.annotation.SuppressLint;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.graphics.Color;
-import android.media.AudioManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
-import android.webkit.WebViewClient;
-import android.widget.FrameLayout;
-
-/**
- * This class is the main Android activity that represents the Cordova
- * application. It should be extended by the user to load the specific
- * html file that contains the application.
- *
- * As an example:
- *
- *
- * package org.apache.cordova.examples;
- *
- * import android.os.Bundle;
- * import org.apache.cordova.*;
- *
- * public class Example extends CordovaActivity {
- * @Override
- * public void onCreate(Bundle savedInstanceState) {
- * super.onCreate(savedInstanceState);
- * super.init();
- * // Load your application
- * loadUrl(launchUrl);
- * }
- * }
- *
- *
- * Cordova xml configuration: Cordova uses a configuration file at
- * res/xml/config.xml to specify its settings. See "The config.xml File"
- * guide in cordova-docs at http://cordova.apache.org/docs for the documentation
- * for the configuration. The use of the set*Property() methods is
- * deprecated in favor of the config.xml file.
- *
- */
-public class CordovaActivity extends Activity {
- public static String TAG = "CordovaActivity";
-
- // The webview for our app
- protected CordovaWebView appView;
-
- private static int ACTIVITY_STARTING = 0;
- private static int ACTIVITY_RUNNING = 1;
- private static int ACTIVITY_EXITING = 2;
-
- // Keep app running when pause is received. (default = true)
- // If true, then the JavaScript and native code continue to run in the background
- // when another application (activity) is started.
- protected boolean keepRunning = true;
-
- // Flag to keep immersive mode if set to fullscreen
- protected boolean immersiveMode;
-
- // Read from config.xml:
- protected CordovaPreferences preferences;
- protected String launchUrl;
- protected ArrayList pluginEntries;
- protected CordovaInterfaceImpl cordovaInterface;
-
- /**
- * Called when the activity is first created.
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- // need to activate preferences before super.onCreate to avoid "requestFeature() must be called before adding content" exception
- loadConfig();
-
- String logLevel = preferences.getString("loglevel", "ERROR");
- LOG.setLogLevel(logLevel);
-
- LOG.i(TAG, "Apache Cordova native platform version " + CordovaWebView.CORDOVA_VERSION + " is starting");
- LOG.d(TAG, "CordovaActivity.onCreate()");
-
- if (!preferences.getBoolean("ShowTitle", false)) {
- getWindow().requestFeature(Window.FEATURE_NO_TITLE);
- }
-
- if (preferences.getBoolean("SetFullscreen", false)) {
- LOG.d(TAG, "The SetFullscreen configuration is deprecated in favor of Fullscreen, and will be removed in a future version.");
- preferences.set("Fullscreen", true);
- }
- if (preferences.getBoolean("Fullscreen", false)) {
- // NOTE: use the FullscreenNotImmersive configuration key to set the activity in a REAL full screen
- // (as was the case in previous cordova versions)
- if (!preferences.getBoolean("FullscreenNotImmersive", false)) {
- immersiveMode = true;
- } else {
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- }
- } else {
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
- }
-
- super.onCreate(savedInstanceState);
-
- cordovaInterface = makeCordovaInterface();
- if (savedInstanceState != null) {
- cordovaInterface.restoreInstanceState(savedInstanceState);
- }
- }
-
- protected void init() {
- appView = makeWebView();
- createViews();
- if (!appView.isInitialized()) {
- appView.init(cordovaInterface, pluginEntries, preferences);
- }
- cordovaInterface.onCordovaInit(appView.getPluginManager());
-
- // Wire the hardware volume controls to control media if desired.
- String volumePref = preferences.getString("DefaultVolumeStream", "");
- if ("media".equals(volumePref.toLowerCase(Locale.ENGLISH))) {
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
- }
- }
-
- @SuppressWarnings("deprecation")
- protected void loadConfig() {
- ConfigXmlParser parser = new ConfigXmlParser();
- parser.parse(this);
- preferences = parser.getPreferences();
- preferences.setPreferencesBundle(getIntent().getExtras());
- launchUrl = parser.getLaunchUrl();
- pluginEntries = parser.getPluginEntries();
- Config.parser = parser;
- }
-
- //Suppressing warnings in AndroidStudio
- @SuppressWarnings({"deprecation", "ResourceType"})
- protected void createViews() {
- //Why are we setting a constant as the ID? This should be investigated
- appView.getView().setId(100);
- appView.getView().setLayoutParams(new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
-
- setContentView(appView.getView());
-
- if (preferences.contains("BackgroundColor")) {
- try {
- int backgroundColor = preferences.getInteger("BackgroundColor", Color.BLACK);
- // Background of activity:
- appView.getView().setBackgroundColor(backgroundColor);
- }
- catch (NumberFormatException e){
- e.printStackTrace();
- }
- }
-
- appView.getView().requestFocusFromTouch();
- }
-
- /**
- * Construct the default web view object.
- *
- * Override this to customize the webview that is used.
- */
- protected CordovaWebView makeWebView() {
- return new CordovaWebViewImpl(makeWebViewEngine());
- }
-
- protected CordovaWebViewEngine makeWebViewEngine() {
- return CordovaWebViewImpl.createEngine(this, preferences);
- }
-
- protected CordovaInterfaceImpl makeCordovaInterface() {
- return new CordovaInterfaceImpl(this) {
- @Override
- public Object onMessage(String id, Object data) {
- // Plumb this to CordovaActivity.onMessage for backwards compatibility
- return CordovaActivity.this.onMessage(id, data);
- }
- };
- }
-
- /**
- * Load the url into the webview.
- */
- public void loadUrl(String url) {
- if (appView == null) {
- init();
- }
-
- // If keepRunning
- this.keepRunning = preferences.getBoolean("KeepRunning", true);
-
- appView.loadUrlIntoView(url, true);
- }
-
- /**
- * Called when the system is about to start resuming a previous activity.
- */
- @Override
- protected void onPause() {
- super.onPause();
- LOG.d(TAG, "Paused the activity.");
-
- if (this.appView != null) {
- // CB-9382 If there is an activity that started for result and main activity is waiting for callback
- // result, we shoudn't stop WebView Javascript timers, as activity for result might be using them
- boolean keepRunning = this.keepRunning || this.cordovaInterface.activityResultCallback != null;
- this.appView.handlePause(keepRunning);
- }
- }
-
- /**
- * Called when the activity receives a new intent
- */
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- //Forward to plugins
- if (this.appView != null)
- this.appView.onNewIntent(intent);
- }
-
- /**
- * Called when the activity will start interacting with the user.
- */
- @Override
- protected void onResume() {
- super.onResume();
- LOG.d(TAG, "Resumed the activity.");
-
- if (this.appView == null) {
- return;
- }
- // Force window to have focus, so application always
- // receive user input. Workaround for some devices (Samsung Galaxy Note 3 at least)
- this.getWindow().getDecorView().requestFocus();
-
- this.appView.handleResume(this.keepRunning);
- }
-
- /**
- * Called when the activity is no longer visible to the user.
- */
- @Override
- protected void onStop() {
- super.onStop();
- LOG.d(TAG, "Stopped the activity.");
-
- if (this.appView == null) {
- return;
- }
- this.appView.handleStop();
- }
-
- /**
- * Called when the activity is becoming visible to the user.
- */
- @Override
- protected void onStart() {
- super.onStart();
- LOG.d(TAG, "Started the activity.");
-
- if (this.appView == null) {
- return;
- }
- this.appView.handleStart();
- }
-
- /**
- * The final call you receive before your activity is destroyed.
- */
- @Override
- public void onDestroy() {
- LOG.d(TAG, "CordovaActivity.onDestroy()");
- super.onDestroy();
-
- if (this.appView != null) {
- appView.handleDestroy();
- }
- }
-
- /**
- * Called when view focus is changed
- */
- @SuppressLint("InlinedApi")
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
- if (hasFocus && immersiveMode) {
- final int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_FULLSCREEN
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-
- getWindow().getDecorView().setSystemUiVisibility(uiOptions);
- }
- }
-
- @SuppressLint("NewApi")
- @Override
- public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
- // Capture requestCode here so that it is captured in the setActivityResultCallback() case.
- cordovaInterface.setActivityResultRequestCode(requestCode);
- super.startActivityForResult(intent, requestCode, options);
- }
-
- /**
- * Called when an activity you launched exits, giving you the requestCode you started it with,
- * the resultCode it returned, and any additional data from it.
- *
- * @param requestCode The request code originally supplied to startActivityForResult(),
- * allowing you to identify who this result came from.
- * @param resultCode The integer result code returned by the child activity through its setResult().
- * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
- LOG.d(TAG, "Incoming Result. Request code = " + requestCode);
- super.onActivityResult(requestCode, resultCode, intent);
- cordovaInterface.onActivityResult(requestCode, resultCode, intent);
- }
-
- /**
- * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
- * The errorCode parameter corresponds to one of the ERROR_* constants.
- *
- * @param errorCode The error code corresponding to an ERROR_* value.
- * @param description A String describing the error.
- * @param failingUrl The url that failed to load.
- */
- public void onReceivedError(final int errorCode, final String description, final String failingUrl) {
- final CordovaActivity me = this;
-
- // If errorUrl specified, then load it
- final String errorUrl = preferences.getString("errorUrl", null);
- if ((errorUrl != null) && (!failingUrl.equals(errorUrl)) && (appView != null)) {
- // Load URL on UI thread
- me.runOnUiThread(new Runnable() {
- public void run() {
- me.appView.showWebPage(errorUrl, false, true, null);
- }
- });
- }
- // If not, then display error dialog
- else {
- final boolean exit = !(errorCode == WebViewClient.ERROR_HOST_LOOKUP);
- me.runOnUiThread(new Runnable() {
- public void run() {
- if (exit) {
- me.appView.getView().setVisibility(View.GONE);
- me.displayError("Application Error", description + " (" + failingUrl + ")", "OK", exit);
- }
- }
- });
- }
- }
-
- /**
- * Display an error dialog and optionally exit application.
- */
- public void displayError(final String title, final String message, final String button, final boolean exit) {
- final CordovaActivity me = this;
- me.runOnUiThread(new Runnable() {
- public void run() {
- try {
- AlertDialog.Builder dlg = new AlertDialog.Builder(me);
- dlg.setMessage(message);
- dlg.setTitle(title);
- dlg.setCancelable(false);
- dlg.setPositiveButton(button,
- new AlertDialog.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- if (exit) {
- finish();
- }
- }
- });
- dlg.create();
- dlg.show();
- } catch (Exception e) {
- finish();
- }
- }
- });
- }
-
- /*
- * Hook in Cordova for menu plugins
- */
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- if (appView != null) {
- appView.getPluginManager().postMessage("onCreateOptionsMenu", menu);
- }
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- if (appView != null) {
- appView.getPluginManager().postMessage("onPrepareOptionsMenu", menu);
- }
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (appView != null) {
- appView.getPluginManager().postMessage("onOptionsItemSelected", item);
- }
- return true;
- }
-
- /**
- * 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) {
- 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)) {
- finish();
- }
- return null;
- }
-
- protected void onSaveInstanceState(Bundle outState) {
- cordovaInterface.onSaveInstanceState(outState);
- super.onSaveInstanceState(outState);
- }
-
- /**
- * Called by the system when the device configuration changes while your activity is running.
- *
- * @param newConfig The new device configuration
- */
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- if (this.appView == null) {
- return;
- }
- PluginManager pm = this.appView.getPluginManager();
- if (pm != null) {
- pm.onConfigurationChanged(newConfig);
- }
- }
-
- /**
- * Called by the system when the user grants permissions
- *
- * @param requestCode
- * @param permissions
- * @param grantResults
- */
- @Override
- public void onRequestPermissionsResult(int requestCode, String permissions[],
- int[] grantResults) {
- try
- {
- cordovaInterface.onRequestPermissionResult(requestCode, permissions, grantResults);
- }
- catch (JSONException e)
- {
- LOG.d(TAG, "JSONException: Parameters fed into the method are not valid");
- e.printStackTrace();
- }
-
- }
-
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaArgs.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaArgs.java
deleted file mode 100644
index d40d26e..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaArgs.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.util.Base64;
-
-public class CordovaArgs {
- private JSONArray baseArgs;
-
- public CordovaArgs(JSONArray args) {
- this.baseArgs = args;
- }
-
-
- // Pass through the basics to the base args.
- public Object get(int index) throws JSONException {
- return baseArgs.get(index);
- }
-
- public boolean getBoolean(int index) throws JSONException {
- return baseArgs.getBoolean(index);
- }
-
- public double getDouble(int index) throws JSONException {
- return baseArgs.getDouble(index);
- }
-
- public int getInt(int index) throws JSONException {
- return baseArgs.getInt(index);
- }
-
- public JSONArray getJSONArray(int index) throws JSONException {
- return baseArgs.getJSONArray(index);
- }
-
- public JSONObject getJSONObject(int index) throws JSONException {
- return baseArgs.getJSONObject(index);
- }
-
- public long getLong(int index) throws JSONException {
- return baseArgs.getLong(index);
- }
-
- public String getString(int index) throws JSONException {
- return baseArgs.getString(index);
- }
-
-
- public Object opt(int index) {
- return baseArgs.opt(index);
- }
-
- public boolean optBoolean(int index) {
- return baseArgs.optBoolean(index);
- }
-
- public double optDouble(int index) {
- return baseArgs.optDouble(index);
- }
-
- public int optInt(int index) {
- return baseArgs.optInt(index);
- }
-
- public JSONArray optJSONArray(int index) {
- return baseArgs.optJSONArray(index);
- }
-
- public JSONObject optJSONObject(int index) {
- return baseArgs.optJSONObject(index);
- }
-
- public long optLong(int index) {
- return baseArgs.optLong(index);
- }
-
- public String optString(int index) {
- return baseArgs.optString(index);
- }
-
- public boolean isNull(int index) {
- return baseArgs.isNull(index);
- }
-
-
- // The interesting custom helpers.
- public byte[] getArrayBuffer(int index) throws JSONException {
- String encoded = baseArgs.getString(index);
- return Base64.decode(encoded, Base64.DEFAULT);
- }
-}
-
-
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java
deleted file mode 100644
index 28c407f..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaBridge.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import android.annotation.SuppressLint;
-
-import java.security.SecureRandom;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-
-/**
- * Contains APIs that the JS can call. All functions in here should also have
- * an equivalent entry in CordovaChromeClient.java, and be added to
- * cordova-js/lib/android/plugin/android/promptbasednativeapi.js
- */
-public class CordovaBridge {
- private static final String LOG_TAG = "CordovaBridge";
- private PluginManager pluginManager;
- private NativeToJsMessageQueue jsMessageQueue;
- private volatile int expectedBridgeSecret = -1; // written by UI thread, read by JS thread.
-
- public CordovaBridge(PluginManager pluginManager, NativeToJsMessageQueue jsMessageQueue) {
- this.pluginManager = pluginManager;
- this.jsMessageQueue = jsMessageQueue;
- }
-
- public String jsExec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
- if (!verifySecret("exec()", bridgeSecret)) {
- return null;
- }
- // If the arguments weren't received, send a message back to JS. It will switch bridge modes and try again. See CB-2666.
- // We send a message meant specifically for this case. It starts with "@" so no other message can be encoded into the same string.
- if (arguments == null) {
- return "@Null arguments.";
- }
-
- jsMessageQueue.setPaused(true);
- try {
- // Tell the resourceApi what thread the JS is running on.
- CordovaResourceApi.jsThread = Thread.currentThread();
-
- pluginManager.exec(service, action, callbackId, arguments);
- String ret = null;
- if (!NativeToJsMessageQueue.DISABLE_EXEC_CHAINING) {
- ret = jsMessageQueue.popAndEncode(false);
- }
- return ret;
- } catch (Throwable e) {
- e.printStackTrace();
- return "";
- } finally {
- jsMessageQueue.setPaused(false);
- }
- }
-
- public void jsSetNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {
- if (!verifySecret("setNativeToJsBridgeMode()", bridgeSecret)) {
- return;
- }
- jsMessageQueue.setBridgeMode(value);
- }
-
- public String jsRetrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {
- if (!verifySecret("retrieveJsMessages()", bridgeSecret)) {
- return null;
- }
- return jsMessageQueue.popAndEncode(fromOnlineEvent);
- }
-
- private boolean verifySecret(String action, int bridgeSecret) throws IllegalAccessException {
- if (!jsMessageQueue.isBridgeEnabled()) {
- if (bridgeSecret == -1) {
- LOG.d(LOG_TAG, action + " call made before bridge was enabled.");
- } else {
- LOG.d(LOG_TAG, "Ignoring " + action + " from previous page load.");
- }
- return false;
- }
- // Bridge secret wrong and bridge not due to it being from the previous page.
- if (expectedBridgeSecret < 0 || bridgeSecret != expectedBridgeSecret) {
- LOG.e(LOG_TAG, "Bridge access attempt with wrong secret token, possibly from malicious code. Disabling exec() bridge!");
- clearBridgeSecret();
- throw new IllegalAccessException();
- }
- return true;
- }
-
- /** Called on page transitions */
- void clearBridgeSecret() {
- expectedBridgeSecret = -1;
- }
-
- public boolean isSecretEstablished() {
- return expectedBridgeSecret != -1;
- }
-
- /** Called by cordova.js to initialize the bridge. */
- //On old Androids SecureRandom isn't really secure, this is the least of your problems if
- //you're running Android 4.3 and below in 2017
- @SuppressLint("TrulyRandom")
- int generateBridgeSecret() {
- SecureRandom randGen = new SecureRandom();
- expectedBridgeSecret = randGen.nextInt(Integer.MAX_VALUE);
- return expectedBridgeSecret;
- }
-
- public void reset() {
- jsMessageQueue.reset();
- clearBridgeSecret();
- }
-
- public String promptOnJsPrompt(String origin, String message, String defaultValue) {
- if (defaultValue != null && defaultValue.length() > 3 && defaultValue.startsWith("gap:")) {
- JSONArray array;
- try {
- array = new JSONArray(defaultValue.substring(4));
- int bridgeSecret = array.getInt(0);
- String service = array.getString(1);
- String action = array.getString(2);
- String callbackId = array.getString(3);
- String r = jsExec(bridgeSecret, service, action, callbackId, message);
- return r == null ? "" : r;
- } catch (JSONException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- return "";
- }
- // Sets the native->JS bridge mode.
- else if (defaultValue != null && defaultValue.startsWith("gap_bridge_mode:")) {
- try {
- int bridgeSecret = Integer.parseInt(defaultValue.substring(16));
- jsSetNativeToJsBridgeMode(bridgeSecret, Integer.parseInt(message));
- } catch (NumberFormatException e){
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- return "";
- }
- // Polling for JavaScript messages
- else if (defaultValue != null && defaultValue.startsWith("gap_poll:")) {
- int bridgeSecret = Integer.parseInt(defaultValue.substring(9));
- try {
- String r = jsRetrieveJsMessages(bridgeSecret, "1".equals(message));
- return r == null ? "" : r;
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- return "";
- }
- else if (defaultValue != null && defaultValue.startsWith("gap_init:")) {
- // Protect against random iframes being able to talk through the bridge.
- // Trust only pages which the app would have been allowed to navigate to anyway.
- if (pluginManager.shouldAllowBridgeAccess(origin)) {
- // Enable the bridge
- int bridgeMode = Integer.parseInt(defaultValue.substring(9));
- jsMessageQueue.setBridgeMode(bridgeMode);
- // Tell JS the bridge secret.
- int secret = generateBridgeSecret();
- return ""+secret;
- } else {
- LOG.e(LOG_TAG, "gap_init called from restricted origin: " + origin);
- }
- return "";
- }
- return null;
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java
deleted file mode 100644
index ccda027..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaClientCertRequest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-
-import android.annotation.SuppressLint;
-import android.webkit.ClientCertRequest;
-
-/**
- * Implementation of the ICordovaClientCertRequest for Android WebView.
- *
- */
-public class CordovaClientCertRequest implements ICordovaClientCertRequest {
-
- private final ClientCertRequest request;
-
- public CordovaClientCertRequest(ClientCertRequest request) {
- this.request = request;
- }
-
- /**
- * Cancel this request
- */
- @SuppressLint("NewApi")
- public void cancel()
- {
- request.cancel();
- }
-
- /*
- * Returns the host name of the server requesting the certificate.
- */
- @SuppressLint("NewApi")
- public String getHost()
- {
- return request.getHost();
- }
-
- /*
- * Returns the acceptable types of asymmetric keys (can be null).
- */
- @SuppressLint("NewApi")
- public String[] getKeyTypes()
- {
- return request.getKeyTypes();
- }
-
- /*
- * Returns the port number of the server requesting the certificate.
- */
- @SuppressLint("NewApi")
- public int getPort()
- {
- return request.getPort();
- }
-
- /*
- * Returns the acceptable certificate issuers for the certificate matching the private key (can be null).
- */
- @SuppressLint("NewApi")
- public Principal[] getPrincipals()
- {
- return request.getPrincipals();
- }
-
- /*
- * Ignore the request for now. Do not remember user's choice.
- */
- @SuppressLint("NewApi")
- public void ignore()
- {
- request.ignore();
- }
-
- /*
- * Proceed with the specified private key and client certificate chain. Remember the user's positive choice and use it for future requests.
- *
- * @param privateKey The privateKey
- * @param chain The certificate chain
- */
- @SuppressLint("NewApi")
- public void proceed(PrivateKey privateKey, X509Certificate[] chain)
- {
- request.proceed(privateKey, chain);
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java
deleted file mode 100644
index a219c99..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaDialogsHelper.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.view.KeyEvent;
-import android.widget.EditText;
-
-/**
- * Helper class for WebViews to implement prompt(), alert(), confirm() dialogs.
- */
-public class CordovaDialogsHelper {
- private final Context context;
- private AlertDialog lastHandledDialog;
-
- public CordovaDialogsHelper(Context context) {
- this.context = context;
- }
-
- public void showAlert(String message, final Result result) {
- AlertDialog.Builder dlg = new AlertDialog.Builder(context);
- dlg.setMessage(message);
- dlg.setTitle("Alert");
- //Don't let alerts break the back button
- dlg.setCancelable(true);
- dlg.setPositiveButton(android.R.string.ok,
- new AlertDialog.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- result.gotResult(true, null);
- }
- });
- dlg.setOnCancelListener(
- new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- result.gotResult(false, null);
- }
- });
- dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
- //DO NOTHING
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK)
- {
- result.gotResult(true, null);
- return false;
- }
- else
- return true;
- }
- });
- lastHandledDialog = dlg.show();
- }
-
- public void showConfirm(String message, final Result result) {
- AlertDialog.Builder dlg = new AlertDialog.Builder(context);
- dlg.setMessage(message);
- dlg.setTitle("Confirm");
- dlg.setCancelable(true);
- dlg.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- result.gotResult(true, null);
- }
- });
- dlg.setNegativeButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- result.gotResult(false, null);
- }
- });
- dlg.setOnCancelListener(
- new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- result.gotResult(false, null);
- }
- });
- dlg.setOnKeyListener(new DialogInterface.OnKeyListener() {
- //DO NOTHING
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK)
- {
- result.gotResult(false, null);
- return false;
- }
- else
- return true;
- }
- });
- lastHandledDialog = dlg.show();
- }
-
- /**
- * Tell the client to display a prompt dialog to the user.
- * If the client returns true, WebView will assume that the client will
- * handle the prompt dialog and call the appropriate JsPromptResult method.
- *
- * Since we are hacking prompts for our own purposes, we should not be using them for
- * this purpose, perhaps we should hack console.log to do this instead!
- */
- public void showPrompt(String message, String defaultValue, final Result result) {
- // Returning false would also show a dialog, but the default one shows the origin (ugly).
- AlertDialog.Builder dlg = new AlertDialog.Builder(context);
- dlg.setMessage(message);
- final EditText input = new EditText(context);
- if (defaultValue != null) {
- input.setText(defaultValue);
- }
- dlg.setView(input);
- dlg.setCancelable(false);
- dlg.setPositiveButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- String userText = input.getText().toString();
- result.gotResult(true, userText);
- }
- });
- dlg.setNegativeButton(android.R.string.cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- result.gotResult(false, null);
- }
- });
- lastHandledDialog = dlg.show();
- }
-
- public void destroyLastDialog(){
- if (lastHandledDialog != null){
- lastHandledDialog.cancel();
- }
- }
-
- public interface Result {
- public void gotResult(boolean success, String value);
- }
-}
\ No newline at end of file
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java
deleted file mode 100644
index 724381e..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaHttpAuthHandler.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import android.webkit.HttpAuthHandler;
-
-/**
- * Specifies interface for HTTP auth handler object which is used to handle auth requests and
- * specifying user credentials.
- */
-public class CordovaHttpAuthHandler implements ICordovaHttpAuthHandler {
-
- private final HttpAuthHandler handler;
-
- public CordovaHttpAuthHandler(HttpAuthHandler handler) {
- this.handler = handler;
- }
-
- /**
- * Instructs the WebView to cancel the authentication request.
- */
- public void cancel () {
- this.handler.cancel();
- }
-
- /**
- * Instructs the WebView to proceed with the authentication with the given credentials.
- *
- * @param username
- * @param password
- */
- public void proceed (String username, String password) {
- this.handler.proceed(username, password);
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java
deleted file mode 100755
index ff90683..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterface.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-
-import org.apache.cordova.CordovaPlugin;
-
-import java.util.concurrent.ExecutorService;
-
-/**
- * The Activity interface that is implemented by CordovaActivity.
- * It is used to isolate plugin development, and remove dependency on entire Cordova library.
- */
-public interface CordovaInterface {
-
- /**
- * Launch an activity for which you would like a result when it finished. When this activity exits,
- * your onActivityResult() method will be called.
- *
- * @param command The command object
- * @param intent The intent to start
- * @param requestCode The request code that is passed to callback to identify the activity
- */
- abstract public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode);
-
- /**
- * Set the plugin to be called when a sub-activity exits.
- *
- * @param plugin The plugin on which onActivityResult is to be called
- */
- abstract public void setActivityResultCallback(CordovaPlugin plugin);
-
- /**
- * Get the Android activity.
- *
- * If a custom engine lives outside of the Activity's lifecycle the return value may be null.
- *
- * @return the Activity
- */
- public abstract Activity getActivity();
-
- /**
- * Get the Android context.
- *
- * @return the Context
- */
- public Context getContext();
-
- /**
- * 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);
-
- /**
- * Returns a shared thread pool that can be used for background tasks.
- */
- public ExecutorService getThreadPool();
-
- /**
- * Sends a permission request to the activity for one permission.
- */
- public void requestPermission(CordovaPlugin plugin, int requestCode, String permission);
-
- /**
- * Sends a permission request to the activity for a group of permissions
- */
- public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions);
-
- /**
- * Check for a permission. Returns true if the permission is granted, false otherwise.
- */
- public boolean hasPermission(String permission);
-
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java
deleted file mode 100644
index 9a6e924..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaInterfaceImpl.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.util.Pair;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * Default implementation of CordovaInterface.
- */
-public class CordovaInterfaceImpl implements CordovaInterface {
- private static final String TAG = "CordovaInterfaceImpl";
- protected Activity activity;
- protected ExecutorService threadPool;
- protected PluginManager pluginManager;
-
- protected ActivityResultHolder savedResult;
- protected CallbackMap permissionResultCallbacks;
- protected CordovaPlugin activityResultCallback;
- protected String initCallbackService;
- protected int activityResultRequestCode;
- protected boolean activityWasDestroyed = false;
- protected Bundle savedPluginState;
-
- public CordovaInterfaceImpl(Activity activity) {
- this(activity, Executors.newCachedThreadPool());
- }
-
- public CordovaInterfaceImpl(Activity activity, ExecutorService threadPool) {
- this.activity = activity;
- this.threadPool = threadPool;
- this.permissionResultCallbacks = new CallbackMap();
- }
-
- @Override
- public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
- setActivityResultCallback(command);
- try {
- activity.startActivityForResult(intent, requestCode);
- } catch (RuntimeException e) { // E.g.: ActivityNotFoundException
- activityResultCallback = null;
- throw e;
- }
- }
-
- @Override
- public void setActivityResultCallback(CordovaPlugin plugin) {
- // Cancel any previously pending activity.
- if (activityResultCallback != null) {
- activityResultCallback.onActivityResult(activityResultRequestCode, Activity.RESULT_CANCELED, null);
- }
- activityResultCallback = plugin;
- }
-
- @Override
- public Activity getActivity() {
- return activity;
- }
-
- @Override
- public Context getContext() {
- return activity;
- }
-
- @Override
- public Object onMessage(String id, Object data) {
- if ("exit".equals(id)) {
- activity.finish();
- }
- return null;
- }
-
- @Override
- public ExecutorService getThreadPool() {
- return threadPool;
- }
-
- /**
- * Dispatches any pending onActivityResult callbacks and sends the resume event if the
- * Activity was destroyed by the OS.
- */
- public void onCordovaInit(PluginManager pluginManager) {
- this.pluginManager = pluginManager;
- if (savedResult != null) {
- onActivityResult(savedResult.requestCode, savedResult.resultCode, savedResult.intent);
- } else if(activityWasDestroyed) {
- // If there was no Activity result, we still need to send out the resume event if the
- // Activity was destroyed by the OS
- activityWasDestroyed = false;
- if(pluginManager != null)
- {
- CoreAndroid appPlugin = (CoreAndroid) pluginManager.getPlugin(CoreAndroid.PLUGIN_NAME);
- if(appPlugin != null) {
- JSONObject obj = new JSONObject();
- try {
- obj.put("action", "resume");
- } catch (JSONException e) {
- LOG.e(TAG, "Failed to create event message", e);
- }
- appPlugin.sendResumeEvent(new PluginResult(PluginResult.Status.OK, obj));
- }
- }
-
- }
- }
-
- /**
- * Routes the result to the awaiting plugin. Returns false if no plugin was waiting.
- */
- public boolean onActivityResult(int requestCode, int resultCode, Intent intent) {
- CordovaPlugin callback = activityResultCallback;
- if(callback == null && initCallbackService != null) {
- // The application was restarted, but had defined an initial callback
- // before being shut down.
- savedResult = new ActivityResultHolder(requestCode, resultCode, intent);
- if (pluginManager != null) {
- callback = pluginManager.getPlugin(initCallbackService);
- if(callback != null) {
- callback.onRestoreStateForActivityResult(savedPluginState.getBundle(callback.getServiceName()),
- new ResumeCallback(callback.getServiceName(), pluginManager));
- }
- }
- }
- activityResultCallback = null;
-
- if (callback != null) {
- LOG.d(TAG, "Sending activity result to plugin");
- initCallbackService = null;
- savedResult = null;
- callback.onActivityResult(requestCode, resultCode, intent);
- return true;
- }
- LOG.w(TAG, "Got an activity result, but no plugin was registered to receive it" + (savedResult != null ? " yet!" : "."));
- return false;
- }
-
- /**
- * Call this from your startActivityForResult() overload. This is required to catch the case
- * where plugins use Activity.startActivityForResult() + CordovaInterface.setActivityResultCallback()
- * rather than CordovaInterface.startActivityForResult().
- */
- public void setActivityResultRequestCode(int requestCode) {
- activityResultRequestCode = requestCode;
- }
-
- /**
- * Saves parameters for startActivityForResult().
- */
- public void onSaveInstanceState(Bundle outState) {
- if (activityResultCallback != null) {
- String serviceName = activityResultCallback.getServiceName();
- outState.putString("callbackService", serviceName);
- }
- if(pluginManager != null){
- outState.putBundle("plugin", pluginManager.onSaveInstanceState());
- }
-
- }
-
- /**
- * Call this from onCreate() so that any saved startActivityForResult parameters will be restored.
- */
- public void restoreInstanceState(Bundle savedInstanceState) {
- initCallbackService = savedInstanceState.getString("callbackService");
- savedPluginState = savedInstanceState.getBundle("plugin");
- activityWasDestroyed = true;
- }
-
- private static class ActivityResultHolder {
- private int requestCode;
- private int resultCode;
- private Intent intent;
-
- public ActivityResultHolder(int requestCode, int resultCode, Intent intent) {
- this.requestCode = requestCode;
- this.resultCode = resultCode;
- this.intent = intent;
- }
- }
-
- /**
- * Called by the system when the user grants permissions
- *
- * @param requestCode
- * @param permissions
- * @param grantResults
- */
- public void onRequestPermissionResult(int requestCode, String[] permissions,
- int[] grantResults) throws JSONException {
- Pair callback = permissionResultCallbacks.getAndRemoveCallback(requestCode);
- if(callback != null) {
- callback.first.onRequestPermissionResult(callback.second, permissions, grantResults);
- }
- }
-
- public void requestPermission(CordovaPlugin plugin, int requestCode, String permission) {
- String[] permissions = new String [1];
- permissions[0] = permission;
- requestPermissions(plugin, requestCode, permissions);
- }
-
- @SuppressLint("NewApi")
- public void requestPermissions(CordovaPlugin plugin, int requestCode, String [] permissions) {
- int mappedRequestCode = permissionResultCallbacks.registerCallback(plugin, requestCode);
- getActivity().requestPermissions(permissions, mappedRequestCode);
- }
-
- public boolean hasPermission(String permission)
- {
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
- {
- int result = activity.checkSelfPermission(permission);
- return PackageManager.PERMISSION_GRANTED == result;
- }
- else
- {
- return true;
- }
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java
deleted file mode 100644
index 41af1db..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPlugin.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import org.apache.cordova.CordovaArgs;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CallbackContext;
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-/**
- * Plugins must extend this class and override one of the execute methods.
- */
-public class CordovaPlugin {
- public CordovaWebView webView;
- public CordovaInterface cordova;
- protected CordovaPreferences preferences;
- private String serviceName;
-
- /**
- * Call this after constructing to initialize the plugin.
- * Final because we want to be able to change args without breaking plugins.
- */
- public final void privateInitialize(String serviceName, CordovaInterface cordova, CordovaWebView webView, CordovaPreferences preferences) {
- assert this.cordova == null;
- this.serviceName = serviceName;
- this.cordova = cordova;
- this.webView = webView;
- this.preferences = preferences;
- initialize(cordova, webView);
- pluginInitialize();
- }
-
- /**
- * Called after plugin construction and fields have been initialized.
- * Prefer to use pluginInitialize instead since there is no value in
- * having parameters on the initialize() function.
- */
- public void initialize(CordovaInterface cordova, CordovaWebView webView) {
- }
-
- /**
- * Called after plugin construction and fields have been initialized.
- */
- protected void pluginInitialize() {
- }
-
- /**
- * Returns the plugin's service name (what you'd use when calling pluginManger.getPlugin())
- */
- public String getServiceName() {
- return serviceName;
- }
-
- /**
- * Executes the request.
- *
- * This method is called from the WebView thread. To do a non-trivial amount of work, use:
- * cordova.getThreadPool().execute(runnable);
- *
- * To run on the UI thread, use:
- * cordova.getActivity().runOnUiThread(runnable);
- *
- * @param action The action to execute.
- * @param rawArgs The exec() arguments in JSON form.
- * @param callbackContext The callback context used when calling back into JavaScript.
- * @return Whether the action was valid.
- */
- public boolean execute(String action, String rawArgs, CallbackContext callbackContext) throws JSONException {
- JSONArray args = new JSONArray(rawArgs);
- return execute(action, args, callbackContext);
- }
-
- /**
- * Executes the request.
- *
- * This method is called from the WebView thread. To do a non-trivial amount of work, use:
- * cordova.getThreadPool().execute(runnable);
- *
- * To run on the UI thread, use:
- * cordova.getActivity().runOnUiThread(runnable);
- *
- * @param action The action to execute.
- * @param args The exec() arguments.
- * @param callbackContext The callback context used when calling back into JavaScript.
- * @return Whether the action was valid.
- */
- public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
- CordovaArgs cordovaArgs = new CordovaArgs(args);
- return execute(action, cordovaArgs, callbackContext);
- }
-
- /**
- * Executes the request.
- *
- * This method is called from the WebView thread. To do a non-trivial amount of work, use:
- * cordova.getThreadPool().execute(runnable);
- *
- * To run on the UI thread, use:
- * cordova.getActivity().runOnUiThread(runnable);
- *
- * @param action The action to execute.
- * @param args The exec() arguments, wrapped with some Cordova helpers.
- * @param callbackContext The callback context used when calling back into JavaScript.
- * @return Whether the action was valid.
- */
- public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
- return false;
- }
-
- /**
- * Called when the system is about to start resuming a previous activity.
- *
- * @param multitasking Flag indicating if multitasking is turned on for app
- */
- public void onPause(boolean multitasking) {
- }
-
- /**
- * Called when the activity will start interacting with the user.
- *
- * @param multitasking Flag indicating if multitasking is turned on for app
- */
- public void onResume(boolean multitasking) {
- }
-
- /**
- * Called when the activity is becoming visible to the user.
- */
- public void onStart() {
- }
-
- /**
- * Called when the activity is no longer visible to the user.
- */
- public void onStop() {
- }
-
- /**
- * Called when the activity receives a new intent.
- */
- public void onNewIntent(Intent intent) {
- }
-
- /**
- * The final call you receive before your activity is destroyed.
- */
- public void onDestroy() {
- }
-
- /**
- * Called when the Activity is being destroyed (e.g. if a plugin calls out to an external
- * Activity and the OS kills the CordovaActivity in the background). The plugin should save its
- * state in this method only if it is awaiting the result of an external Activity and needs
- * to preserve some information so as to handle that result; onRestoreStateForActivityResult()
- * will only be called if the plugin is the recipient of an Activity result
- *
- * @return Bundle containing the state of the plugin or null if state does not need to be saved
- */
- public Bundle onSaveInstanceState() {
- return null;
- }
-
- /**
- * Called when a plugin is the recipient of an Activity result after the CordovaActivity has
- * been destroyed. The Bundle will be the same as the one the plugin returned in
- * onSaveInstanceState()
- *
- * @param state Bundle containing the state of the plugin
- * @param callbackContext Replacement Context to return the plugin result to
- */
- public void onRestoreStateForActivityResult(Bundle state, CallbackContext callbackContext) {}
-
- /**
- * Called when a message is sent to plugin.
- *
- * @param id The message id
- * @param data The message data
- * @return Object to stop propagation or null
- */
- public Object onMessage(String id, Object data) {
- return null;
- }
-
- /**
- * Called when an activity you launched exits, giving you the requestCode you started it with,
- * the resultCode it returned, and any additional data from it.
- *
- * @param requestCode The request code originally supplied to startActivityForResult(),
- * allowing you to identify who this result came from.
- * @param resultCode The integer result code returned by the child activity through its setResult().
- * @param intent An Intent, which can return result data to the caller (various data can be
- * attached to Intent "extras").
- */
- public void onActivityResult(int requestCode, int resultCode, Intent intent) {
- }
-
- /**
- * Hook for blocking the loading of external resources.
- *
- * This will be called when the WebView's shouldInterceptRequest wants to
- * know whether to open a connection to an external resource. Return false
- * to block the request: if any plugin returns false, Cordova will block
- * the request. If all plugins return null, the default policy will be
- * enforced. If at least one plugin returns true, and no plugins return
- * false, then the request will proceed.
- *
- * Note that this only affects resource requests which are routed through
- * WebViewClient.shouldInterceptRequest, such as XMLHttpRequest requests and
- * img tag loads. WebSockets and media requests (such as and
- * tags) are not affected by this method. Use CSP headers to control access
- * to such resources.
- */
- public Boolean shouldAllowRequest(String url) {
- return null;
- }
-
- /**
- * Hook for blocking navigation by the Cordova WebView. This applies both to top-level and
- * iframe navigations.
- *
- * This will be called when the WebView's needs to know whether to navigate
- * to a new page. Return false to block the navigation: if any plugin
- * returns false, Cordova will block the navigation. If all plugins return
- * null, the default policy will be enforced. It at least one plugin returns
- * true, and no plugins return false, then the navigation will proceed.
- */
- public Boolean shouldAllowNavigation(String url) {
- return null;
- }
-
- /**
- * Hook for allowing page to call exec(). By default, this returns the result of
- * shouldAllowNavigation(). It's generally unsafe to allow untrusted content to be loaded
- * into a CordovaWebView, even within an iframe, so it's best not to touch this.
- */
- public Boolean shouldAllowBridgeAccess(String url) {
- return shouldAllowNavigation(url);
- }
-
- /**
- * Hook for blocking the launching of Intents by the Cordova application.
- *
- * This will be called when the WebView will not navigate to a page, but
- * could launch an intent to handle the URL. Return false to block this: if
- * any plugin returns false, Cordova will block the navigation. If all
- * plugins return null, the default policy will be enforced. If at least one
- * plugin returns true, and no plugins return false, then the URL will be
- * opened.
- */
- public Boolean shouldOpenExternalUrl(String url) {
- return null;
- }
-
- /**
- * Allows plugins to handle a link being clicked. Return true here to cancel the navigation.
- *
- * @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.
- */
- public boolean onOverrideUrlLoading(String url) {
- return false;
- }
-
- /**
- * Hook for redirecting requests. Applies to WebView requests as well as requests made by plugins.
- * To handle the request directly, return a URI in the form:
- *
- * cdvplugin://pluginId/...
- *
- * And implement handleOpenForRead().
- * To make this easier, use the toPluginUri() and fromPluginUri() helpers:
- *
- * public Uri remapUri(Uri uri) { return toPluginUri(uri); }
- *
- * public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
- * Uri origUri = fromPluginUri(uri);
- * ...
- * }
- */
- public Uri remapUri(Uri uri) {
- return null;
- }
-
- /**
- * Called to handle CordovaResourceApi.openForRead() calls for a cdvplugin://pluginId/ URL.
- * Should never return null.
- * Added in cordova-android@4.0.0
- */
- public CordovaResourceApi.OpenForReadResult handleOpenForRead(Uri uri) throws IOException {
- throw new FileNotFoundException("Plugin can't handle uri: " + uri);
- }
-
- /**
- * Refer to remapUri()
- * Added in cordova-android@4.0.0
- */
- protected Uri toPluginUri(Uri origUri) {
- return new Uri.Builder()
- .scheme(CordovaResourceApi.PLUGIN_URI_SCHEME)
- .authority(serviceName)
- .appendQueryParameter("origUri", origUri.toString())
- .build();
- }
-
- /**
- * Refer to remapUri()
- * Added in cordova-android@4.0.0
- */
- protected Uri fromPluginUri(Uri pluginUri) {
- return Uri.parse(pluginUri.getQueryParameter("origUri"));
- }
-
- /**
- * Called when the WebView does a top-level navigation or refreshes.
- *
- * Plugins should stop any long-running processes and clean up internal state.
- *
- * Does nothing by default.
- */
- public void onReset() {
- }
-
- /**
- * Called when the system received an HTTP authentication request. Plugin can use
- * the supplied HttpAuthHandler to process this auth challenge.
- *
- * @param view The WebView that is initiating the callback
- * @param handler The HttpAuthHandler used to set the WebView's response
- * @param host The host requiring authentication
- * @param realm The realm for which authentication is required
- *
- * @return Returns True if plugin will resolve this auth challenge, otherwise False
- *
- */
- public boolean onReceivedHttpAuthRequest(CordovaWebView view, ICordovaHttpAuthHandler handler, String host, String realm) {
- return false;
- }
-
- /**
- * Called when he system received an SSL client certificate request. Plugin can use
- * the supplied ClientCertRequest to process this certificate challenge.
- *
- * @param view The WebView that is initiating the callback
- * @param request The client certificate request
- *
- * @return Returns True if plugin will resolve this auth challenge, otherwise False
- *
- */
- public boolean onReceivedClientCertRequest(CordovaWebView view, ICordovaClientCertRequest request) {
- return false;
- }
-
- /**
- * Called by the system when the device configuration changes while your activity is running.
- *
- * @param newConfig The new device configuration
- */
- public void onConfigurationChanged(Configuration newConfig) {
- }
-
- /**
- * Called by the Plugin Manager when we need to actually request permissions
- *
- * @param requestCode Passed to the activity to track the request
- *
- * @return Returns the permission that was stored in the plugin
- */
-
- public void requestPermissions(int requestCode) {
- }
-
- /*
- * Called by the WebView implementation to check for geolocation permissions, can be used
- * by other Java methods in the event that a plugin is using this as a dependency.
- *
- * @return Returns true if the plugin has all the permissions it needs to operate.
- */
-
- public boolean hasPermisssion() {
- return true;
- }
-
- /**
- * Called by the system when the user grants permissions
- *
- * @param requestCode
- * @param permissions
- * @param grantResults
- */
- public void onRequestPermissionResult(int requestCode, String[] permissions,
- int[] grantResults) throws JSONException {
-
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java
deleted file mode 100644
index 4dbc93e..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaPreferences.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova;
-
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.cordova.LOG;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class CordovaPreferences {
- private HashMap prefs = new HashMap(20);
- private Bundle preferencesBundleExtras;
-
- public void setPreferencesBundle(Bundle extras) {
- preferencesBundleExtras = extras;
- }
-
- public void set(String name, String value) {
- prefs.put(name.toLowerCase(Locale.ENGLISH), value);
- }
-
- public void set(String name, boolean value) {
- set(name, "" + value);
- }
-
- public void set(String name, int value) {
- set(name, "" + value);
- }
-
- public void set(String name, double value) {
- set(name, "" + value);
- }
-
- public Map getAll() {
- return prefs;
- }
-
- public boolean getBoolean(String name, boolean defaultValue) {
- name = name.toLowerCase(Locale.ENGLISH);
- String value = prefs.get(name);
- if (value != null) {
- return Boolean.parseBoolean(value);
- }
- return defaultValue;
- }
-
- // Added in 4.0.0
- public boolean contains(String name) {
- return getString(name, null) != null;
- }
-
- public int getInteger(String name, int defaultValue) {
- name = name.toLowerCase(Locale.ENGLISH);
- String value = prefs.get(name);
- if (value != null) {
- // Use Integer.decode() can't handle it if the highest bit is set.
- return (int)(long)Long.decode(value);
- }
- return defaultValue;
- }
-
- public double getDouble(String name, double defaultValue) {
- name = name.toLowerCase(Locale.ENGLISH);
- String value = prefs.get(name);
- if (value != null) {
- return Double.valueOf(value);
- }
- return defaultValue;
- }
-
- public String getString(String name, String defaultValue) {
- name = name.toLowerCase(Locale.ENGLISH);
- String value = prefs.get(name);
- if (value != null) {
- return value;
- }
- return defaultValue;
- }
-
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java
deleted file mode 100644
index 3c438e2..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaResourceApi.java
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.cordova;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.content.res.AssetManager;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Looper;
-import android.util.Base64;
-import android.webkit.MimeTypeMap;
-
-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.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.nio.channels.FileChannel;
-import java.util.Locale;
-
-/**
- * What this class provides:
- * 1. Helpers for reading & writing to URLs.
- * - E.g. handles assets, resources, content providers, files, data URIs, http[s]
- * - E.g. Can be used to query for mime-type & content length.
- *
- * 2. To allow plugins to redirect URLs (via remapUrl).
- * - All plugins should call remapUrl() on URLs they receive from JS *before*
- * passing the URL onto other utility functions in this class.
- * - For an example usage of this, refer to the org.apache.cordova.file plugin.
- *
- * Future Work:
- * - Consider using a Cursor to query content URLs for their size (like the file plugin does).
- * - Allow plugins to remapUri to "cdv-plugin://plugin-name/foo", which CordovaResourceApi
- * would then delegate to pluginManager.getPlugin(plugin-name).openForRead(url)
- * - Currently, plugins *can* do this by remapping to a data: URL, but it's inefficient
- * for large payloads.
- */
-public class CordovaResourceApi {
- @SuppressWarnings("unused")
- private static final String LOG_TAG = "CordovaResourceApi";
-
- public static final int URI_TYPE_FILE = 0;
- public static final int URI_TYPE_ASSET = 1;
- public static final int URI_TYPE_CONTENT = 2;
- public static final int URI_TYPE_RESOURCE = 3;
- public static final int URI_TYPE_DATA = 4;
- public static final int URI_TYPE_HTTP = 5;
- public static final int URI_TYPE_HTTPS = 6;
- public static final int URI_TYPE_PLUGIN = 7;
- public static final int URI_TYPE_UNKNOWN = -1;
-
- public static final String PLUGIN_URI_SCHEME = "cdvplugin";
-
- private static final String[] LOCAL_FILE_PROJECTION = { "_data" };
-
- public static Thread jsThread;
-
- private final AssetManager assetManager;
- private final ContentResolver contentResolver;
- private final PluginManager pluginManager;
- private boolean threadCheckingEnabled = true;
-
-
- public CordovaResourceApi(Context context, PluginManager pluginManager) {
- this.contentResolver = context.getContentResolver();
- this.assetManager = context.getAssets();
- this.pluginManager = pluginManager;
- }
-
- public void setThreadCheckingEnabled(boolean value) {
- threadCheckingEnabled = value;
- }
-
- public boolean isThreadCheckingEnabled() {
- return threadCheckingEnabled;
- }
-
-
- public static int getUriType(Uri uri) {
- assertNonRelative(uri);
- String scheme = uri.getScheme();
- if (ContentResolver.SCHEME_CONTENT.equalsIgnoreCase(scheme)) {
- return URI_TYPE_CONTENT;
- }
- if (ContentResolver.SCHEME_ANDROID_RESOURCE.equalsIgnoreCase(scheme)) {
- return URI_TYPE_RESOURCE;
- }
- if (ContentResolver.SCHEME_FILE.equalsIgnoreCase(scheme)) {
- if (uri.getPath().startsWith("/android_asset/")) {
- return URI_TYPE_ASSET;
- }
- return URI_TYPE_FILE;
- }
- if ("data".equalsIgnoreCase(scheme)) {
- return URI_TYPE_DATA;
- }
- if ("http".equalsIgnoreCase(scheme)) {
- return URI_TYPE_HTTP;
- }
- if ("https".equalsIgnoreCase(scheme)) {
- return URI_TYPE_HTTPS;
- }
- if (PLUGIN_URI_SCHEME.equalsIgnoreCase(scheme)) {
- return URI_TYPE_PLUGIN;
- }
- return URI_TYPE_UNKNOWN;
- }
-
- public Uri remapUri(Uri uri) {
- assertNonRelative(uri);
- Uri pluginUri = pluginManager.remapUri(uri);
- return pluginUri != null ? pluginUri : uri;
- }
-
- public String remapPath(String path) {
- return remapUri(Uri.fromFile(new File(path))).getPath();
- }
-
- /**
- * Returns a File that points to the resource, or null if the resource
- * is not on the local filesystem.
- */
- public File mapUriToFile(Uri uri) {
- assertBackgroundThread();
- switch (getUriType(uri)) {
- case URI_TYPE_FILE:
- return new File(uri.getPath());
- case URI_TYPE_CONTENT: {
- Cursor cursor = contentResolver.query(uri, LOCAL_FILE_PROJECTION, null, null, null);
- if (cursor != null) {
- try {
- int columnIndex = cursor.getColumnIndex(LOCAL_FILE_PROJECTION[0]);
- if (columnIndex != -1 && cursor.getCount() > 0) {
- cursor.moveToFirst();
- String realPath = cursor.getString(columnIndex);
- if (realPath != null) {
- return new File(realPath);
- }
- }
- } finally {
- cursor.close();
- }
- }
- }
- }
- return null;
- }
-
- public String getMimeType(Uri uri) {
- switch (getUriType(uri)) {
- case URI_TYPE_FILE:
- case URI_TYPE_ASSET:
- return getMimeTypeFromPath(uri.getPath());
- case URI_TYPE_CONTENT:
- case URI_TYPE_RESOURCE:
- return contentResolver.getType(uri);
- case URI_TYPE_DATA: {
- return getDataUriMimeType(uri);
- }
- case URI_TYPE_HTTP:
- case URI_TYPE_HTTPS: {
- try {
- HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
- conn.setDoInput(false);
- conn.setRequestMethod("HEAD");
- String mimeType = conn.getHeaderField("Content-Type");
- if (mimeType != null) {
- mimeType = mimeType.split(";")[0];
- }
- return mimeType;
- } catch (IOException e) {
- }
- }
- }
-
- return null;
- }
-
-
- //This already exists
- private String getMimeTypeFromPath(String path) {
- String extension = path;
- int lastDot = extension.lastIndexOf('.');
- if (lastDot != -1) {
- extension = extension.substring(lastDot + 1);
- }
- // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185).
- extension = extension.toLowerCase(Locale.getDefault());
- if (extension.equals("3ga")) {
- return "audio/3gpp";
- } else if (extension.equals("js")) {
- // Missing from the map :(.
- return "text/javascript";
- }
- return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
- }
-
- /**
- * Opens a stream to the given URI, also providing the MIME type & length.
- * @return Never returns null.
- * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
- * resolved before being passed into this function.
- * @throws Throws an IOException if the URI cannot be opened.
- * @throws Throws an IllegalStateException if called on a foreground thread.
- */
- public OpenForReadResult openForRead(Uri uri) throws IOException {
- return openForRead(uri, false);
- }
-
- /**
- * Opens a stream to the given URI, also providing the MIME type & length.
- * @return Never returns null.
- * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
- * resolved before being passed into this function.
- * @throws Throws an IOException if the URI cannot be opened.
- * @throws Throws an IllegalStateException if called on a foreground thread and skipThreadCheck is false.
- */
- public OpenForReadResult openForRead(Uri uri, boolean skipThreadCheck) throws IOException {
- if (!skipThreadCheck) {
- assertBackgroundThread();
- }
- switch (getUriType(uri)) {
- case URI_TYPE_FILE: {
- FileInputStream inputStream = new FileInputStream(uri.getPath());
- String mimeType = getMimeTypeFromPath(uri.getPath());
- long length = inputStream.getChannel().size();
- return new OpenForReadResult(uri, inputStream, mimeType, length, null);
- }
- case URI_TYPE_ASSET: {
- String assetPath = uri.getPath().substring(15);
- AssetFileDescriptor assetFd = null;
- InputStream inputStream;
- long length = -1;
- try {
- assetFd = assetManager.openFd(assetPath);
- inputStream = assetFd.createInputStream();
- length = assetFd.getLength();
- } catch (FileNotFoundException e) {
- // Will occur if the file is compressed.
- inputStream = assetManager.open(assetPath);
- length = inputStream.available();
- }
- String mimeType = getMimeTypeFromPath(assetPath);
- return new OpenForReadResult(uri, inputStream, mimeType, length, assetFd);
- }
- case URI_TYPE_CONTENT:
- case URI_TYPE_RESOURCE: {
- String mimeType = contentResolver.getType(uri);
- AssetFileDescriptor assetFd = contentResolver.openAssetFileDescriptor(uri, "r");
- InputStream inputStream = assetFd.createInputStream();
- long length = assetFd.getLength();
- return new OpenForReadResult(uri, inputStream, mimeType, length, assetFd);
- }
- case URI_TYPE_DATA: {
- OpenForReadResult ret = readDataUri(uri);
- if (ret == null) {
- break;
- }
- return ret;
- }
- case URI_TYPE_HTTP:
- case URI_TYPE_HTTPS: {
- HttpURLConnection conn = (HttpURLConnection)new URL(uri.toString()).openConnection();
- conn.setDoInput(true);
- String mimeType = conn.getHeaderField("Content-Type");
- if (mimeType != null) {
- mimeType = mimeType.split(";")[0];
- }
- int length = conn.getContentLength();
- InputStream inputStream = conn.getInputStream();
- return new OpenForReadResult(uri, inputStream, mimeType, length, null);
- }
- case URI_TYPE_PLUGIN: {
- String pluginId = uri.getHost();
- CordovaPlugin plugin = pluginManager.getPlugin(pluginId);
- if (plugin == null) {
- throw new FileNotFoundException("Invalid plugin ID in URI: " + uri);
- }
- return plugin.handleOpenForRead(uri);
- }
- }
- throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
- }
-
- public OutputStream openOutputStream(Uri uri) throws IOException {
- return openOutputStream(uri, false);
- }
-
- /**
- * Opens a stream to the given URI.
- * @return Never returns null.
- * @throws Throws an InvalidArgumentException for relative URIs. Relative URIs should be
- * resolved before being passed into this function.
- * @throws Throws an IOException if the URI cannot be opened.
- */
- public OutputStream openOutputStream(Uri uri, boolean append) throws IOException {
- assertBackgroundThread();
- switch (getUriType(uri)) {
- case URI_TYPE_FILE: {
- File localFile = new File(uri.getPath());
- File parent = localFile.getParentFile();
- if (parent != null) {
- parent.mkdirs();
- }
- return new FileOutputStream(localFile, append);
- }
- case URI_TYPE_CONTENT:
- case URI_TYPE_RESOURCE: {
- AssetFileDescriptor assetFd = contentResolver.openAssetFileDescriptor(uri, append ? "wa" : "w");
- return assetFd.createOutputStream();
- }
- }
- throw new FileNotFoundException("URI not supported by CordovaResourceApi: " + uri);
- }
-
- public HttpURLConnection createHttpConnection(Uri uri) throws IOException {
- assertBackgroundThread();
- return (HttpURLConnection)new URL(uri.toString()).openConnection();
- }
-
- // Copies the input to the output in the most efficient manner possible.
- // Closes both streams.
- public void copyResource(OpenForReadResult input, OutputStream outputStream) throws IOException {
- assertBackgroundThread();
- try {
- InputStream inputStream = input.inputStream;
- if (inputStream instanceof FileInputStream && outputStream instanceof FileOutputStream) {
- FileChannel inChannel = ((FileInputStream)input.inputStream).getChannel();
- FileChannel outChannel = ((FileOutputStream)outputStream).getChannel();
- long offset = 0;
- long length = input.length;
- if (input.assetFd != null) {
- offset = input.assetFd.getStartOffset();
- }
- // transferFrom()'s 2nd arg is a relative position. Need to set the absolute
- // position first.
- inChannel.position(offset);
- outChannel.transferFrom(inChannel, 0, length);
- } else {
- final int BUFFER_SIZE = 8192;
- byte[] buffer = new byte[BUFFER_SIZE];
-
- for (;;) {
- int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
-
- if (bytesRead <= 0) {
- break;
- }
- outputStream.write(buffer, 0, bytesRead);
- }
- }
- } finally {
- input.inputStream.close();
- if (outputStream != null) {
- outputStream.close();
- }
- }
- }
-
- public void copyResource(Uri sourceUri, OutputStream outputStream) throws IOException {
- copyResource(openForRead(sourceUri), outputStream);
- }
-
- // Added in 3.5.0.
- public void copyResource(Uri sourceUri, Uri dstUri) throws IOException {
- copyResource(openForRead(sourceUri), openOutputStream(dstUri));
- }
-
- private void assertBackgroundThread() {
- if (threadCheckingEnabled) {
- Thread curThread = Thread.currentThread();
- if (curThread == Looper.getMainLooper().getThread()) {
- throw new IllegalStateException("Do not perform IO operations on the UI thread. Use CordovaInterface.getThreadPool() instead.");
- }
- if (curThread == jsThread) {
- throw new IllegalStateException("Tried to perform an IO operation on the WebCore thread. Use CordovaInterface.getThreadPool() instead.");
- }
- }
- }
-
- private String getDataUriMimeType(Uri uri) {
- String uriAsString = uri.getSchemeSpecificPart();
- int commaPos = uriAsString.indexOf(',');
- if (commaPos == -1) {
- return null;
- }
- String[] mimeParts = uriAsString.substring(0, commaPos).split(";");
- if (mimeParts.length > 0) {
- return mimeParts[0];
- }
- return null;
- }
-
- private OpenForReadResult readDataUri(Uri uri) {
- String uriAsString = uri.getSchemeSpecificPart();
- int commaPos = uriAsString.indexOf(',');
- if (commaPos == -1) {
- return null;
- }
- String[] mimeParts = uriAsString.substring(0, commaPos).split(";");
- String contentType = null;
- boolean base64 = false;
- if (mimeParts.length > 0) {
- contentType = mimeParts[0];
- }
- for (int i = 1; i < mimeParts.length; ++i) {
- if ("base64".equalsIgnoreCase(mimeParts[i])) {
- base64 = true;
- }
- }
- String dataPartAsString = uriAsString.substring(commaPos + 1);
- byte[] data;
- if (base64) {
- data = Base64.decode(dataPartAsString, Base64.DEFAULT);
- } else {
- try {
- data = dataPartAsString.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- data = dataPartAsString.getBytes();
- }
- }
- InputStream inputStream = new ByteArrayInputStream(data);
- return new OpenForReadResult(uri, inputStream, contentType, data.length, null);
- }
-
- private static void assertNonRelative(Uri uri) {
- if (!uri.isAbsolute()) {
- throw new IllegalArgumentException("Relative URIs are not supported.");
- }
- }
-
- public static final class OpenForReadResult {
- public final Uri uri;
- public final InputStream inputStream;
- public final String mimeType;
- public final long length;
- public final AssetFileDescriptor assetFd;
-
- public OpenForReadResult(Uri uri, InputStream inputStream, String mimeType, long length, AssetFileDescriptor assetFd) {
- this.uri = uri;
- this.inputStream = inputStream;
- this.mimeType = mimeType;
- this.length = length;
- this.assetFd = assetFd;
- }
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java
deleted file mode 100644
index 64d410e..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebView.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import java.util.List;
-import java.util.Map;
-
-import android.content.Context;
-import android.content.Intent;
-import android.view.View;
-import android.webkit.WebChromeClient.CustomViewCallback;
-
-/**
- * Main interface for interacting with a Cordova webview - implemented by CordovaWebViewImpl.
- * This is an interface so that it can be easily mocked in tests.
- * Methods may be added to this interface without a major version bump, as plugins & embedders
- * are not expected to implement it.
- */
-public interface CordovaWebView {
- public static final String CORDOVA_VERSION = "7.1.2";
-
- void init(CordovaInterface cordova, List pluginEntries, CordovaPreferences preferences);
-
- boolean isInitialized();
-
- View getView();
-
- void loadUrlIntoView(String url, boolean recreatePlugins);
-
- void stopLoading();
-
- boolean canGoBack();
-
- void clearCache();
-
- /** Use parameter-less overload */
- @Deprecated
- void clearCache(boolean b);
-
- void clearHistory();
-
- boolean backHistory();
-
- void handlePause(boolean keepRunning);
-
- void onNewIntent(Intent intent);
-
- void handleResume(boolean keepRunning);
-
- void handleStart();
-
- void handleStop();
-
- void handleDestroy();
-
- /**
- * Send JavaScript statement back to JavaScript.
- *
- * Deprecated (https://issues.apache.org/jira/browse/CB-6851)
- * Instead of executing snippets of JS, you should use the exec bridge
- * to create a Java->JS communication channel.
- * To do this:
- * 1. Within plugin.xml (to have your JS run before deviceready):
- *
- * 2. Within your .js (call exec on start-up):
- * require('cordova/channel').onCordovaReady.subscribe(function() {
- * require('cordova/exec')(win, null, 'Plugin', 'method', []);
- * function win(message) {
- * ... process message from java here ...
- * }
- * });
- * 3. Within your .java:
- * PluginResult dataResult = new PluginResult(PluginResult.Status.OK, CODE);
- * dataResult.setKeepCallback(true);
- * savedCallbackContext.sendPluginResult(dataResult);
- */
- @Deprecated
- void sendJavascript(String statememt);
-
- /**
- * Load the specified URL in the Cordova webview or a new browser instance.
- *
- * NOTE: If openExternal is false, only whitelisted URLs can be loaded.
- *
- * @param url The url to load.
- * @param openExternal Load url in browser instead of Cordova webview.
- * @param clearHistory Clear the history stack, so new page becomes top of history
- * @param params Parameters for new app
- */
- void showWebPage(String url, boolean openExternal, boolean clearHistory, Map params);
-
- /**
- * Deprecated in 4.0.0. Use your own View-toggling logic.
- */
- @Deprecated
- boolean isCustomViewShowing();
-
- /**
- * Deprecated in 4.0.0. Use your own View-toggling logic.
- */
- @Deprecated
- void showCustomView(View view, CustomViewCallback callback);
-
- /**
- * Deprecated in 4.0.0. Use your own View-toggling logic.
- */
- @Deprecated
- void hideCustomView();
-
- CordovaResourceApi getResourceApi();
-
- void setButtonPlumbedToJs(int keyCode, boolean override);
- boolean isButtonPlumbedToJs(int keyCode);
-
- void sendPluginResult(PluginResult cr, String callbackId);
-
- PluginManager getPluginManager();
- CordovaWebViewEngine getEngine();
- CordovaPreferences getPreferences();
- ICordovaCookieManager getCookieManager();
-
- String getUrl();
-
- // TODO: Work on deleting these by removing refs from plugins.
- Context getContext();
- void loadUrl(String url);
- Object postMessage(String id, Object data);
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java
deleted file mode 100644
index c8e5a55..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewEngine.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import android.view.KeyEvent;
-import android.view.View;
-import android.webkit.ValueCallback;
-
-/**
- * Interface for all Cordova engines.
- * No methods will be added to this class (in order to be compatible with existing engines).
- * Instead, we will create a new interface: e.g. CordovaWebViewEngineV2
- */
-public interface CordovaWebViewEngine {
- void init(CordovaWebView parentWebView, CordovaInterface cordova, Client client,
- CordovaResourceApi resourceApi, PluginManager pluginManager,
- NativeToJsMessageQueue nativeToJsMessageQueue);
-
- CordovaWebView getCordovaWebView();
- ICordovaCookieManager getCookieManager();
- View getView();
-
- void loadUrl(String url, boolean clearNavigationStack);
-
- void stopLoading();
-
- /** Return the currently loaded URL */
- String getUrl();
-
- void clearCache();
-
- /** After calling clearHistory(), canGoBack() should be false. */
- void clearHistory();
-
- boolean canGoBack();
-
- /** Returns whether a navigation occurred */
- boolean goBack();
-
- /** Pauses / resumes the WebView's event loop. */
- void setPaused(boolean value);
-
- /** Clean up all resources associated with the WebView. */
- void destroy();
-
- /** Add the evaulate Javascript method **/
- void evaluateJavascript(String js, ValueCallback callback);
-
- /**
- * Used to retrieve the associated CordovaWebView given a View without knowing the type of Engine.
- * E.g. ((CordovaWebView.EngineView)activity.findViewById(android.R.id.webView)).getCordovaWebView();
- */
- public interface EngineView {
- CordovaWebView getCordovaWebView();
- }
-
- /**
- * Contains methods that an engine uses to communicate with the parent CordovaWebView.
- * Methods may be added in future cordova versions, but never removed.
- */
- public interface Client {
- Boolean onDispatchKeyEvent(KeyEvent event);
- void clearLoadTimeoutTimer();
- void onPageStarted(String newUrl);
- void onReceivedError(int errorCode, String description, String failingUrl);
- void onPageFinishedLoading(String url);
- boolean onNavigationAttempt(String url);
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewImpl.java b/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewImpl.java
deleted file mode 100644
index fb99c34..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CordovaWebViewImpl.java
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.WebChromeClient;
-import android.widget.FrameLayout;
-
-import org.apache.cordova.engine.SystemWebViewEngine;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.lang.reflect.Constructor;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Main class for interacting with a Cordova webview. Manages plugins, events, and a CordovaWebViewEngine.
- * Class uses two-phase initialization. You must call init() before calling any other methods.
- */
-public class CordovaWebViewImpl implements CordovaWebView {
-
- public static final String TAG = "CordovaWebViewImpl";
-
- private PluginManager pluginManager;
-
- protected final CordovaWebViewEngine engine;
- private CordovaInterface cordova;
-
- // Flag to track that a loadUrl timeout occurred
- private int loadUrlTimeout = 0;
-
- private CordovaResourceApi resourceApi;
- private CordovaPreferences preferences;
- private CoreAndroid appPlugin;
- private NativeToJsMessageQueue nativeToJsMessageQueue;
- private EngineClient engineClient = new EngineClient();
- private boolean hasPausedEver;
-
- // The URL passed to loadUrl(), not necessarily the URL of the current page.
- String loadedUrl;
-
- /** custom view created by the browser (a video player for example) */
- private View mCustomView;
- private WebChromeClient.CustomViewCallback mCustomViewCallback;
-
- private Set boundKeyCodes = new HashSet();
-
- public static CordovaWebViewEngine createEngine(Context context, CordovaPreferences preferences) {
- String className = preferences.getString("webview", SystemWebViewEngine.class.getCanonicalName());
- try {
- Class> webViewClass = Class.forName(className);
- Constructor> constructor = webViewClass.getConstructor(Context.class, CordovaPreferences.class);
- return (CordovaWebViewEngine) constructor.newInstance(context, preferences);
- } catch (Exception e) {
- throw new RuntimeException("Failed to create webview. ", e);
- }
- }
-
- public CordovaWebViewImpl(CordovaWebViewEngine cordovaWebViewEngine) {
- this.engine = cordovaWebViewEngine;
- }
-
- // Convenience method for when creating programmatically (not from Config.xml).
- public void init(CordovaInterface cordova) {
- init(cordova, new ArrayList(), new CordovaPreferences());
- }
-
- @SuppressLint("Assert")
- @Override
- public void init(CordovaInterface cordova, List pluginEntries, CordovaPreferences preferences) {
- if (this.cordova != null) {
- throw new IllegalStateException();
- }
- this.cordova = cordova;
- this.preferences = preferences;
- pluginManager = new PluginManager(this, this.cordova, pluginEntries);
- resourceApi = new CordovaResourceApi(engine.getView().getContext(), pluginManager);
- nativeToJsMessageQueue = new NativeToJsMessageQueue();
- nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.NoOpBridgeMode());
- nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.LoadUrlBridgeMode(engine, cordova));
-
- if (preferences.getBoolean("DisallowOverscroll", false)) {
- engine.getView().setOverScrollMode(View.OVER_SCROLL_NEVER);
- }
- engine.init(this, cordova, engineClient, resourceApi, pluginManager, nativeToJsMessageQueue);
- // This isn't enforced by the compiler, so assert here.
- assert engine.getView() instanceof CordovaWebViewEngine.EngineView;
-
- pluginManager.addService(CoreAndroid.PLUGIN_NAME, "org.apache.cordova.CoreAndroid");
- pluginManager.init();
-
- }
-
- @Override
- public boolean isInitialized() {
- return cordova != null;
- }
-
- @Override
- public void loadUrlIntoView(final String url, boolean recreatePlugins) {
- LOG.d(TAG, ">>> loadUrl(" + url + ")");
- if (url.equals("about:blank") || url.startsWith("javascript:")) {
- engine.loadUrl(url, false);
- return;
- }
-
- recreatePlugins = recreatePlugins || (loadedUrl == null);
-
- if (recreatePlugins) {
- // Don't re-initialize on first load.
- if (loadedUrl != null) {
- appPlugin = null;
- pluginManager.init();
- }
- loadedUrl = url;
- }
-
- // Create a timeout timer for loadUrl
- final int currentLoadUrlTimeout = loadUrlTimeout;
- final int loadUrlTimeoutValue = preferences.getInteger("LoadUrlTimeoutValue", 20000);
-
- // Timeout error method
- final Runnable loadError = new Runnable() {
- public void run() {
- stopLoading();
- LOG.e(TAG, "CordovaWebView: TIMEOUT ERROR!");
-
- // Handle other errors by passing them to the webview in JS
- JSONObject data = new JSONObject();
- try {
- data.put("errorCode", -6);
- data.put("description", "The connection to the server was unsuccessful.");
- data.put("url", url);
- } catch (JSONException e) {
- // Will never happen.
- }
- pluginManager.postMessage("onReceivedError", data);
- }
- };
-
- // Timeout timer method
- final Runnable timeoutCheck = new Runnable() {
- public void run() {
- try {
- synchronized (this) {
- wait(loadUrlTimeoutValue);
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- // If timeout, then stop loading and handle error
- if (loadUrlTimeout == currentLoadUrlTimeout) {
- cordova.getActivity().runOnUiThread(loadError);
- }
- }
- };
-
- final boolean _recreatePlugins = recreatePlugins;
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- if (loadUrlTimeoutValue > 0) {
- cordova.getThreadPool().execute(timeoutCheck);
- }
- engine.loadUrl(url, _recreatePlugins);
- }
- });
- }
-
-
- @Override
- public void loadUrl(String url) {
- loadUrlIntoView(url, true);
- }
-
- @Override
- public void showWebPage(String url, boolean openExternal, boolean clearHistory, Map params) {
- LOG.d(TAG, "showWebPage(%s, %b, %b, HashMap)", url, openExternal, clearHistory);
-
- // If clearing history
- if (clearHistory) {
- engine.clearHistory();
- }
-
- // If loading into our webview
- if (!openExternal) {
- // Make sure url is in whitelist
- if (pluginManager.shouldAllowNavigation(url)) {
- // TODO: What about params?
- // Load new URL
- loadUrlIntoView(url, true);
- } else {
- LOG.w(TAG, "showWebPage: Refusing to load URL into webview since it is not in the whitelist. URL=" + url);
- }
- }
- if (!pluginManager.shouldOpenExternalUrl(url)) {
- LOG.w(TAG, "showWebPage: Refusing to send intent for URL since it is not in the whitelist. URL=" + url);
- return;
- }
- try {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- // To send an intent without CATEGORY_BROWSER, a custom plugin should be used.
- intent.addCategory(Intent.CATEGORY_BROWSABLE);
- Uri uri = Uri.parse(url);
- // Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
- // Adding the MIME type to http: URLs causes them to not be handled by the downloader.
- if ("file".equals(uri.getScheme())) {
- intent.setDataAndType(uri, resourceApi.getMimeType(uri));
- } else {
- intent.setData(uri);
- }
- cordova.getActivity().startActivity(intent);
- } catch (android.content.ActivityNotFoundException e) {
- LOG.e(TAG, "Error loading url " + url, e);
- }
- }
-
- @Override
- @Deprecated
- public void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
- // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
- LOG.d(TAG, "showing Custom View");
- // if a view already exists then immediately terminate the new one
- if (mCustomView != null) {
- callback.onCustomViewHidden();
- return;
- }
-
- // Store the view and its callback for later (to kill it properly)
- mCustomView = view;
- mCustomViewCallback = callback;
-
- // Add the custom view to its container.
- ViewGroup parent = (ViewGroup) engine.getView().getParent();
- parent.addView(view, new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT,
- Gravity.CENTER));
-
- // Hide the content view.
- engine.getView().setVisibility(View.GONE);
-
- // Finally show the custom view container.
- parent.setVisibility(View.VISIBLE);
- parent.bringToFront();
- }
-
- @Override
- @Deprecated
- public void hideCustomView() {
- // This code is adapted from the original Android Browser code, licensed under the Apache License, Version 2.0
- if (mCustomView == null) return;
- LOG.d(TAG, "Hiding Custom View");
-
- // Hide the custom view.
- mCustomView.setVisibility(View.GONE);
-
- // Remove the custom view from its container.
- ViewGroup parent = (ViewGroup) engine.getView().getParent();
- parent.removeView(mCustomView);
- mCustomView = null;
- mCustomViewCallback.onCustomViewHidden();
-
- // Show the content view.
- engine.getView().setVisibility(View.VISIBLE);
- }
-
- @Override
- @Deprecated
- public boolean isCustomViewShowing() {
- return mCustomView != null;
- }
-
- @Override
- @Deprecated
- public void sendJavascript(String statement) {
- nativeToJsMessageQueue.addJavaScript(statement);
- }
-
- @Override
- public void sendPluginResult(PluginResult cr, String callbackId) {
- nativeToJsMessageQueue.addPluginResult(cr, callbackId);
- }
-
- @Override
- public PluginManager getPluginManager() {
- return pluginManager;
- }
- @Override
- public CordovaPreferences getPreferences() {
- return preferences;
- }
- @Override
- public ICordovaCookieManager getCookieManager() {
- return engine.getCookieManager();
- }
- @Override
- public CordovaResourceApi getResourceApi() {
- return resourceApi;
- }
- @Override
- public CordovaWebViewEngine getEngine() {
- return engine;
- }
- @Override
- public View getView() {
- return engine.getView();
- }
- @Override
- public Context getContext() {
- return engine.getView().getContext();
- }
-
- private void sendJavascriptEvent(String event) {
- if (appPlugin == null) {
- appPlugin = (CoreAndroid)pluginManager.getPlugin(CoreAndroid.PLUGIN_NAME);
- }
-
- if (appPlugin == null) {
- LOG.w(TAG, "Unable to fire event without existing plugin");
- return;
- }
- appPlugin.fireJavascriptEvent(event);
- }
-
- @Override
- public void setButtonPlumbedToJs(int keyCode, boolean override) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_BACK:
- case KeyEvent.KEYCODE_MENU:
- // TODO: Why are search and menu buttons handled separately?
- if (override) {
- boundKeyCodes.add(keyCode);
- } else {
- boundKeyCodes.remove(keyCode);
- }
- return;
- default:
- throw new IllegalArgumentException("Unsupported keycode: " + keyCode);
- }
- }
-
- @Override
- public boolean isButtonPlumbedToJs(int keyCode) {
- return boundKeyCodes.contains(keyCode);
- }
-
- @Override
- public Object postMessage(String id, Object data) {
- return pluginManager.postMessage(id, data);
- }
-
- // Engine method proxies:
- @Override
- public String getUrl() {
- return engine.getUrl();
- }
-
- @Override
- public void stopLoading() {
- // Clear timeout flag
- loadUrlTimeout++;
- }
-
- @Override
- public boolean canGoBack() {
- return engine.canGoBack();
- }
-
- @Override
- public void clearCache() {
- engine.clearCache();
- }
-
- @Override
- @Deprecated
- public void clearCache(boolean b) {
- engine.clearCache();
- }
-
- @Override
- public void clearHistory() {
- engine.clearHistory();
- }
-
- @Override
- public boolean backHistory() {
- return engine.goBack();
- }
-
- /////// LifeCycle methods ///////
- @Override
- public void onNewIntent(Intent intent) {
- if (this.pluginManager != null) {
- this.pluginManager.onNewIntent(intent);
- }
- }
- @Override
- public void handlePause(boolean keepRunning) {
- if (!isInitialized()) {
- return;
- }
- hasPausedEver = true;
- pluginManager.onPause(keepRunning);
- sendJavascriptEvent("pause");
-
- // If app doesn't want to run in background
- if (!keepRunning) {
- // Pause JavaScript timers. This affects all webviews within the app!
- engine.setPaused(true);
- }
- }
- @Override
- public void handleResume(boolean keepRunning) {
- if (!isInitialized()) {
- return;
- }
-
- // Resume JavaScript timers. This affects all webviews within the app!
- engine.setPaused(false);
- this.pluginManager.onResume(keepRunning);
-
- // In order to match the behavior of the other platforms, we only send onResume after an
- // onPause has occurred. The resume event might still be sent if the Activity was killed
- // while waiting for the result of an external Activity once the result is obtained
- if (hasPausedEver) {
- sendJavascriptEvent("resume");
- }
- }
- @Override
- public void handleStart() {
- if (!isInitialized()) {
- return;
- }
- pluginManager.onStart();
- }
- @Override
- public void handleStop() {
- if (!isInitialized()) {
- return;
- }
- pluginManager.onStop();
- }
- @Override
- public void handleDestroy() {
- if (!isInitialized()) {
- return;
- }
- // Cancel pending timeout timer.
- loadUrlTimeout++;
-
- // Forward to plugins
- this.pluginManager.onDestroy();
-
- // TODO: about:blank is a bit special (and the default URL for new frames)
- // We should use a blank data: url instead so it's more obvious
- this.loadUrl("about:blank");
-
- // TODO: Should not destroy webview until after about:blank is done loading.
- engine.destroy();
- hideCustomView();
- }
-
- protected class EngineClient implements CordovaWebViewEngine.Client {
- @Override
- public void clearLoadTimeoutTimer() {
- loadUrlTimeout++;
- }
-
- @Override
- public void onPageStarted(String newUrl) {
- LOG.d(TAG, "onPageDidNavigate(" + newUrl + ")");
- boundKeyCodes.clear();
- pluginManager.onReset();
- pluginManager.postMessage("onPageStarted", newUrl);
- }
-
- @Override
- public void onReceivedError(int errorCode, String description, String failingUrl) {
- clearLoadTimeoutTimer();
- JSONObject data = new JSONObject();
- try {
- data.put("errorCode", errorCode);
- data.put("description", description);
- data.put("url", failingUrl);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- pluginManager.postMessage("onReceivedError", data);
- }
-
- @Override
- public void onPageFinishedLoading(String url) {
- LOG.d(TAG, "onPageFinished(" + url + ")");
-
- clearLoadTimeoutTimer();
-
- // Broadcast message that page has loaded
- pluginManager.postMessage("onPageFinished", url);
-
- // Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly
- if (engine.getView().getVisibility() != View.VISIBLE) {
- Thread t = new Thread(new Runnable() {
- public void run() {
- try {
- Thread.sleep(2000);
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- pluginManager.postMessage("spinner", "stop");
- }
- });
- } catch (InterruptedException e) {
- }
- }
- });
- t.start();
- }
-
- // Shutdown if blank loaded
- if (url.equals("about:blank")) {
- pluginManager.postMessage("exit", null);
- }
- }
-
- @Override
- public Boolean onDispatchKeyEvent(KeyEvent event) {
- int keyCode = event.getKeyCode();
- boolean isBackButton = keyCode == KeyEvent.KEYCODE_BACK;
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- if (isBackButton && mCustomView != null) {
- return true;
- } else if (boundKeyCodes.contains(keyCode)) {
- return true;
- } else if (isBackButton) {
- return engine.canGoBack();
- }
- } else if (event.getAction() == KeyEvent.ACTION_UP) {
- if (isBackButton && mCustomView != null) {
- hideCustomView();
- return true;
- } else if (boundKeyCodes.contains(keyCode)) {
- String eventName = null;
- switch (keyCode) {
- case KeyEvent.KEYCODE_VOLUME_DOWN:
- eventName = "volumedownbutton";
- break;
- case KeyEvent.KEYCODE_VOLUME_UP:
- eventName = "volumeupbutton";
- break;
- case KeyEvent.KEYCODE_SEARCH:
- eventName = "searchbutton";
- break;
- case KeyEvent.KEYCODE_MENU:
- eventName = "menubutton";
- break;
- case KeyEvent.KEYCODE_BACK:
- eventName = "backbutton";
- break;
- }
- if (eventName != null) {
- sendJavascriptEvent(eventName);
- return true;
- }
- } else if (isBackButton) {
- return engine.goBack();
- }
- }
- return null;
- }
-
- @Override
- public boolean onNavigationAttempt(String url) {
- // Give plugins the chance to handle the url
- if (pluginManager.onOverrideUrlLoading(url)) {
- return true;
- } else if (pluginManager.shouldAllowNavigation(url)) {
- return false;
- } else if (pluginManager.shouldOpenExternalUrl(url)) {
- showWebPage(url, true, false, null);
- return true;
- }
- LOG.w(TAG, "Blocked (possibly sub-frame) navigation to non-allowed URL: " + url);
- return true;
- }
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/CoreAndroid.java b/platforms/android/CordovaLib/src/org/apache/cordova/CoreAndroid.java
deleted file mode 100755
index e384f8d..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/CoreAndroid.java
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.telephony.TelephonyManager;
-import android.view.KeyEvent;
-
-import java.lang.reflect.Field;
-import java.util.HashMap;
-
-/**
- * This class exposes methods in Cordova that can be called from JavaScript.
- */
-public class CoreAndroid extends CordovaPlugin {
-
- public static final String PLUGIN_NAME = "CoreAndroid";
- protected static final String TAG = "CordovaApp";
- private BroadcastReceiver telephonyReceiver;
- private CallbackContext messageChannel;
- private PluginResult pendingResume;
- private final Object messageChannelLock = new Object();
-
- /**
- * Send an event to be fired on the Javascript side.
- *
- * @param action The name of the event to be fired
- */
- public void fireJavascriptEvent(String action) {
- sendEventMessage(action);
- }
-
- /**
- * Sets the context of the Command. This can then be used to do things like
- * get file paths associated with the Activity.
- */
- @Override
- public void pluginInitialize() {
- this.initTelephonyReceiver();
- }
-
- /**
- * Executes the request and returns PluginResult.
- *
- * @param action The action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param callbackContext The callback context from which we were invoked.
- * @return A PluginResult object with a status and message.
- */
- public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
- PluginResult.Status status = PluginResult.Status.OK;
- String result = "";
-
- try {
- if (action.equals("clearCache")) {
- this.clearCache();
- }
- else if (action.equals("show")) {
- // This gets called from JavaScript onCordovaReady to show the webview.
- // I recommend we change the name of the Message as spinner/stop is not
- // indicative of what this actually does (shows the webview).
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- webView.getPluginManager().postMessage("spinner", "stop");
- }
- });
- }
- else if (action.equals("loadUrl")) {
- this.loadUrl(args.getString(0), args.optJSONObject(1));
- }
- else if (action.equals("cancelLoadUrl")) {
- //this.cancelLoadUrl();
- }
- else if (action.equals("clearHistory")) {
- this.clearHistory();
- }
- else if (action.equals("backHistory")) {
- this.backHistory();
- }
- else if (action.equals("overrideButton")) {
- this.overrideButton(args.getString(0), args.getBoolean(1));
- }
- else if (action.equals("overrideBackbutton")) {
- this.overrideBackbutton(args.getBoolean(0));
- }
- else if (action.equals("exitApp")) {
- this.exitApp();
- }
- else if (action.equals("messageChannel")) {
- synchronized(messageChannelLock) {
- messageChannel = callbackContext;
- if (pendingResume != null) {
- sendEventMessage(pendingResume);
- pendingResume = null;
- }
- }
- return true;
- }
-
- callbackContext.sendPluginResult(new PluginResult(status, result));
- return true;
- } catch (JSONException e) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
- return false;
- }
- }
-
- //--------------------------------------------------------------------------
- // LOCAL METHODS
- //--------------------------------------------------------------------------
-
- /**
- * Clear the resource cache.
- */
- public void clearCache() {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- webView.clearCache(true);
- }
- });
- }
-
- /**
- * Load the url into the webview.
- *
- * @param url
- * @param props Properties that can be passed in to the Cordova activity (i.e. loadingDialog, wait, ...)
- * @throws JSONException
- */
- public void loadUrl(String url, JSONObject props) throws JSONException {
- LOG.d("App", "App.loadUrl("+url+","+props+")");
- int wait = 0;
- boolean openExternal = false;
- boolean clearHistory = false;
-
- // If there are properties, then set them on the Activity
- HashMap params = new HashMap();
- if (props != null) {
- JSONArray keys = props.names();
- for (int i = 0; i < keys.length(); i++) {
- String key = keys.getString(i);
- if (key.equals("wait")) {
- wait = props.getInt(key);
- }
- else if (key.equalsIgnoreCase("openexternal")) {
- openExternal = props.getBoolean(key);
- }
- else if (key.equalsIgnoreCase("clearhistory")) {
- clearHistory = props.getBoolean(key);
- }
- else {
- Object value = props.get(key);
- if (value == null) {
-
- }
- else if (value.getClass().equals(String.class)) {
- params.put(key, (String)value);
- }
- else if (value.getClass().equals(Boolean.class)) {
- params.put(key, (Boolean)value);
- }
- else if (value.getClass().equals(Integer.class)) {
- params.put(key, (Integer)value);
- }
- }
- }
- }
-
- // If wait property, then delay loading
-
- if (wait > 0) {
- try {
- synchronized(this) {
- this.wait(wait);
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- this.webView.showWebPage(url, openExternal, clearHistory, params);
- }
-
- /**
- * Clear page history for the app.
- */
- public void clearHistory() {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- webView.clearHistory();
- }
- });
- }
-
- /**
- * Go to previous page displayed.
- * This is the same as pressing the backbutton on Android device.
- */
- public void backHistory() {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- webView.backHistory();
- }
- });
- }
-
- /**
- * Override the default behavior of the Android back button.
- * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
- *
- * @param override T=override, F=cancel override
- */
- public void overrideBackbutton(boolean override) {
- LOG.i("App", "WARNING: Back Button Default Behavior will be overridden. The backbutton event will be fired!");
- webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_BACK, override);
- }
-
- /**
- * Override the default behavior of the Android volume buttons.
- * If overridden, when the volume button is pressed, the "volume[up|down]button" JavaScript event will be fired.
- *
- * @param button volumeup, volumedown
- * @param override T=override, F=cancel override
- */
- public void overrideButton(String button, boolean override) {
- LOG.i("App", "WARNING: Volume Button Default Behavior will be overridden. The volume event will be fired!");
- if (button.equals("volumeup")) {
- webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_UP, override);
- }
- else if (button.equals("volumedown")) {
- webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_VOLUME_DOWN, override);
- }
- else if (button.equals("menubutton")) {
- webView.setButtonPlumbedToJs(KeyEvent.KEYCODE_MENU, override);
- }
- }
-
- /**
- * Return whether the Android back button is overridden by the user.
- *
- * @return boolean
- */
- public boolean isBackbuttonOverridden() {
- return webView.isButtonPlumbedToJs(KeyEvent.KEYCODE_BACK);
- }
-
- /**
- * Exit the Android application.
- */
- public void exitApp() {
- this.webView.getPluginManager().postMessage("exit", null);
- }
-
-
- /**
- * Listen for telephony events: RINGING, OFFHOOK and IDLE
- * Send these events to all plugins using
- * CordovaActivity.onMessage("telephone", "ringing" | "offhook" | "idle")
- */
- private void initTelephonyReceiver() {
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
- //final CordovaInterface mycordova = this.cordova;
- this.telephonyReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
-
- // If state has changed
- if ((intent != null) && intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
- if (intent.hasExtra(TelephonyManager.EXTRA_STATE)) {
- String extraData = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
- if (extraData.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
- LOG.i(TAG, "Telephone RINGING");
- webView.getPluginManager().postMessage("telephone", "ringing");
- }
- else if (extraData.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
- LOG.i(TAG, "Telephone OFFHOOK");
- webView.getPluginManager().postMessage("telephone", "offhook");
- }
- else if (extraData.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
- LOG.i(TAG, "Telephone IDLE");
- webView.getPluginManager().postMessage("telephone", "idle");
- }
- }
- }
- }
- };
-
- // Register the receiver
- webView.getContext().registerReceiver(this.telephonyReceiver, intentFilter);
- }
-
- private void sendEventMessage(String action) {
- JSONObject obj = new JSONObject();
- try {
- obj.put("action", action);
- } catch (JSONException e) {
- LOG.e(TAG, "Failed to create event message", e);
- }
- sendEventMessage(new PluginResult(PluginResult.Status.OK, obj));
- }
-
- private void sendEventMessage(PluginResult payload) {
- payload.setKeepCallback(true);
- if (messageChannel != null) {
- messageChannel.sendPluginResult(payload);
- }
- }
-
- /*
- * Unregister the receiver
- *
- */
- public void onDestroy()
- {
- webView.getContext().unregisterReceiver(this.telephonyReceiver);
- }
-
- /**
- * Used to send the resume event in the case that the Activity is destroyed by the OS
- *
- * @param resumeEvent PluginResult containing the payload for the resume event to be fired
- */
- public void sendResumeEvent(PluginResult resumeEvent) {
- // This operation must be synchronized because plugin results that trigger resume
- // events can be processed asynchronously
- synchronized(messageChannelLock) {
- if (messageChannel != null) {
- sendEventMessage(resumeEvent);
- } else {
- // Might get called before the page loads, so we need to store it until the
- // messageChannel gets created
- this.pendingResume = resumeEvent;
- }
- }
- }
-
- /*
- * This needs to be implemented if you wish to use the Camera Plugin or other plugins
- * that read the Build Configuration.
- *
- * Thanks to Phil@Medtronic and Graham Borland for finding the answer and posting it to
- * StackOverflow. This is annoying as hell!
- *
- */
-
- public static Object getBuildConfigValue(Context ctx, String key)
- {
- try
- {
- Class> clazz = Class.forName(ctx.getPackageName() + ".BuildConfig");
- Field field = clazz.getField(key);
- return field.get(null);
- } catch (ClassNotFoundException e) {
- LOG.d(TAG, "Unable to get the BuildConfig, is this built with ANT?");
- e.printStackTrace();
- } catch (NoSuchFieldException e) {
- LOG.d(TAG, key + " is not a valid field. Check your build.gradle");
- } catch (IllegalAccessException e) {
- LOG.d(TAG, "Illegal Access Exception: Let's print a stack trace.");
- e.printStackTrace();
- }
-
- return null;
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ExposedJsApi.java b/platforms/android/CordovaLib/src/org/apache/cordova/ExposedJsApi.java
deleted file mode 100644
index acc65c6..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/ExposedJsApi.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova;
-
-import org.json.JSONException;
-
-/*
- * Any exposed Javascript API MUST implement these three things!
- */
-public interface ExposedJsApi {
- public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException;
- public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException;
- public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException;
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaClientCertRequest.java b/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaClientCertRequest.java
deleted file mode 100644
index 455d2f9..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaClientCertRequest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-
-/**
- * Specifies interface for handling certificate requests.
- */
-public interface ICordovaClientCertRequest {
- /**
- * Cancel this request
- */
- public void cancel();
-
- /*
- * Returns the host name of the server requesting the certificate.
- */
- public String getHost();
-
- /*
- * Returns the acceptable types of asymmetric keys (can be null).
- */
- public String[] getKeyTypes();
-
- /*
- * Returns the port number of the server requesting the certificate.
- */
- public int getPort();
-
- /*
- * Returns the acceptable certificate issuers for the certificate matching the private key (can be null).
- */
- public Principal[] getPrincipals();
-
- /*
- * Ignore the request for now. Do not remember user's choice.
- */
- public void ignore();
-
- /*
- * Proceed with the specified private key and client certificate chain. Remember the user's positive choice and use it for future requests.
- *
- * @param privateKey The privateKey
- * @param chain The certificate chain
- */
- public void proceed(PrivateKey privateKey, X509Certificate[] chain);
-}
\ No newline at end of file
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaCookieManager.java b/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaCookieManager.java
deleted file mode 100644
index e776194..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaCookieManager.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova;
-
-public interface ICordovaCookieManager {
-
- public void setCookiesEnabled(boolean accept);
-
- public void setCookie(final String url, final String value);
-
- public String getCookie(final String url);
-
- public void clearCookies();
-
- public void flush();
-};
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaHttpAuthHandler.java b/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaHttpAuthHandler.java
deleted file mode 100644
index c55818a..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/ICordovaHttpAuthHandler.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-/**
- * Specifies interface for HTTP auth handler object which is used to handle auth requests and
- * specifying user credentials.
- */
- public interface ICordovaHttpAuthHandler {
- /**
- * Instructs the WebView to cancel the authentication request.
- */
- public void cancel ();
-
- /**
- * Instructs the WebView to proceed with the authentication with the given credentials.
- *
- * @param username The user name
- * @param password The password
- */
- public void proceed (String username, String password);
-}
\ No newline at end of file
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/LOG.java b/platforms/android/CordovaLib/src/org/apache/cordova/LOG.java
deleted file mode 100755
index 9fe7a7d..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/LOG.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import android.util.Log;
-
-/**
- * Log to Android logging system.
- *
- * Log message can be a string or a printf formatted string with arguments.
- * See http://developer.android.com/reference/java/util/Formatter.html
- */
-public class LOG {
-
- public static final int VERBOSE = Log.VERBOSE;
- public static final int DEBUG = Log.DEBUG;
- public static final int INFO = Log.INFO;
- public static final int WARN = Log.WARN;
- public static final int ERROR = Log.ERROR;
-
- // Current log level
- public static int LOGLEVEL = Log.ERROR;
-
- /**
- * Set the current log level.
- *
- * @param logLevel
- */
- public static void setLogLevel(int logLevel) {
- LOGLEVEL = logLevel;
- Log.i("CordovaLog", "Changing log level to " + logLevel);
- }
-
- /**
- * Set the current log level.
- *
- * @param logLevel
- */
- public static void setLogLevel(String logLevel) {
- if ("VERBOSE".equals(logLevel)) LOGLEVEL = VERBOSE;
- else if ("DEBUG".equals(logLevel)) LOGLEVEL = DEBUG;
- else if ("INFO".equals(logLevel)) LOGLEVEL = INFO;
- else if ("WARN".equals(logLevel)) LOGLEVEL = WARN;
- else if ("ERROR".equals(logLevel)) LOGLEVEL = ERROR;
- Log.i("CordovaLog", "Changing log level to " + logLevel + "(" + LOGLEVEL + ")");
- }
-
- /**
- * Determine if log level will be logged
- *
- * @param logLevel
- * @return true if the parameter passed in is greater than or equal to the current log level
- */
- public static boolean isLoggable(int logLevel) {
- return (logLevel >= LOGLEVEL);
- }
-
- /**
- * Verbose log message.
- *
- * @param tag
- * @param s
- */
- public static void v(String tag, String s) {
- if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, s);
- }
-
- /**
- * Debug log message.
- *
- * @param tag
- * @param s
- */
- public static void d(String tag, String s) {
- if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, s);
- }
-
- /**
- * Info log message.
- *
- * @param tag
- * @param s
- */
- public static void i(String tag, String s) {
- if (LOG.INFO >= LOGLEVEL) Log.i(tag, s);
- }
-
- /**
- * Warning log message.
- *
- * @param tag
- * @param s
- */
- public static void w(String tag, String s) {
- if (LOG.WARN >= LOGLEVEL) Log.w(tag, s);
- }
-
- /**
- * Error log message.
- *
- * @param tag
- * @param s
- */
- public static void e(String tag, String s) {
- if (LOG.ERROR >= LOGLEVEL) Log.e(tag, s);
- }
-
- /**
- * Verbose log message.
- *
- * @param tag
- * @param s
- * @param e
- */
- public static void v(String tag, String s, Throwable e) {
- if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, s, e);
- }
-
- /**
- * Debug log message.
- *
- * @param tag
- * @param s
- * @param e
- */
- public static void d(String tag, String s, Throwable e) {
- if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, s, e);
- }
-
- /**
- * Info log message.
- *
- * @param tag
- * @param s
- * @param e
- */
- public static void i(String tag, String s, Throwable e) {
- if (LOG.INFO >= LOGLEVEL) Log.i(tag, s, e);
- }
-
- /**
- * Warning log message.
- *
- * @param tag
- * @param e
- */
- public static void w(String tag, Throwable e) {
- if (LOG.WARN >= LOGLEVEL) Log.w(tag, e);
- }
-
- /**
- * Warning log message.
- *
- * @param tag
- * @param s
- * @param e
- */
- public static void w(String tag, String s, Throwable e) {
- if (LOG.WARN >= LOGLEVEL) Log.w(tag, s, e);
- }
-
- /**
- * Error log message.
- *
- * @param tag
- * @param s
- * @param e
- */
- public static void e(String tag, String s, Throwable e) {
- if (LOG.ERROR >= LOGLEVEL) Log.e(tag, s, e);
- }
-
- /**
- * Verbose log message with printf formatting.
- *
- * @param tag
- * @param s
- * @param args
- */
- public static void v(String tag, String s, Object... args) {
- if (LOG.VERBOSE >= LOGLEVEL) Log.v(tag, String.format(s, args));
- }
-
- /**
- * Debug log message with printf formatting.
- *
- * @param tag
- * @param s
- * @param args
- */
- public static void d(String tag, String s, Object... args) {
- if (LOG.DEBUG >= LOGLEVEL) Log.d(tag, String.format(s, args));
- }
-
- /**
- * Info log message with printf formatting.
- *
- * @param tag
- * @param s
- * @param args
- */
- public static void i(String tag, String s, Object... args) {
- if (LOG.INFO >= LOGLEVEL) Log.i(tag, String.format(s, args));
- }
-
- /**
- * Warning log message with printf formatting.
- *
- * @param tag
- * @param s
- * @param args
- */
- public static void w(String tag, String s, Object... args) {
- if (LOG.WARN >= LOGLEVEL) Log.w(tag, String.format(s, args));
- }
-
- /**
- * Error log message with printf formatting.
- *
- * @param tag
- * @param s
- * @param args
- */
- public static void e(String tag, String s, Object... args) {
- if (LOG.ERROR >= LOGLEVEL) Log.e(tag, String.format(s, args));
- }
-
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/NativeToJsMessageQueue.java b/platforms/android/CordovaLib/src/org/apache/cordova/NativeToJsMessageQueue.java
deleted file mode 100755
index d17b1c4..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/NativeToJsMessageQueue.java
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-
-/**
- * Holds the list of messages to be sent to the WebView.
- */
-public class NativeToJsMessageQueue {
- private static final String LOG_TAG = "JsMessageQueue";
-
- // Set this to true to force plugin results to be encoding as
- // JS instead of the custom format (useful for benchmarking).
- // Doesn't work for multipart messages.
- private static final boolean FORCE_ENCODE_USING_EVAL = false;
-
- // Disable sending back native->JS messages during an exec() when the active
- // exec() is asynchronous. Set this to true when running bridge benchmarks.
- static final boolean DISABLE_EXEC_CHAINING = false;
-
- // Arbitrarily chosen upper limit for how much data to send to JS in one shot.
- // This currently only chops up on message boundaries. It may be useful
- // to allow it to break up messages.
- private static int MAX_PAYLOAD_SIZE = 50 * 1024 * 10240;
-
- /**
- * When true, the active listener is not fired upon enqueue. When set to false,
- * the active listener will be fired if the queue is non-empty.
- */
- private boolean paused;
-
- /**
- * The list of JavaScript statements to be sent to JavaScript.
- */
- private final LinkedList queue = new LinkedList();
-
- /**
- * The array of listeners that can be used to send messages to JS.
- */
- private ArrayList bridgeModes = new ArrayList();
-
- /**
- * When null, the bridge is disabled. This occurs during page transitions.
- * When disabled, all callbacks are dropped since they are assumed to be
- * relevant to the previous page.
- */
- private BridgeMode activeBridgeMode;
-
- public void addBridgeMode(BridgeMode bridgeMode) {
- bridgeModes.add(bridgeMode);
- }
-
- public boolean isBridgeEnabled() {
- return activeBridgeMode != null;
- }
-
- public boolean isEmpty() {
- return queue.isEmpty();
- }
-
- /**
- * Changes the bridge mode.
- */
- public void setBridgeMode(int value) {
- if (value < -1 || value >= bridgeModes.size()) {
- LOG.d(LOG_TAG, "Invalid NativeToJsBridgeMode: " + value);
- } else {
- BridgeMode newMode = value < 0 ? null : bridgeModes.get(value);
- if (newMode != activeBridgeMode) {
- LOG.d(LOG_TAG, "Set native->JS mode to " + (newMode == null ? "null" : newMode.getClass().getSimpleName()));
- synchronized (this) {
- activeBridgeMode = newMode;
- if (newMode != null) {
- newMode.reset();
- if (!paused && !queue.isEmpty()) {
- newMode.onNativeToJsMessageAvailable(this);
- }
- }
- }
- }
- }
- }
-
- /**
- * Clears all messages and resets to the default bridge mode.
- */
- public void reset() {
- synchronized (this) {
- queue.clear();
- setBridgeMode(-1);
- }
- }
-
- private int calculatePackedMessageLength(JsMessage message) {
- int messageLen = message.calculateEncodedLength();
- String messageLenStr = String.valueOf(messageLen);
- return messageLenStr.length() + messageLen + 1;
- }
-
- private void packMessage(JsMessage message, StringBuilder sb) {
- int len = message.calculateEncodedLength();
- sb.append(len)
- .append(' ');
- message.encodeAsMessage(sb);
- }
-
- /**
- * Combines and returns queued messages combined into a single string.
- * Combines as many messages as possible, while staying under MAX_PAYLOAD_SIZE.
- * Returns null if the queue is empty.
- */
- public String popAndEncode(boolean fromOnlineEvent) {
- synchronized (this) {
- if (activeBridgeMode == null) {
- return null;
- }
- activeBridgeMode.notifyOfFlush(this, fromOnlineEvent);
- if (queue.isEmpty()) {
- return null;
- }
- int totalPayloadLen = 0;
- int numMessagesToSend = 0;
- for (JsMessage message : queue) {
- int messageSize = calculatePackedMessageLength(message);
- if (numMessagesToSend > 0 && totalPayloadLen + messageSize > MAX_PAYLOAD_SIZE && MAX_PAYLOAD_SIZE > 0) {
- break;
- }
- totalPayloadLen += messageSize;
- numMessagesToSend += 1;
- }
-
- StringBuilder sb = new StringBuilder(totalPayloadLen);
- for (int i = 0; i < numMessagesToSend; ++i) {
- JsMessage message = queue.removeFirst();
- packMessage(message, sb);
- }
-
- if (!queue.isEmpty()) {
- // Attach a char to indicate that there are more messages pending.
- sb.append('*');
- }
- String ret = sb.toString();
- return ret;
- }
- }
-
- /**
- * Same as popAndEncode(), except encodes in a form that can be executed as JS.
- */
- public String popAndEncodeAsJs() {
- synchronized (this) {
- int length = queue.size();
- if (length == 0) {
- return null;
- }
- int totalPayloadLen = 0;
- int numMessagesToSend = 0;
- for (JsMessage message : queue) {
- int messageSize = message.calculateEncodedLength() + 50; // overestimate.
- if (numMessagesToSend > 0 && totalPayloadLen + messageSize > MAX_PAYLOAD_SIZE && MAX_PAYLOAD_SIZE > 0) {
- break;
- }
- totalPayloadLen += messageSize;
- numMessagesToSend += 1;
- }
- boolean willSendAllMessages = numMessagesToSend == queue.size();
- StringBuilder sb = new StringBuilder(totalPayloadLen + (willSendAllMessages ? 0 : 100));
- // Wrap each statement in a try/finally so that if one throws it does
- // not affect the next.
- for (int i = 0; i < numMessagesToSend; ++i) {
- JsMessage message = queue.removeFirst();
- if (willSendAllMessages && (i + 1 == numMessagesToSend)) {
- message.encodeAsJsMessage(sb);
- } else {
- sb.append("try{");
- message.encodeAsJsMessage(sb);
- sb.append("}finally{");
- }
- }
- if (!willSendAllMessages) {
- sb.append("window.setTimeout(function(){cordova.require('cordova/plugin/android/polling').pollOnce();},0);");
- }
- for (int i = willSendAllMessages ? 1 : 0; i < numMessagesToSend; ++i) {
- sb.append('}');
- }
- String ret = sb.toString();
- return ret;
- }
- }
-
- /**
- * Add a JavaScript statement to the list.
- */
- public void addJavaScript(String statement) {
- enqueueMessage(new JsMessage(statement));
- }
-
- /**
- * Add a JavaScript statement to the list.
- */
- public void addPluginResult(PluginResult result, String callbackId) {
- if (callbackId == null) {
- LOG.e(LOG_TAG, "Got plugin result with no callbackId", new Throwable());
- return;
- }
- // Don't send anything if there is no result and there is no need to
- // clear the callbacks.
- boolean noResult = result.getStatus() == PluginResult.Status.NO_RESULT.ordinal();
- boolean keepCallback = result.getKeepCallback();
- if (noResult && keepCallback) {
- return;
- }
- JsMessage message = new JsMessage(result, callbackId);
- if (FORCE_ENCODE_USING_EVAL) {
- StringBuilder sb = new StringBuilder(message.calculateEncodedLength() + 50);
- message.encodeAsJsMessage(sb);
- message = new JsMessage(sb.toString());
- }
-
- enqueueMessage(message);
- }
-
- private void enqueueMessage(JsMessage message) {
- synchronized (this) {
- if (activeBridgeMode == null) {
- LOG.d(LOG_TAG, "Dropping Native->JS message due to disabled bridge");
- return;
- }
- queue.add(message);
- if (!paused) {
- activeBridgeMode.onNativeToJsMessageAvailable(this);
- }
- }
- }
-
- public void setPaused(boolean value) {
- if (paused && value) {
- // This should never happen. If a use-case for it comes up, we should
- // change pause to be a counter.
- LOG.e(LOG_TAG, "nested call to setPaused detected.", new Throwable());
- }
- paused = value;
- if (!value) {
- synchronized (this) {
- if (!queue.isEmpty() && activeBridgeMode != null) {
- activeBridgeMode.onNativeToJsMessageAvailable(this);
- }
- }
- }
- }
-
- public static abstract class BridgeMode {
- public abstract void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue);
- public void notifyOfFlush(NativeToJsMessageQueue queue, boolean fromOnlineEvent) {}
- public void reset() {}
- }
-
- /** Uses JS polls for messages on a timer.. */
- public static class NoOpBridgeMode extends BridgeMode {
- @Override public void onNativeToJsMessageAvailable(NativeToJsMessageQueue queue) {
- }
- }
-
- /** Uses webView.loadUrl("javascript:") to execute messages. */
- public static class LoadUrlBridgeMode extends BridgeMode {
- private final CordovaWebViewEngine engine;
- private final CordovaInterface cordova;
-
- public LoadUrlBridgeMode(CordovaWebViewEngine engine, CordovaInterface cordova) {
- this.engine = engine;
- this.cordova = cordova;
- }
-
- @Override
- public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- String js = queue.popAndEncodeAsJs();
- if (js != null) {
- engine.loadUrl("javascript:" + js, false);
- }
- }
- });
- }
- }
-
- /** Uses online/offline events to tell the JS when to poll for messages. */
- public static class OnlineEventsBridgeMode extends BridgeMode {
- private final OnlineEventsBridgeModeDelegate delegate;
- private boolean online;
- private boolean ignoreNextFlush;
-
- public interface OnlineEventsBridgeModeDelegate {
- void setNetworkAvailable(boolean value);
- void runOnUiThread(Runnable r);
- }
-
- public OnlineEventsBridgeMode(OnlineEventsBridgeModeDelegate delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public void reset() {
- delegate.runOnUiThread(new Runnable() {
- public void run() {
- online = false;
- // If the following call triggers a notifyOfFlush, then ignore it.
- ignoreNextFlush = true;
- delegate.setNetworkAvailable(true);
- }
- });
- }
-
- @Override
- public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) {
- delegate.runOnUiThread(new Runnable() {
- public void run() {
- if (!queue.isEmpty()) {
- ignoreNextFlush = false;
- delegate.setNetworkAvailable(online);
- }
- }
- });
- }
- // Track when online/offline events are fired so that we don't fire excess events.
- @Override
- public void notifyOfFlush(final NativeToJsMessageQueue queue, boolean fromOnlineEvent) {
- if (fromOnlineEvent && !ignoreNextFlush) {
- online = !online;
- }
- }
- }
-
- /** Uses webView.evaluateJavascript to execute messages. */
- public static class EvalBridgeMode extends BridgeMode {
- private final CordovaWebViewEngine engine;
- private final CordovaInterface cordova;
-
- public EvalBridgeMode(CordovaWebViewEngine engine, CordovaInterface cordova) {
- this.engine = engine;
- this.cordova = cordova;
- }
-
- @Override
- public void onNativeToJsMessageAvailable(final NativeToJsMessageQueue queue) {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- String js = queue.popAndEncodeAsJs();
- if (js != null) {
- engine.evaluateJavascript(js, null);
- }
- }
- });
- }
- }
-
-
-
- private static class JsMessage {
- final String jsPayloadOrCallbackId;
- final PluginResult pluginResult;
- JsMessage(String js) {
- if (js == null) {
- throw new NullPointerException();
- }
- jsPayloadOrCallbackId = js;
- pluginResult = null;
- }
- JsMessage(PluginResult pluginResult, String callbackId) {
- if (callbackId == null || pluginResult == null) {
- throw new NullPointerException();
- }
- jsPayloadOrCallbackId = callbackId;
- this.pluginResult = pluginResult;
- }
-
- static int calculateEncodedLengthHelper(PluginResult pluginResult) {
- switch (pluginResult.getMessageType()) {
- case PluginResult.MESSAGE_TYPE_BOOLEAN: // f or t
- case PluginResult.MESSAGE_TYPE_NULL: // N
- return 1;
- case PluginResult.MESSAGE_TYPE_NUMBER: // n
- return 1 + pluginResult.getMessage().length();
- case PluginResult.MESSAGE_TYPE_STRING: // s
- return 1 + pluginResult.getStrMessage().length();
- case PluginResult.MESSAGE_TYPE_BINARYSTRING:
- return 1 + pluginResult.getMessage().length();
- case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
- return 1 + pluginResult.getMessage().length();
- case PluginResult.MESSAGE_TYPE_MULTIPART:
- int ret = 1;
- for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
- int length = calculateEncodedLengthHelper(pluginResult.getMultipartMessage(i));
- int argLength = String.valueOf(length).length();
- ret += argLength + 1 + length;
- }
- return ret;
- case PluginResult.MESSAGE_TYPE_JSON:
- default:
- return pluginResult.getMessage().length();
- }
- }
-
- int calculateEncodedLength() {
- if (pluginResult == null) {
- return jsPayloadOrCallbackId.length() + 1;
- }
- int statusLen = String.valueOf(pluginResult.getStatus()).length();
- int ret = 2 + statusLen + 1 + jsPayloadOrCallbackId.length() + 1;
- return ret + calculateEncodedLengthHelper(pluginResult);
- }
-
- static void encodeAsMessageHelper(StringBuilder sb, PluginResult pluginResult) {
- switch (pluginResult.getMessageType()) {
- case PluginResult.MESSAGE_TYPE_BOOLEAN:
- sb.append(pluginResult.getMessage().charAt(0)); // t or f.
- break;
- case PluginResult.MESSAGE_TYPE_NULL: // N
- sb.append('N');
- break;
- case PluginResult.MESSAGE_TYPE_NUMBER: // n
- sb.append('n')
- .append(pluginResult.getMessage());
- break;
- case PluginResult.MESSAGE_TYPE_STRING: // s
- sb.append('s');
- sb.append(pluginResult.getStrMessage());
- break;
- 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;
- case PluginResult.MESSAGE_TYPE_MULTIPART:
- sb.append('M');
- for (int i = 0; i < pluginResult.getMultipartMessagesSize(); i++) {
- PluginResult multipartMessage = pluginResult.getMultipartMessage(i);
- sb.append(String.valueOf(calculateEncodedLengthHelper(multipartMessage)));
- sb.append(' ');
- encodeAsMessageHelper(sb, multipartMessage);
- }
- break;
- case PluginResult.MESSAGE_TYPE_JSON:
- default:
- sb.append(pluginResult.getMessage()); // [ or {
- }
- }
-
- void encodeAsMessage(StringBuilder sb) {
- if (pluginResult == null) {
- sb.append('J')
- .append(jsPayloadOrCallbackId);
- return;
- }
- int status = pluginResult.getStatus();
- boolean noResult = status == PluginResult.Status.NO_RESULT.ordinal();
- boolean resultOk = status == PluginResult.Status.OK.ordinal();
- boolean keepCallback = pluginResult.getKeepCallback();
-
- sb.append((noResult || resultOk) ? 'S' : 'F')
- .append(keepCallback ? '1' : '0')
- .append(status)
- .append(' ')
- .append(jsPayloadOrCallbackId)
- .append(' ');
-
- encodeAsMessageHelper(sb, pluginResult);
- }
-
- void buildJsMessage(StringBuilder sb) {
- switch (pluginResult.getMessageType()) {
- case PluginResult.MESSAGE_TYPE_MULTIPART:
- int size = pluginResult.getMultipartMessagesSize();
- for (int i=0; i pluginMap = new LinkedHashMap();
- private final LinkedHashMap entryMap = new LinkedHashMap();
-
- private final CordovaInterface ctx;
- private final CordovaWebView app;
- private boolean isInitialized;
-
- private CordovaPlugin permissionRequester;
-
- public PluginManager(CordovaWebView cordovaWebView, CordovaInterface cordova, Collection pluginEntries) {
- this.ctx = cordova;
- this.app = cordovaWebView;
- setPluginEntries(pluginEntries);
- }
-
- public Collection getPluginEntries() {
- return entryMap.values();
- }
-
- public void setPluginEntries(Collection pluginEntries) {
- if (isInitialized) {
- this.onPause(false);
- this.onDestroy();
- pluginMap.clear();
- entryMap.clear();
- }
- for (PluginEntry entry : pluginEntries) {
- addService(entry);
- }
- if (isInitialized) {
- startupPlugins();
- }
- }
-
- /**
- * Init when loading a new HTML page into webview.
- */
- public void init() {
- LOG.d(TAG, "init()");
- isInitialized = true;
- this.onPause(false);
- this.onDestroy();
- pluginMap.clear();
- this.startupPlugins();
- }
-
- /**
- * Create plugins objects that have onload set.
- */
- private void startupPlugins() {
- for (PluginEntry entry : entryMap.values()) {
- // Add a null entry to for each non-startup plugin to avoid ConcurrentModificationException
- // When iterating plugins.
- if (entry.onload) {
- getPlugin(entry.service);
- } else {
- pluginMap.put(entry.service, null);
- }
- }
- }
-
- /**
- * Receives a request for execution and fulfills it by finding the appropriate
- * Java class and calling it's execute method.
- *
- * PluginManager.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 service String containing the service to run
- * @param action String containing 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 rawArgs An Array literal string containing any arguments needed in the
- * plugin execute method.
- */
- public void exec(final String service, final String action, final String callbackId, final String rawArgs) {
- CordovaPlugin plugin = getPlugin(service);
- if (plugin == null) {
- LOG.d(TAG, "exec() call to unknown plugin: " + service);
- PluginResult cr = new PluginResult(PluginResult.Status.CLASS_NOT_FOUND_EXCEPTION);
- app.sendPluginResult(cr, callbackId);
- return;
- }
- CallbackContext callbackContext = new CallbackContext(callbackId, app);
- try {
- long pluginStartTime = System.currentTimeMillis();
- boolean wasValidAction = plugin.execute(action, rawArgs, callbackContext);
- long duration = System.currentTimeMillis() - pluginStartTime;
-
- if (duration > SLOW_EXEC_WARNING_THRESHOLD) {
- LOG.w(TAG, "THREAD WARNING: exec() call to " + service + "." + action + " blocked the main thread for " + duration + "ms. Plugin should use CordovaInterface.getThreadPool().");
- }
- if (!wasValidAction) {
- PluginResult cr = new PluginResult(PluginResult.Status.INVALID_ACTION);
- callbackContext.sendPluginResult(cr);
- }
- } catch (JSONException e) {
- PluginResult cr = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
- callbackContext.sendPluginResult(cr);
- } catch (Exception e) {
- LOG.e(TAG, "Uncaught exception from plugin", e);
- callbackContext.error(e.getMessage());
- }
- }
-
- /**
- * Get the plugin object that implements the service.
- * If the plugin object does not already exist, then create it.
- * If the service doesn't exist, then return null.
- *
- * @param service The name of the service.
- * @return CordovaPlugin or null
- */
- public CordovaPlugin getPlugin(String service) {
- CordovaPlugin ret = pluginMap.get(service);
- if (ret == null) {
- PluginEntry pe = entryMap.get(service);
- if (pe == null) {
- return null;
- }
- if (pe.plugin != null) {
- ret = pe.plugin;
- } else {
- ret = instantiatePlugin(pe.pluginClass);
- }
- ret.privateInitialize(service, ctx, app, app.getPreferences());
- pluginMap.put(service, ret);
- }
- return ret;
- }
-
- /**
- * Add a plugin class that implements a service to the service entry table.
- * This does not create the plugin object instance.
- *
- * @param service The service name
- * @param className The plugin class name
- */
- public void addService(String service, String className) {
- PluginEntry entry = new PluginEntry(service, className, false);
- this.addService(entry);
- }
-
- /**
- * Add a plugin class that implements a service to the service entry table.
- * This does not create the plugin object instance.
- *
- * @param entry The plugin entry
- */
- public void addService(PluginEntry entry) {
- this.entryMap.put(entry.service, entry);
- if (entry.plugin != null) {
- entry.plugin.privateInitialize(entry.service, ctx, app, app.getPreferences());
- pluginMap.put(entry.service, entry.plugin);
- }
- }
-
- /**
- * Called when the system is about to start resuming a previous activity.
- *
- * @param multitasking Flag indicating if multitasking is turned on for app
- */
- public void onPause(boolean multitasking) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onPause(multitasking);
- }
- }
- }
-
- /**
- * Called when the system received an HTTP authentication request. Plugins can use
- * the supplied HttpAuthHandler to process this auth challenge.
- *
- * @param view The WebView that is initiating the callback
- * @param handler The HttpAuthHandler used to set the WebView's response
- * @param host The host requiring authentication
- * @param realm The realm for which authentication is required
- *
- * @return Returns True if there is a plugin which will resolve this auth challenge, otherwise False
- *
- */
- public boolean onReceivedHttpAuthRequest(CordovaWebView view, ICordovaHttpAuthHandler handler, String host, String realm) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null && plugin.onReceivedHttpAuthRequest(app, handler, host, realm)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Called when he system received an SSL client certificate request. Plugin can use
- * the supplied ClientCertRequest to process this certificate challenge.
- *
- * @param view The WebView that is initiating the callback
- * @param request The client certificate request
- *
- * @return Returns True if plugin will resolve this auth challenge, otherwise False
- *
- */
- public boolean onReceivedClientCertRequest(CordovaWebView view, ICordovaClientCertRequest request) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null && plugin.onReceivedClientCertRequest(app, request)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Called when the activity will start interacting with the user.
- *
- * @param multitasking Flag indicating if multitasking is turned on for app
- */
- public void onResume(boolean multitasking) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onResume(multitasking);
- }
- }
- }
-
- /**
- * Called when the activity is becoming visible to the user.
- */
- public void onStart() {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onStart();
- }
- }
- }
-
- /**
- * Called when the activity is no longer visible to the user.
- */
- public void onStop() {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onStop();
- }
- }
- }
-
- /**
- * The final call you receive before your activity is destroyed.
- */
- public void onDestroy() {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onDestroy();
- }
- }
- }
-
- /**
- * Send a message to all plugins.
- *
- * @param id The message id
- * @param data The message data
- * @return Object to stop propagation or null
- */
- public Object postMessage(String id, Object data) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- Object obj = plugin.onMessage(id, data);
- if (obj != null) {
- return obj;
- }
- }
- }
- return ctx.onMessage(id, data);
- }
-
- /**
- * Called when the activity receives a new intent.
- */
- public void onNewIntent(Intent intent) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onNewIntent(intent);
- }
- }
- }
-
- /**
- * Called when the webview is going to request an external resource.
- *
- * This delegates to the installed plugins, and returns true/false for the
- * first plugin to provide a non-null result. If no plugins respond, then
- * the default policy is applied.
- *
- * @param url The URL that is being requested.
- * @return Returns true to allow the resource to load,
- * false to block the resource.
- */
- public boolean shouldAllowRequest(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null) {
- Boolean result = plugin.shouldAllowRequest(url);
- if (result != null) {
- return result;
- }
- }
- }
-
- // Default policy:
- if (url.startsWith("blob:") || url.startsWith("data:") || url.startsWith("about:blank")) {
- return true;
- }
- // TalkBack requires this, so allow it by default.
- if (url.startsWith("https://ssl.gstatic.com/accessibility/javascript/android/")) {
- return true;
- }
- if (url.startsWith("file://")) {
- //This directory on WebKit/Blink based webviews contains SQLite databases!
- //DON'T CHANGE THIS UNLESS YOU KNOW WHAT YOU'RE DOING!
- return !url.contains("/app_webview/");
- }
- return false;
- }
-
- /**
- * Called when the webview is going to change the URL of the loaded content.
- *
- * This delegates to the installed plugins, and returns true/false for the
- * first plugin to provide a non-null result. If no plugins respond, then
- * the default policy is applied.
- *
- * @param url The URL that is being requested.
- * @return Returns true to allow the navigation,
- * false to block the navigation.
- */
- public boolean shouldAllowNavigation(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null) {
- Boolean result = plugin.shouldAllowNavigation(url);
- if (result != null) {
- return result;
- }
- }
- }
-
- // Default policy:
- return url.startsWith("file://") || url.startsWith("about:blank");
- }
-
-
- /**
- * Called when the webview is requesting the exec() bridge be enabled.
- */
- public boolean shouldAllowBridgeAccess(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null) {
- Boolean result = plugin.shouldAllowBridgeAccess(url);
- if (result != null) {
- return result;
- }
- }
- }
-
- // Default policy:
- return url.startsWith("file://");
- }
-
- /**
- * Called when the webview is going not going to navigate, but may launch
- * an Intent for an URL.
- *
- * This delegates to the installed plugins, and returns true/false for the
- * first plugin to provide a non-null result. If no plugins respond, then
- * the default policy is applied.
- *
- * @param url The URL that is being requested.
- * @return Returns true to allow the URL to launch an intent,
- * false to block the intent.
- */
- public Boolean shouldOpenExternalUrl(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null) {
- Boolean result = plugin.shouldOpenExternalUrl(url);
- if (result != null) {
- return result;
- }
- }
- }
- // Default policy:
- // External URLs are not allowed
- return false;
- }
-
- /**
- * Called when the URL of the webview changes.
- *
- * @param url The URL that is being changed to.
- * @return Return false to allow the URL to load, return true to prevent the URL from loading.
- */
- public boolean onOverrideUrlLoading(String url) {
- for (PluginEntry entry : this.entryMap.values()) {
- CordovaPlugin plugin = pluginMap.get(entry.service);
- if (plugin != null && plugin.onOverrideUrlLoading(url)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Called when the app navigates or refreshes.
- */
- public void onReset() {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onReset();
- }
- }
- }
-
- Uri remapUri(Uri uri) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- Uri ret = plugin.remapUri(uri);
- if (ret != null) {
- return ret;
- }
- }
- }
- return null;
- }
-
- /**
- * Create a plugin based on class name.
- */
- private CordovaPlugin instantiatePlugin(String className) {
- CordovaPlugin ret = null;
- try {
- Class> c = null;
- if ((className != null) && !("".equals(className))) {
- c = Class.forName(className);
- }
- if (c != null & CordovaPlugin.class.isAssignableFrom(c)) {
- ret = (CordovaPlugin) c.newInstance();
- }
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("Error adding plugin " + className + ".");
- }
- return ret;
- }
-
- /**
- * Called by the system when the device configuration changes while your activity is running.
- *
- * @param newConfig The new device configuration
- */
- public void onConfigurationChanged(Configuration newConfig) {
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- plugin.onConfigurationChanged(newConfig);
- }
- }
- }
-
- public Bundle onSaveInstanceState() {
- Bundle state = new Bundle();
- for (CordovaPlugin plugin : this.pluginMap.values()) {
- if (plugin != null) {
- Bundle pluginState = plugin.onSaveInstanceState();
- if(pluginState != null) {
- state.putBundle(plugin.getServiceName(), pluginState);
- }
- }
- }
- return state;
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/PluginResult.java b/platforms/android/CordovaLib/src/org/apache/cordova/PluginResult.java
deleted file mode 100644
index 2b3ac72..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/PluginResult.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import java.util.List;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
-
-import android.util.Base64;
-
-public class PluginResult {
- private final int status;
- private final int messageType;
- private boolean keepCallback = false;
- private String strMessage;
- private String encodedMessage;
- private List multipartMessages;
-
- public PluginResult(Status status) {
- this(status, PluginResult.StatusMessages[status.ordinal()]);
- }
-
- public PluginResult(Status status, String message) {
- this.status = status.ordinal();
- this.messageType = message == null ? MESSAGE_TYPE_NULL : MESSAGE_TYPE_STRING;
- this.strMessage = message;
- }
-
- public PluginResult(Status status, JSONArray message) {
- this.status = status.ordinal();
- this.messageType = MESSAGE_TYPE_JSON;
- encodedMessage = message.toString();
- }
-
- public PluginResult(Status status, JSONObject message) {
- this.status = status.ordinal();
- this.messageType = MESSAGE_TYPE_JSON;
- encodedMessage = message.toString();
- }
-
- public PluginResult(Status status, int i) {
- this.status = status.ordinal();
- this.messageType = MESSAGE_TYPE_NUMBER;
- this.encodedMessage = ""+i;
- }
-
- public PluginResult(Status status, float f) {
- this.status = status.ordinal();
- this.messageType = MESSAGE_TYPE_NUMBER;
- this.encodedMessage = ""+f;
- }
-
- public PluginResult(Status status, boolean b) {
- this.status = status.ordinal();
- this.messageType = MESSAGE_TYPE_BOOLEAN;
- this.encodedMessage = Boolean.toString(b);
- }
-
- public PluginResult(Status status, byte[] data) {
- this(status, data, false);
- }
-
- public PluginResult(Status status, byte[] data, boolean binaryString) {
- this.status = status.ordinal();
- this.messageType = binaryString ? MESSAGE_TYPE_BINARYSTRING : MESSAGE_TYPE_ARRAYBUFFER;
- this.encodedMessage = Base64.encodeToString(data, Base64.NO_WRAP);
- }
-
- // The keepCallback and status of multipartMessages are ignored.
- public PluginResult(Status status, List multipartMessages) {
- this.status = status.ordinal();
- this.messageType = MESSAGE_TYPE_MULTIPART;
- this.multipartMessages = multipartMessages;
- }
-
- public void setKeepCallback(boolean b) {
- this.keepCallback = b;
- }
-
- public int getStatus() {
- return status;
- }
-
- public int getMessageType() {
- return messageType;
- }
-
- public String getMessage() {
- if (encodedMessage == null) {
- encodedMessage = JSONObject.quote(strMessage);
- }
- return encodedMessage;
- }
-
- public int getMultipartMessagesSize() {
- return multipartMessages.size();
- }
-
- public PluginResult getMultipartMessage(int index) {
- return multipartMessages.get(index);
- }
-
- /**
- * If messageType == MESSAGE_TYPE_STRING, then returns the message string.
- * Otherwise, returns null.
- */
- public String getStrMessage() {
- return strMessage;
- }
-
- public boolean getKeepCallback() {
- return this.keepCallback;
- }
-
- @Deprecated // Use sendPluginResult instead of sendJavascript.
- public String getJSONString() {
- return "{\"status\":" + this.status + ",\"message\":" + this.getMessage() + ",\"keepCallback\":" + this.keepCallback + "}";
- }
-
- @Deprecated // Use sendPluginResult instead of sendJavascript.
- public String toCallbackString(String callbackId) {
- // If no result to be sent and keeping callback, then no need to sent back to JavaScript
- if ((status == PluginResult.Status.NO_RESULT.ordinal()) && keepCallback) {
- return null;
- }
-
- // Check the success (OK, NO_RESULT & !KEEP_CALLBACK)
- if ((status == PluginResult.Status.OK.ordinal()) || (status == PluginResult.Status.NO_RESULT.ordinal())) {
- return toSuccessCallbackString(callbackId);
- }
-
- return toErrorCallbackString(callbackId);
- }
-
- @Deprecated // Use sendPluginResult instead of sendJavascript.
- public String toSuccessCallbackString(String callbackId) {
- return "cordova.callbackSuccess('"+callbackId+"',"+this.getJSONString()+");";
- }
-
- @Deprecated // Use sendPluginResult instead of sendJavascript.
- public String toErrorCallbackString(String callbackId) {
- return "cordova.callbackError('"+callbackId+"', " + this.getJSONString()+ ");";
- }
-
- public static final int MESSAGE_TYPE_STRING = 1;
- public static final int MESSAGE_TYPE_JSON = 2;
- public static final int MESSAGE_TYPE_NUMBER = 3;
- 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 final int MESSAGE_TYPE_MULTIPART = 8;
-
- public static String[] StatusMessages = new String[] {
- "No result",
- "OK",
- "Class not found",
- "Illegal access",
- "Instantiation error",
- "Malformed url",
- "IO error",
- "Invalid action",
- "JSON error",
- "Error"
- };
-
- public enum Status {
- NO_RESULT,
- OK,
- CLASS_NOT_FOUND_EXCEPTION,
- ILLEGAL_ACCESS_EXCEPTION,
- INSTANTIATION_EXCEPTION,
- MALFORMED_URL_EXCEPTION,
- IO_EXCEPTION,
- INVALID_ACTION,
- JSON_EXCEPTION,
- ERROR
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/ResumeCallback.java b/platforms/android/CordovaLib/src/org/apache/cordova/ResumeCallback.java
deleted file mode 100644
index 49a43b5..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/ResumeCallback.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ResumeCallback extends CallbackContext {
- private final String TAG = "CordovaResumeCallback";
- private String serviceName;
- private PluginManager pluginManager;
-
- public ResumeCallback(String serviceName, PluginManager pluginManager) {
- super("resumecallback", null);
- this.serviceName = serviceName;
- this.pluginManager = pluginManager;
- }
-
- @Override
- public void sendPluginResult(PluginResult pluginResult) {
- synchronized (this) {
- if (finished) {
- LOG.w(TAG, serviceName + " attempted to send a second callback to ResumeCallback\nResult was: " + pluginResult.getMessage());
- return;
- } else {
- finished = true;
- }
- }
-
- JSONObject event = new JSONObject();
- JSONObject pluginResultObject = new JSONObject();
-
- try {
- pluginResultObject.put("pluginServiceName", this.serviceName);
- pluginResultObject.put("pluginStatus", PluginResult.StatusMessages[pluginResult.getStatus()]);
-
- event.put("action", "resume");
- event.put("pendingResult", pluginResultObject);
- } catch (JSONException e) {
- LOG.e(TAG, "Unable to create resume object for Activity Result");
- }
-
- PluginResult eventResult = new PluginResult(PluginResult.Status.OK, event);
-
- // We send a list of results to the js so that we don't have to decode
- // the PluginResult passed to this CallbackContext into JSON twice.
- // The results are combined into an event payload before the event is
- // fired on the js side of things (see platform.js)
- List result = new ArrayList();
- result.add(eventResult);
- result.add(pluginResult);
-
- CoreAndroid appPlugin = (CoreAndroid) pluginManager.getPlugin(CoreAndroid.PLUGIN_NAME);
- appPlugin.sendResumeEvent(new PluginResult(PluginResult.Status.OK, result));
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/Whitelist.java b/platforms/android/CordovaLib/src/org/apache/cordova/Whitelist.java
deleted file mode 100644
index d0f823c..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/Whitelist.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova;
-
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.cordova.LOG;
-
-import android.net.Uri;
-
-public class Whitelist {
- private static class URLPattern {
- public Pattern scheme;
- public Pattern host;
- public Integer port;
- public Pattern path;
-
- private String regexFromPattern(String pattern, boolean allowWildcards) {
- final String toReplace = "\\.[]{}()^$?+|";
- StringBuilder regex = new StringBuilder();
- for (int i=0; i < pattern.length(); i++) {
- char c = pattern.charAt(i);
- if (c == '*' && allowWildcards) {
- regex.append(".");
- } else if (toReplace.indexOf(c) > -1) {
- regex.append('\\');
- }
- regex.append(c);
- }
- return regex.toString();
- }
-
- public URLPattern(String scheme, String host, String port, String path) throws MalformedURLException {
- try {
- if (scheme == null || "*".equals(scheme)) {
- this.scheme = null;
- } else {
- this.scheme = Pattern.compile(regexFromPattern(scheme, false), Pattern.CASE_INSENSITIVE);
- }
- if ("*".equals(host)) {
- this.host = null;
- } else if (host.startsWith("*.")) {
- this.host = Pattern.compile("([a-z0-9.-]*\\.)?" + regexFromPattern(host.substring(2), false), Pattern.CASE_INSENSITIVE);
- } else {
- this.host = Pattern.compile(regexFromPattern(host, false), Pattern.CASE_INSENSITIVE);
- }
- if (port == null || "*".equals(port)) {
- this.port = null;
- } else {
- this.port = Integer.parseInt(port,10);
- }
- if (path == null || "/*".equals(path)) {
- this.path = null;
- } else {
- this.path = Pattern.compile(regexFromPattern(path, true));
- }
- } catch (NumberFormatException e) {
- throw new MalformedURLException("Port must be a number");
- }
- }
-
- public boolean matches(Uri uri) {
- try {
- return ((scheme == null || scheme.matcher(uri.getScheme()).matches()) &&
- (host == null || host.matcher(uri.getHost()).matches()) &&
- (port == null || port.equals(uri.getPort())) &&
- (path == null || path.matcher(uri.getPath()).matches()));
- } catch (Exception e) {
- LOG.d(TAG, e.toString());
- return false;
- }
- }
- }
-
- private ArrayList whiteList;
-
- public static final String TAG = "Whitelist";
-
- public Whitelist() {
- this.whiteList = new ArrayList();
- }
-
- /* Match patterns (from http://developer.chrome.com/extensions/match_patterns.html)
- *
- * := ://
- * := '*' | 'http' | 'https' | 'file' | 'ftp' | 'chrome-extension'
- * := '*' | '*.' +
- * := '/'
- *
- * We extend this to explicitly allow a port attached to the host, and we allow
- * the scheme to be omitted for backwards compatibility. (Also host is not required
- * to begin with a "*" or "*.".)
- */
- public void addWhiteListEntry(String origin, boolean subdomains) {
- if (whiteList != null) {
- try {
- // Unlimited access to network resources
- if (origin.compareTo("*") == 0) {
- LOG.d(TAG, "Unlimited access to network resources");
- whiteList = null;
- }
- else { // specific access
- Pattern parts = Pattern.compile("^((\\*|[A-Za-z-]+):(//)?)?(\\*|((\\*\\.)?[^*/:]+))?(:(\\d+))?(/.*)?");
- Matcher m = parts.matcher(origin);
- if (m.matches()) {
- String scheme = m.group(2);
- String host = m.group(4);
- // Special case for two urls which are allowed to have empty hosts
- if (("file".equals(scheme) || "content".equals(scheme)) && host == null) host = "*";
- String port = m.group(8);
- String path = m.group(9);
- if (scheme == null) {
- // XXX making it stupid friendly for people who forget to include protocol/SSL
- whiteList.add(new URLPattern("http", host, port, path));
- whiteList.add(new URLPattern("https", host, port, path));
- } else {
- whiteList.add(new URLPattern(scheme, host, port, path));
- }
- }
- }
- } catch (Exception e) {
- LOG.d(TAG, "Failed to add origin %s", origin);
- }
- }
- }
-
-
- /**
- * Determine if URL is in approved list of URLs to load.
- *
- * @param uri
- * @return true if wide open or whitelisted
- */
- public boolean isUrlWhiteListed(String uri) {
- // If there is no whitelist, then it's wide open
- if (whiteList == null) return true;
-
- Uri parsedUri = Uri.parse(uri);
- // Look for match in white list
- Iterator pit = whiteList.iterator();
- while (pit.hasNext()) {
- URLPattern p = pit.next();
- if (p.matches(parsedUri)) {
- return true;
- }
- }
- return false;
- }
-
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemCookieManager.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemCookieManager.java
deleted file mode 100644
index acf795f..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemCookieManager.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova.engine;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.webkit.CookieManager;
-import android.webkit.WebView;
-
-import org.apache.cordova.ICordovaCookieManager;
-
-class SystemCookieManager implements ICordovaCookieManager {
-
- protected final WebView webView;
- private final CookieManager cookieManager;
-
- //Added because lint can't see the conditional RIGHT ABOVE this
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public SystemCookieManager(WebView webview) {
- webView = webview;
- cookieManager = CookieManager.getInstance();
-
- //REALLY? Nobody has seen this UNTIL NOW?
- cookieManager.setAcceptFileSchemeCookies(true);
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- cookieManager.setAcceptThirdPartyCookies(webView, true);
- }
- }
-
- public void setCookiesEnabled(boolean accept) {
- cookieManager.setAcceptCookie(accept);
- }
-
- public void setCookie(final String url, final String value) {
- cookieManager.setCookie(url, value);
- }
-
- public String getCookie(final String url) {
- return cookieManager.getCookie(url);
- }
-
- public void clearCookies() {
- cookieManager.removeAllCookie();
- }
-
- public void flush() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- cookieManager.flush();
- }
- }
-};
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemExposedJsApi.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemExposedJsApi.java
deleted file mode 100755
index 94c3d93..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemExposedJsApi.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.engine;
-
-import android.webkit.JavascriptInterface;
-
-import org.apache.cordova.CordovaBridge;
-import org.apache.cordova.ExposedJsApi;
-import org.json.JSONException;
-
-/**
- * Contains APIs that the JS can call. All functions in here should also have
- * an equivalent entry in CordovaChromeClient.java, and be added to
- * cordova-js/lib/android/plugin/android/promptbasednativeapi.js
- */
-class SystemExposedJsApi implements ExposedJsApi {
- private final CordovaBridge bridge;
-
- SystemExposedJsApi(CordovaBridge bridge) {
- this.bridge = bridge;
- }
-
- @JavascriptInterface
- public String exec(int bridgeSecret, String service, String action, String callbackId, String arguments) throws JSONException, IllegalAccessException {
- return bridge.jsExec(bridgeSecret, service, action, callbackId, arguments);
- }
-
- @JavascriptInterface
- public void setNativeToJsBridgeMode(int bridgeSecret, int value) throws IllegalAccessException {
- bridge.jsSetNativeToJsBridgeMode(bridgeSecret, value);
- }
-
- @JavascriptInterface
- public String retrieveJsMessages(int bridgeSecret, boolean fromOnlineEvent) throws IllegalAccessException {
- return bridge.jsRetrieveJsMessages(bridgeSecret, fromOnlineEvent);
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebChromeClient.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebChromeClient.java
deleted file mode 100755
index a27fc6a..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebChromeClient.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.engine;
-
-import java.util.Arrays;
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.Context;
-import android.content.ActivityNotFoundException;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.webkit.ConsoleMessage;
-import android.webkit.GeolocationPermissions.Callback;
-import android.webkit.JsPromptResult;
-import android.webkit.JsResult;
-import android.webkit.ValueCallback;
-import android.webkit.WebChromeClient;
-import android.webkit.WebStorage;
-import android.webkit.WebView;
-import android.webkit.PermissionRequest;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-
-import org.apache.cordova.CordovaDialogsHelper;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.LOG;
-
-/**
- * This class is the WebChromeClient that implements callbacks for our web view.
- * The kind of callbacks that happen here are on the chrome outside the document,
- * such as onCreateWindow(), onConsoleMessage(), onProgressChanged(), etc. Related
- * to but different than CordovaWebViewClient.
- */
-public class SystemWebChromeClient extends WebChromeClient {
-
- private static final int FILECHOOSER_RESULTCODE = 5173;
- private static final String LOG_TAG = "SystemWebChromeClient";
- private long MAX_QUOTA = 100 * 1024 * 1024;
- protected final SystemWebViewEngine parentEngine;
-
- // the video progress view
- private View mVideoProgressView;
-
- private CordovaDialogsHelper dialogsHelper;
- private Context appContext;
-
- private WebChromeClient.CustomViewCallback mCustomViewCallback;
- private View mCustomView;
-
- public SystemWebChromeClient(SystemWebViewEngine parentEngine) {
- this.parentEngine = parentEngine;
- appContext = parentEngine.webView.getContext();
- dialogsHelper = new CordovaDialogsHelper(appContext);
- }
-
- /**
- * Tell the client to display a javascript alert dialog.
- */
- @Override
- public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
- dialogsHelper.showAlert(message, new CordovaDialogsHelper.Result() {
- @Override public void gotResult(boolean success, String value) {
- if (success) {
- result.confirm();
- } else {
- result.cancel();
- }
- }
- });
- return true;
- }
-
- /**
- * Tell the client to display a confirm dialog to the user.
- */
- @Override
- public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
- dialogsHelper.showConfirm(message, new CordovaDialogsHelper.Result() {
- @Override
- public void gotResult(boolean success, String value) {
- if (success) {
- result.confirm();
- } else {
- result.cancel();
- }
- }
- });
- return true;
- }
-
- /**
- * Tell the client to display a prompt dialog to the user.
- * If the client returns true, WebView will assume that the client will
- * handle the prompt dialog and call the appropriate JsPromptResult method.
- *
- * Since we are hacking prompts for our own purposes, we should not be using them for
- * this purpose, perhaps we should hack console.log to do this instead!
- */
- @Override
- public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result) {
- // Unlike the @JavascriptInterface bridge, this method is always called on the UI thread.
- String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message, defaultValue);
- if (handledRet != null) {
- result.confirm(handledRet);
- } else {
- dialogsHelper.showPrompt(message, defaultValue, new CordovaDialogsHelper.Result() {
- @Override
- public void gotResult(boolean success, String value) {
- if (success) {
- result.confirm(value);
- } else {
- result.cancel();
- }
- }
- });
- }
- return true;
- }
-
- /**
- * Handle database quota exceeded notification.
- */
- @Override
- public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
- long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
- {
- LOG.d(LOG_TAG, "onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
- quotaUpdater.updateQuota(MAX_QUOTA);
- }
-
- @Override
- public boolean onConsoleMessage(ConsoleMessage consoleMessage)
- {
- if (consoleMessage.message() != null)
- LOG.d(LOG_TAG, "%s: Line %d : %s" , consoleMessage.sourceId() , consoleMessage.lineNumber(), consoleMessage.message());
- return super.onConsoleMessage(consoleMessage);
- }
-
- @Override
- /**
- * Instructs the client to show a prompt to ask the user to set the Geolocation permission state for the specified origin.
- *
- * This also checks for the Geolocation Plugin and requests permission from the application to use Geolocation.
- *
- * @param origin
- * @param callback
- */
- public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
- super.onGeolocationPermissionsShowPrompt(origin, callback);
- callback.invoke(origin, true, false);
- //Get the plugin, it should be loaded
- CordovaPlugin geolocation = parentEngine.pluginManager.getPlugin("Geolocation");
- if(geolocation != null && !geolocation.hasPermisssion())
- {
- geolocation.requestPermissions(0);
- }
-
- }
-
- // API level 7 is required for this, see if we could lower this using something else
- @Override
- public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
- parentEngine.getCordovaWebView().showCustomView(view, callback);
- }
-
- @Override
- public void onHideCustomView() {
- parentEngine.getCordovaWebView().hideCustomView();
- }
-
- @Override
- /**
- * Ask the host application for a custom progress view to show while
- * a is loading.
- * @return View The progress view.
- */
- public View getVideoLoadingProgressView() {
-
- if (mVideoProgressView == null) {
- // Create a new Loading view programmatically.
-
- // create the linear layout
- LinearLayout layout = new LinearLayout(parentEngine.getView().getContext());
- layout.setOrientation(LinearLayout.VERTICAL);
- RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT);
- layout.setLayoutParams(layoutParams);
- // the proress bar
- ProgressBar bar = new ProgressBar(parentEngine.getView().getContext());
- LinearLayout.LayoutParams barLayoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- barLayoutParams.gravity = Gravity.CENTER;
- bar.setLayoutParams(barLayoutParams);
- layout.addView(bar);
-
- mVideoProgressView = layout;
- }
- return mVideoProgressView;
- }
-
- // support:
- // openFileChooser() is for pre KitKat and in KitKat mr1 (it's known broken in KitKat).
- // For Lollipop, we use onShowFileChooser().
- public void openFileChooser(ValueCallback uploadMsg) {
- this.openFileChooser(uploadMsg, "*/*");
- }
-
- public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
- this.openFileChooser(uploadMsg, acceptType, null);
- }
-
- public void openFileChooser(final ValueCallback uploadMsg, String acceptType, String capture)
- {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("*/*");
- parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent intent) {
- Uri result = intent == null || resultCode != Activity.RESULT_OK ? null : intent.getData();
- LOG.d(LOG_TAG, "Receive file chooser URL: " + result);
- uploadMsg.onReceiveValue(result);
- }
- }, intent, FILECHOOSER_RESULTCODE);
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @Override
- public boolean onShowFileChooser(WebView webView, final ValueCallback filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) {
- Intent intent = fileChooserParams.createIntent();
- try {
- parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent intent) {
- Uri[] result = WebChromeClient.FileChooserParams.parseResult(resultCode, intent);
- LOG.d(LOG_TAG, "Receive file chooser URL: " + result);
- filePathsCallback.onReceiveValue(result);
- }
- }, intent, FILECHOOSER_RESULTCODE);
- } catch (ActivityNotFoundException e) {
- LOG.w("No activity found to handle file chooser intent.", e);
- filePathsCallback.onReceiveValue(null);
- }
- return true;
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @Override
- public void onPermissionRequest(final PermissionRequest request) {
- LOG.d(LOG_TAG, "onPermissionRequest: " + Arrays.toString(request.getResources()));
- request.grant(request.getResources());
- }
-
- public void destroyLastDialog(){
- dialogsHelper.destroyLastDialog();
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebView.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebView.java
deleted file mode 100644
index 01c2f00..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebView.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova.engine;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.webkit.WebChromeClient;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CordovaWebViewEngine;
-
-/**
- * Custom WebView subclass that enables us to capture events needed for Cordova.
- */
-public class SystemWebView extends WebView implements CordovaWebViewEngine.EngineView {
- private SystemWebViewClient viewClient;
- SystemWebChromeClient chromeClient;
- private SystemWebViewEngine parentEngine;
- private CordovaInterface cordova;
-
- public SystemWebView(Context context) {
- this(context, null);
- }
-
- public SystemWebView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- // Package visibility to enforce that only SystemWebViewEngine should call this method.
- void init(SystemWebViewEngine parentEngine, CordovaInterface cordova) {
- this.cordova = cordova;
- this.parentEngine = parentEngine;
- if (this.viewClient == null) {
- setWebViewClient(new SystemWebViewClient(parentEngine));
- }
-
- if (this.chromeClient == null) {
- setWebChromeClient(new SystemWebChromeClient(parentEngine));
- }
- }
-
- @Override
- public CordovaWebView getCordovaWebView() {
- return parentEngine != null ? parentEngine.getCordovaWebView() : null;
- }
-
- @Override
- public void setWebViewClient(WebViewClient client) {
- viewClient = (SystemWebViewClient)client;
- super.setWebViewClient(client);
- }
-
- @Override
- public void setWebChromeClient(WebChromeClient client) {
- chromeClient = (SystemWebChromeClient)client;
- super.setWebChromeClient(client);
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- Boolean ret = parentEngine.client.onDispatchKeyEvent(event);
- if (ret != null) {
- return ret.booleanValue();
- }
- return super.dispatchKeyEvent(event);
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewClient.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewClient.java
deleted file mode 100755
index 0b6a577..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewClient.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.engine;
-
-import android.annotation.TargetApi;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.net.http.SslError;
-import android.os.Build;
-import android.webkit.ClientCertRequest;
-import android.webkit.HttpAuthHandler;
-import android.webkit.SslErrorHandler;
-import android.webkit.WebResourceResponse;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import org.apache.cordova.AuthenticationToken;
-import org.apache.cordova.CordovaClientCertRequest;
-import org.apache.cordova.CordovaHttpAuthHandler;
-import org.apache.cordova.CordovaResourceApi;
-import org.apache.cordova.LOG;
-import org.apache.cordova.PluginManager;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Hashtable;
-
-
-/**
- * This class is the WebViewClient that implements callbacks for our web view.
- * The kind of callbacks that happen here are regarding the rendering of the
- * document instead of the chrome surrounding it, such as onPageStarted(),
- * shouldOverrideUrlLoading(), etc. Related to but different than
- * CordovaChromeClient.
- */
-public class SystemWebViewClient extends WebViewClient {
-
- private static final String TAG = "SystemWebViewClient";
- protected final SystemWebViewEngine parentEngine;
- private boolean doClearHistory = false;
- boolean isCurrentlyLoading;
-
- /** The authorization tokens. */
- private Hashtable authenticationTokens = new Hashtable();
-
- public SystemWebViewClient(SystemWebViewEngine parentEngine) {
- this.parentEngine = parentEngine;
- }
-
- /**
- * Give the host application a chance to take over the control when a new url
- * is about to be loaded in the current WebView.
- *
- * @param view The WebView that is initiating the callback.
- * @param url The url to be loaded.
- * @return true to override, false for default behavior
- */
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- return parentEngine.client.onNavigationAttempt(url);
- }
-
- /**
- * 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
- */
- @Override
- public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
-
- // Get the authentication token (if specified)
- AuthenticationToken token = this.getAuthenticationToken(host, realm);
- if (token != null) {
- handler.proceed(token.getUserName(), token.getPassword());
- return;
- }
-
- // Check if there is some plugin which can resolve this auth challenge
- PluginManager pluginManager = this.parentEngine.pluginManager;
- if (pluginManager != null && pluginManager.onReceivedHttpAuthRequest(null, new CordovaHttpAuthHandler(handler), host, realm)) {
- parentEngine.client.clearLoadTimeoutTimer();
- return;
- }
-
- // By default handle 401 like we'd normally do!
- super.onReceivedHttpAuthRequest(view, handler, host, realm);
- }
-
- /**
- * On received client cert request.
- * The method forwards the request to any running plugins before using the default implementation.
- *
- * @param view
- * @param request
- */
- @Override
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public void onReceivedClientCertRequest (WebView view, ClientCertRequest request)
- {
-
- // Check if there is some plugin which can resolve this certificate request
- PluginManager pluginManager = this.parentEngine.pluginManager;
- if (pluginManager != null && pluginManager.onReceivedClientCertRequest(null, new CordovaClientCertRequest(request))) {
- parentEngine.client.clearLoadTimeoutTimer();
- return;
- }
-
- // By default pass to WebViewClient
- super.onReceivedClientCertRequest(view, request);
- }
-
- /**
- * 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) {
- super.onPageStarted(view, url, favicon);
- isCurrentlyLoading = true;
- // Flush stale messages & reset plugins.
- parentEngine.bridge.reset();
- parentEngine.client.onPageStarted(url);
- }
-
- /**
- * 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.
- */
- @Override
- public void onPageFinished(WebView view, String url) {
- super.onPageFinished(view, url);
- // Ignore excessive calls, if url is not about:blank (CB-8317).
- if (!isCurrentlyLoading && !url.startsWith("about:")) {
- return;
- }
- isCurrentlyLoading = false;
-
- /**
- * Because of a timing issue we need to clear this history in onPageFinished as well as
- * onPageStarted. However we only want to do this if the doClearHistory boolean is set to
- * true. You see when you load a url with a # in it which is common in jQuery applications
- * onPageStared is not called. Clearing the history at that point would break jQuery apps.
- */
- if (this.doClearHistory) {
- view.clearHistory();
- this.doClearHistory = false;
- }
- parentEngine.client.onPageFinishedLoading(url);
-
- }
-
- /**
- * Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
- * The errorCode parameter corresponds to one of the ERROR_* constants.
- *
- * @param view The WebView that is initiating the callback.
- * @param errorCode The error code corresponding to an ERROR_* value.
- * @param description A String describing the error.
- * @param failingUrl The url that failed to load.
- */
- @Override
- public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
- // Ignore error due to stopLoading().
- if (!isCurrentlyLoading) {
- return;
- }
- LOG.d(TAG, "CordovaWebViewClient.onReceivedError: Error code=%s Description=%s URL=%s", errorCode, description, failingUrl);
-
- // If this is a "Protocol Not Supported" error, then revert to the previous
- // page. If there was no previous page, then punt. The application's config
- // is likely incorrect (start page set to sms: or something like that)
- if (errorCode == WebViewClient.ERROR_UNSUPPORTED_SCHEME) {
- parentEngine.client.clearLoadTimeoutTimer();
-
- if (view.canGoBack()) {
- view.goBack();
- return;
- } else {
- super.onReceivedError(view, errorCode, description, failingUrl);
- }
- }
- parentEngine.client.onReceivedError(errorCode, description, failingUrl);
- }
-
- /**
- * 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) {
-
- final String packageName = parentEngine.cordova.getActivity().getPackageName();
- final PackageManager pm = parentEngine.cordova.getActivity().getPackageManager();
-
- ApplicationInfo appInfo;
- try {
- appInfo = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
- if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
- // debug = true
- handler.proceed();
- return;
- } else {
- // debug = false
- super.onReceivedSslError(view, handler, error);
- }
- } catch (NameNotFoundException e) {
- // When it doubt, lock it out!
- super.onReceivedSslError(view, handler, error);
- }
- }
-
-
- /**
- * 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();
- }
-
- @Override
- public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
- try {
- // Check the against the whitelist and lock out access to the WebView directory
- // Changing this will cause problems for your application
- if (!parentEngine.pluginManager.shouldAllowRequest(url)) {
- LOG.w(TAG, "URL blocked by whitelist: " + url);
- // Results in a 404.
- return new WebResourceResponse("text/plain", "UTF-8", null);
- }
-
- CordovaResourceApi resourceApi = parentEngine.resourceApi;
- Uri origUri = Uri.parse(url);
- // Allow plugins to intercept WebView requests.
- Uri remappedUri = resourceApi.remapUri(origUri);
-
- if (!origUri.equals(remappedUri) || needsSpecialsInAssetUrlFix(origUri) || needsKitKatContentUrlFix(origUri)) {
- CordovaResourceApi.OpenForReadResult result = resourceApi.openForRead(remappedUri, true);
- return new WebResourceResponse(result.mimeType, "UTF-8", result.inputStream);
- }
- // If we don't need to special-case the request, let the browser load it.
- return null;
- } catch (IOException e) {
- if (!(e instanceof FileNotFoundException)) {
- LOG.e(TAG, "Error occurred while loading a file (returning a 404).", e);
- }
- // Results in a 404.
- return new WebResourceResponse("text/plain", "UTF-8", null);
- }
- }
-
- private static boolean needsKitKatContentUrlFix(Uri uri) {
- return "content".equals(uri.getScheme());
- }
-
- private static boolean needsSpecialsInAssetUrlFix(Uri uri) {
- if (CordovaResourceApi.getUriType(uri) != CordovaResourceApi.URI_TYPE_ASSET) {
- return false;
- }
- if (uri.getQuery() != null || uri.getFragment() != null) {
- return true;
- }
-
- if (!uri.toString().contains("%")) {
- return false;
- }
-
- return false;
- }
-}
diff --git a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewEngine.java b/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewEngine.java
deleted file mode 100755
index 1cbd7f8..0000000
--- a/platforms/android/CordovaLib/src/org/apache/cordova/engine/SystemWebViewEngine.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova.engine;
-
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.os.Build;
-import android.view.View;
-import android.webkit.ValueCallback;
-import android.webkit.WebSettings;
-import android.webkit.WebSettings.LayoutAlgorithm;
-import android.webkit.WebView;
-
-import org.apache.cordova.CordovaBridge;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPreferences;
-import org.apache.cordova.CordovaResourceApi;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CordovaWebViewEngine;
-import org.apache.cordova.ICordovaCookieManager;
-import org.apache.cordova.LOG;
-import org.apache.cordova.NativeToJsMessageQueue;
-import org.apache.cordova.PluginManager;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-
-/**
- * Glue class between CordovaWebView (main Cordova logic) and SystemWebView (the actual View).
- * We make the Engine separate from the actual View so that:
- * A) We don't need to worry about WebView methods clashing with CordovaWebViewEngine methods
- * (e.g.: goBack() is void for WebView, and boolean for CordovaWebViewEngine)
- * B) Separating the actual View from the Engine makes API surfaces smaller.
- * Class uses two-phase initialization. However, CordovaWebView is responsible for calling .init().
- */
-public class SystemWebViewEngine implements CordovaWebViewEngine {
- public static final String TAG = "SystemWebViewEngine";
-
- protected final SystemWebView webView;
- protected final SystemCookieManager cookieManager;
- protected CordovaPreferences preferences;
- protected CordovaBridge bridge;
- protected CordovaWebViewEngine.Client client;
- protected CordovaWebView parentWebView;
- protected CordovaInterface cordova;
- protected PluginManager pluginManager;
- protected CordovaResourceApi resourceApi;
- protected NativeToJsMessageQueue nativeToJsMessageQueue;
- private BroadcastReceiver receiver;
-
- /** Used when created via reflection. */
- public SystemWebViewEngine(Context context, CordovaPreferences preferences) {
- this(new SystemWebView(context), preferences);
- }
-
- public SystemWebViewEngine(SystemWebView webView) {
- this(webView, null);
- }
-
- public SystemWebViewEngine(SystemWebView webView, CordovaPreferences preferences) {
- this.preferences = preferences;
- this.webView = webView;
- cookieManager = new SystemCookieManager(webView);
- }
-
- @Override
- public void init(CordovaWebView parentWebView, CordovaInterface cordova, CordovaWebViewEngine.Client client,
- CordovaResourceApi resourceApi, PluginManager pluginManager,
- NativeToJsMessageQueue nativeToJsMessageQueue) {
- if (this.cordova != null) {
- throw new IllegalStateException();
- }
- // Needed when prefs are not passed by the constructor
- if (preferences == null) {
- preferences = parentWebView.getPreferences();
- }
- this.parentWebView = parentWebView;
- this.cordova = cordova;
- this.client = client;
- this.resourceApi = resourceApi;
- this.pluginManager = pluginManager;
- this.nativeToJsMessageQueue = nativeToJsMessageQueue;
- webView.init(this, cordova);
-
- initWebViewSettings();
-
- nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.OnlineEventsBridgeMode(new NativeToJsMessageQueue.OnlineEventsBridgeMode.OnlineEventsBridgeModeDelegate() {
- @Override
- public void setNetworkAvailable(boolean value) {
- //sometimes this can be called after calling webview.destroy() on destroy()
- //thus resulting in a NullPointerException
- if(webView!=null) {
- webView.setNetworkAvailable(value);
- }
- }
- @Override
- public void runOnUiThread(Runnable r) {
- SystemWebViewEngine.this.cordova.getActivity().runOnUiThread(r);
- }
- }));
- nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.EvalBridgeMode(this, cordova));
- bridge = new CordovaBridge(pluginManager, nativeToJsMessageQueue);
- exposeJsInterface(webView, bridge);
- }
-
- @Override
- public CordovaWebView getCordovaWebView() {
- return parentWebView;
- }
-
- @Override
- public ICordovaCookieManager getCookieManager() {
- return cookieManager;
- }
-
- @Override
- public View getView() {
- return webView;
- }
-
- @SuppressLint({"NewApi", "SetJavaScriptEnabled"})
- @SuppressWarnings("deprecation")
- private void initWebViewSettings() {
- webView.setInitialScale(0);
- webView.setVerticalScrollBarEnabled(false);
- // Enable JavaScript
- final WebSettings settings = webView.getSettings();
- settings.setJavaScriptEnabled(true);
- settings.setJavaScriptCanOpenWindowsAutomatically(true);
- settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
-
- String manufacturer = android.os.Build.MANUFACTURER;
- LOG.d(TAG, "CordovaWebView is running on device made by: " + manufacturer);
-
- //We don't save any form data in the application
- settings.setSaveFormData(false);
- settings.setSavePassword(false);
-
- // Jellybean rightfully tried to lock this down. Too bad they didn't give us a whitelist
- // while we do this
- settings.setAllowUniversalAccessFromFileURLs(true);
- settings.setMediaPlaybackRequiresUserGesture(false);
-
- // Enable database
- // We keep this disabled because we use or shim to get around DOM_EXCEPTION_ERROR_16
- String databasePath = webView.getContext().getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
- settings.setDatabaseEnabled(true);
- settings.setDatabasePath(databasePath);
-
-
- //Determine whether we're in debug or release mode, and turn on Debugging!
- ApplicationInfo appInfo = webView.getContext().getApplicationContext().getApplicationInfo();
- if ((appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
- enableRemoteDebugging();
- }
-
- settings.setGeolocationDatabasePath(databasePath);
-
- // Enable DOM storage
- settings.setDomStorageEnabled(true);
-
- // Enable built-in geolocation
- settings.setGeolocationEnabled(true);
-
- // Enable AppCache
- // Fix for CB-2282
- settings.setAppCacheMaxSize(5 * 1048576);
- settings.setAppCachePath(databasePath);
- settings.setAppCacheEnabled(true);
-
- // Fix for CB-1405
- // Google issue 4641
- String defaultUserAgent = settings.getUserAgentString();
-
- // Fix for CB-3360
- String overrideUserAgent = preferences.getString("OverrideUserAgent", null);
- if (overrideUserAgent != null) {
- settings.setUserAgentString(overrideUserAgent);
- } else {
- String appendUserAgent = preferences.getString("AppendUserAgent", null);
- if (appendUserAgent != null) {
- settings.setUserAgentString(defaultUserAgent + " " + appendUserAgent);
- }
- }
- // End CB-3360
-
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
- if (this.receiver == null) {
- this.receiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- settings.getUserAgentString();
- }
- };
- webView.getContext().registerReceiver(this.receiver, intentFilter);
- }
- // end CB-1405
- }
-
- private void enableRemoteDebugging() {
- try {
- WebView.setWebContentsDebuggingEnabled(true);
- } catch (IllegalArgumentException e) {
- LOG.d(TAG, "You have one job! To turn on Remote Web Debugging! YOU HAVE FAILED! ");
- e.printStackTrace();
- }
- }
-
- // Yeah, we know. It'd be great if lint was just a little smarter.
- @SuppressLint("AddJavascriptInterface")
- private static void exposeJsInterface(WebView webView, CordovaBridge bridge) {
- SystemExposedJsApi exposedJsApi = new SystemExposedJsApi(bridge);
- webView.addJavascriptInterface(exposedJsApi, "_cordovaNative");
- }
-
-
- /**
- * Load the url into the webview.
- */
- @Override
- public void loadUrl(final String url, boolean clearNavigationStack) {
- webView.loadUrl(url);
- }
-
- @Override
- public String getUrl() {
- return webView.getUrl();
- }
-
- @Override
- public void stopLoading() {
- webView.stopLoading();
- }
-
- @Override
- public void clearCache() {
- webView.clearCache(true);
- }
-
- @Override
- public void clearHistory() {
- webView.clearHistory();
- }
-
- @Override
- public boolean canGoBack() {
- return webView.canGoBack();
- }
-
- /**
- * Go to previous page in history. (We manage our own history)
- *
- * @return true if we went back, false if we are already at top
- */
- @Override
- public boolean goBack() {
- // Check webview first to see if there is a history
- // This is needed to support curPage#diffLink, since they are added to parentEngine's history, but not our history url array (JQMobile behavior)
- if (webView.canGoBack()) {
- webView.goBack();
- return true;
- }
- return false;
- }
-
- @Override
- public void setPaused(boolean value) {
- if (value) {
- webView.onPause();
- webView.pauseTimers();
- } else {
- webView.onResume();
- webView.resumeTimers();
- }
- }
-
- @Override
- public void destroy() {
- webView.chromeClient.destroyLastDialog();
- webView.destroy();
- // unregister the receiver
- if (receiver != null) {
- try {
- webView.getContext().unregisterReceiver(receiver);
- } catch (Exception e) {
- LOG.e(TAG, "Error unregistering configuration receiver: " + e.getMessage(), e);
- }
- }
- }
-
- @Override
- public void evaluateJavascript(String js, ValueCallback callback) {
- webView.evaluateJavascript(js, callback);
- }
-}
diff --git a/platforms/android/android.json b/platforms/android/android.json
deleted file mode 100644
index d1ae1a1..0000000
--- a/platforms/android/android.json
+++ /dev/null
@@ -1,418 +0,0 @@
-{
- "prepare_queue": {
- "installed": [],
- "uninstalled": []
- },
- "config_munge": {
- "files": {
- "res/xml/config.xml": {
- "parents": {
- "/widget": [
- {
- "xml": " ",
- "count": 1
- }
- ],
- "/*": [
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- }
- ]
- }
- },
- "config.xml": {
- "parents": {
- "/*": [
- {
- "xml": " ",
- "count": 1
- }
- ]
- }
- },
- "AndroidManifest.xml": {
- "parents": {
- "/*": [
- {
- "xml": " ",
- "count": 3
- },
- {
- "xml": " ",
- "count": 1
- }
- ],
- "/manifest/application/activity": [
- {
- "xml": " ",
- "count": 1
- }
- ],
- "/manifest": [
- {
- "xml": " ",
- "count": 1
- },
- {
- "xml": " ",
- "count": 1
- }
- ],
- "/manifest/application": [
- {
- "xml": " ",
- "count": 1
- }
- ]
- }
- }
- }
- },
- "installed_plugins": {
- "cordova-plugin-filechooser": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-plugin-share-content": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-plugin-file": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-plugin-file-transfer": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "com-darryncampbell-cordova-plugin-intent": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-plugin-inappbrowser": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-plugin-whitelist": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-plugin-splashscreen": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-plugin-device": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-android-support-gradle-release": {
- "ANDROID_SUPPORT_VERSION": "27.+",
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-plugin-filepath": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- },
- "cordova-sqlite-storage": {
- "PACKAGE_NAME": "com.monkeystew.goober_m"
- }
- },
- "dependent_plugins": {},
- "modules": [
- {
- "id": "cordova-plugin-filechooser.FileChooser",
- "file": "plugins/cordova-plugin-filechooser/www/fileChooser.js",
- "pluginId": "cordova-plugin-filechooser",
- "clobbers": [
- "fileChooser"
- ]
- },
- {
- "id": "cordova-plugin-share-content.ShareContentPlugin",
- "file": "plugins/cordova-plugin-share-content/www/sharecontentplugin.js",
- "pluginId": "cordova-plugin-share-content",
- "merges": [
- "shareContentPlugin"
- ]
- },
- {
- "id": "cordova-plugin-file.DirectoryEntry",
- "file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.DirectoryEntry"
- ]
- },
- {
- "id": "cordova-plugin-file.DirectoryReader",
- "file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.DirectoryReader"
- ]
- },
- {
- "id": "cordova-plugin-file.Entry",
- "file": "plugins/cordova-plugin-file/www/Entry.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.Entry"
- ]
- },
- {
- "id": "cordova-plugin-file.File",
- "file": "plugins/cordova-plugin-file/www/File.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.File"
- ]
- },
- {
- "id": "cordova-plugin-file.FileEntry",
- "file": "plugins/cordova-plugin-file/www/FileEntry.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.FileEntry"
- ]
- },
- {
- "id": "cordova-plugin-file.FileError",
- "file": "plugins/cordova-plugin-file/www/FileError.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.FileError"
- ]
- },
- {
- "id": "cordova-plugin-file.FileReader",
- "file": "plugins/cordova-plugin-file/www/FileReader.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.FileReader"
- ]
- },
- {
- "id": "cordova-plugin-file.FileSystem",
- "file": "plugins/cordova-plugin-file/www/FileSystem.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.FileSystem"
- ]
- },
- {
- "id": "cordova-plugin-file.FileUploadOptions",
- "file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.FileUploadOptions"
- ]
- },
- {
- "id": "cordova-plugin-file.FileUploadResult",
- "file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.FileUploadResult"
- ]
- },
- {
- "id": "cordova-plugin-file.FileWriter",
- "file": "plugins/cordova-plugin-file/www/FileWriter.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.FileWriter"
- ]
- },
- {
- "id": "cordova-plugin-file.Flags",
- "file": "plugins/cordova-plugin-file/www/Flags.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.Flags"
- ]
- },
- {
- "id": "cordova-plugin-file.LocalFileSystem",
- "file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.LocalFileSystem"
- ],
- "merges": [
- "window"
- ]
- },
- {
- "id": "cordova-plugin-file.Metadata",
- "file": "plugins/cordova-plugin-file/www/Metadata.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.Metadata"
- ]
- },
- {
- "id": "cordova-plugin-file.ProgressEvent",
- "file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.ProgressEvent"
- ]
- },
- {
- "id": "cordova-plugin-file.fileSystems",
- "file": "plugins/cordova-plugin-file/www/fileSystems.js",
- "pluginId": "cordova-plugin-file"
- },
- {
- "id": "cordova-plugin-file.requestFileSystem",
- "file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
- "pluginId": "cordova-plugin-file",
- "clobbers": [
- "window.requestFileSystem"
- ]
- },
- {
- "id": "cordova-plugin-file.resolveLocalFileSystemURI",
- "file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
- "pluginId": "cordova-plugin-file",
- "merges": [
- "window"
- ]
- },
- {
- "id": "cordova-plugin-file.isChrome",
- "file": "plugins/cordova-plugin-file/www/browser/isChrome.js",
- "pluginId": "cordova-plugin-file",
- "runs": true
- },
- {
- "id": "cordova-plugin-file.androidFileSystem",
- "file": "plugins/cordova-plugin-file/www/android/FileSystem.js",
- "pluginId": "cordova-plugin-file",
- "merges": [
- "FileSystem"
- ]
- },
- {
- "id": "cordova-plugin-file.fileSystems-roots",
- "file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
- "pluginId": "cordova-plugin-file",
- "runs": true
- },
- {
- "id": "cordova-plugin-file.fileSystemPaths",
- "file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
- "pluginId": "cordova-plugin-file",
- "merges": [
- "cordova"
- ],
- "runs": true
- },
- {
- "id": "cordova-plugin-file-transfer.FileTransferError",
- "file": "plugins/cordova-plugin-file-transfer/www/FileTransferError.js",
- "pluginId": "cordova-plugin-file-transfer",
- "clobbers": [
- "window.FileTransferError"
- ]
- },
- {
- "id": "cordova-plugin-file-transfer.FileTransfer",
- "file": "plugins/cordova-plugin-file-transfer/www/FileTransfer.js",
- "pluginId": "cordova-plugin-file-transfer",
- "clobbers": [
- "window.FileTransfer"
- ]
- },
- {
- "id": "com-darryncampbell-cordova-plugin-intent.IntentShim",
- "file": "plugins/com-darryncampbell-cordova-plugin-intent/www/IntentShim.js",
- "pluginId": "com-darryncampbell-cordova-plugin-intent",
- "clobbers": [
- "intentShim"
- ]
- },
- {
- "id": "cordova-plugin-inappbrowser.inappbrowser",
- "file": "plugins/cordova-plugin-inappbrowser/www/inappbrowser.js",
- "pluginId": "cordova-plugin-inappbrowser",
- "clobbers": [
- "cordova.InAppBrowser.open",
- "window.open"
- ]
- },
- {
- "id": "cordova-plugin-splashscreen.SplashScreen",
- "file": "plugins/cordova-plugin-splashscreen/www/splashscreen.js",
- "pluginId": "cordova-plugin-splashscreen",
- "clobbers": [
- "navigator.splashscreen"
- ]
- },
- {
- "id": "cordova-plugin-device.device",
- "file": "plugins/cordova-plugin-device/www/device.js",
- "pluginId": "cordova-plugin-device",
- "clobbers": [
- "device"
- ]
- },
- {
- "id": "cordova-plugin-filepath.FilePath",
- "file": "plugins/cordova-plugin-filepath/www/FilePath.js",
- "pluginId": "cordova-plugin-filepath",
- "clobbers": [
- "window.FilePath"
- ]
- },
- {
- "id": "cordova-sqlite-storage.SQLitePlugin",
- "file": "plugins/cordova-sqlite-storage/www/SQLitePlugin.js",
- "pluginId": "cordova-sqlite-storage",
- "clobbers": [
- "SQLitePlugin"
- ]
- }
- ],
- "plugin_metadata": {
- "cordova-plugin-filechooser": "1.0.1",
- "cordova-plugin-share-content": "1.0.0",
- "cordova-plugin-file": "6.0.1",
- "cordova-plugin-file-transfer": "1.7.1",
- "com-darryncampbell-cordova-plugin-intent": "1.1.1",
- "cordova-plugin-inappbrowser": "3.0.0",
- "cordova-plugin-whitelist": "1.3.3",
- "cordova-plugin-splashscreen": "5.0.2",
- "cordova-plugin-device": "2.0.2",
- "cordova-android-support-gradle-release": "1.4.7",
- "cordova-plugin-filepath": "1.4.2",
- "cordova-sqlite-storage": "2.5.1"
- }
-}
\ No newline at end of file
diff --git a/platforms/android/app/build.gradle b/platforms/android/app/build.gradle
deleted file mode 100644
index c13ca2f..0000000
--- a/platforms/android/app/build.gradle
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-apply plugin: 'com.android.application'
-
-buildscript {
- repositories {
- mavenCentral()
- maven {
- url "https://maven.google.com"
- }
- jcenter()
- }
-
- dependencies {
- classpath 'com.android.tools.build:gradle:3.0.1'
- }
-}
-
-// Allow plugins to declare Maven dependencies via build-extras.gradle.
-allprojects {
- repositories {
- mavenCentral();
- jcenter()
- }
-}
-
-task wrapper(type: Wrapper) {
- gradleVersion = '4.1.0'
-}
-
-// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
-// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
-ext {
- apply from: '../CordovaLib/cordova.gradle'
- // The value for android.compileSdkVersion.
- if (!project.hasProperty('cdvCompileSdkVersion')) {
- cdvCompileSdkVersion = null;
- }
- // The value for android.buildToolsVersion.
- if (!project.hasProperty('cdvBuildToolsVersion')) {
- cdvBuildToolsVersion = null;
- }
- // Sets the versionCode to the given value.
- if (!project.hasProperty('cdvVersionCode')) {
- cdvVersionCode = null
- }
- // Sets the minSdkVersion to the given value.
- if (!project.hasProperty('cdvMinSdkVersion')) {
- cdvMinSdkVersion = null
- }
- // Whether to build architecture-specific APKs.
- if (!project.hasProperty('cdvBuildMultipleApks')) {
- cdvBuildMultipleApks = null
- }
- // Whether to append a 0 "abi digit" to versionCode when only a single APK is build
- if (!project.hasProperty('cdvVersionCodeForceAbiDigit')) {
- cdvVersionCodeForceAbiDigit = null
- }
- // .properties files to use for release signing.
- if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) {
- cdvReleaseSigningPropertiesFile = null
- }
- // .properties files to use for debug signing.
- if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
- cdvDebugSigningPropertiesFile = null
- }
- // Set by build.js script.
- if (!project.hasProperty('cdvBuildArch')) {
- cdvBuildArch = null
- }
-
- // Plugin gradle extensions can append to this to have code run at the end.
- cdvPluginPostBuildExtras = []
-}
-
-// PLUGIN GRADLE EXTENSIONS START
-// PLUGIN GRADLE EXTENSIONS END
-
-def hasBuildExtras = file('build-extras.gradle').exists()
-if (hasBuildExtras) {
- apply from: 'build-extras.gradle'
-}
-
-// Set property defaults after extension .gradle files.
-if (ext.cdvCompileSdkVersion == null) {
- ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget()
- //ext.cdvCompileSdkVersion = project.ext.defaultCompileSdkVersion
-}
-if (ext.cdvBuildToolsVersion == null) {
- ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
- //ext.cdvBuildToolsVersion = project.ext.defaultBuildToolsVersion
-}
-if (ext.cdvDebugSigningPropertiesFile == null && file('../debug-signing.properties').exists()) {
- ext.cdvDebugSigningPropertiesFile = '../debug-signing.properties'
-}
-if (ext.cdvReleaseSigningPropertiesFile == null && file('../release-signing.properties').exists()) {
- ext.cdvReleaseSigningPropertiesFile = '../release-signing.properties'
-}
-
-// Cast to appropriate types.
-ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
-ext.cdvVersionCodeForceAbiDigit = cdvVersionCodeForceAbiDigit == null ? false : cdvVersionCodeForceAbiDigit.toBoolean();
-ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? null : defaultMinSdkVersion
-ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)
-
-def computeBuildTargetName(debugBuild) {
- def ret = 'assemble'
- if (cdvBuildMultipleApks && cdvBuildArch) {
- def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch
- ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1);
- }
- return ret + (debugBuild ? 'Debug' : 'Release')
-}
-
-// Make cdvBuild a task that depends on the debug/arch-sepecific task.
-task cdvBuildDebug
-cdvBuildDebug.dependsOn {
- return computeBuildTargetName(true)
-}
-
-task cdvBuildRelease
-cdvBuildRelease.dependsOn {
- return computeBuildTargetName(false)
-}
-
-task cdvPrintProps << {
- println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
- println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
- println('cdvVersionCode=' + cdvVersionCode)
- println('cdvVersionCodeForceAbiDigit=' + cdvVersionCodeForceAbiDigit)
- println('cdvMinSdkVersion=' + cdvMinSdkVersion)
- println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
- println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
- println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
- println('cdvBuildArch=' + cdvBuildArch)
- println('computedVersionCode=' + android.defaultConfig.versionCode)
- android.productFlavors.each { flavor ->
- println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
- }
-}
-
-android {
-
- defaultConfig {
- versionCode cdvVersionCode ?: new BigInteger("" + privateHelpers.extractIntFromManifest("versionCode"))
- applicationId privateHelpers.extractStringFromManifest("package")
-
- if (cdvMinSdkVersion != null) {
- minSdkVersion cdvMinSdkVersion
- }
- }
-
- lintOptions {
- abortOnError false;
- }
-
- compileSdkVersion cdvCompileSdkVersion
- buildToolsVersion cdvBuildToolsVersion
-
- //This code exists for Crosswalk and other Native APIs.
- //By default, we multiply the existing version code in the Android Manifest by 10 and
- //add a number for each architecture. If you are not using Crosswalk or SQLite, you can
- //ignore this chunk of code, and your version codes will be respected.
-
- if (Boolean.valueOf(cdvBuildMultipleApks)) {
- flavorDimensions "default"
-
- productFlavors {
- armeabi {
- versionCode defaultConfig.versionCode*10 + 1
- ndk {
- abiFilters = ["armeabi"]
- }
- }
- armv7 {
- versionCode defaultConfig.versionCode*10 + 2
- ndk {
- abiFilters = ["armeabi-v7a"]
- }
- }
- arm64 {
- versionCode defaultConfig.versionCode*10 + 3
- ndk {
- abiFilters = ["arm64-v8a"]
- }
- }
- x86 {
- versionCode defaultConfig.versionCode*10 + 4
- ndk {
- abiFilters = ["x86"]
- }
- }
- x86_64 {
- versionCode defaultConfig.versionCode*10 + 5
- ndk {
- abiFilters = ["x86_64"]
- }
- }
- }
- } else if (Boolean.valueOf(cdvVersionCodeForceAbiDigit)) {
- // This provides compatibility to the default logic for versionCode before cordova-android 5.2.0
- defaultConfig {
- versionCode defaultConfig.versionCode*10
- }
- }
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-
- if (cdvReleaseSigningPropertiesFile) {
- signingConfigs {
- release {
- // These must be set or Gradle will complain (even if they are overridden).
- keyAlias = ""
- keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
- storeFile = null
- storePassword = "__unset"
- }
- }
- buildTypes {
- release {
- signingConfig signingConfigs.release
- }
- }
- addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
- }
- if (cdvDebugSigningPropertiesFile) {
- addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
- }
-}
-
-/*
- * WARNING: Cordova Lib and platform scripts do management inside of this code here,
- * if you are adding the dependencies manually, do so outside the comments, otherwise
- * the Cordova tools will overwrite them
- */
-
-
-dependencies {
- implementation fileTree(dir: 'libs', include: '*.jar')
- // SUB-PROJECT DEPENDENCIES START
- implementation(project(path: ":CordovaLib"))
- compile "com.android.support:support-v4:27.+"
- compile "com.android.support:support-v4:27.+"
- compile "com.android.support:appcompat-v7:27.+"
- // SUB-PROJECT DEPENDENCIES END
-}
-
-def promptForReleaseKeyPassword() {
- if (!cdvReleaseSigningPropertiesFile) {
- return;
- }
- if ('__unset'.equals(android.signingConfigs.release.storePassword)) {
- android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ')
- }
- if ('__unset'.equals(android.signingConfigs.release.keyPassword)) {
- android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: ');
- }
-}
-
-gradle.taskGraph.whenReady { taskGraph ->
- taskGraph.getAllTasks().each() { task ->
- if(['validateReleaseSigning', 'validateSigningRelease', 'validateSigningArmv7Release', 'validateSigningX76Release'].contains(task.name)) {
- promptForReleaseKeyPassword()
- }
- }
-}
-
-def addSigningProps(propsFilePath, signingConfig) {
- def propsFile = file(propsFilePath)
- def props = new Properties()
- propsFile.withReader { reader ->
- props.load(reader)
- }
-
- def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile'))
- if (!storeFile.isAbsolute()) {
- storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
- }
- if (!storeFile.exists()) {
- throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
- }
- signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
- signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword))
- signingConfig.storeFile = storeFile
- signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword))
- def storeType = props.get('storeType', props.get('key.store.type', ''))
- if (!storeType) {
- def filename = storeFile.getName().toLowerCase();
- if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
- storeType = 'pkcs12'
- } else {
- storeType = signingConfig.storeType // "jks"
- }
- }
- signingConfig.storeType = storeType
-}
-
-for (def func : cdvPluginPostBuildExtras) {
- func()
-}
-
-// This can be defined within build-extras.gradle as:
-// ext.postBuildExtras = { ... code here ... }
-if (hasProperty('postBuildExtras')) {
- postBuildExtras()
-}
diff --git a/platforms/android/app/libs/sqlite-connector.jar b/platforms/android/app/libs/sqlite-connector.jar
deleted file mode 100644
index 73387a1..0000000
Binary files a/platforms/android/app/libs/sqlite-connector.jar and /dev/null differ
diff --git a/platforms/android/app/libs/sqlite-native-driver.jar b/platforms/android/app/libs/sqlite-native-driver.jar
deleted file mode 100644
index b1850ad..0000000
Binary files a/platforms/android/app/libs/sqlite-native-driver.jar and /dev/null differ
diff --git a/platforms/android/app/src/main/AndroidManifest.xml b/platforms/android/app/src/main/AndroidManifest.xml
deleted file mode 100644
index 2da4d2e..0000000
--- a/platforms/android/app/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/platforms/android/app/src/main/app/cordova-android-support-gradle-release/cordova-android-support-gradle-release.gradle b/platforms/android/app/src/main/app/cordova-android-support-gradle-release/cordova-android-support-gradle-release.gradle
deleted file mode 100644
index 1b0bd72..0000000
--- a/platforms/android/app/src/main/app/cordova-android-support-gradle-release/cordova-android-support-gradle-release.gradle
+++ /dev/null
@@ -1,31 +0,0 @@
-repositories{
- // Google APIs are now hosted at Maven
- maven {
- url 'https://maven.google.com'
- }
-}
-
-def PLUGIN_NAME = "cordova-android-support-gradle-release"
-
-// Fetch ANDROID_SUPPORT_VERSION var from properties.gradle
-apply from: PLUGIN_NAME + '/properties.gradle'
-
-// List of libs to search for.
-def LIBS = [
- 'com.android.support'
-]
-
-def IGNORED = [
- 'multidex',
- 'multidex-instrumentation'
-]
-
-println("+-----------------------------------------------------------------");
-println("| " + PLUGIN_NAME + ": " + ANDROID_SUPPORT_VERSION);
-println("+-----------------------------------------------------------------");
-
-configurations.all {
- resolutionStrategy.eachDependency { DependencyResolveDetails details ->
- if (details.requested.group in LIBS && !(details.requested.name in IGNORED)) { details.useVersion ANDROID_SUPPORT_VERSION }
- }
-}
diff --git a/platforms/android/app/src/main/app/cordova-android-support-gradle-release/properties.gradle b/platforms/android/app/src/main/app/cordova-android-support-gradle-release/properties.gradle
deleted file mode 100644
index 5d42a85..0000000
--- a/platforms/android/app/src/main/app/cordova-android-support-gradle-release/properties.gradle
+++ /dev/null
@@ -1 +0,0 @@
-ext {ANDROID_SUPPORT_VERSION = "27.+"}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/cordova-android-support-gradle-release/cordova-android-support-gradle-release.gradle b/platforms/android/app/src/main/cordova-android-support-gradle-release/cordova-android-support-gradle-release.gradle
deleted file mode 100644
index 1b0bd72..0000000
--- a/platforms/android/app/src/main/cordova-android-support-gradle-release/cordova-android-support-gradle-release.gradle
+++ /dev/null
@@ -1,31 +0,0 @@
-repositories{
- // Google APIs are now hosted at Maven
- maven {
- url 'https://maven.google.com'
- }
-}
-
-def PLUGIN_NAME = "cordova-android-support-gradle-release"
-
-// Fetch ANDROID_SUPPORT_VERSION var from properties.gradle
-apply from: PLUGIN_NAME + '/properties.gradle'
-
-// List of libs to search for.
-def LIBS = [
- 'com.android.support'
-]
-
-def IGNORED = [
- 'multidex',
- 'multidex-instrumentation'
-]
-
-println("+-----------------------------------------------------------------");
-println("| " + PLUGIN_NAME + ": " + ANDROID_SUPPORT_VERSION);
-println("+-----------------------------------------------------------------");
-
-configurations.all {
- resolutionStrategy.eachDependency { DependencyResolveDetails details ->
- if (details.requested.group in LIBS && !(details.requested.name in IGNORED)) { details.useVersion ANDROID_SUPPORT_VERSION }
- }
-}
diff --git a/platforms/android/app/src/main/cordova-android-support-gradle-release/properties.gradle b/platforms/android/app/src/main/cordova-android-support-gradle-release/properties.gradle
deleted file mode 100644
index 5d42a85..0000000
--- a/platforms/android/app/src/main/cordova-android-support-gradle-release/properties.gradle
+++ /dev/null
@@ -1 +0,0 @@
-ext {ANDROID_SUPPORT_VERSION = "27.+"}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/java/com/darryncampbell/plugin/intent/IntentShim.java b/platforms/android/app/src/main/java/com/darryncampbell/plugin/intent/IntentShim.java
deleted file mode 100644
index e5e2a09..0000000
--- a/platforms/android/app/src/main/java/com/darryncampbell/plugin/intent/IntentShim.java
+++ /dev/null
@@ -1,801 +0,0 @@
-package com.darryncampbell.cordova.plugin.intent;
-
-import android.Manifest;
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.ClipData;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Environment;
-import android.provider.DocumentsContract;
-import android.provider.MediaStore;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-import android.support.v4.content.FileProvider;
-import android.text.Html;
-import android.util.Log;
-import android.webkit.MimeTypeMap;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaActivity;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaResourceApi;
-import org.apache.cordova.PluginResult;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.File;
-
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import static android.os.Environment.getExternalStorageDirectory;
-import static android.os.Environment.getExternalStorageState;
-
-public class IntentShim extends CordovaPlugin {
-
- private static final String LOG_TAG = "Cordova Intents Shim";
- private CallbackContext onNewIntentCallbackContext = null;
- private CallbackContext onBroadcastCallbackContext = null;
- private CallbackContext onActivityResultCallbackContext = null;
-
- private Intent deferredIntent = null;
-
- public IntentShim() {
-
- }
-
- public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException
- {
- Log.d(LOG_TAG, "Action: " + action);
- if (action.equals("startActivity") || action.equals("startActivityForResult"))
- {
- // Credit: https://github.com/chrisekelley/cordova-webintent
- if (args.length() != 1) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
-
- JSONObject obj = args.getJSONObject(0);
- Intent intent = populateIntent(obj, callbackContext);
- int requestCode = obj.has("requestCode") ? obj.getInt("requestCode") : 1;
-
- boolean bExpectResult = false;
- if (action.equals("startActivityForResult"))
- {
- bExpectResult = true;
- this.onActivityResultCallbackContext = callbackContext;
- }
- startActivity(intent, bExpectResult, requestCode, callbackContext);
-
- return true;
- }
- else if (action.equals("sendBroadcast"))
- {
- // Credit: https://github.com/chrisekelley/cordova-webintent
- if (args.length() != 1) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
-
- // Parse the arguments
- JSONObject obj = args.getJSONObject(0);
- Intent intent = populateIntent(obj, callbackContext);
-
- sendBroadcast(intent);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
- return true;
- }
- else if (action.equals("startService"))
- {
- if (args.length() != 1) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
- JSONObject obj = args.getJSONObject(0);
- Intent intent = populateIntent(obj, callbackContext);
- startService(intent);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
- return true;
- }
- else if (action.equals("registerBroadcastReceiver")) {
- try
- {
- // Ensure we only have a single registered broadcast receiver
- ((CordovaActivity)this.cordova.getActivity()).unregisterReceiver(myBroadcastReceiver);
- }
- catch (IllegalArgumentException e) {}
-
- // No error callback
- if(args.length() != 1) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
-
- // Expect an array of filterActions
- JSONObject obj = args.getJSONObject(0);
- JSONArray filterActions = obj.has("filterActions") ? obj.getJSONArray("filterActions") : null;
- if (filterActions == null || filterActions.length() == 0)
- {
- // The arguments are not correct
- Log.w(LOG_TAG, "filterActions argument is not in the expected format");
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
-
- this.onBroadcastCallbackContext = callbackContext;
-
- PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
- result.setKeepCallback(true);
-
- IntentFilter filter = new IntentFilter();
- for (int i = 0; i < filterActions.length(); i++) {
- Log.d(LOG_TAG, "Registering broadcast receiver for filter: " + filterActions.getString(i));
- filter.addAction(filterActions.getString(i));
- }
-
- // Allow an array of filterCategories
- JSONArray filterCategories = obj.has("filterCategories") ? obj.getJSONArray("filterCategories") : null;
- if (filterCategories != null) {
- for (int i = 0; i < filterCategories.length(); i++) {
- Log.d(LOG_TAG, "Registering broadcast receiver for category filter: " + filterCategories.getString(i));
- filter.addCategory(filterCategories.getString(i));
- }
- }
-
- // Add any specified Data Schemes
- // https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent/issues/24
- JSONArray filterDataSchemes = obj.has("filterDataSchemes") ? obj.getJSONArray("filterDataSchemes") : null;
- if (filterDataSchemes != null && filterDataSchemes.length() > 0)
- {
- for (int i = 0; i < filterDataSchemes.length(); i++)
- {
- Log.d(LOG_TAG, "Associating data scheme to filter: " + filterDataSchemes.getString(i));
- filter.addDataScheme(filterDataSchemes.getString(i));
- }
- }
-
- ((CordovaActivity)this.cordova.getActivity()).registerReceiver(myBroadcastReceiver, filter);
-
- callbackContext.sendPluginResult(result);
- }
- else if (action.equals("unregisterBroadcastReceiver"))
- {
- try
- {
- ((CordovaActivity)this.cordova.getActivity()).unregisterReceiver(myBroadcastReceiver);
- }
- catch (IllegalArgumentException e) {}
- }
- else if (action.equals("onIntent"))
- {
- // Credit: https://github.com/napolitano/cordova-plugin-intent
- if(args.length() != 1) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
-
- this.onNewIntentCallbackContext = callbackContext;
-
- if (this.deferredIntent != null) {
- fireOnNewIntent(this.deferredIntent);
- this.deferredIntent = null;
- }
-
- PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
- result.setKeepCallback(true);
- callbackContext.sendPluginResult(result);
- return true;
- }
- else if (action.equals("onActivityResult"))
- {
- if(args.length() != 1) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
-
- this.onActivityResultCallbackContext = callbackContext;
-
- PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
- result.setKeepCallback(true);
- callbackContext.sendPluginResult(result);
- return true;
- }
- else if (action.equals("getIntent"))
- {
- // Credit: https://github.com/napolitano/cordova-plugin-intent
- if(args.length() != 0) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
-
- Intent intent;
-
- if (this.deferredIntent != null) {
- intent = this.deferredIntent;
- this.deferredIntent = null;
- }
- else {
- intent = cordova.getActivity().getIntent();
- }
-
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, getIntentJson(intent)));
- return true;
- }
- else if (action.equals("sendResult"))
- {
- // Assuming this application was started with startActivityForResult, send the result back
- // https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent/issues/3
- Intent result = new Intent();
- if (args.length() > 0)
- {
- JSONObject json = args.getJSONObject(0);
- JSONObject extras = (json.has("extras"))?json.getJSONObject("extras"):null;
-
- // Populate the extras if any exist
- if (extras != null) {
- JSONArray extraNames = extras.names();
- for (int i = 0; i < extraNames.length(); i++) {
- String key = extraNames.getString(i);
- Object extrasObj = extras.get(key);
- if (extrasObj instanceof JSONObject) {
- // The extra is a bundle
- Bundle bundle = toBundle((JSONObject) extras.get(key));
- result.putExtra(key, bundle);
- } else {
- String value = extras.getString(key);
- result.putExtra(key, value);
- }
- }
- }
- }
-
- //set result
- cordova.getActivity().setResult(Activity.RESULT_OK, result);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
-
- //finish the activity
- cordova.getActivity().finish();
-
- }
- else if (action.equals("realPathFromUri"))
- {
- if (args.length() != 1) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION));
- return false;
- }
-
- JSONObject obj = args.getJSONObject(0);
- String realPath = getRealPathFromURI_API19(obj, callbackContext);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, realPath));
- return true;
-
- }
-
- return true;
- }
-
- private Uri remapUriWithFileProvider(String uriAsString, final CallbackContext callbackContext)
- {
- // Create the URI via FileProvider Special case for N and above when installing apks
- int permissionCheck = ContextCompat.checkSelfPermission(this.cordova.getActivity(),
- Manifest.permission.READ_EXTERNAL_STORAGE);
- if (permissionCheck != PackageManager.PERMISSION_GRANTED)
- {
- // Could do better here - if the app does not already have permission should
- // only continue when we get the success callback from this.
- ActivityCompat.requestPermissions(this.cordova.getActivity(),
- new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
- callbackContext.error("Please grant read external storage permission");
- return null;
- }
-
- try
- {
- String externalStorageState = getExternalStorageState();
- if (externalStorageState.equals(Environment.MEDIA_MOUNTED) || externalStorageState.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
- String fileName = uriAsString.substring(uriAsString.indexOf('/') + 2, uriAsString.length());
- File uriAsFile = new File(fileName);
- boolean fileExists = uriAsFile.exists();
- if (!fileExists)
- {
- Log.e(LOG_TAG, "File at path " + uriAsFile.getPath() + " with name " + uriAsFile.getName() + "does not exist");
- callbackContext.error("File not found: " + uriAsFile.toString());
- return null;
- }
- String PACKAGE_NAME = this.cordova.getActivity().getPackageName() + ".darryncampbell.cordova.plugin.intent.fileprovider";
- Uri uri = FileProvider.getUriForFile(this.cordova.getActivity().getApplicationContext(), PACKAGE_NAME, uriAsFile);
- return uri;
- }
- else
- {
- Log.e(LOG_TAG, "Storage directory is not mounted. Please ensure the device is not connected via USB for file transfer");
- callbackContext.error("Storage directory is returning not mounted");
- return null;
- }
- }
- catch(StringIndexOutOfBoundsException e)
- {
- Log.e(LOG_TAG, "URL is not well formed");
- callbackContext.error("URL is not well formed");
- return null;
- }
- }
-
- private String getRealPathFromURI_API19(JSONObject obj, CallbackContext callbackContext) throws JSONException
- {
- // Credit: https://stackoverflow.com/questions/2789276/android-get-real-path-by-uri-getpath/2790688
- Uri uri = obj.has("uri") ? Uri.parse(obj.getString("uri")) : null;
- if (uri == null)
- {
- Log.w(LOG_TAG, "URI is not a specified parameter");
- throw new JSONException("URI is not a specified parameter");
- }
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
- String filePath = "";
- if (uri.getHost().contains("com.android.providers.media")) {
- int permissionCheck = ContextCompat.checkSelfPermission(this.cordova.getActivity(),
- Manifest.permission.READ_EXTERNAL_STORAGE);
- if (permissionCheck != PackageManager.PERMISSION_GRANTED)
- {
- // Could do better here - if the app does not already have permission should
- // only continue when we get the success callback from this.
- ActivityCompat.requestPermissions(this.cordova.getActivity(),
- new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
- callbackContext.error("Please grant read external storage permission");
- return null;
- }
-
- // Image pick from recent
- String wholeID = DocumentsContract.getDocumentId(uri);
-
- // Split at colon, use second item in the array
- String id = wholeID.split(":")[1];
-
- String[] column = {MediaStore.Images.Media.DATA};
-
- // where id is equal to
- String sel = MediaStore.Images.Media._ID + "=?";
-
- // This line requires read storage permission
-
- Cursor cursor = this.cordova.getActivity().getApplicationContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- column, sel, new String[]{id}, null);
-
- int columnIndex = cursor.getColumnIndex(column[0]);
-
- if (cursor.moveToFirst()) {
- filePath = cursor.getString(columnIndex);
- }
- cursor.close();
- return filePath;
- } else {
- // image pick from gallery
- String[] proj = {MediaStore.Images.Media.DATA};
- Cursor cursor = this.cordova.getActivity().getApplicationContext().getContentResolver().query(uri, proj, null, null, null);
- int column_index
- = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
- cursor.moveToFirst();
- return cursor.getString(column_index);
- }
- }
-
- return "Requires KK or higher";
- }
-
- private void startActivity(Intent i, boolean bExpectResult, int requestCode, CallbackContext callbackContext) {
-
- if (i.resolveActivityInfo(this.cordova.getActivity().getPackageManager(), 0) != null)
- {
- if (bExpectResult)
- {
- cordova.setActivityResultCallback(this);
- ((CordovaActivity) this.cordova.getActivity()).startActivityForResult(i, requestCode);
- }
- else
- {
- ((CordovaActivity)this.cordova.getActivity()).startActivity(i);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
- }
- }
- else
- {
- // Return an error as there is no app to handle this intent
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR));
- }
- }
-
- private void sendBroadcast(Intent intent) {
- ((CordovaActivity)this.cordova.getActivity()).sendBroadcast(intent);
- }
-
- private void startService(Intent intent)
- {
- ((CordovaActivity)this.cordova.getActivity()).startService(intent);
- }
-
- private Intent populateIntent(JSONObject obj, CallbackContext callbackContext) throws JSONException
- {
- // Credit: https://github.com/chrisekelley/cordova-webintent
- // Credit: https://github.com/chrisekelley/cordova-webintent
- String type = obj.has("type") ? obj.getString("type") : null;
- String packageAssociated = obj.has("package") ? obj.getString("package") : null;
-
- //Uri uri = obj.has("url") ? resourceApi.remapUri(Uri.parse(obj.getString("url"))) : null;
- Uri uri = null;
- final CordovaResourceApi resourceApi = webView.getResourceApi();
- if (obj.has("url"))
- {
- String uriAsString = obj.getString("url");
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && uriAsString.startsWith("file://"))
- {
- uri = remapUriWithFileProvider(uriAsString, callbackContext);
- }
- else
- {
- uri = resourceApi.remapUri(Uri.parse(obj.getString("url")));
- }
- }
-
- JSONObject extras = obj.has("extras") ? obj.getJSONObject("extras") : null;
- Map extrasMap = new HashMap();
- Bundle bundle = null;
- String bundleKey = "";
- if (extras != null) {
- JSONArray extraNames = extras.names();
- for (int i = 0; i < extraNames.length(); i++) {
- String key = extraNames.getString(i);
- Object extrasObj = extras.get(key);
- if (extrasObj instanceof JSONObject) {
- // The extra is a bundle
- bundleKey = key;
- bundle = toBundle((JSONObject) extras.get(key));
- } else {
- extrasMap.put(key, extras.get(key));
- }
- }
- }
-
- String action = obj.has("action") ? obj.getString("action") : null;
- Intent i = new Intent();
- if (action != null)
- i.setAction(action);
-
- if (type != null && uri != null) {
- i.setDataAndType(uri, type); //Fix the crash problem with android 2.3.6
- } else {
- if (type != null) {
- i.setType(type);
- }
- if (uri != null)
- {
- i.setData(uri);
- }
- }
-
- JSONObject component = obj.has("component") ? obj.getJSONObject("component") : null;
- if (component != null)
- {
- // User has specified an explicit intent
- String componentPackage = component.has("package") ? component.getString("package") : null;
- String componentClass = component.has("class") ? component.getString("class") : null;
- if (componentPackage == null || componentClass == null)
- {
- Log.w(LOG_TAG, "Component specified but missing corresponding package or class");
- throw new JSONException("Component specified but missing corresponding package or class");
- }
-
- else
- {
- ComponentName componentName = new ComponentName(componentPackage, componentClass);
- i.setComponent(componentName);
- }
- }
-
- if (packageAssociated != null)
- i.setPackage(packageAssociated);
-
- JSONArray flags = obj.has("flags") ? obj.getJSONArray("flags") : null;
- if (flags != null)
- {
- int length = flags.length();
- for (int k = 0; k < length; k++)
- {
- i.addFlags(flags.getInt(k));
- }
- }
-
- if (bundle != null)
- i.putExtra(bundleKey, bundle);
-
- for (String key : extrasMap.keySet()) {
- Object value = extrasMap.get(key);
- String valueStr = String.valueOf(value);
- // If type is text html, the extra text must sent as HTML
- if (key.equals(Intent.EXTRA_TEXT) && type.equals("text/html")) {
- i.putExtra(key, Html.fromHtml(valueStr));
- } else if (key.equals(Intent.EXTRA_STREAM)) {
- // allows sharing of images as attachments.
- // value in this case should be a URI of a file
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && valueStr.startsWith("file://"))
- {
- Uri uriOfStream = remapUriWithFileProvider(valueStr, callbackContext);
- if (uriOfStream != null)
- i.putExtra(key, uriOfStream);
- }
- else
- {
- //final CordovaResourceApi resourceApi = webView.getResourceApi();
- i.putExtra(key, resourceApi.remapUri(Uri.parse(valueStr)));
- }
- } else if (key.equals(Intent.EXTRA_EMAIL)) {
- // allows to add the email address of the receiver
- i.putExtra(Intent.EXTRA_EMAIL, new String[] { valueStr });
- } else {
- if (value instanceof Boolean) {
- i.putExtra(key, Boolean.valueOf(valueStr));
- } else if(value instanceof Integer) {
- i.putExtra(key, Integer.valueOf(valueStr));
- } else if(value instanceof Long) {
- i.putExtra(key, Long.valueOf(valueStr));
- } else if(value instanceof Double) {
- i.putExtra(key, Double.valueOf(valueStr));
- } else {
- i.putExtra(key, valueStr);
- }
- }
- }
-
- i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- return i;
- }
-
- @Override
- public void onNewIntent(Intent intent) {
- if (this.onNewIntentCallbackContext != null) {
- fireOnNewIntent(intent);
- }
- else {
- // save the intent for use when onIntent action is called in the execute method
- this.deferredIntent = intent;
- }
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent intent)
- {
- super.onActivityResult(requestCode, resultCode, intent);
- if (onActivityResultCallbackContext != null && intent != null)
- {
- intent.putExtra("requestCode", requestCode);
- intent.putExtra("resultCode", resultCode);
- PluginResult result = new PluginResult(PluginResult.Status.OK, getIntentJson(intent));
- result.setKeepCallback(true);
- onActivityResultCallbackContext.sendPluginResult(result);
- }
- else if (onActivityResultCallbackContext != null)
- {
- Intent canceledIntent = new Intent();
- canceledIntent.putExtra("requestCode", requestCode);
- canceledIntent.putExtra("resultCode", resultCode);
- PluginResult canceledResult = new PluginResult(PluginResult.Status.OK, getIntentJson(canceledIntent));
- canceledResult.setKeepCallback(true);
- onActivityResultCallbackContext.sendPluginResult(canceledResult);
- }
-
- }
-
- private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (onBroadcastCallbackContext != null)
- {
- PluginResult result = new PluginResult(PluginResult.Status.OK, getIntentJson(intent));
- result.setKeepCallback(true);
- onBroadcastCallbackContext.sendPluginResult(result);
- }
- }
- };
-
- /**
- * Sends the provided Intent to the onNewIntentCallbackContext.
- *
- * @param intent This is the intent to send to the JS layer.
- */
- private void fireOnNewIntent(Intent intent) {
- PluginResult result = new PluginResult(PluginResult.Status.OK, getIntentJson(intent));
- result.setKeepCallback(true);
- this.onNewIntentCallbackContext.sendPluginResult(result);
- }
-
- /**
- * Return JSON representation of intent attributes
- *
- * @param intent
- * Credit: https://github.com/napolitano/cordova-plugin-intent
- */
- private JSONObject getIntentJson(Intent intent) {
- JSONObject intentJSON = null;
- ClipData clipData = null;
- JSONObject[] items = null;
- ContentResolver cR = this.cordova.getActivity().getApplicationContext().getContentResolver();
- MimeTypeMap mime = MimeTypeMap.getSingleton();
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- clipData = intent.getClipData();
- if(clipData != null) {
- int clipItemCount = clipData.getItemCount();
- items = new JSONObject[clipItemCount];
-
- for (int i = 0; i < clipItemCount; i++) {
-
- ClipData.Item item = clipData.getItemAt(i);
-
- try {
- items[i] = new JSONObject();
- items[i].put("htmlText", item.getHtmlText());
- items[i].put("intent", item.getIntent());
- items[i].put("text", item.getText());
- items[i].put("uri", item.getUri());
-
- if (item.getUri() != null) {
- String type = cR.getType(item.getUri());
- String extension = mime.getExtensionFromMimeType(cR.getType(item.getUri()));
-
- items[i].put("type", type);
- items[i].put("extension", extension);
- }
-
- } catch (JSONException e) {
- Log.d(LOG_TAG, " Error thrown during intent > JSON conversion");
- Log.d(LOG_TAG, e.getMessage());
- Log.d(LOG_TAG, Arrays.toString(e.getStackTrace()));
- }
-
- }
- }
- }
-
- try {
- intentJSON = new JSONObject();
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- if(items != null) {
- intentJSON.put("clipItems", new JSONArray(items));
- }
- }
-
- intentJSON.put("type", intent.getType());
- intentJSON.put("extras", toJsonObject(intent.getExtras()));
- intentJSON.put("action", intent.getAction());
- intentJSON.put("categories", intent.getCategories());
- intentJSON.put("flags", intent.getFlags());
- intentJSON.put("component", intent.getComponent());
- intentJSON.put("data", intent.getData());
- intentJSON.put("package", intent.getPackage());
-
- return intentJSON;
- } catch (JSONException e) {
- Log.d(LOG_TAG, " Error thrown during intent > JSON conversion");
- Log.d(LOG_TAG, e.getMessage());
- Log.d(LOG_TAG, Arrays.toString(e.getStackTrace()));
-
- return null;
- }
- }
-
- private static JSONObject toJsonObject(Bundle bundle) {
- // Credit: https://github.com/napolitano/cordova-plugin-intent
- try {
- return (JSONObject) toJsonValue(bundle);
- } catch (JSONException e) {
- throw new IllegalArgumentException("Cannot convert bundle to JSON: " + e.getMessage(), e);
- }
- }
-
- private static Object toJsonValue(final Object value) throws JSONException {
- // Credit: https://github.com/napolitano/cordova-plugin-intent
- if (value == null) {
- return null;
- } else if (value instanceof Bundle) {
- final Bundle bundle = (Bundle) value;
- final JSONObject result = new JSONObject();
- for (final String key : bundle.keySet()) {
- result.put(key, toJsonValue(bundle.get(key)));
- }
- return result;
- } else if ((value.getClass().isArray())) {
- final JSONArray result = new JSONArray();
- int length = Array.getLength(value);
- for (int i = 0; i < length; ++i) {
- result.put(i, toJsonValue(Array.get(value, i)));
- }
- return result;
- }
- else if (value instanceof ArrayList>) {
- final ArrayList arrayList = (ArrayList>)value;
- final JSONArray result = new JSONArray();
- for (int i = 0; i < arrayList.size(); i++)
- result.put(toJsonValue(arrayList.get(i)));
- return result;
- }
- else if (
- value instanceof String
- || value instanceof Boolean
- || value instanceof Integer
- || value instanceof Long
- || value instanceof Double) {
- return value;
- } else {
- return String.valueOf(value);
- }
- }
-
- private Bundle toBundle(final JSONObject obj) {
- Bundle returnBundle = new Bundle();
- if (obj == null) {
- return null;
- }
- try {
- Iterator> keys = obj.keys();
- while(keys.hasNext())
- {
- String key = (String)keys.next();
- Object compare = obj.get(key);
- if (obj.get(key) instanceof String)
- returnBundle.putString(key, obj.getString(key));
- else if (obj.get(key) instanceof Boolean)
- returnBundle.putBoolean(key, obj.getBoolean(key));
- else if (obj.get(key) instanceof Integer)
- returnBundle.putInt(key, obj.getInt(key));
- else if (obj.get(key) instanceof Long)
- returnBundle.putLong(key, obj.getLong(key));
- else if (obj.get(key) instanceof Double)
- returnBundle.putDouble(key, obj.getDouble(key));
- else if (obj.get(key).getClass().isArray() || obj.get(key) instanceof JSONArray)
- {
- JSONArray jsonArray = obj.getJSONArray(key);
- int length = jsonArray.length();
- if (jsonArray.get(0) instanceof String)
- {
- String[] stringArray = new String[length];
- for (int j = 0; j < length; j++)
- stringArray[j] = jsonArray.getString(j);
- returnBundle.putStringArray(key, stringArray);
- //returnBundle.putParcelableArray(key, obj.get);
- }
- else
- {
- Bundle[] bundleArray = new Bundle[length];
- for (int k = 0; k < length ; k++)
- bundleArray[k] = toBundle(jsonArray.getJSONObject(k));
- returnBundle.putParcelableArray(key, bundleArray);
- }
- }
- else if (obj.get(key) instanceof JSONObject)
- returnBundle.putBundle(key, toBundle((JSONObject)obj.get(key)));
- }
- }
- catch (JSONException e) {
- e.printStackTrace();
- }
-
-
- return returnBundle;
- }
-}
diff --git a/platforms/android/app/src/main/java/com/ferdinandsilva/android/ShareContentPlugin.java b/platforms/android/app/src/main/java/com/ferdinandsilva/android/ShareContentPlugin.java
deleted file mode 100644
index b8320cc..0000000
--- a/platforms/android/app/src/main/java/com/ferdinandsilva/android/ShareContentPlugin.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.ferdinandsilva.android;
-
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ContentValues;
-import android.net.Uri;
-import android.app.Activity;
-import android.telephony.SmsManager;
-
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaInterface;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public class ShareContentPlugin extends CordovaPlugin {
- public static final String TAG = "ShareContentPlugin";
-
- public static Context thisContext;
-
- public ShareContentPlugin() {
- }
-
- public void initialize(CordovaInterface cordova, CordovaWebView webView) {
- super.initialize(cordova, webView);
- ShareContentPlugin.thisContext = cordova.getActivity().getApplicationContext();
- }
-
- public void share(String text_to_share, CallbackContext callbackContext) {
-
- Intent shareIntent = new Intent();
- shareIntent.setAction(Intent.ACTION_SEND);
- shareIntent.putExtra(Intent.EXTRA_TEXT, text_to_share);
- shareIntent.setType("text/plain");
- shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- ShareContentPlugin.thisContext.startActivity(shareIntent);
- callbackContext.success(text_to_share);
- }
-
- public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
-
- if ("share".equals(action)) {
- share(args.get(0).toString(), callbackContext);
- } else {
- return false;
- }
-
- return true;
- }
-
-}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/java/com/hiddentao/cordova/filepath/FilePath.java b/platforms/android/app/src/main/java/com/hiddentao/cordova/filepath/FilePath.java
deleted file mode 100644
index 4ad84b5..0000000
--- a/platforms/android/app/src/main/java/com/hiddentao/cordova/filepath/FilePath.java
+++ /dev/null
@@ -1,435 +0,0 @@
-package com.hiddentao.cordova.filepath;
-
-
-import android.Manifest;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.provider.OpenableColumns;
-import android.util.Log;
-import android.database.Cursor;
-import android.os.Build;
-import android.os.Environment;
-import android.provider.DocumentsContract;
-import android.provider.MediaStore;
-import android.support.v4.app.ActivityCompat;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.PermissionHelper;
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.json.JSONException;
-
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.util.List;
-import java.io.File;
-
-public class FilePath extends CordovaPlugin {
-
- private static final String TAG = "[FilePath plugin]: ";
-
- private static final int INVALID_ACTION_ERROR_CODE = -1;
-
- private static final int GET_PATH_ERROR_CODE = 0;
- private static final String GET_PATH_ERROR_ID = null;
-
- private static final int GET_CLOUD_PATH_ERROR_CODE = 1;
- private static final String GET_CLOUD_PATH_ERROR_ID = "cloud";
-
- private static final int RC_READ_EXTERNAL_STORAGE = 5;
-
- private static CallbackContext callback;
- private static String uriStr;
-
- public static final int READ_REQ_CODE = 0;
-
- public static final String READ = Manifest.permission.READ_EXTERNAL_STORAGE;
-
- protected void getReadPermission(int requestCode) {
- PermissionHelper.requestPermission(this, requestCode, READ);
- }
-
- public void initialize(CordovaInterface cordova, final CordovaWebView webView) {
- super.initialize(cordova, webView);
- }
-
- /**
- * Executes the request and returns PluginResult.
- *
- * @param action The action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param callbackContext The callback context through which to return stuff to caller.
- * @return A PluginResult object with a status and message.
- */
- @Override
- public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
- this.callback = callbackContext;
- this.uriStr = args.getString(0);
-
- if (action.equals("resolveNativePath")) {
- if (PermissionHelper.hasPermission(this, READ)) {
- resolveNativePath();
- }
- else {
- getReadPermission(READ_REQ_CODE);
- }
-
- return true;
- }
- else {
- JSONObject resultObj = new JSONObject();
-
- resultObj.put("code", INVALID_ACTION_ERROR_CODE);
- resultObj.put("message", "Invalid action.");
-
- callbackContext.error(resultObj);
- }
-
- return false;
- }
-
- public void resolveNativePath() throws JSONException {
- JSONObject resultObj = new JSONObject();
- /* content:///... */
- Uri pvUrl = Uri.parse(this.uriStr);
-
- Log.d(TAG, "URI: " + this.uriStr);
-
- Context appContext = this.cordova.getActivity().getApplicationContext();
- String filePath = getPath(appContext, pvUrl);
-
- //check result; send error/success callback
- if (filePath == GET_PATH_ERROR_ID) {
- resultObj.put("code", GET_PATH_ERROR_CODE);
- resultObj.put("message", "Unable to resolve filesystem path.");
-
- this.callback.error(resultObj);
- }
- else if (filePath.equals(GET_CLOUD_PATH_ERROR_ID)) {
- resultObj.put("code", GET_CLOUD_PATH_ERROR_CODE);
- resultObj.put("message", "Files from cloud cannot be resolved to filesystem, download is required.");
-
- this.callback.error(resultObj);
- }
- else {
- Log.d(TAG, "Filepath: " + filePath);
-
- this.callback.success("file://" + filePath);
- }
- }
-
- public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException {
- for (int r:grantResults) {
- if (r == PackageManager.PERMISSION_DENIED) {
- JSONObject resultObj = new JSONObject();
- resultObj.put("code", 3);
- resultObj.put("message", "Filesystem permission was denied.");
-
- this.callback.error(resultObj);
- return;
- }
- }
-
- if (requestCode == READ_REQ_CODE) {
- resolveNativePath();
- }
- }
-
-
- /**
- * @param uri The Uri to check.
- * @return Whether the Uri authority is ExternalStorageProvider.
- */
- private static boolean isExternalStorageDocument(Uri uri) {
- return "com.android.externalstorage.documents".equals(uri.getAuthority());
- }
-
- /**
- * @param uri The Uri to check.
- * @return Whether the Uri authority is DownloadsProvider.
- */
- private static boolean isDownloadsDocument(Uri uri) {
- return "com.android.providers.downloads.documents".equals(uri.getAuthority());
- }
-
- /**
- * @param uri The Uri to check.
- * @return Whether the Uri authority is MediaProvider.
- */
- private static boolean isMediaDocument(Uri uri) {
- return "com.android.providers.media.documents".equals(uri.getAuthority());
- }
-
- /**
- * @param uri The Uri to check.
- * @return Whether the Uri authority is Google Photos.
- */
- private static boolean isGooglePhotosUri(Uri uri) {
- return ("com.google.android.apps.photos.content".equals(uri.getAuthority())
- || "com.google.android.apps.photos.contentprovider".equals(uri.getAuthority()));
- }
-
- /**
- * @param uri The Uri to check.
- * @return Whether the Uri authority is Google Drive.
- */
- private static boolean isGoogleDriveUri(Uri uri) {
- return "com.google.android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.android.apps.docs.storage.legacy".equals(uri.getAuthority());
- }
-
- /**
- * Get the value of the data column for this Uri. This is useful for
- * MediaStore Uris, and other file-based ContentProviders.
- *
- * @param context The context.
- * @param uri The Uri to query.
- * @param selection (Optional) Filter used in the query.
- * @param selectionArgs (Optional) Selection arguments used in the query.
- * @return The value of the _data column, which is typically a file path.
- */
- private static String getDataColumn(Context context, Uri uri, String selection,
- String[] selectionArgs) {
-
- Cursor cursor = null;
- final String column = "_data";
- final String[] projection = {
- column
- };
-
- try {
- cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
- null);
- if (cursor != null && cursor.moveToFirst()) {
- final int column_index = cursor.getColumnIndexOrThrow(column);
- return cursor.getString(column_index);
- }
- } finally {
- if (cursor != null)
- cursor.close();
- }
- return null;
- }
-
- /**
- * Get content:// from segment list
- * In the new Uri Authority of Google Photos, the last segment is not the content:// anymore
- * So let's iterate through all segments and find the content uri!
- *
- * @param segments The list of segment
- */
- private static String getContentFromSegments(List segments) {
- String contentPath = "";
-
- for(String item : segments) {
- if (item.startsWith("content://")) {
- contentPath = item;
- break;
- }
- }
-
- return contentPath;
- }
-
- /**
- * Check if a file exists on device
- *
- * @param filePath The absolute file path
- */
- private static boolean fileExists(String filePath) {
- File file = new File(filePath);
-
- return file.exists();
- }
-
- /**
- * Get full file path from external storage
- *
- * @param pathData The storage type and the relative path
- */
- private static String getPathFromExtSD(String[] pathData) {
- final String type = pathData[0];
- final String relativePath = "/" + pathData[1];
- String fullPath = "";
-
- // on my Sony devices (4.4.4 & 5.1.1), `type` is a dynamic string
- // something like "71F8-2C0A", some kind of unique id per storage
- // don't know any API that can get the root path of that storage based on its id.
- //
- // so no "primary" type, but let the check here for other devices
- if ("primary".equalsIgnoreCase(type)) {
- fullPath = Environment.getExternalStorageDirectory() + relativePath;
- if (fileExists(fullPath)) {
- return fullPath;
- }
- }
-
- // Environment.isExternalStorageRemovable() is `true` for external and internal storage
- // so we cannot relay on it.
- //
- // instead, for each possible path, check if file exists
- // we'll start with secondary storage as this could be our (physically) removable sd card
- fullPath = System.getenv("SECONDARY_STORAGE") + relativePath;
- if (fileExists(fullPath)) {
- return fullPath;
- }
-
- fullPath = System.getenv("EXTERNAL_STORAGE") + relativePath;
- if (fileExists(fullPath)) {
- return fullPath;
- }
-
- return fullPath;
- }
-
- /**
- * Get a file path from a Uri. This will get the the path for Storage Access
- * Framework Documents, as well as the _data field for the MediaStore and
- * other file-based ContentProviders.
- *
- * Callers should check whether the path is local before assuming it
- * represents a local file.
- *
- * @param context The context.
- * @param uri The Uri to query.
- */
- private static String getPath(final Context context, final Uri uri) {
-
- Log.d(TAG, "File - " +
- "Authority: " + uri.getAuthority() +
- ", Fragment: " + uri.getFragment() +
- ", Port: " + uri.getPort() +
- ", Query: " + uri.getQuery() +
- ", Scheme: " + uri.getScheme() +
- ", Host: " + uri.getHost() +
- ", Segments: " + uri.getPathSegments().toString()
- );
-
- final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
-
- // DocumentProvider
- if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
- // ExternalStorageProvider
- if (isExternalStorageDocument(uri)) {
- final String docId = DocumentsContract.getDocumentId(uri);
- final String[] split = docId.split(":");
- final String type = split[0];
-
- String fullPath = getPathFromExtSD(split);
- if (fullPath != "") {
- return fullPath;
- }
- else {
- return null;
- }
- }
- // DownloadsProvider
- else if (isDownloadsDocument(uri)) {
- final String id = DocumentsContract.getDocumentId(uri);
- try {
- final Uri contentUri = ContentUris.withAppendedId(
- Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
-
- return getDataColumn(context, contentUri, null, null);
- } catch(NumberFormatException e) {
- //In Android 8 and Android P the id is not a number
- return uri.getPath().replaceFirst("^/document/raw:", "").replaceFirst("^raw:", "");
- }
- }
- // MediaProvider
- else if (isMediaDocument(uri)) {
- final String docId = DocumentsContract.getDocumentId(uri);
- final String[] split = docId.split(":");
- final String type = split[0];
-
- Uri contentUri = null;
- if ("image".equals(type)) {
- contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
- } else if ("video".equals(type)) {
- contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
- } else if ("audio".equals(type)) {
- contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
- }
-
- final String selection = "_id=?";
- final String[] selectionArgs = new String[] {
- split[1]
- };
-
- return getDataColumn(context, contentUri, selection, selectionArgs);
- }
- else if(isGoogleDriveUri(uri)){
- return getDriveFilePath(uri,context);
- }
- }
- // MediaStore (and general)
- else if ("content".equalsIgnoreCase(uri.getScheme())) {
-
- // Return the remote address
- if (isGooglePhotosUri(uri)) {
- String contentPath = getContentFromSegments(uri.getPathSegments());
- if (contentPath != "") {
- return getPath(context, Uri.parse(contentPath));
- }
- else {
- return null;
- }
- }
-
- if(isGoogleDriveUri(uri)){
- return getDriveFilePath(uri,context);
- }
-
- return getDataColumn(context, uri, null, null);
- }
- // File
- else if ("file".equalsIgnoreCase(uri.getScheme())) {
- return uri.getPath();
- }
-
- return null;
- }
-
- private static String getDriveFilePath(Uri uri,Context context){
- Uri returnUri =uri;
- Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
- /*
- * Get the column indexes of the data in the Cursor,
- * * move to the first row in the Cursor, get the data,
- * * and display it.
- * */
- int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
- int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
- returnCursor.moveToFirst();
- String name = (returnCursor.getString(nameIndex));
- String size = (Long.toString(returnCursor.getLong(sizeIndex)));
- File file = new File(context.getCacheDir(),name);
- try {
- InputStream inputStream = context.getContentResolver().openInputStream(uri);
- FileOutputStream outputStream = new FileOutputStream(file);
- int read = 0;
- int maxBufferSize = 1 * 1024 * 1024;
- int bytesAvailable = inputStream.available();
-
- //int bufferSize = 1024;
- int bufferSize = Math.min(bytesAvailable, maxBufferSize);
-
- final byte[] buffers = new byte[bufferSize];
- while ((read = inputStream.read(buffers)) != -1) {
- outputStream.write(buffers, 0, read);
- }
- Log.e("File Size","Size " + file.length());
- inputStream.close();
- outputStream.close();
- Log.e("File Path","Path " + file.getPath());
- Log.e("File Size","Size " + file.length());
- }catch (Exception e){
- Log.e("Exception",e.getMessage());
- }
- return file.getPath();
- }
-}
diff --git a/platforms/android/app/src/main/java/com/megster/cordova/FileChooser.java b/platforms/android/app/src/main/java/com/megster/cordova/FileChooser.java
deleted file mode 100644
index 087b540..0000000
--- a/platforms/android/app/src/main/java/com/megster/cordova/FileChooser.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.megster.cordova;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.util.Log;
-
-import org.apache.cordova.CordovaArgs;
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.PluginResult;
-import org.json.JSONException;
-
-public class FileChooser extends CordovaPlugin {
-
- private static final String TAG = "FileChooser";
- private static final String ACTION_OPEN = "open";
- private static final int PICK_FILE_REQUEST = 1;
- CallbackContext callback;
-
- @Override
- public boolean execute(String action, CordovaArgs args, CallbackContext callbackContext) throws JSONException {
-
- if (action.equals(ACTION_OPEN)) {
- chooseFile(callbackContext);
- return true;
- }
-
- return false;
- }
-
- public void chooseFile(CallbackContext callbackContext) {
-
- // type and title should be configurable
-
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.setType("*/*");
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
-
- Intent chooser = Intent.createChooser(intent, "Select File");
- cordova.startActivityForResult(this, chooser, PICK_FILE_REQUEST);
-
- PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
- pluginResult.setKeepCallback(true);
- callback = callbackContext;
- callbackContext.sendPluginResult(pluginResult);
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
-
- if (requestCode == PICK_FILE_REQUEST && callback != null) {
-
- if (resultCode == Activity.RESULT_OK) {
-
- Uri uri = data.getData();
-
- if (uri != null) {
-
- Log.w(TAG, uri.toString());
- callback.success(uri.toString());
-
- } else {
-
- callback.error("File uri was null");
-
- }
-
- } else if (resultCode == Activity.RESULT_CANCELED) {
-
- // TODO NO_RESULT or error callback?
- PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
- callback.sendPluginResult(pluginResult);
-
- } else {
-
- callback.error(resultCode);
- }
- }
- }
-}
diff --git a/platforms/android/app/src/main/java/com/monkeystew/goober_m/MainActivity.java b/platforms/android/app/src/main/java/com/monkeystew/goober_m/MainActivity.java
deleted file mode 100644
index d1d6b7c..0000000
--- a/platforms/android/app/src/main/java/com/monkeystew/goober_m/MainActivity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-package com.monkeystew.goober_m;
-
-import android.os.Bundle;
-import org.apache.cordova.*;
-
-public class MainActivity extends CordovaActivity
-{
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
-
- // enable Cordova apps to be started in the background
- Bundle extras = getIntent().getExtras();
- if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
- moveTaskToBack(true);
- }
-
- // Set by in config.xml
- loadUrl(launchUrl);
- }
-}
diff --git a/platforms/android/app/src/main/java/io/sqlc/SQLiteAndroidDatabase.java b/platforms/android/app/src/main/java/io/sqlc/SQLiteAndroidDatabase.java
deleted file mode 100644
index 6540f86..0000000
--- a/platforms/android/app/src/main/java/io/sqlc/SQLiteAndroidDatabase.java
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- * Copyright (c) 2012-present Christopher J. Brody (aka Chris Brody)
- * Copyright (c) 2005-2010, Nitobi Software Inc.
- * Copyright (c) 2010, IBM Corporation
- */
-
-package io.sqlc;
-
-import android.annotation.SuppressLint;
-
-import android.database.Cursor;
-import android.database.CursorWindow;
-
-import android.database.sqlite.SQLiteConstraintException;
-import android.database.sqlite.SQLiteCursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
-import android.database.sqlite.SQLiteStatement;
-
-import android.util.Log;
-
-import java.io.File;
-
-import java.lang.IllegalArgumentException;
-import java.lang.Number;
-
-import java.util.Locale;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.cordova.CallbackContext;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * Android Database helper class
- */
-class SQLiteAndroidDatabase
-{
- private static final Pattern FIRST_WORD = Pattern.compile("^[\\s;]*([^\\s;]+)",
- Pattern.CASE_INSENSITIVE);
-
- private static final Pattern WHERE_CLAUSE = Pattern.compile("\\s+WHERE\\s+(.+)$",
- Pattern.CASE_INSENSITIVE);
-
- private static final Pattern UPDATE_TABLE_NAME = Pattern.compile("^\\s*UPDATE\\s+(\\S+)",
- Pattern.CASE_INSENSITIVE);
-
- private static final Pattern DELETE_TABLE_NAME = Pattern.compile("^\\s*DELETE\\s+FROM\\s+(\\S+)",
- Pattern.CASE_INSENSITIVE);
-
- private static final boolean isPostHoneycomb = android.os.Build.VERSION.SDK_INT >= 11;
-
- File dbFile;
-
- SQLiteDatabase mydb;
-
- boolean isTransactionActive = false;
-
- /**
- * NOTE: Using default constructor, no explicit constructor.
- */
-
- /**
- * Open a database.
- *
- * @param dbfile The database File specification
- */
- void open(File dbfile) throws Exception {
- dbFile = dbfile; // for possible bug workaround
- mydb = SQLiteDatabase.openOrCreateDatabase(dbfile, null);
- }
-
- /**
- * Close a database (in the current thread).
- */
- void closeDatabaseNow() {
- if (mydb != null) {
- if (isTransactionActive) {
- mydb.endTransaction();
- isTransactionActive = false;
- }
- mydb.close();
- mydb = null;
- }
- }
-
- void bugWorkaround() throws Exception {
- this.closeDatabaseNow();
- this.open(dbFile);
- }
-
- /**
- * Executes a batch request and sends the results via cbc.
- *
- * @param queryarr Array of query strings
- * @param jsonparamsArr Array of JSON query parameters
- * @param cbc Callback context from Cordova API
- */
- void executeSqlBatch(String[] queryarr, JSONArray[] jsonparamsArr, CallbackContext cbc) {
-
- if (mydb == null) {
- // not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database
- // (internal plugin error)
- cbc.error("INTERNAL PLUGIN ERROR: database not open");
- return;
- }
-
- int len = queryarr.length;
- JSONArray batchResults = new JSONArray();
-
- for (int i = 0; i < len; i++) {
- executeSqlBatchStatement(queryarr[i], jsonparamsArr[i], batchResults);
- }
-
- cbc.success(batchResults);
- }
-
- @SuppressLint("NewApi")
- private void executeSqlBatchStatement(String query, JSONArray json_params, JSONArray batchResults) {
-
- if (mydb == null) {
- // Should not happen here
- return;
-
- } else {
-
- int rowsAffectedCompat = 0;
- boolean needRowsAffectedCompat = false;
-
- JSONObject queryResult = null;
-
- String errorMessage = "unknown";
- int code = 0; // SQLException.UNKNOWN_ERR
-
- try {
- boolean needRawQuery = true;
-
- //Log.v("executeSqlBatch", "get query type");
- QueryType queryType = getQueryType(query);
- //Log.v("executeSqlBatch", "query type: " + queryType);
-
- if (queryType == QueryType.update || queryType == queryType.delete) {
- if (isPostHoneycomb) {
- SQLiteStatement myStatement = mydb.compileStatement(query);
-
- if (json_params != null) {
- bindArgsToStatement(myStatement, json_params);
- }
-
- int rowsAffected = -1; // (assuming invalid)
-
- // Use try & catch just in case android.os.Build.VERSION.SDK_INT >= 11 is lying:
- // (Catch SQLiteException here to avoid extra retry)
- try {
- rowsAffected = myStatement.executeUpdateDelete();
- // Indicate valid results:
- needRawQuery = false;
- } catch (SQLiteConstraintException ex) {
- // Indicate problem & stop this query:
- ex.printStackTrace();
- errorMessage = "constraint failure: " + ex.getMessage();
- code = 6; // SQLException.CONSTRAINT_ERR
- Log.v("executeSqlBatch", "SQLiteStatement.executeUpdateDelete(): Error=" + errorMessage);
- needRawQuery = false;
- } catch (SQLiteException ex) {
- // Indicate problem & stop this query:
- ex.printStackTrace();
- errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLiteStatement.executeUpdateDelete(): Error=" + errorMessage);
- needRawQuery = false;
- } catch (Exception ex) {
- // Assuming SDK_INT was lying & method not found:
- // do nothing here & try again with raw query.
- ex.printStackTrace();
- Log.v("executeSqlBatch", "SQLiteStatement.executeUpdateDelete(): runtime error (fallback to old API): " + errorMessage);
- }
-
- // "finally" cleanup myStatement
- myStatement.close();
-
- if (rowsAffected != -1) {
- queryResult = new JSONObject();
- queryResult.put("rowsAffected", rowsAffected);
- }
- }
-
- if (needRawQuery) { // for pre-honeycomb behavior
- rowsAffectedCompat = countRowsAffectedCompat(queryType, query, json_params, mydb);
- needRowsAffectedCompat = true;
- }
- }
-
- // INSERT:
- if (queryType == QueryType.insert && json_params != null) {
- needRawQuery = false;
-
- SQLiteStatement myStatement = mydb.compileStatement(query);
-
- bindArgsToStatement(myStatement, json_params);
-
- long insertId = -1; // (invalid)
-
- try {
- insertId = myStatement.executeInsert();
-
- // statement has finished with no constraint violation:
- queryResult = new JSONObject();
- if (insertId != -1) {
- queryResult.put("insertId", insertId);
- queryResult.put("rowsAffected", 1);
- } else {
- queryResult.put("rowsAffected", 0);
- }
- } catch (SQLiteConstraintException ex) {
- // report constraint violation error result with the error message
- ex.printStackTrace();
- errorMessage = "constraint failure: " + ex.getMessage();
- code = 6; // SQLException.CONSTRAINT_ERR
- Log.v("executeSqlBatch", "SQLiteDatabase.executeInsert(): Error=" + errorMessage);
- } catch (SQLiteException ex) {
- // report some other error result with the error message
- ex.printStackTrace();
- errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLiteDatabase.executeInsert(): Error=" + errorMessage);
- }
-
- // "finally" cleanup myStatement
- myStatement.close();
- }
-
- if (queryType == QueryType.begin) {
- needRawQuery = false;
- try {
- mydb.beginTransaction();
- isTransactionActive = true;
-
- queryResult = new JSONObject();
- queryResult.put("rowsAffected", 0);
- } catch (SQLiteException ex) {
- ex.printStackTrace();
- errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLiteDatabase.beginTransaction(): Error=" + errorMessage);
- }
- }
-
- if (queryType == QueryType.commit) {
- needRawQuery = false;
- try {
- mydb.setTransactionSuccessful();
- mydb.endTransaction();
- isTransactionActive = false;
-
- queryResult = new JSONObject();
- queryResult.put("rowsAffected", 0);
- } catch (SQLiteException ex) {
- ex.printStackTrace();
- errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLiteDatabase.setTransactionSuccessful/endTransaction(): Error=" + errorMessage);
- }
- }
-
- if (queryType == QueryType.rollback) {
- needRawQuery = false;
- try {
- mydb.endTransaction();
- isTransactionActive = false;
-
- queryResult = new JSONObject();
- queryResult.put("rowsAffected", 0);
- } catch (SQLiteException ex) {
- ex.printStackTrace();
- errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLiteDatabase.endTransaction(): Error=" + errorMessage);
- }
- }
-
- // raw query for other statements:
- if (needRawQuery) {
- try {
- queryResult = this.executeSqlStatementQuery(mydb, query, json_params);
-
- } catch (SQLiteConstraintException ex) {
- // report constraint violation error result with the error message
- ex.printStackTrace();
- errorMessage = "constraint failure: " + ex.getMessage();
- code = 6; // SQLException.CONSTRAINT_ERR
- Log.v("executeSqlBatch", "Raw query error=" + errorMessage);
- } catch (SQLiteException ex) {
- // report some other error result with the error message
- ex.printStackTrace();
- errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "Raw query error=" + errorMessage);
- }
-
- if (needRowsAffectedCompat) {
- queryResult.put("rowsAffected", rowsAffectedCompat);
- }
- }
- } catch (Exception ex) {
- ex.printStackTrace();
- errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLiteAndroidDatabase.executeSql[Batch](): Error=" + errorMessage);
- }
-
- try {
- if (queryResult != null) {
- JSONObject r = new JSONObject();
-
- r.put("type", "success");
- r.put("result", queryResult);
-
- batchResults.put(r);
- } else {
- JSONObject r = new JSONObject();
- r.put("type", "error");
-
- JSONObject er = new JSONObject();
- er.put("message", errorMessage);
- er.put("code", code);
- r.put("result", er);
-
- batchResults.put(r);
- }
- } catch (JSONException ex) {
- ex.printStackTrace();
- Log.v("executeSqlBatch", "SQLiteAndroidDatabase.executeSql[Batch](): Error=" + ex.getMessage());
- // TODO what to do?
- }
- }
- }
-
- private final int countRowsAffectedCompat(QueryType queryType, String query, JSONArray json_params,
- SQLiteDatabase mydb) throws JSONException {
- // quick and dirty way to calculate the rowsAffected in pre-Honeycomb. just do a SELECT
- // beforehand using the same WHERE clause. might not be perfect, but it's better than nothing
- Matcher whereMatcher = WHERE_CLAUSE.matcher(query);
-
- String where = "";
-
- int pos = 0;
- while (whereMatcher.find(pos)) {
- where = " WHERE " + whereMatcher.group(1);
- pos = whereMatcher.start(1);
- }
- // WHERE clause may be omitted, and also be sure to find the last one,
- // e.g. for cases where there's a subquery
-
- // bindings may be in the update clause, so only take the last n
- int numQuestionMarks = 0;
- for (int j = 0; j < where.length(); j++) {
- if (where.charAt(j) == '?') {
- numQuestionMarks++;
- }
- }
-
- JSONArray subParams = null;
-
- if (json_params != null) {
- // only take the last n of every array of sqlArgs
- JSONArray origArray = json_params;
- subParams = new JSONArray();
- int startPos = origArray.length() - numQuestionMarks;
- for (int j = startPos; j < origArray.length(); j++) {
- subParams.put(j - startPos, origArray.get(j));
- }
- }
-
- if (queryType == QueryType.update) {
- Matcher tableMatcher = UPDATE_TABLE_NAME.matcher(query);
- if (tableMatcher.find()) {
- String table = tableMatcher.group(1);
- try {
- SQLiteStatement statement = mydb.compileStatement(
- "SELECT count(*) FROM " + table + where);
-
- if (subParams != null) {
- bindArgsToStatement(statement, subParams);
- }
-
- return (int)statement.simpleQueryForLong();
- } catch (Exception e) {
- // assume we couldn't count for whatever reason, keep going
- Log.e(SQLiteAndroidDatabase.class.getSimpleName(), "uncaught", e);
- }
- }
- } else { // delete
- Matcher tableMatcher = DELETE_TABLE_NAME.matcher(query);
- if (tableMatcher.find()) {
- String table = tableMatcher.group(1);
- try {
- SQLiteStatement statement = mydb.compileStatement(
- "SELECT count(*) FROM " + table + where);
- bindArgsToStatement(statement, subParams);
-
- return (int)statement.simpleQueryForLong();
- } catch (Exception e) {
- // assume we couldn't count for whatever reason, keep going
- Log.e(SQLiteAndroidDatabase.class.getSimpleName(), "uncaught", e);
-
- }
- }
- }
-
- return 0;
- }
-
- private void bindArgsToStatement(SQLiteStatement myStatement, JSONArray sqlArgs) throws JSONException {
- for (int i = 0; i < sqlArgs.length(); i++) {
- if (sqlArgs.get(i) instanceof Float || sqlArgs.get(i) instanceof Double) {
- myStatement.bindDouble(i + 1, sqlArgs.getDouble(i));
- } else if (sqlArgs.get(i) instanceof Number) {
- myStatement.bindLong(i + 1, sqlArgs.getLong(i));
- } else if (sqlArgs.isNull(i)) {
- myStatement.bindNull(i + 1);
- } else {
- myStatement.bindString(i + 1, sqlArgs.getString(i));
- }
- }
- }
-
- /**
- * Get rows results from query cursor.
- *
- * @param cur Cursor into query results
- * @return results in string form
- */
- private JSONObject executeSqlStatementQuery(SQLiteDatabase mydb, String query,
- JSONArray paramsAsJson) throws Exception {
- JSONObject rowsResult = new JSONObject();
-
- Cursor cur = null;
- try {
- String[] params = null;
-
- params = new String[paramsAsJson.length()];
-
- for (int j = 0; j < paramsAsJson.length(); j++) {
- if (paramsAsJson.isNull(j))
- params[j] = "";
- else
- params[j] = paramsAsJson.getString(j);
- }
-
- cur = mydb.rawQuery(query, params);
- } catch (Exception ex) {
- ex.printStackTrace();
- String errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLiteAndroidDatabase.executeSql[Batch](): Error=" + errorMessage);
- throw ex;
- }
-
- // If query result has rows
- if (cur != null && cur.moveToFirst()) {
- JSONArray rowsArrayResult = new JSONArray();
- String key = "";
- int colCount = cur.getColumnCount();
-
- // Build up JSON result object for each row
- do {
- JSONObject row = new JSONObject();
- try {
- for (int i = 0; i < colCount; ++i) {
- key = cur.getColumnName(i);
-
- if (isPostHoneycomb) {
-
- // Use try & catch just in case android.os.Build.VERSION.SDK_INT >= 11 is lying:
- try {
- bindPostHoneycomb(row, key, cur, i);
- } catch (Exception ex) {
- bindPreHoneycomb(row, key, cur, i);
- }
- } else {
- bindPreHoneycomb(row, key, cur, i);
- }
- }
-
- rowsArrayResult.put(row);
-
- } catch (JSONException e) {
- e.printStackTrace();
- }
- } while (cur.moveToNext());
-
- try {
- rowsResult.put("rows", rowsArrayResult);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
-
- if (cur != null) {
- cur.close();
- }
-
- return rowsResult;
- }
-
- @SuppressLint("NewApi")
- private void bindPostHoneycomb(JSONObject row, String key, Cursor cur, int i) throws JSONException {
- int curType = cur.getType(i);
-
- switch (curType) {
- case Cursor.FIELD_TYPE_NULL:
- row.put(key, JSONObject.NULL);
- break;
- case Cursor.FIELD_TYPE_INTEGER:
- row.put(key, cur.getLong(i));
- break;
- case Cursor.FIELD_TYPE_FLOAT:
- row.put(key, cur.getDouble(i));
- break;
- case Cursor.FIELD_TYPE_STRING:
- default: /* (BLOB) */
- row.put(key, cur.getString(i));
- break;
- }
- }
-
- private void bindPreHoneycomb(JSONObject row, String key, Cursor cursor, int i) throws JSONException {
- // Since cursor.getType() is not available pre-honeycomb, this is
- // a workaround so we don't have to bind everything as a string
- // Details here: http://stackoverflow.com/q/11658239
- SQLiteCursor sqLiteCursor = (SQLiteCursor) cursor;
- CursorWindow cursorWindow = sqLiteCursor.getWindow();
- int pos = cursor.getPosition();
- if (cursorWindow.isNull(pos, i)) {
- row.put(key, JSONObject.NULL);
- } else if (cursorWindow.isLong(pos, i)) {
- row.put(key, cursor.getLong(i));
- } else if (cursorWindow.isFloat(pos, i)) {
- row.put(key, cursor.getDouble(i));
- } else {
- // STRING or BLOB:
- row.put(key, cursor.getString(i));
- }
- }
-
- static QueryType getQueryType(String query) {
- Matcher matcher = FIRST_WORD.matcher(query);
-
- // FIND & return query type, or throw:
- if (matcher.find()) {
- try {
- String first = matcher.group(1);
-
- // explictly reject if blank
- // (needed for SQLCipher version)
- if (first.length() == 0) throw new RuntimeException("query not found");
-
- return QueryType.valueOf(first.toLowerCase(Locale.ENGLISH));
- } catch (IllegalArgumentException ignore) {
- // unknown verb (NOT blank)
- return QueryType.other;
- }
- } else {
- // explictly reject if blank
- // (needed for SQLCipher version)
- throw new RuntimeException("query not found");
- }
- }
-
- static enum QueryType {
- update,
- insert,
- delete,
- select,
- begin,
- commit,
- rollback,
- other
- }
-} /* vim: set expandtab : */
diff --git a/platforms/android/app/src/main/java/io/sqlc/SQLiteConnectorDatabase.java b/platforms/android/app/src/main/java/io/sqlc/SQLiteConnectorDatabase.java
deleted file mode 100644
index e16e822..0000000
--- a/platforms/android/app/src/main/java/io/sqlc/SQLiteConnectorDatabase.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (c) 2012-present Christopher J. Brody (aka Chris Brody)
- * Copyright (c) 2005-2010, Nitobi Software Inc.
- * Copyright (c) 2010, IBM Corporation
- */
-
-package io.sqlc;
-
-import android.annotation.SuppressLint;
-
-import android.util.Log;
-
-import java.io.File;
-
-import java.lang.IllegalArgumentException;
-import java.lang.Number;
-
-import java.sql.SQLException;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.cordova.CallbackContext;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import io.liteglue.SQLCode;
-import io.liteglue.SQLColumnType;
-import io.liteglue.SQLiteConnector;
-import io.liteglue.SQLiteConnection;
-import io.liteglue.SQLiteOpenFlags;
-import io.liteglue.SQLiteStatement;
-
-/**
- * Android SQLite-Connector Database helper class
- */
-class SQLiteConnectorDatabase extends SQLiteAndroidDatabase
-{
- static SQLiteConnector connector = new SQLiteConnector();
-
- SQLiteConnection mydb;
-
- /**
- * NOTE: Using default constructor, no explicit constructor.
- */
-
-
- /**
- * Open a database.
- *
- * @param dbFile The database File specification
- */
- @Override
- void open(File dbFile) throws Exception {
- mydb = connector.newSQLiteConnection(dbFile.getAbsolutePath(),
- SQLiteOpenFlags.READWRITE | SQLiteOpenFlags.CREATE);
- }
-
- /**
- * Close a database (in the current thread).
- */
- @Override
- void closeDatabaseNow() {
- try {
- if (mydb != null)
- mydb.dispose();
- } catch (Exception e) {
- Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database, ignoring", e);
- }
- }
-
- /**
- * Ignore Android bug workaround for NDK version
- */
- @Override
- void bugWorkaround() { }
-
- /**
- * Executes a batch request and sends the results via cbc.
- *
- * @param dbname The name of the database.
- * @param queryarr Array of query strings
- * @param jsonparams Array of JSON query parameters
- * @param cbc Callback context from Cordova API
- */
- @Override
- void executeSqlBatch( String[] queryarr, JSONArray[] jsonparams, CallbackContext cbc) {
-
- if (mydb == null) {
- // not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database
- cbc.error("database has been closed");
- return;
- }
-
- int len = queryarr.length;
- JSONArray batchResults = new JSONArray();
-
- for (int i = 0; i < len; i++) {
- int rowsAffectedCompat = 0;
- boolean needRowsAffectedCompat = false;
-
- JSONObject queryResult = null;
-
- String errorMessage = "unknown";
- int sqliteErrorCode = -1;
- int code = 0; // SQLException.UNKNOWN_ERR
-
- try {
- String query = queryarr[i];
-
- long lastTotal = mydb.getTotalChanges();
- queryResult = this.executeSQLiteStatement(query, jsonparams[i], cbc);
- long newTotal = mydb.getTotalChanges();
- long rowsAffected = newTotal - lastTotal;
-
- queryResult.put("rowsAffected", rowsAffected);
- if (rowsAffected > 0) {
- long insertId = mydb.getLastInsertRowid();
- if (insertId > 0) {
- queryResult.put("insertId", insertId);
- }
- }
- } catch (SQLException ex) {
- ex.printStackTrace();
- sqliteErrorCode = ex.getErrorCode();
- errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): SQL Error code = " + sqliteErrorCode + " message = " + errorMessage);
-
- switch(sqliteErrorCode) {
- case SQLCode.ERROR:
- code = 5; // SQLException.SYNTAX_ERR
- break;
- case 13: // SQLITE_FULL
- code = 4; // SQLException.QUOTA_ERR
- break;
- case SQLCode.CONSTRAINT:
- code = 6; // SQLException.CONSTRAINT_ERR
- break;
- default:
- /* do nothing */
- }
- } catch (JSONException ex) {
- // NOT expected:
- ex.printStackTrace();
- errorMessage = ex.getMessage();
- code = 0; // SQLException.UNKNOWN_ERR
- Log.e("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): UNEXPECTED JSON Error=" + errorMessage);
- }
-
- try {
- if (queryResult != null) {
- JSONObject r = new JSONObject();
-
- r.put("type", "success");
- r.put("result", queryResult);
-
- batchResults.put(r);
- } else {
- JSONObject r = new JSONObject();
- r.put("type", "error");
-
- JSONObject er = new JSONObject();
- er.put("message", errorMessage);
- er.put("code", code);
- r.put("result", er);
-
- batchResults.put(r);
- }
- } catch (JSONException ex) {
- ex.printStackTrace();
- Log.e("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + ex.getMessage());
- // TODO what to do?
- }
- }
-
- cbc.success(batchResults);
- }
-
- /**
- * Get rows results from query cursor.
- *
- * @param cur Cursor into query results
- * @return results in string form
- */
- private JSONObject executeSQLiteStatement(String query, JSONArray paramsAsJson,
- CallbackContext cbc) throws JSONException, SQLException {
- JSONObject rowsResult = new JSONObject();
-
- boolean hasRows = false;
-
- SQLiteStatement myStatement = mydb.prepareStatement(query);
-
- try {
- String[] params = null;
-
- params = new String[paramsAsJson.length()];
-
- for (int i = 0; i < paramsAsJson.length(); ++i) {
- if (paramsAsJson.isNull(i)) {
- myStatement.bindNull(i + 1);
- } else {
- Object p = paramsAsJson.get(i);
- if (p instanceof Float || p instanceof Double)
- myStatement.bindDouble(i + 1, paramsAsJson.getDouble(i));
- else if (p instanceof Number)
- myStatement.bindLong(i + 1, paramsAsJson.getLong(i));
- else
- myStatement.bindTextNativeString(i + 1, paramsAsJson.getString(i));
- }
- }
-
- hasRows = myStatement.step();
- } catch (SQLException ex) {
- ex.printStackTrace();
- String errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + errorMessage);
-
- // cleanup statement and throw the exception:
- myStatement.dispose();
- throw ex;
- } catch (JSONException ex) {
- ex.printStackTrace();
- String errorMessage = ex.getMessage();
- Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + errorMessage);
-
- // cleanup statement and throw the exception:
- myStatement.dispose();
- throw ex;
- }
-
- // If query result has rows
- if (hasRows) {
- JSONArray rowsArrayResult = new JSONArray();
- String key = "";
- int colCount = myStatement.getColumnCount();
-
- // Build up JSON result object for each row
- do {
- JSONObject row = new JSONObject();
- try {
- for (int i = 0; i < colCount; ++i) {
- key = myStatement.getColumnName(i);
-
- switch (myStatement.getColumnType(i)) {
- case SQLColumnType.NULL:
- row.put(key, JSONObject.NULL);
- break;
-
- case SQLColumnType.REAL:
- row.put(key, myStatement.getColumnDouble(i));
- break;
-
- case SQLColumnType.INTEGER:
- row.put(key, myStatement.getColumnLong(i));
- break;
-
- case SQLColumnType.BLOB:
- case SQLColumnType.TEXT:
- default: // (just in case)
- row.put(key, myStatement.getColumnTextNativeString(i));
- }
-
- }
-
- rowsArrayResult.put(row);
-
- } catch (JSONException e) {
- e.printStackTrace();
- }
- } while (myStatement.step());
-
- try {
- rowsResult.put("rows", rowsArrayResult);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
-
- myStatement.dispose();
-
- return rowsResult;
- }
-
-} /* vim: set expandtab : */
diff --git a/platforms/android/app/src/main/java/io/sqlc/SQLitePlugin.java b/platforms/android/app/src/main/java/io/sqlc/SQLitePlugin.java
deleted file mode 100755
index fdf92d0..0000000
--- a/platforms/android/app/src/main/java/io/sqlc/SQLitePlugin.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * Copyright (c) 2012-present Christopher J. Brody (aka Chris Brody)
- * Copyright (c) 2005-2010, Nitobi Software Inc.
- * Copyright (c) 2010, IBM Corporation
- */
-
-package io.sqlc;
-
-import android.annotation.SuppressLint;
-
-import android.util.Log;
-
-import java.io.File;
-
-import java.lang.IllegalArgumentException;
-import java.lang.Number;
-
-import java.util.Map;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public class SQLitePlugin extends CordovaPlugin {
-
- /**
- * Multiple database runner map (static).
- *
- * NOTE: no public static accessor to db (runner) map since it is not
- * expected to work properly with db threading.
- *
- * FUTURE TBD put DBRunner into a public class that can provide external accessor.
- *
- * ADDITIONAL NOTE: Storing as Map to avoid portabiity issue
- * between Java 6/7/8 as discussed in:
- * https://gist.github.com/AlainODea/1375759b8720a3f9f094
- *
- * THANKS to @NeoLSN (Jason Yang/楊朝傑) for giving the pointer in:
- * https://github.com/litehelpers/Cordova-sqlite-storage/issues/727
- */
- static Map dbrmap = new ConcurrentHashMap();
-
- /**
- * NOTE: Using default constructor, no explicit constructor.
- */
-
- /**
- * Executes the request and returns PluginResult.
- *
- * @param actionAsString The action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param cbc Callback context from Cordova API
- * @return Whether the action was valid.
- */
- @Override
- public boolean execute(String actionAsString, JSONArray args, CallbackContext cbc) {
-
- Action action;
- try {
- action = Action.valueOf(actionAsString);
- } catch (IllegalArgumentException e) {
- // shouldn't ever happen
- Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error", e);
- return false;
- }
-
- try {
- return executeAndPossiblyThrow(action, args, cbc);
- } catch (JSONException e) {
- // TODO: signal JSON problem to JS
- Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error", e);
- return false;
- }
- }
-
- private boolean executeAndPossiblyThrow(Action action, JSONArray args, CallbackContext cbc)
- throws JSONException {
-
- boolean status = true;
- JSONObject o;
- String echo_value;
- String dbname;
-
- switch (action) {
- case echoStringValue:
- o = args.getJSONObject(0);
- echo_value = o.getString("value");
- cbc.success(echo_value);
- break;
-
- case open:
- o = args.getJSONObject(0);
- dbname = o.getString("name");
- // open database and start reading its queue
- this.startDatabase(dbname, o, cbc);
- break;
-
- case close:
- o = args.getJSONObject(0);
- dbname = o.getString("path");
- // put request in the q to close the db
- this.closeDatabase(dbname, cbc);
- break;
-
- case delete:
- o = args.getJSONObject(0);
- dbname = o.getString("path");
-
- deleteDatabase(dbname, cbc);
-
- break;
-
- case executeSqlBatch:
- case backgroundExecuteSqlBatch:
- JSONObject allargs = args.getJSONObject(0);
- JSONObject dbargs = allargs.getJSONObject("dbargs");
- dbname = dbargs.getString("dbname");
- JSONArray txargs = allargs.getJSONArray("executes");
-
- if (txargs.isNull(0)) {
- cbc.error("INTERNAL PLUGIN ERROR: missing executes list");
- } else {
- int len = txargs.length();
- String[] queries = new String[len];
- JSONArray[] jsonparams = new JSONArray[len];
-
- for (int i = 0; i < len; i++) {
- JSONObject a = txargs.getJSONObject(i);
- queries[i] = a.getString("sql");
- jsonparams[i] = a.getJSONArray("params");
- }
-
- // put db query in the queue to be executed in the db thread:
- DBQuery q = new DBQuery(queries, jsonparams, cbc);
- DBRunner r = dbrmap.get(dbname);
- if (r != null) {
- try {
- r.q.put(q);
- } catch(Exception e) {
- Log.e(SQLitePlugin.class.getSimpleName(), "couldn't add to queue", e);
- cbc.error("INTERNAL PLUGIN ERROR: couldn't add to queue");
- }
- } else {
- cbc.error("INTERNAL PLUGIN ERROR: database not open");
- }
- }
- break;
- }
-
- return status;
- }
-
- /**
- * Clean up and close all open databases.
- */
- @Override
- public void onDestroy() {
- while (!dbrmap.isEmpty()) {
- String dbname = dbrmap.keySet().iterator().next();
-
- this.closeDatabaseNow(dbname);
-
- DBRunner r = dbrmap.get(dbname);
- try {
- // stop the db runner thread:
- r.q.put(new DBQuery());
- } catch(Exception e) {
- Log.e(SQLitePlugin.class.getSimpleName(), "INTERNAL PLUGIN CLEANUP ERROR: could not stop db thread due to exception", e);
- }
- dbrmap.remove(dbname);
- }
- }
-
- // --------------------------------------------------------------------------
- // LOCAL METHODS
- // --------------------------------------------------------------------------
-
- private void startDatabase(String dbname, JSONObject options, CallbackContext cbc) {
- DBRunner r = dbrmap.get(dbname);
-
- if (r != null) {
- // NO LONGER EXPECTED due to BUG 666 workaround solution:
- cbc.error("INTERNAL ERROR: database already open for db name: " + dbname);
- } else {
- r = new DBRunner(dbname, options, cbc);
- dbrmap.put(dbname, r);
- this.cordova.getThreadPool().execute(r);
- }
- }
- /**
- * Open a database.
- *
- * @param dbName The name of the database file
- */
- private SQLiteAndroidDatabase openDatabase(String dbname, CallbackContext cbc, boolean old_impl) throws Exception {
- try {
- // ASSUMPTION: no db (connection/handle) is already stored in the map
- // [should be true according to the code in DBRunner.run()]
-
- File dbfile = this.cordova.getActivity().getDatabasePath(dbname);
-
- if (!dbfile.exists()) {
- dbfile.getParentFile().mkdirs();
- }
-
- Log.v("info", "Open sqlite db: " + dbfile.getAbsolutePath());
-
- SQLiteAndroidDatabase mydb = old_impl ? new SQLiteAndroidDatabase() : new SQLiteConnectorDatabase();
- mydb.open(dbfile);
-
- if (cbc != null) // XXX Android locking/closing BUG workaround
- cbc.success();
-
- return mydb;
- } catch (Exception e) {
- if (cbc != null) // XXX Android locking/closing BUG workaround
- cbc.error("can't open database " + e);
- throw e;
- }
- }
-
- /**
- * Close a database (in another thread).
- *
- * @param dbName The name of the database file
- */
- private void closeDatabase(String dbname, CallbackContext cbc) {
- DBRunner r = dbrmap.get(dbname);
- if (r != null) {
- try {
- r.q.put(new DBQuery(false, cbc));
- } catch(Exception e) {
- if (cbc != null) {
- cbc.error("couldn't close database" + e);
- }
- Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e);
- }
- } else {
- if (cbc != null) {
- cbc.success();
- }
- }
- }
-
- /**
- * Close a database (in the current thread).
- *
- * @param dbname The name of the database file
- */
- private void closeDatabaseNow(String dbname) {
- DBRunner r = dbrmap.get(dbname);
-
- if (r != null) {
- SQLiteAndroidDatabase mydb = r.mydb;
-
- if (mydb != null)
- mydb.closeDatabaseNow();
- }
- }
-
- private void deleteDatabase(String dbname, CallbackContext cbc) {
- DBRunner r = dbrmap.get(dbname);
- if (r != null) {
- try {
- r.q.put(new DBQuery(true, cbc));
- } catch(Exception e) {
- if (cbc != null) {
- cbc.error("couldn't close database" + e);
- }
- Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e);
- }
- } else {
- boolean deleteResult = this.deleteDatabaseNow(dbname);
- if (deleteResult) {
- cbc.success();
- } else {
- cbc.error("couldn't delete database");
- }
- }
- }
-
- /**
- * Delete a database.
- *
- * @param dbName The name of the database file
- *
- * @return true if successful or false if an exception was encountered
- */
- private boolean deleteDatabaseNow(String dbname) {
- File dbfile = this.cordova.getActivity().getDatabasePath(dbname);
-
- try {
- return cordova.getActivity().deleteDatabase(dbfile.getAbsolutePath());
- } catch (Exception e) {
- Log.e(SQLitePlugin.class.getSimpleName(), "couldn't delete database", e);
- return false;
- }
- }
-
- private class DBRunner implements Runnable {
- final String dbname;
- private boolean oldImpl;
- private boolean bugWorkaround;
-
- final BlockingQueue q;
- final CallbackContext openCbc;
-
- SQLiteAndroidDatabase mydb;
-
- DBRunner(final String dbname, JSONObject options, CallbackContext cbc) {
- this.dbname = dbname;
- this.oldImpl = options.has("androidOldDatabaseImplementation");
- Log.v(SQLitePlugin.class.getSimpleName(), "Android db implementation: built-in android.database.sqlite package");
- this.bugWorkaround = this.oldImpl && options.has("androidBugWorkaround");
- if (this.bugWorkaround)
- Log.v(SQLitePlugin.class.getSimpleName(), "Android db closing/locking workaround applied");
-
- this.q = new LinkedBlockingQueue();
- this.openCbc = cbc;
- }
-
- public void run() {
- try {
- this.mydb = openDatabase(dbname, this.openCbc, this.oldImpl);
- } catch (Exception e) {
- Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error, stopping db thread", e);
- dbrmap.remove(dbname);
- return;
- }
-
- DBQuery dbq = null;
-
- try {
- dbq = q.take();
-
- while (!dbq.stop) {
- mydb.executeSqlBatch(dbq.queries, dbq.jsonparams, dbq.cbc);
-
- if (this.bugWorkaround && dbq.queries.length == 1 && dbq.queries[0] == "COMMIT")
- mydb.bugWorkaround();
-
- dbq = q.take();
- }
- } catch (Exception e) {
- Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error", e);
- }
-
- if (dbq != null && dbq.close) {
- try {
- closeDatabaseNow(dbname);
-
- dbrmap.remove(dbname); // (should) remove ourself
-
- if (!dbq.delete) {
- dbq.cbc.success();
- } else {
- try {
- boolean deleteResult = deleteDatabaseNow(dbname);
- if (deleteResult) {
- dbq.cbc.success();
- } else {
- dbq.cbc.error("couldn't delete database");
- }
- } catch (Exception e) {
- Log.e(SQLitePlugin.class.getSimpleName(), "couldn't delete database", e);
- dbq.cbc.error("couldn't delete database: " + e);
- }
- }
- } catch (Exception e) {
- Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e);
- if (dbq.cbc != null) {
- dbq.cbc.error("couldn't close database: " + e);
- }
- }
- }
- }
- }
-
- private final class DBQuery {
- // XXX TODO replace with DBRunner action enum:
- final boolean stop;
- final boolean close;
- final boolean delete;
- final String[] queries;
- final JSONArray[] jsonparams;
- final CallbackContext cbc;
-
- DBQuery(String[] myqueries, JSONArray[] params, CallbackContext c) {
- this.stop = false;
- this.close = false;
- this.delete = false;
- this.queries = myqueries;
- this.jsonparams = params;
- this.cbc = c;
- }
-
- DBQuery(boolean delete, CallbackContext cbc) {
- this.stop = true;
- this.close = true;
- this.delete = delete;
- this.queries = null;
- this.jsonparams = null;
- this.cbc = cbc;
- }
-
- // signal the DBRunner thread to stop:
- DBQuery() {
- this.stop = true;
- this.close = false;
- this.delete = false;
- this.queries = null;
- this.jsonparams = null;
- this.cbc = null;
- }
- }
-
- private static enum Action {
- echoStringValue,
- open,
- close,
- delete,
- executeSqlBatch,
- backgroundExecuteSqlBatch,
- }
-}
-
-/* vim: set expandtab : */
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/device/Device.java b/platforms/android/app/src/main/java/org/apache/cordova/device/Device.java
deleted file mode 100644
index e9efcb4..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/device/Device.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.device;
-
-import java.util.TimeZone;
-
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaInterface;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.provider.Settings;
-
-public class Device extends CordovaPlugin {
- public static final String TAG = "Device";
-
- public static String platform; // Device OS
- public static String uuid; // Device UUID
-
- private static final String ANDROID_PLATFORM = "Android";
- private static final String AMAZON_PLATFORM = "amazon-fireos";
- private static final String AMAZON_DEVICE = "Amazon";
-
- /**
- * Constructor.
- */
- public Device() {
- }
-
- /**
- * Sets the context of the Command. This can then be used to do things like
- * get file paths associated with the Activity.
- *
- * @param cordova The context of the main Activity.
- * @param webView The CordovaWebView Cordova is running in.
- */
- public void initialize(CordovaInterface cordova, CordovaWebView webView) {
- super.initialize(cordova, webView);
- Device.uuid = getUuid();
- }
-
- /**
- * Executes the request and returns PluginResult.
- *
- * @param action The action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param callbackContext The callback id used when calling back into JavaScript.
- * @return True if the action was valid, false if not.
- */
- public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
- if ("getDeviceInfo".equals(action)) {
- JSONObject r = new JSONObject();
- r.put("uuid", Device.uuid);
- r.put("version", this.getOSVersion());
- r.put("platform", this.getPlatform());
- r.put("model", this.getModel());
- r.put("manufacturer", this.getManufacturer());
- r.put("isVirtual", this.isVirtual());
- r.put("serial", this.getSerialNumber());
- callbackContext.success(r);
- }
- else {
- return false;
- }
- return true;
- }
-
- //--------------------------------------------------------------------------
- // LOCAL METHODS
- //--------------------------------------------------------------------------
-
- /**
- * Get the OS name.
- *
- * @return
- */
- public String getPlatform() {
- String platform;
- if (isAmazonDevice()) {
- platform = AMAZON_PLATFORM;
- } else {
- platform = ANDROID_PLATFORM;
- }
- return platform;
- }
-
- /**
- * Get the device's Universally Unique Identifier (UUID).
- *
- * @return
- */
- public String getUuid() {
- String uuid = Settings.Secure.getString(this.cordova.getActivity().getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
- return uuid;
- }
-
- public String getModel() {
- String model = android.os.Build.MODEL;
- return model;
- }
-
- public String getProductName() {
- String productname = android.os.Build.PRODUCT;
- return productname;
- }
-
- public String getManufacturer() {
- String manufacturer = android.os.Build.MANUFACTURER;
- return manufacturer;
- }
-
- public String getSerialNumber() {
- String serial = android.os.Build.SERIAL;
- return serial;
- }
-
- /**
- * Get the OS version.
- *
- * @return
- */
- public String getOSVersion() {
- String osversion = android.os.Build.VERSION.RELEASE;
- return osversion;
- }
-
- public String getSDKVersion() {
- @SuppressWarnings("deprecation")
- String sdkversion = android.os.Build.VERSION.SDK;
- return sdkversion;
- }
-
- public String getTimeZoneID() {
- TimeZone tz = TimeZone.getDefault();
- return (tz.getID());
- }
-
- /**
- * Function to check if the device is manufactured by Amazon
- *
- * @return
- */
- public boolean isAmazonDevice() {
- if (android.os.Build.MANUFACTURER.equals(AMAZON_DEVICE)) {
- return true;
- }
- return false;
- }
-
- public boolean isVirtual() {
- return android.os.Build.FINGERPRINT.contains("generic") ||
- android.os.Build.PRODUCT.contains("sdk");
- }
-
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/AssetFilesystem.java b/platforms/android/app/src/main/java/org/apache/cordova/file/AssetFilesystem.java
deleted file mode 100644
index b035c40..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/AssetFilesystem.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.cordova.file;
-
-import android.content.res.AssetManager;
-import android.net.Uri;
-
-import org.apache.cordova.CordovaResourceApi;
-import org.apache.cordova.LOG;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-public class AssetFilesystem extends Filesystem {
-
- private final AssetManager assetManager;
-
- // A custom gradle hook creates the cdvasset.manifest file, which speeds up asset listing a tonne.
- // See: http://stackoverflow.com/questions/16911558/android-assetmanager-list-incredibly-slow
- private static Object listCacheLock = new Object();
- private static boolean listCacheFromFile;
- private static Map listCache;
- private static Map lengthCache;
-
- private static final String LOG_TAG = "AssetFilesystem";
-
- private void lazyInitCaches() {
- synchronized (listCacheLock) {
- if (listCache == null) {
- ObjectInputStream ois = null;
- try {
- ois = new ObjectInputStream(assetManager.open("cdvasset.manifest"));
- listCache = (Map) ois.readObject();
- lengthCache = (Map) ois.readObject();
- listCacheFromFile = true;
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- // Asset manifest won't exist if the gradle hook isn't set up correctly.
- } finally {
- if (ois != null) {
- try {
- ois.close();
- } catch (IOException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- }
- }
- }
- if (listCache == null) {
- LOG.w("AssetFilesystem", "Asset manifest not found. Recursive copies and directory listing will be slow.");
- listCache = new HashMap();
- }
- }
- }
- }
-
- private String[] listAssets(String assetPath) throws IOException {
- if (assetPath.startsWith("/")) {
- assetPath = assetPath.substring(1);
- }
- if (assetPath.endsWith("/")) {
- assetPath = assetPath.substring(0, assetPath.length() - 1);
- }
- lazyInitCaches();
- String[] ret = listCache.get(assetPath);
- if (ret == null) {
- if (listCacheFromFile) {
- ret = new String[0];
- } else {
- ret = assetManager.list(assetPath);
- listCache.put(assetPath, ret);
- }
- }
- return ret;
- }
-
- private long getAssetSize(String assetPath) throws FileNotFoundException {
- if (assetPath.startsWith("/")) {
- assetPath = assetPath.substring(1);
- }
- lazyInitCaches();
- if (lengthCache != null) {
- Long ret = lengthCache.get(assetPath);
- if (ret == null) {
- throw new FileNotFoundException("Asset not found: " + assetPath);
- }
- return ret;
- }
- CordovaResourceApi.OpenForReadResult offr = null;
- try {
- offr = resourceApi.openForRead(nativeUriForFullPath(assetPath));
- long length = offr.length;
- if (length < 0) {
- // available() doesn't always yield the file size, but for assets it does.
- length = offr.inputStream.available();
- }
- return length;
- } catch (IOException e) {
- FileNotFoundException fnfe = new FileNotFoundException("File not found: " + assetPath);
- fnfe.initCause(e);
- throw fnfe;
- } finally {
- if (offr != null) {
- try {
- offr.inputStream.close();
- } catch (IOException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- }
- }
- }
- }
-
- public AssetFilesystem(AssetManager assetManager, CordovaResourceApi resourceApi) {
- super(Uri.parse("file:///android_asset/"), "assets", resourceApi);
- this.assetManager = assetManager;
- }
-
- @Override
- public Uri toNativeUri(LocalFilesystemURL inputURL) {
- return nativeUriForFullPath(inputURL.path);
- }
-
- @Override
- public LocalFilesystemURL toLocalUri(Uri inputURL) {
- if (!"file".equals(inputURL.getScheme())) {
- return null;
- }
- File f = new File(inputURL.getPath());
- // Removes and duplicate /s (e.g. file:///a//b/c)
- Uri resolvedUri = Uri.fromFile(f);
- String rootUriNoTrailingSlash = rootUri.getEncodedPath();
- rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
- if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
- return null;
- }
- String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
- // Strip leading slash
- if (!subPath.isEmpty()) {
- subPath = subPath.substring(1);
- }
- Uri.Builder b = new Uri.Builder()
- .scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
- .authority("localhost")
- .path(name);
- if (!subPath.isEmpty()) {
- b.appendEncodedPath(subPath);
- }
- if (isDirectory(subPath) || inputURL.getPath().endsWith("/")) {
- // Add trailing / for directories.
- b.appendEncodedPath("");
- }
- return LocalFilesystemURL.parse(b.build());
- }
-
- private boolean isDirectory(String assetPath) {
- try {
- return listAssets(assetPath).length != 0;
- } catch (IOException e) {
- return false;
- }
- }
-
- @Override
- public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
- String pathNoSlashes = inputURL.path.substring(1);
- if (pathNoSlashes.endsWith("/")) {
- pathNoSlashes = pathNoSlashes.substring(0, pathNoSlashes.length() - 1);
- }
-
- String[] files;
- try {
- files = listAssets(pathNoSlashes);
- } catch (IOException e) {
- FileNotFoundException fnfe = new FileNotFoundException();
- fnfe.initCause(e);
- throw fnfe;
- }
-
- LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
- for (int i = 0; i < files.length; ++i) {
- entries[i] = localUrlforFullPath(new File(inputURL.path, files[i]).getPath());
- }
- return entries;
- }
-
- @Override
- public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
- String path, JSONObject options, boolean directory)
- throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- if (options != null && options.optBoolean("create")) {
- throw new UnsupportedOperationException("Assets are read-only");
- }
-
- // Check whether the supplied path is absolute or relative
- if (directory && !path.endsWith("/")) {
- path += "/";
- }
-
- LocalFilesystemURL requestedURL;
- if (path.startsWith("/")) {
- requestedURL = localUrlforFullPath(normalizePath(path));
- } else {
- requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
- }
-
- // Throws a FileNotFoundException if it doesn't exist.
- getFileMetadataForLocalURL(requestedURL);
-
- boolean isDir = isDirectory(requestedURL.path);
- if (directory && !isDir) {
- throw new TypeMismatchException("path doesn't exist or is file");
- } else if (!directory && isDir) {
- throw new TypeMismatchException("path doesn't exist or is directory");
- }
-
- // Return the directory
- return makeEntryForURL(requestedURL);
- }
-
- @Override
- public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
- JSONObject metadata = new JSONObject();
- long size = inputURL.isDirectory ? 0 : getAssetSize(inputURL.path);
- try {
- metadata.put("size", size);
- metadata.put("type", inputURL.isDirectory ? "text/directory" : resourceApi.getMimeType(toNativeUri(inputURL)));
- metadata.put("name", new File(inputURL.path).getName());
- metadata.put("fullPath", inputURL.path);
- metadata.put("lastModifiedDate", 0);
- } catch (JSONException e) {
- return null;
- }
- return metadata;
- }
-
- @Override
- public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
- return false;
- }
-
- @Override
- long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset, boolean isBinary) throws NoModificationAllowedException, IOException {
- throw new NoModificationAllowedException("Assets are read-only");
- }
-
- @Override
- long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException, NoModificationAllowedException {
- throw new NoModificationAllowedException("Assets are read-only");
- }
-
- @Override
- String filesystemPathForURL(LocalFilesystemURL url) {
- return new File(rootUri.getPath(), url.path).toString();
- }
-
- @Override
- LocalFilesystemURL URLforFilesystemPath(String path) {
- return null;
- }
-
- @Override
- boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException {
- throw new NoModificationAllowedException("Assets are read-only");
- }
-
- @Override
- boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws NoModificationAllowedException {
- throw new NoModificationAllowedException("Assets are read-only");
- }
-
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/ContentFilesystem.java b/platforms/android/app/src/main/java/org/apache/cordova/file/ContentFilesystem.java
deleted file mode 100644
index 6b983c0..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/ContentFilesystem.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.cordova.file;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.DocumentsContract;
-import android.provider.MediaStore;
-import android.provider.OpenableColumns;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import org.apache.cordova.CordovaResourceApi;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public class ContentFilesystem extends Filesystem {
-
- private final Context context;
-
- public ContentFilesystem(Context context, CordovaResourceApi resourceApi) {
- super(Uri.parse("content://"), "content", resourceApi);
- this.context = context;
- }
-
- @Override
- public Uri toNativeUri(LocalFilesystemURL inputURL) {
- String authorityAndPath = inputURL.uri.getEncodedPath().substring(this.name.length() + 2);
- if (authorityAndPath.length() < 2) {
- return null;
- }
- String ret = "content://" + authorityAndPath;
- String query = inputURL.uri.getEncodedQuery();
- if (query != null) {
- ret += '?' + query;
- }
- String frag = inputURL.uri.getEncodedFragment();
- if (frag != null) {
- ret += '#' + frag;
- }
- return Uri.parse(ret);
- }
-
- @Override
- public LocalFilesystemURL toLocalUri(Uri inputURL) {
- if (!"content".equals(inputURL.getScheme())) {
- return null;
- }
- String subPath = inputURL.getEncodedPath();
- if (subPath.length() > 0) {
- subPath = subPath.substring(1);
- }
- Uri.Builder b = new Uri.Builder()
- .scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
- .authority("localhost")
- .path(name)
- .appendPath(inputURL.getAuthority());
- if (subPath.length() > 0) {
- b.appendEncodedPath(subPath);
- }
- Uri localUri = b.encodedQuery(inputURL.getEncodedQuery())
- .encodedFragment(inputURL.getEncodedFragment())
- .build();
- return LocalFilesystemURL.parse(localUri);
- }
-
- @Override
- public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
- String fileName, JSONObject options, boolean directory) throws IOException, TypeMismatchException, JSONException {
- throw new UnsupportedOperationException("getFile() not supported for content:. Use resolveLocalFileSystemURL instead.");
- }
-
- @Override
- public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL)
- throws NoModificationAllowedException {
- Uri contentUri = toNativeUri(inputURL);
- try {
- context.getContentResolver().delete(contentUri, null, null);
- } 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
- // first case, which is generally only the case with images.
- NoModificationAllowedException nmae = new NoModificationAllowedException("Deleting not supported for content uri: " + contentUri);
- nmae.initCause(t);
- throw nmae;
- }
- return true;
- }
-
- @Override
- public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL)
- throws NoModificationAllowedException {
- throw new NoModificationAllowedException("Cannot remove content url");
- }
-
- @Override
- public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
- throw new UnsupportedOperationException("readEntriesAtLocalURL() not supported for content:. Use resolveLocalFileSystemURL instead.");
- }
-
- @Override
- public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
- long size = -1;
- long lastModified = 0;
- Uri nativeUri = toNativeUri(inputURL);
- String mimeType = resourceApi.getMimeType(nativeUri);
- Cursor cursor = openCursorForURL(nativeUri);
- try {
- if (cursor != null && cursor.moveToFirst()) {
- Long sizeForCursor = resourceSizeForCursor(cursor);
- if (sizeForCursor != null) {
- size = sizeForCursor.longValue();
- }
- Long modified = lastModifiedDateForCursor(cursor);
- if (modified != null)
- lastModified = modified.longValue();
- } else {
- // Some content providers don't support cursors at all!
- CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(nativeUri);
- size = offr.length;
- }
- } catch (IOException e) {
- FileNotFoundException fnfe = new FileNotFoundException();
- fnfe.initCause(e);
- throw fnfe;
- } finally {
- if (cursor != null)
- cursor.close();
- }
-
- JSONObject metadata = new JSONObject();
- try {
- metadata.put("size", size);
- metadata.put("type", mimeType);
- metadata.put("name", name);
- metadata.put("fullPath", inputURL.path);
- metadata.put("lastModifiedDate", lastModified);
- } catch (JSONException e) {
- return null;
- }
- return metadata;
- }
-
- @Override
- public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
- int offset, boolean isBinary) throws NoModificationAllowedException {
- throw new NoModificationAllowedException("Couldn't write to file given its content URI");
- }
- @Override
- public long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
- throws NoModificationAllowedException {
- throw new NoModificationAllowedException("Couldn't truncate file given its content URI");
- }
-
- protected Cursor openCursorForURL(Uri nativeUri) {
- ContentResolver contentResolver = context.getContentResolver();
- try {
- return contentResolver.query(nativeUri, null, null, null, null);
- } catch (UnsupportedOperationException e) {
- return null;
- }
- }
-
- private Long resourceSizeForCursor(Cursor cursor) {
- int columnIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
- if (columnIndex != -1) {
- String sizeStr = cursor.getString(columnIndex);
- if (sizeStr != null) {
- return Long.parseLong(sizeStr);
- }
- }
- return null;
- }
-
- protected Long lastModifiedDateForCursor(Cursor cursor) {
- int columnIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DATE_MODIFIED);
- if (columnIndex == -1) {
- columnIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED);
- }
- if (columnIndex != -1) {
- String dateStr = cursor.getString(columnIndex);
- if (dateStr != null) {
- return Long.parseLong(dateStr);
- }
- }
- return null;
- }
-
- @Override
- public String filesystemPathForURL(LocalFilesystemURL url) {
- File f = resourceApi.mapUriToFile(toNativeUri(url));
- return f == null ? null : f.getAbsolutePath();
- }
-
- @Override
- public LocalFilesystemURL URLforFilesystemPath(String path) {
- // Returns null as we don't support reverse mapping back to content:// URLs
- return null;
- }
-
- @Override
- public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
- return true;
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/DirectoryManager.java b/platforms/android/app/src/main/java/org/apache/cordova/file/DirectoryManager.java
deleted file mode 100644
index 07af5ea..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/DirectoryManager.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.file;
-
-import android.os.Environment;
-import android.os.StatFs;
-
-import java.io.File;
-
-/**
- * This class provides file directory utilities.
- * All file operations are performed on the SD card.
- *
- * It is used by the FileUtils class.
- */
-public class DirectoryManager {
-
- @SuppressWarnings("unused")
- private static final String LOG_TAG = "DirectoryManager";
-
- /**
- * Determine if a file or directory exists.
- * @param name The name of the file to check.
- * @return T=exists, F=not found
- */
- public static boolean testFileExists(String name) {
- boolean status;
-
- // If SD card exists
- if ((testSaveLocationExists()) && (!name.equals(""))) {
- File path = Environment.getExternalStorageDirectory();
- File newPath = constructFilePaths(path.toString(), name);
- status = newPath.exists();
- }
- // If no SD card
- else {
- status = false;
- }
- return status;
- }
-
- /**
- * Get the free space in external storage
- *
- * @return Size in KB or -1 if not available
- */
- public static long getFreeExternalStorageSpace() {
- String status = Environment.getExternalStorageState();
- long freeSpaceInBytes = 0;
-
- // Check if external storage exists
- if (status.equals(Environment.MEDIA_MOUNTED)) {
- freeSpaceInBytes = getFreeSpaceInBytes(Environment.getExternalStorageDirectory().getPath());
- } else {
- // If no external storage then return -1
- return -1;
- }
-
- return freeSpaceInBytes / 1024;
- }
-
- /**
- * Given a path return the number of free bytes in the filesystem containing the path.
- *
- * @param path to the file system
- * @return free space in bytes
- */
- public static long getFreeSpaceInBytes(String path) {
- try {
- StatFs stat = new StatFs(path);
- long blockSize = stat.getBlockSize();
- long availableBlocks = stat.getAvailableBlocks();
- return availableBlocks * blockSize;
- } catch (IllegalArgumentException e) {
- // The path was invalid. Just return 0 free bytes.
- return 0;
- }
- }
-
- /**
- * Determine if SD card exists.
- *
- * @return T=exists, F=not found
- */
- public static boolean testSaveLocationExists() {
- String sDCardStatus = Environment.getExternalStorageState();
- boolean status;
-
- // If SD card is mounted
- if (sDCardStatus.equals(Environment.MEDIA_MOUNTED)) {
- status = true;
- }
-
- // If no SD card
- else {
- status = false;
- }
- return status;
- }
-
- /**
- * Create a new file object from two file paths.
- *
- * @param file1 Base file path
- * @param file2 Remaining file path
- * @return File object
- */
- private static File constructFilePaths (String file1, String file2) {
- File newPath;
- if (file2.startsWith(file1)) {
- newPath = new File(file2);
- }
- else {
- newPath = new File(file1 + "/" + file2);
- }
- return newPath;
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/EncodingException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/EncodingException.java
deleted file mode 100644
index e9e1653..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/EncodingException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova.file;
-
-@SuppressWarnings("serial")
-public class EncodingException extends Exception {
-
- public EncodingException(String message) {
- super(message);
- }
-
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/FileExistsException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/FileExistsException.java
deleted file mode 100644
index 5c4d83d..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/FileExistsException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova.file;
-
-@SuppressWarnings("serial")
-public class FileExistsException extends Exception {
-
- public FileExistsException(String msg) {
- super(msg);
- }
-
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/FileUtils.java b/platforms/android/app/src/main/java/org/apache/cordova/file/FileUtils.java
deleted file mode 100644
index 1d6e61f..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/FileUtils.java
+++ /dev/null
@@ -1,1225 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.cordova.file;
-
-import android.Manifest;
-import android.app.Activity;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Environment;
-import android.util.Base64;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.LOG;
-import org.apache.cordova.PermissionHelper;
-import org.apache.cordova.PluginResult;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.security.Permission;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-
-/**
- * This class provides file and directory services to JavaScript.
- */
-public class FileUtils extends CordovaPlugin {
- private static final String LOG_TAG = "FileUtils";
-
- public static int NOT_FOUND_ERR = 1;
- public static int SECURITY_ERR = 2;
- public static int ABORT_ERR = 3;
-
- public static int NOT_READABLE_ERR = 4;
- public static int ENCODING_ERR = 5;
- public static int NO_MODIFICATION_ALLOWED_ERR = 6;
- public static int INVALID_STATE_ERR = 7;
- public static int SYNTAX_ERR = 8;
- public static int INVALID_MODIFICATION_ERR = 9;
- public static int QUOTA_EXCEEDED_ERR = 10;
- public static int TYPE_MISMATCH_ERR = 11;
- public static int PATH_EXISTS_ERR = 12;
-
- /*
- * Permission callback codes
- */
-
- public static final int ACTION_GET_FILE = 0;
- public static final int ACTION_WRITE = 1;
- public static final int ACTION_GET_DIRECTORY = 2;
-
- public static final int WRITE = 3;
- public static final int READ = 4;
-
- public static int UNKNOWN_ERR = 1000;
-
- private boolean configured = false;
-
- private PendingRequests pendingRequests;
-
-
-
- /*
- * We need both read and write when accessing the storage, I think.
- */
-
- private String [] permissions = {
- Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.WRITE_EXTERNAL_STORAGE };
-
- // This field exists only to support getEntry, below, which has been deprecated
- private static FileUtils filePlugin;
-
- private interface FileOp {
- void run(JSONArray args) throws Exception;
- }
-
- private ArrayList filesystems;
-
- public void registerFilesystem(Filesystem fs) {
- if (fs != null && filesystemForName(fs.name)== null) {
- this.filesystems.add(fs);
- }
- }
-
- private Filesystem filesystemForName(String name) {
- for (Filesystem fs:filesystems) {
- if (fs != null && fs.name != null && fs.name.equals(name)) {
- return fs;
- }
- }
- return null;
- }
-
- protected String[] getExtraFileSystemsPreference(Activity activity) {
- String fileSystemsStr = preferences.getString("androidextrafilesystems", "files,files-external,documents,sdcard,cache,cache-external,assets,root");
- return fileSystemsStr.split(",");
- }
-
- protected void registerExtraFileSystems(String[] filesystems, HashMap availableFileSystems) {
- HashSet installedFileSystems = new HashSet();
-
- /* Register filesystems in order */
- for (String fsName : filesystems) {
- if (!installedFileSystems.contains(fsName)) {
- String fsRoot = availableFileSystems.get(fsName);
- if (fsRoot != null) {
- File newRoot = new File(fsRoot);
- if (newRoot.mkdirs() || newRoot.isDirectory()) {
- registerFilesystem(new LocalFilesystem(fsName, webView.getContext(), webView.getResourceApi(), newRoot));
- installedFileSystems.add(fsName);
- } else {
- LOG.d(LOG_TAG, "Unable to create root dir for filesystem \"" + fsName + "\", skipping");
- }
- } else {
- LOG.d(LOG_TAG, "Unrecognized extra filesystem identifier: " + fsName);
- }
- }
- }
- }
-
- protected HashMap getAvailableFileSystems(Activity activity) {
- Context context = activity.getApplicationContext();
- HashMap availableFileSystems = new HashMap();
-
- availableFileSystems.put("files", context.getFilesDir().getAbsolutePath());
- availableFileSystems.put("documents", new File(context.getFilesDir(), "Documents").getAbsolutePath());
- availableFileSystems.put("cache", context.getCacheDir().getAbsolutePath());
- availableFileSystems.put("root", "/");
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- try {
- availableFileSystems.put("files-external", context.getExternalFilesDir(null).getAbsolutePath());
- availableFileSystems.put("sdcard", Environment.getExternalStorageDirectory().getAbsolutePath());
- availableFileSystems.put("cache-external", context.getExternalCacheDir().getAbsolutePath());
- }
- catch(NullPointerException e) {
- LOG.d(LOG_TAG, "External storage unavailable, check to see if USB Mass Storage Mode is on");
- }
- }
-
- return availableFileSystems;
- }
-
- @Override
- public void initialize(CordovaInterface cordova, CordovaWebView webView) {
- super.initialize(cordova, webView);
- this.filesystems = new ArrayList();
- this.pendingRequests = new PendingRequests();
-
- String tempRoot = null;
- String persistentRoot = null;
-
- Activity activity = cordova.getActivity();
- String packageName = activity.getPackageName();
-
- String location = preferences.getString("androidpersistentfilelocation", "internal");
-
- tempRoot = activity.getCacheDir().getAbsolutePath();
- if ("internal".equalsIgnoreCase(location)) {
- persistentRoot = activity.getFilesDir().getAbsolutePath() + "/files/";
- this.configured = true;
- } else if ("compatibility".equalsIgnoreCase(location)) {
- /*
- * Fall-back to compatibility mode -- this is the logic implemented in
- * earlier versions of this plugin, and should be maintained here so
- * that apps which were originally deployed with older versions of the
- * plugin can continue to provide access to files stored under those
- * versions.
- */
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- persistentRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
- tempRoot = Environment.getExternalStorageDirectory().getAbsolutePath() +
- "/Android/data/" + packageName + "/cache/";
- } else {
- persistentRoot = "/data/data/" + packageName;
- }
- this.configured = true;
- }
-
- if (this.configured) {
- // Create the directories if they don't exist.
- File tmpRootFile = new File(tempRoot);
- File persistentRootFile = new File(persistentRoot);
- tmpRootFile.mkdirs();
- persistentRootFile.mkdirs();
-
- // Register initial filesystems
- // Note: The temporary and persistent filesystems need to be the first two
- // registered, so that they will match window.TEMPORARY and window.PERSISTENT,
- // per spec.
- this.registerFilesystem(new LocalFilesystem("temporary", webView.getContext(), webView.getResourceApi(), tmpRootFile));
- this.registerFilesystem(new LocalFilesystem("persistent", webView.getContext(), webView.getResourceApi(), persistentRootFile));
- this.registerFilesystem(new ContentFilesystem(webView.getContext(), webView.getResourceApi()));
- this.registerFilesystem(new AssetFilesystem(webView.getContext().getAssets(), webView.getResourceApi()));
-
- registerExtraFileSystems(getExtraFileSystemsPreference(activity), getAvailableFileSystems(activity));
-
- // Initialize static plugin reference for deprecated getEntry method
- if (filePlugin == null) {
- FileUtils.filePlugin = this;
- }
- } else {
- LOG.e(LOG_TAG, "File plugin configuration error: Please set AndroidPersistentFileLocation in config.xml to one of \"internal\" (for new applications) or \"compatibility\" (for compatibility with previous versions)");
- activity.finish();
- }
- }
-
- public static FileUtils getFilePlugin() {
- return filePlugin;
- }
-
- private Filesystem filesystemForURL(LocalFilesystemURL localURL) {
- if (localURL == null) return null;
- return filesystemForName(localURL.fsName);
- }
-
- @Override
- public Uri remapUri(Uri uri) {
- // Remap only cdvfile: URLs (not content:).
- if (!LocalFilesystemURL.FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
- return null;
- }
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- return null;
- }
- String path = fs.filesystemPathForURL(inputURL);
- if (path != null) {
- return Uri.parse("file://" + fs.filesystemPathForURL(inputURL));
- }
- return null;
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
-
- public boolean execute(String action, final String rawArgs, final CallbackContext callbackContext) {
- if (!configured) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "File plugin is not configured. Please see the README.md file for details on how to update config.xml"));
- return true;
- }
- if (action.equals("testSaveLocationExists")) {
- threadhelper(new FileOp() {
- public void run(JSONArray args) {
- boolean b = DirectoryManager.testSaveLocationExists();
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getFreeDiskSpace")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) {
- // The getFreeDiskSpace plugin API is not documented, but some apps call it anyway via exec().
- // For compatibility it always returns free space in the primary external storage, and
- // does NOT fallback to internal store if external storage is unavailable.
- long l = DirectoryManager.getFreeExternalStorageSpace();
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, l));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("testFileExists")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException {
- String fname=args.getString(0);
- boolean b = DirectoryManager.testFileExists(fname);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("testDirectoryExists")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException {
- String fname=args.getString(0);
- boolean b = DirectoryManager.testFileExists(fname);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readAsText")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, MalformedURLException {
- String encoding = args.getString(1);
- int start = args.getInt(2);
- int end = args.getInt(3);
- String fname=args.getString(0);
- readFileAs(fname, start, end, callbackContext, encoding, PluginResult.MESSAGE_TYPE_STRING);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readAsDataURL")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, MalformedURLException {
- int start = args.getInt(1);
- int end = args.getInt(2);
- String fname=args.getString(0);
- readFileAs(fname, start, end, callbackContext, null, -1);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readAsArrayBuffer")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, MalformedURLException {
- int start = args.getInt(1);
- int end = args.getInt(2);
- String fname=args.getString(0);
- readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_ARRAYBUFFER);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readAsBinaryString")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, MalformedURLException {
- int start = args.getInt(1);
- int end = args.getInt(2);
- String fname=args.getString(0);
- readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_BINARYSTRING);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("write")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
- String fname=args.getString(0);
- String nativeURL = resolveLocalFileSystemURI(fname).getString("nativeURL");
- String data=args.getString(1);
- int offset=args.getInt(2);
- Boolean isBinary=args.getBoolean(3);
-
- if(needPermission(nativeURL, WRITE)) {
- getWritePermission(rawArgs, ACTION_WRITE, callbackContext);
- }
- else {
- long fileSize = write(fname, data, offset, isBinary);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
- }
-
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("truncate")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
- String fname=args.getString(0);
- int offset=args.getInt(1);
- long fileSize = truncateFile(fname, offset);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("requestAllFileSystems")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws IOException, JSONException {
- callbackContext.success(requestAllFileSystems());
- }
- }, rawArgs, callbackContext);
- } else if (action.equals("requestAllPaths")) {
- cordova.getThreadPool().execute(
- new Runnable() {
- public void run() {
- try {
- callbackContext.success(requestAllPaths());
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- );
- } else if (action.equals("requestFileSystem")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException {
- int fstype = args.getInt(0);
- long requiredSize = args.optLong(1);
- requestFileSystem(fstype, requiredSize, callbackContext);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("resolveLocalFileSystemURI")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws IOException, JSONException {
- String fname=args.getString(0);
- JSONObject obj = resolveLocalFileSystemURI(fname);
- callbackContext.success(obj);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getFileMetadata")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
- String fname=args.getString(0);
- JSONObject obj = getFileMetadata(fname);
- callbackContext.success(obj);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getParent")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, IOException {
- String fname=args.getString(0);
- JSONObject obj = getParent(fname);
- callbackContext.success(obj);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getDirectory")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- String dirname = args.getString(0);
- String path = args.getString(1);
- String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
- boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
-
- if(containsCreate && needPermission(nativeURL, WRITE)) {
- getWritePermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
- }
- else if(!containsCreate && needPermission(nativeURL, READ)) {
- getReadPermission(rawArgs, ACTION_GET_DIRECTORY, callbackContext);
- }
- else {
- JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
- callbackContext.success(obj);
- }
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getFile")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- String dirname = args.getString(0);
- String path = args.getString(1);
- String nativeURL = resolveLocalFileSystemURI(dirname).getString("nativeURL");
- boolean containsCreate = (args.isNull(2)) ? false : args.getJSONObject(2).optBoolean("create", false);
-
- if(containsCreate && needPermission(nativeURL, WRITE)) {
- getWritePermission(rawArgs, ACTION_GET_FILE, callbackContext);
- }
- else if(!containsCreate && needPermission(nativeURL, READ)) {
- getReadPermission(rawArgs, ACTION_GET_FILE, callbackContext);
- }
- else {
- JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
- callbackContext.success(obj);
- }
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("remove")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, NoModificationAllowedException, InvalidModificationException, MalformedURLException {
- String fname=args.getString(0);
- boolean success = remove(fname);
- if (success) {
- callbackContext.success();
- } else {
- callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- }
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("removeRecursively")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, FileExistsException, MalformedURLException, NoModificationAllowedException {
- String fname=args.getString(0);
- boolean success = removeRecursively(fname);
- if (success) {
- callbackContext.success();
- } else {
- callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- }
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("moveTo")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
- String fname=args.getString(0);
- String newParent=args.getString(1);
- String newName=args.getString(2);
- JSONObject entry = transferTo(fname, newParent, newName, true);
- callbackContext.success(entry);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("copyTo")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
- String fname=args.getString(0);
- String newParent=args.getString(1);
- String newName=args.getString(2);
- JSONObject entry = transferTo(fname, newParent, newName, false);
- callbackContext.success(entry);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readEntries")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
- String fname=args.getString(0);
- JSONArray entries = readEntries(fname);
- callbackContext.success(entries);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("_getLocalFilesystemPath")) {
- // Internal method for testing: Get the on-disk location of a local filesystem url.
- // [Currently used for testing file-transfer]
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
- String localURLstr = args.getString(0);
- String fname = filesystemPathForURL(localURLstr);
- callbackContext.success(fname);
- }
- }, rawArgs, callbackContext);
- }
- else {
- return false;
- }
- return true;
- }
-
- private void getReadPermission(String rawArgs, int action, CallbackContext callbackContext) {
- int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
- PermissionHelper.requestPermission(this, requestCode, Manifest.permission.READ_EXTERNAL_STORAGE);
- }
-
- private void getWritePermission(String rawArgs, int action, CallbackContext callbackContext) {
- int requestCode = pendingRequests.createRequest(rawArgs, action, callbackContext);
- PermissionHelper.requestPermission(this, requestCode, Manifest.permission.WRITE_EXTERNAL_STORAGE);
- }
-
- private boolean hasReadPermission() {
- return PermissionHelper.hasPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
- }
-
- private boolean hasWritePermission() {
- return PermissionHelper.hasPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
- }
-
- private boolean needPermission(String nativeURL, int permissionType) throws JSONException {
- JSONObject j = requestAllPaths();
- ArrayList allowedStorageDirectories = new ArrayList();
- allowedStorageDirectories.add(j.getString("applicationDirectory"));
- allowedStorageDirectories.add(j.getString("applicationStorageDirectory"));
- if(j.has("externalApplicationStorageDirectory")) {
- allowedStorageDirectories.add(j.getString("externalApplicationStorageDirectory"));
- }
-
- if(permissionType == READ && hasReadPermission()) {
- return false;
- }
- else if(permissionType == WRITE && hasWritePermission()) {
- return false;
- }
-
- // Permission required if the native url lies outside the allowed storage directories
- for(String directory : allowedStorageDirectories) {
- if(nativeURL.startsWith(directory)) {
- return false;
- }
- }
- return true;
- }
-
-
- public LocalFilesystemURL resolveNativeUri(Uri nativeUri) {
- LocalFilesystemURL localURL = null;
-
- // Try all installed filesystems. Return the best matching URL
- // (determined by the shortest resulting URL)
- for (Filesystem fs : filesystems) {
- LocalFilesystemURL url = fs.toLocalUri(nativeUri);
- if (url != null) {
- // A shorter fullPath implies that the filesystem is a better
- // match for the local path than the previous best.
- if (localURL == null || (url.uri.toString().length() < localURL.toString().length())) {
- localURL = url;
- }
- }
- }
- return localURL;
- }
-
- /*
- * These two native-only methods can be used by other plugins to translate between
- * device file system paths and URLs. By design, there is no direct JavaScript
- * interface to these methods.
- */
-
- public String filesystemPathForURL(String localURLstr) throws MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(localURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.filesystemPathForURL(inputURL);
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
- }
-
- public LocalFilesystemURL filesystemURLforLocalPath(String localPath) {
- LocalFilesystemURL localURL = null;
- int shortestFullPath = 0;
-
- // Try all installed filesystems. Return the best matching URL
- // (determined by the shortest resulting URL)
- for (Filesystem fs: filesystems) {
- LocalFilesystemURL url = fs.URLforFilesystemPath(localPath);
- if (url != null) {
- // A shorter fullPath implies that the filesystem is a better
- // match for the local path than the previous best.
- if (localURL == null || (url.path.length() < shortestFullPath)) {
- localURL = url;
- shortestFullPath = url.path.length();
- }
- }
- }
- return localURL;
- }
-
-
- /* helper to execute functions async and handle the result codes
- *
- */
- private void threadhelper(final FileOp f, final String rawArgs, final CallbackContext callbackContext){
- cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- try {
- JSONArray args = new JSONArray(rawArgs);
- f.run(args);
- } catch ( Exception e) {
- if( e instanceof EncodingException){
- callbackContext.error(FileUtils.ENCODING_ERR);
- } else if(e instanceof FileNotFoundException) {
- callbackContext.error(FileUtils.NOT_FOUND_ERR);
- } else if(e instanceof FileExistsException) {
- callbackContext.error(FileUtils.PATH_EXISTS_ERR);
- } else if(e instanceof NoModificationAllowedException ) {
- callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- } else if(e instanceof InvalidModificationException ) {
- callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
- } else if(e instanceof MalformedURLException ) {
- callbackContext.error(FileUtils.ENCODING_ERR);
- } else if(e instanceof IOException ) {
- callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
- } else if(e instanceof EncodingException ) {
- callbackContext.error(FileUtils.ENCODING_ERR);
- } else if(e instanceof TypeMismatchException ) {
- callbackContext.error(FileUtils.TYPE_MISMATCH_ERR);
- } else if(e instanceof JSONException ) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
- } else if (e instanceof SecurityException) {
- callbackContext.error(FileUtils.SECURITY_ERR);
- } else {
- e.printStackTrace();
- callbackContext.error(FileUtils.UNKNOWN_ERR);
- }
- }
- }
- });
- }
-
- /**
- * Allows the user to look up the Entry for a file or directory referred to by a local URI.
- *
- * @param uriString of the file/directory to look up
- * @return a JSONObject representing a Entry from the filesystem
- * @throws MalformedURLException if the url is not valid
- * @throws FileNotFoundException if the file does not exist
- * @throws IOException if the user can't read the file
- * @throws JSONException
- */
- private JSONObject resolveLocalFileSystemURI(String uriString) throws IOException, JSONException {
- if (uriString == null) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- Uri uri = Uri.parse(uriString);
- boolean isNativeUri = false;
-
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
- if (inputURL == null) {
- /* Check for file://, content:// urls */
- inputURL = resolveNativeUri(uri);
- isNativeUri = true;
- }
-
- try {
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- if (fs.exists(inputURL)) {
- if (!isNativeUri) {
- // If not already resolved as native URI, resolve to a native URI and back to
- // fix the terminating slash based on whether the entry is a directory or file.
- inputURL = fs.toLocalUri(fs.toNativeUri(inputURL));
- }
-
- return fs.getEntryForLocalURL(inputURL);
- }
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
- throw new FileNotFoundException();
- }
-
- /**
- * Read the list of files from this directory.
- *
- * @return a JSONArray containing JSONObjects that represent Entry objects.
- * @throws FileNotFoundException if the directory is not found.
- * @throws JSONException
- * @throws MalformedURLException
- */
- private JSONArray readEntries(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.readEntriesAtLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
- }
-
- /**
- * A setup method that handles the move/copy of files/directories
- *
- * @param newName for the file directory to be called, if null use existing file name
- * @param move if false do a copy, if true do a move
- * @return a Entry object
- * @throws NoModificationAllowedException
- * @throws IOException
- * @throws InvalidModificationException
- * @throws EncodingException
- * @throws JSONException
- * @throws FileExistsException
- */
- private JSONObject transferTo(String srcURLstr, String destURLstr, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
- if (srcURLstr == null || destURLstr == null) {
- // either no source or no destination provided
- throw new FileNotFoundException();
- }
-
- LocalFilesystemURL srcURL = LocalFilesystemURL.parse(srcURLstr);
- LocalFilesystemURL destURL = LocalFilesystemURL.parse(destURLstr);
-
- Filesystem srcFs = this.filesystemForURL(srcURL);
- Filesystem destFs = this.filesystemForURL(destURL);
-
- // Check for invalid file name
- if (newName != null && newName.contains(":")) {
- throw new EncodingException("Bad file name");
- }
-
- return destFs.copyFileToURL(destURL, newName, srcFs, srcURL, move);
- }
-
- /**
- * Deletes a directory and all of its contents, if any. In the event of an error
- * [e.g. trying to delete a directory that contains a file that cannot be removed],
- * some of the contents of the directory may be deleted.
- * It is an error to attempt to delete the root directory of a filesystem.
- *
- * @return a boolean representing success of failure
- * @throws FileExistsException
- * @throws NoModificationAllowedException
- * @throws MalformedURLException
- */
- private boolean removeRecursively(String baseURLstr) throws FileExistsException, NoModificationAllowedException, MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- // You can't delete the root directory.
- if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {
- throw new NoModificationAllowedException("You can't delete the root directory");
- }
-
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.recursiveRemoveFileAtLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
- }
-
-
- /**
- * Deletes a file or directory. It is an error to attempt to delete a directory that is not empty.
- * It is an error to attempt to delete the root directory of a filesystem.
- *
- * @return a boolean representing success of failure
- * @throws NoModificationAllowedException
- * @throws InvalidModificationException
- * @throws MalformedURLException
- */
- private boolean remove(String baseURLstr) throws NoModificationAllowedException, InvalidModificationException, MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- // You can't delete the root directory.
- if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {
-
- throw new NoModificationAllowedException("You can't delete the root directory");
- }
-
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.removeFileAtLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
- }
-
- /**
- * Creates or looks up a file.
- *
- * @param baseURLstr base directory
- * @param path file/directory to lookup or create
- * @param options specify whether to create or not
- * @param directory if true look up directory, if false look up file
- * @return a Entry object
- * @throws FileExistsException
- * @throws IOException
- * @throws TypeMismatchException
- * @throws EncodingException
- * @throws JSONException
- */
- private JSONObject getFile(String baseURLstr, String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.getFileForLocalURL(inputURL, path, options, directory);
-
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
-
- }
-
- /**
- * Look up the parent DirectoryEntry containing this Entry.
- * If this Entry is the root of its filesystem, its parent is itself.
- */
- private JSONObject getParent(String baseURLstr) throws JSONException, IOException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.getParentForLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
- }
-
- /**
- * Returns a File that represents the current state of the file that this FileEntry represents.
- *
- * @return returns a JSONObject represent a W3C File object
- */
- private JSONObject getFileMetadata(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.getFileMetadataForLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
- }
-
- /**
- * Requests a filesystem in which to store application data.
- *
- * @param type of file system requested
- * @param requiredSize required free space in the file system in bytes
- * @param callbackContext context for returning the result or error
- * @throws JSONException
- */
- private void requestFileSystem(int type, long requiredSize, final CallbackContext callbackContext) throws JSONException {
- Filesystem rootFs = null;
- try {
- rootFs = this.filesystems.get(type);
- } catch (ArrayIndexOutOfBoundsException e) {
- // Pass null through
- }
- if (rootFs == null) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FileUtils.NOT_FOUND_ERR));
- } else {
- // If a nonzero required size was specified, check that the retrieved filesystem has enough free space.
- long availableSize = 0;
- if (requiredSize > 0) {
- availableSize = rootFs.getFreeSpaceInBytes();
- }
-
- if (availableSize < requiredSize) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FileUtils.QUOTA_EXCEEDED_ERR));
- } else {
- JSONObject fs = new JSONObject();
- fs.put("name", rootFs.name);
- fs.put("root", rootFs.getRootEntry());
- callbackContext.success(fs);
- }
- }
- }
-
- /**
- * Requests a filesystem in which to store application data.
- *
- * @return a JSONObject representing the file system
- */
- private JSONArray requestAllFileSystems() throws IOException, JSONException {
- JSONArray ret = new JSONArray();
- for (Filesystem fs : filesystems) {
- ret.put(fs.getRootEntry());
- }
- return ret;
- }
-
- private static String toDirUrl(File f) {
- return Uri.fromFile(f).toString() + '/';
- }
-
- private JSONObject requestAllPaths() throws JSONException {
- Context context = cordova.getActivity();
- JSONObject ret = new JSONObject();
- ret.put("applicationDirectory", "file:///android_asset/");
- ret.put("applicationStorageDirectory", toDirUrl(context.getFilesDir().getParentFile()));
- ret.put("dataDirectory", toDirUrl(context.getFilesDir()));
- ret.put("cacheDirectory", toDirUrl(context.getCacheDir()));
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- try {
- ret.put("externalApplicationStorageDirectory", toDirUrl(context.getExternalFilesDir(null).getParentFile()));
- ret.put("externalDataDirectory", toDirUrl(context.getExternalFilesDir(null)));
- ret.put("externalCacheDirectory", toDirUrl(context.getExternalCacheDir()));
- ret.put("externalRootDirectory", toDirUrl(Environment.getExternalStorageDirectory()));
- }
- catch(NullPointerException e) {
- /* If external storage is unavailable, context.getExternal* returns null */
- LOG.d(LOG_TAG, "Unable to access these paths, most liklely due to USB storage");
- }
- }
- return ret;
- }
-
- /**
- * Returns a JSON object representing the given File. Internal APIs should be modified
- * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
- *
- * @param file the File to convert
- * @return a JSON representation of the given File
- * @throws JSONException
- */
- public JSONObject getEntryForFile(File file) throws JSONException {
- JSONObject entry;
-
- for (Filesystem fs : filesystems) {
- entry = fs.makeEntryForFile(file);
- if (entry != null) {
- return entry;
- }
- }
- return null;
- }
-
- /**
- * Returns a JSON object representing the given File. Deprecated, as this is only used by
- * FileTransfer, and because it is a static method that should really be an instance method,
- * since it depends on the actual filesystem roots in use. Internal APIs should be modified
- * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
- *
- * @param file the File to convert
- * @return a JSON representation of the given File
- * @throws JSONException
- */
- @Deprecated
- public static JSONObject getEntry(File file) throws JSONException {
- if (getFilePlugin() != null) {
- return getFilePlugin().getEntryForFile(file);
- }
- return null;
- }
-
- /**
- * Read the contents of a file.
- * This is done in a background thread; the result is sent to the callback.
- *
- * @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 void readFileAs(final String srcURLstr, final int start, final int end, final CallbackContext callbackContext, final String encoding, final int resultType) throws MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
-
- fs.readFileAtURL(inputURL, start, end, new Filesystem.ReadFileCallback() {
- public void handleData(InputStream inputStream, String contentType) {
- try {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- final int BUFFER_SIZE = 8192;
- byte[] buffer = new byte[BUFFER_SIZE];
-
- for (;;) {
- int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
-
- if (bytesRead <= 0) {
- break;
- }
- os.write(buffer, 0, bytesRead);
- }
-
- PluginResult result;
- switch (resultType) {
- case PluginResult.MESSAGE_TYPE_STRING:
- result = new PluginResult(PluginResult.Status.OK, os.toString(encoding));
- break;
- case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
- result = new PluginResult(PluginResult.Status.OK, os.toByteArray());
- break;
- case PluginResult.MESSAGE_TYPE_BINARYSTRING:
- result = new PluginResult(PluginResult.Status.OK, os.toByteArray(), true);
- break;
- default: // Base64.
- byte[] base64 = Base64.encode(os.toByteArray(), Base64.NO_WRAP);
- String s = "data:" + contentType + ";base64," + new String(base64, "US-ASCII");
- result = new PluginResult(PluginResult.Status.OK, s);
- }
-
- callbackContext.sendPluginResult(result);
- } catch (IOException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
- }
- }
- });
-
-
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- } 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));
- }
- }
-
-
- /**
- * Write contents of file.
- *
- * @param data The contents of the file.
- * @param offset The position to begin writing the file.
- * @param isBinary True if the file contents are base64-encoded binary data
- */
- /**/
- public long write(String srcURLstr, String data, int offset, boolean isBinary) throws FileNotFoundException, IOException, NoModificationAllowedException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
-
- long x = fs.writeToFileAtURL(inputURL, data, offset, isBinary); LOG.d("TEST",srcURLstr + ": "+x); return x;
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
-
- }
-
- /**
- * Truncate the file to size
- */
- private long truncateFile(String srcURLstr, long size) throws FileNotFoundException, IOException, NoModificationAllowedException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
-
- return fs.truncateFileAtURL(inputURL, size);
- } catch (IllegalArgumentException e) {
- MalformedURLException mue = new MalformedURLException("Unrecognized filesystem URL");
- mue.initCause(e);
- throw mue;
- }
- }
-
-
- /*
- * Handle the response
- */
-
- public void onRequestPermissionResult(int requestCode, String[] permissions,
- int[] grantResults) throws JSONException {
-
- final PendingRequests.Request req = pendingRequests.getAndRemove(requestCode);
- if (req != null) {
- for(int r:grantResults)
- {
- if(r == PackageManager.PERMISSION_DENIED)
- {
- req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR));
- return;
- }
- }
- switch(req.getAction())
- {
- case ACTION_GET_FILE:
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- String dirname = args.getString(0);
-
- String path = args.getString(1);
- JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
- req.getCallbackContext().success(obj);
- }
- }, req.getRawArgs(), req.getCallbackContext());
- break;
- case ACTION_GET_DIRECTORY:
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- String dirname = args.getString(0);
-
- String path = args.getString(1);
- JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
- req.getCallbackContext().success(obj);
- }
- }, req.getRawArgs(), req.getCallbackContext());
- break;
- case ACTION_WRITE:
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
- String fname=args.getString(0);
- String data=args.getString(1);
- int offset=args.getInt(2);
- Boolean isBinary=args.getBoolean(3);
- long fileSize = write(fname, data, offset, isBinary);
- req.getCallbackContext().sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
- }
- }, req.getRawArgs(), req.getCallbackContext());
- break;
- }
- } else {
- LOG.d(LOG_TAG, "Received permission callback for unknown request code");
- }
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/Filesystem.java b/platforms/android/app/src/main/java/org/apache/cordova/file/Filesystem.java
deleted file mode 100644
index c69d3bd..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/Filesystem.java
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.cordova.file;
-
-import android.net.Uri;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import org.apache.cordova.CordovaResourceApi;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-public abstract class Filesystem {
-
- protected final Uri rootUri;
- protected final CordovaResourceApi resourceApi;
- public final String name;
- private JSONObject rootEntry;
-
- public Filesystem(Uri rootUri, String name, CordovaResourceApi resourceApi) {
- this.rootUri = rootUri;
- this.name = name;
- this.resourceApi = resourceApi;
- }
-
- public interface ReadFileCallback {
- public void handleData(InputStream inputStream, String contentType) throws IOException;
- }
-
- public static JSONObject makeEntryForURL(LocalFilesystemURL inputURL, Uri nativeURL) {
- try {
- String path = inputURL.path;
- int end = path.endsWith("/") ? 1 : 0;
- String[] parts = path.substring(0, path.length() - end).split("/+");
- String fileName = parts[parts.length - 1];
-
- JSONObject entry = new JSONObject();
- entry.put("isFile", !inputURL.isDirectory);
- entry.put("isDirectory", inputURL.isDirectory);
- entry.put("name", fileName);
- entry.put("fullPath", path);
- // The file system can't be specified, as it would lead to an infinite loop,
- // but the filesystem name can be.
- entry.put("filesystemName", inputURL.fsName);
- // Backwards compatibility
- entry.put("filesystem", "temporary".equals(inputURL.fsName) ? 0 : 1);
-
- String nativeUrlStr = nativeURL.toString();
- if (inputURL.isDirectory && !nativeUrlStr.endsWith("/")) {
- nativeUrlStr += "/";
- }
- entry.put("nativeURL", nativeUrlStr);
- return entry;
- } catch (JSONException e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- }
- }
-
- public JSONObject makeEntryForURL(LocalFilesystemURL inputURL) {
- Uri nativeUri = toNativeUri(inputURL);
- return nativeUri == null ? null : makeEntryForURL(inputURL, nativeUri);
- }
-
- public JSONObject makeEntryForNativeUri(Uri nativeUri) {
- LocalFilesystemURL inputUrl = toLocalUri(nativeUri);
- return inputUrl == null ? null : makeEntryForURL(inputUrl, nativeUri);
- }
-
- public JSONObject getEntryForLocalURL(LocalFilesystemURL inputURL) throws IOException {
- return makeEntryForURL(inputURL);
- }
-
- public JSONObject makeEntryForFile(File file) {
- return makeEntryForNativeUri(Uri.fromFile(file));
- }
-
- abstract JSONObject getFileForLocalURL(LocalFilesystemURL inputURL, String path,
- JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException;
-
- abstract boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException;
-
- abstract boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException, NoModificationAllowedException;
-
- abstract LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException;
-
- public final JSONArray readEntriesAtLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
- LocalFilesystemURL[] children = listChildren(inputURL);
- JSONArray entries = new JSONArray();
- if (children != null) {
- for (LocalFilesystemURL url : children) {
- entries.put(makeEntryForURL(url));
- }
- }
- return entries;
- }
-
- abstract JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;
-
- public Uri getRootUri() {
- return rootUri;
- }
-
- public boolean exists(LocalFilesystemURL inputURL) {
- try {
- getFileMetadataForLocalURL(inputURL);
- } catch (FileNotFoundException e) {
- return false;
- }
- return true;
- }
-
- public Uri nativeUriForFullPath(String fullPath) {
- Uri ret = null;
- if (fullPath != null) {
- String encodedPath = Uri.fromFile(new File(fullPath)).getEncodedPath();
- if (encodedPath.startsWith("/")) {
- encodedPath = encodedPath.substring(1);
- }
- ret = rootUri.buildUpon().appendEncodedPath(encodedPath).build();
- }
- return ret;
- }
-
- public LocalFilesystemURL localUrlforFullPath(String fullPath) {
- Uri nativeUri = nativeUriForFullPath(fullPath);
- if (nativeUri != null) {
- return toLocalUri(nativeUri);
- }
- return null;
- }
-
- /**
- * Removes multiple repeated //s, and collapses processes ../s.
- */
- protected static String normalizePath(String rawPath) {
- // If this is an absolute path, trim the leading "/" and replace it later
- boolean isAbsolutePath = rawPath.startsWith("/");
- if (isAbsolutePath) {
- rawPath = rawPath.replaceFirst("/+", "");
- }
- ArrayList components = new ArrayList(Arrays.asList(rawPath.split("/+")));
- for (int index = 0; index < components.size(); ++index) {
- if (components.get(index).equals("..")) {
- components.remove(index);
- if (index > 0) {
- components.remove(index-1);
- --index;
- }
- }
- }
- StringBuilder normalizedPath = new StringBuilder();
- for(String component: components) {
- normalizedPath.append("/");
- normalizedPath.append(component);
- }
- if (isAbsolutePath) {
- return normalizedPath.toString();
- } else {
- return normalizedPath.toString().substring(1);
- }
- }
-
- /**
- * Gets the free space in bytes available on this filesystem.
- * Subclasses may override this method to return nonzero free space.
- */
- public long getFreeSpaceInBytes() {
- return 0;
- }
-
- public abstract Uri toNativeUri(LocalFilesystemURL inputURL);
- public abstract LocalFilesystemURL toLocalUri(Uri inputURL);
-
- public JSONObject getRootEntry() {
- if (rootEntry == null) {
- rootEntry = makeEntryForNativeUri(rootUri);
- }
- return rootEntry;
- }
-
- public JSONObject getParentForLocalURL(LocalFilesystemURL inputURL) throws IOException {
- Uri parentUri = inputURL.uri;
- String parentPath = new File(inputURL.uri.getPath()).getParent();
- if (!"/".equals(parentPath)) {
- parentUri = inputURL.uri.buildUpon().path(parentPath + '/').build();
- }
- return getEntryForLocalURL(LocalFilesystemURL.parse(parentUri));
- }
-
- protected LocalFilesystemURL makeDestinationURL(String newName, LocalFilesystemURL srcURL, LocalFilesystemURL destURL, boolean isDirectory) {
- // I know this looks weird but it is to work around a JSON bug.
- if ("null".equals(newName) || "".equals(newName)) {
- newName = srcURL.uri.getLastPathSegment();;
- }
-
- String newDest = destURL.uri.toString();
- if (newDest.endsWith("/")) {
- newDest = newDest + newName;
- } else {
- newDest = newDest + "/" + newName;
- }
- if (isDirectory) {
- newDest += '/';
- }
- return LocalFilesystemURL.parse(newDest);
- }
-
- /* Read a source URL (possibly from a different filesystem, srcFs,) and copy it to
- * the destination URL on this filesystem, optionally with a new filename.
- * If move is true, then this method should either perform an atomic move operation
- * or remove the source file when finished.
- */
- public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
- Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
- // First, check to see that we can do it
- if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
- throw new NoModificationAllowedException("Cannot move file at source URL");
- }
- final LocalFilesystemURL destination = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
-
- Uri srcNativeUri = srcFs.toNativeUri(srcURL);
-
- CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(srcNativeUri);
- OutputStream os = null;
- try {
- os = getOutputStreamForURL(destination);
- } catch (IOException e) {
- ofrr.inputStream.close();
- throw e;
- }
- // Closes streams.
- resourceApi.copyResource(ofrr, os);
-
- if (move) {
- srcFs.removeFileAtLocalURL(srcURL);
- }
- return getEntryForLocalURL(destination);
- }
-
- public OutputStream getOutputStreamForURL(LocalFilesystemURL inputURL) throws IOException {
- return resourceApi.openOutputStream(toNativeUri(inputURL));
- }
-
- public void readFileAtURL(LocalFilesystemURL inputURL, long start, long end,
- ReadFileCallback readFileCallback) throws IOException {
- CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(toNativeUri(inputURL));
- if (end < 0) {
- end = ofrr.length;
- }
- long numBytesToRead = end - start;
- try {
- if (start > 0) {
- ofrr.inputStream.skip(start);
- }
- InputStream inputStream = ofrr.inputStream;
- if (end < ofrr.length) {
- inputStream = new LimitedInputStream(inputStream, numBytesToRead);
- }
- readFileCallback.handleData(inputStream, ofrr.mimeType);
- } finally {
- ofrr.inputStream.close();
- }
- }
-
- abstract long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset,
- boolean isBinary) throws NoModificationAllowedException, IOException;
-
- abstract long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
- throws IOException, NoModificationAllowedException;
-
- // This method should return null if filesystem urls cannot be mapped to paths
- abstract String filesystemPathForURL(LocalFilesystemURL url);
-
- abstract LocalFilesystemURL URLforFilesystemPath(String path);
-
- abstract boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL);
-
- protected class LimitedInputStream extends FilterInputStream {
- long numBytesToRead;
- public LimitedInputStream(InputStream in, long numBytesToRead) {
- super(in);
- this.numBytesToRead = numBytesToRead;
- }
- @Override
- public int read() throws IOException {
- if (numBytesToRead <= 0) {
- return -1;
- }
- numBytesToRead--;
- return in.read();
- }
- @Override
- public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
- if (numBytesToRead <= 0) {
- return -1;
- }
- int bytesToRead = byteCount;
- if (byteCount > numBytesToRead) {
- bytesToRead = (int)numBytesToRead; // Cast okay; long is less than int here.
- }
- int numBytesRead = in.read(buffer, byteOffset, bytesToRead);
- numBytesToRead -= numBytesRead;
- return numBytesRead;
- }
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/InvalidModificationException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/InvalidModificationException.java
deleted file mode 100644
index 8f6bec5..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/InvalidModificationException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-
-package org.apache.cordova.file;
-
-@SuppressWarnings("serial")
-public class InvalidModificationException extends Exception {
-
- public InvalidModificationException(String message) {
- super(message);
- }
-
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystem.java b/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystem.java
deleted file mode 100644
index 051f994..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystem.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.cordova.file;
-
-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.OutputStream;
-import java.io.RandomAccessFile;
-import java.nio.channels.FileChannel;
-import org.apache.cordova.CordovaResourceApi;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.os.Build;
-import android.os.Environment;
-import android.util.Base64;
-import android.net.Uri;
-import android.content.Context;
-import android.content.Intent;
-
-import java.nio.charset.Charset;
-
-public class LocalFilesystem extends Filesystem {
- private final Context context;
-
- public LocalFilesystem(String name, Context context, CordovaResourceApi resourceApi, File fsRoot) {
- super(Uri.fromFile(fsRoot).buildUpon().appendEncodedPath("").build(), name, resourceApi);
- this.context = context;
- }
-
- public String filesystemPathForFullPath(String fullPath) {
- return new File(rootUri.getPath(), fullPath).toString();
- }
-
- @Override
- public String filesystemPathForURL(LocalFilesystemURL url) {
- return filesystemPathForFullPath(url.path);
- }
-
- private String fullPathForFilesystemPath(String absolutePath) {
- if (absolutePath != null && absolutePath.startsWith(rootUri.getPath())) {
- return absolutePath.substring(rootUri.getPath().length() - 1);
- }
- return null;
- }
-
- @Override
- public Uri toNativeUri(LocalFilesystemURL inputURL) {
- return nativeUriForFullPath(inputURL.path);
- }
-
- @Override
- public LocalFilesystemURL toLocalUri(Uri inputURL) {
- if (!"file".equals(inputURL.getScheme())) {
- return null;
- }
- File f = new File(inputURL.getPath());
- // Removes and duplicate /s (e.g. file:///a//b/c)
- Uri resolvedUri = Uri.fromFile(f);
- String rootUriNoTrailingSlash = rootUri.getEncodedPath();
- rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
- if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
- return null;
- }
- String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
- // Strip leading slash
- if (!subPath.isEmpty()) {
- subPath = subPath.substring(1);
- }
- Uri.Builder b = new Uri.Builder()
- .scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
- .authority("localhost")
- .path(name);
- if (!subPath.isEmpty()) {
- b.appendEncodedPath(subPath);
- }
- if (f.isDirectory()) {
- // Add trailing / for directories.
- b.appendEncodedPath("");
- }
- return LocalFilesystemURL.parse(b.build());
- }
-
- @Override
- public LocalFilesystemURL URLforFilesystemPath(String path) {
- return localUrlforFullPath(fullPathForFilesystemPath(path));
- }
-
- @Override
- public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
- String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- boolean create = false;
- boolean exclusive = false;
-
- if (options != null) {
- create = options.optBoolean("create");
- if (create) {
- exclusive = options.optBoolean("exclusive");
- }
- }
-
- // Check for a ":" character in the file to line up with BB and iOS
- if (path.contains(":")) {
- throw new EncodingException("This path has an invalid \":\" in it.");
- }
-
- LocalFilesystemURL requestedURL;
-
- // Check whether the supplied path is absolute or relative
- if (directory && !path.endsWith("/")) {
- path += "/";
- }
- if (path.startsWith("/")) {
- requestedURL = localUrlforFullPath(normalizePath(path));
- } else {
- requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
- }
-
- File fp = new File(this.filesystemPathForURL(requestedURL));
-
- if (create) {
- if (exclusive && fp.exists()) {
- throw new FileExistsException("create/exclusive fails");
- }
- if (directory) {
- fp.mkdir();
- } else {
- fp.createNewFile();
- }
- if (!fp.exists()) {
- throw new FileExistsException("create fails");
- }
- }
- else {
- if (!fp.exists()) {
- throw new FileNotFoundException("path does not exist");
- }
- if (directory) {
- if (fp.isFile()) {
- throw new TypeMismatchException("path doesn't exist or is file");
- }
- } else {
- if (fp.isDirectory()) {
- throw new TypeMismatchException("path doesn't exist or is directory");
- }
- }
- }
-
- // Return the directory
- return makeEntryForURL(requestedURL);
- }
-
- @Override
- public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException {
-
- File fp = new File(filesystemPathForURL(inputURL));
-
- // You can't delete a directory that is not empty
- if (fp.isDirectory() && fp.list().length > 0) {
- throw new InvalidModificationException("You can't delete a directory that is not empty.");
- }
-
- return fp.delete();
- }
-
- @Override
- public boolean exists(LocalFilesystemURL inputURL) {
- File fp = new File(filesystemPathForURL(inputURL));
- return fp.exists();
- }
-
- @Override
- public long getFreeSpaceInBytes() {
- return DirectoryManager.getFreeSpaceInBytes(rootUri.getPath());
- }
-
- @Override
- public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException {
- File directory = new File(filesystemPathForURL(inputURL));
- return removeDirRecursively(directory);
- }
-
- protected boolean removeDirRecursively(File directory) throws FileExistsException {
- if (directory.isDirectory()) {
- for (File file : directory.listFiles()) {
- removeDirRecursively(file);
- }
- }
-
- if (!directory.delete()) {
- throw new FileExistsException("could not delete: " + directory.getName());
- } else {
- return true;
- }
- }
-
- @Override
- public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
- File fp = new File(filesystemPathForURL(inputURL));
-
- if (!fp.exists()) {
- // The directory we are listing doesn't exist so we should fail.
- throw new FileNotFoundException();
- }
-
- File[] files = fp.listFiles();
- if (files == null) {
- // inputURL is a directory
- return null;
- }
- LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
- for (int i = 0; i < files.length; i++) {
- entries[i] = URLforFilesystemPath(files[i].getPath());
- }
-
- return entries;
- }
-
- @Override
- public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
- File file = new File(filesystemPathForURL(inputURL));
-
- if (!file.exists()) {
- throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
- }
-
- JSONObject metadata = new JSONObject();
- try {
- // Ensure that directories report a size of 0
- metadata.put("size", file.isDirectory() ? 0 : file.length());
- metadata.put("type", resourceApi.getMimeType(Uri.fromFile(file)));
- metadata.put("name", file.getName());
- metadata.put("fullPath", inputURL.path);
- metadata.put("lastModifiedDate", file.lastModified());
- } catch (JSONException e) {
- return null;
- }
- return metadata;
- }
-
- private void copyFile(Filesystem srcFs, LocalFilesystemURL srcURL, File destFile, boolean move) throws IOException, InvalidModificationException, NoModificationAllowedException {
- if (move) {
- String realSrcPath = srcFs.filesystemPathForURL(srcURL);
- if (realSrcPath != null) {
- File srcFile = new File(realSrcPath);
- if (srcFile.renameTo(destFile)) {
- return;
- }
- // Trying to rename the file failed. Possibly because we moved across file system on the device.
- }
- }
-
- CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(srcFs.toNativeUri(srcURL));
- copyResource(offr, new FileOutputStream(destFile));
-
- if (move) {
- srcFs.removeFileAtLocalURL(srcURL);
- }
- }
-
- private void copyDirectory(Filesystem srcFs, LocalFilesystemURL srcURL, File dstDir, boolean move) throws IOException, NoModificationAllowedException, InvalidModificationException, FileExistsException {
- if (move) {
- String realSrcPath = srcFs.filesystemPathForURL(srcURL);
- if (realSrcPath != null) {
- File srcDir = new File(realSrcPath);
- // If the destination directory already exists and is empty then delete it. This is according to spec.
- if (dstDir.exists()) {
- if (dstDir.list().length > 0) {
- throw new InvalidModificationException("directory is not empty");
- }
- dstDir.delete();
- }
- // Try to rename the directory
- if (srcDir.renameTo(dstDir)) {
- return;
- }
- // Trying to rename the file failed. Possibly because we moved across file system on the device.
- }
- }
-
- if (dstDir.exists()) {
- if (dstDir.list().length > 0) {
- throw new InvalidModificationException("directory is not empty");
- }
- } else {
- if (!dstDir.mkdir()) {
- // If we can't create the directory then fail
- throw new NoModificationAllowedException("Couldn't create the destination directory");
- }
- }
-
- LocalFilesystemURL[] children = srcFs.listChildren(srcURL);
- for (LocalFilesystemURL childLocalUrl : children) {
- File target = new File(dstDir, new File(childLocalUrl.path).getName());
- if (childLocalUrl.isDirectory) {
- copyDirectory(srcFs, childLocalUrl, target, false);
- } else {
- copyFile(srcFs, childLocalUrl, target, false);
- }
- }
-
- if (move) {
- srcFs.recursiveRemoveFileAtLocalURL(srcURL);
- }
- }
-
- @Override
- public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
- Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
-
- // Check to see if the destination directory exists
- String newParent = this.filesystemPathForURL(destURL);
- File destinationDir = new File(newParent);
- if (!destinationDir.exists()) {
- // The destination does not exist so we should fail.
- throw new FileNotFoundException("The source does not exist");
- }
-
- // Figure out where we should be copying to
- final LocalFilesystemURL destinationURL = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
-
- Uri dstNativeUri = toNativeUri(destinationURL);
- Uri srcNativeUri = srcFs.toNativeUri(srcURL);
- // Check to see if source and destination are the same file
- if (dstNativeUri.equals(srcNativeUri)) {
- throw new InvalidModificationException("Can't copy onto itself");
- }
-
- if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
- throw new InvalidModificationException("Source URL is read-only (cannot move)");
- }
-
- File destFile = new File(dstNativeUri.getPath());
- if (destFile.exists()) {
- if (!srcURL.isDirectory && destFile.isDirectory()) {
- throw new InvalidModificationException("Can't copy/move a file to an existing directory");
- } else if (srcURL.isDirectory && destFile.isFile()) {
- throw new InvalidModificationException("Can't copy/move a directory to an existing file");
- }
- }
-
- if (srcURL.isDirectory) {
- // E.g. Copy /sdcard/myDir to /sdcard/myDir/backup
- if (dstNativeUri.toString().startsWith(srcNativeUri.toString() + '/')) {
- throw new InvalidModificationException("Can't copy directory into itself");
- }
- copyDirectory(srcFs, srcURL, destFile, move);
- } else {
- copyFile(srcFs, srcURL, destFile, move);
- }
- return makeEntryForURL(destinationURL);
- }
-
- @Override
- public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
- int offset, boolean isBinary) throws IOException, NoModificationAllowedException {
-
- boolean append = false;
- if (offset > 0) {
- this.truncateFileAtURL(inputURL, offset);
- append = true;
- }
-
- byte[] rawData;
- if (isBinary) {
- rawData = Base64.decode(data, Base64.DEFAULT);
- } else {
- rawData = data.getBytes(Charset.defaultCharset());
- }
- ByteArrayInputStream in = new ByteArrayInputStream(rawData);
- try
- {
- byte buff[] = new byte[rawData.length];
- String absolutePath = filesystemPathForURL(inputURL);
- FileOutputStream out = new FileOutputStream(absolutePath, append);
- try {
- in.read(buff, 0, buff.length);
- out.write(buff, 0, rawData.length);
- out.flush();
- } finally {
- // Always close the output
- out.close();
- }
- if (isPublicDirectory(absolutePath)) {
- broadcastNewFile(Uri.fromFile(new File(absolutePath)));
- }
- }
- catch (NullPointerException e)
- {
- // This is a bug in the Android implementation of the Java Stack
- NoModificationAllowedException realException = new NoModificationAllowedException(inputURL.toString());
- realException.initCause(e);
- throw realException;
- }
-
- return rawData.length;
- }
-
- private boolean isPublicDirectory(String absolutePath) {
- // TODO: should expose a way to scan app's private files (maybe via a flag).
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- // Lollipop has a bug where SD cards are null.
- for (File f : context.getExternalMediaDirs()) {
- if(f != null && absolutePath.startsWith(f.getAbsolutePath())) {
- return true;
- }
- }
- }
-
- String extPath = Environment.getExternalStorageDirectory().getAbsolutePath();
- return absolutePath.startsWith(extPath);
- }
-
- /**
- * Send broadcast of new file so files appear over MTP
- */
- private void broadcastNewFile(Uri nativeUri) {
- Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, nativeUri);
- context.sendBroadcast(intent);
- }
-
- @Override
- public long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException {
- File file = new File(filesystemPathForURL(inputURL));
-
- if (!file.exists()) {
- throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
- }
-
- RandomAccessFile raf = new RandomAccessFile(filesystemPathForURL(inputURL), "rw");
- try {
- if (raf.length() >= size) {
- FileChannel channel = raf.getChannel();
- channel.truncate(size);
- return size;
- }
-
- return raf.length();
- } finally {
- raf.close();
- }
-
-
- }
-
- @Override
- public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
- String path = filesystemPathForURL(inputURL);
- File file = new File(path);
- return file.exists();
- }
-
- // This is a copy & paste from CordovaResource API that is required since CordovaResourceApi
- // has a bug pre-4.0.0.
- // TODO: Once cordova-android@4.0.0 is released, delete this copy and make the plugin depend on
- // 4.0.0 with an engine tag.
- private static void copyResource(CordovaResourceApi.OpenForReadResult input, OutputStream outputStream) throws IOException {
- try {
- InputStream inputStream = input.inputStream;
- if (inputStream instanceof FileInputStream && outputStream instanceof FileOutputStream) {
- FileChannel inChannel = ((FileInputStream)input.inputStream).getChannel();
- FileChannel outChannel = ((FileOutputStream)outputStream).getChannel();
- long offset = 0;
- long length = input.length;
- if (input.assetFd != null) {
- offset = input.assetFd.getStartOffset();
- }
- // transferFrom()'s 2nd arg is a relative position. Need to set the absolute
- // position first.
- inChannel.position(offset);
- outChannel.transferFrom(inChannel, 0, length);
- } else {
- final int BUFFER_SIZE = 8192;
- byte[] buffer = new byte[BUFFER_SIZE];
-
- for (;;) {
- int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
-
- if (bytesRead <= 0) {
- break;
- }
- outputStream.write(buffer, 0, bytesRead);
- }
- }
- } finally {
- input.inputStream.close();
- if (outputStream != null) {
- outputStream.close();
- }
- }
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystemURL.java b/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystemURL.java
deleted file mode 100644
index b96b6ee..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/LocalFilesystemURL.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-package org.apache.cordova.file;
-
-import android.net.Uri;
-
-public class LocalFilesystemURL {
-
- public static final String FILESYSTEM_PROTOCOL = "cdvfile";
-
- public final Uri uri;
- public final String fsName;
- public final String path;
- public final boolean isDirectory;
-
- private LocalFilesystemURL(Uri uri, String fsName, String fsPath, boolean isDirectory) {
- this.uri = uri;
- this.fsName = fsName;
- this.path = fsPath;
- this.isDirectory = isDirectory;
- }
-
- public static LocalFilesystemURL parse(Uri uri) {
- if (!FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
- return null;
- }
- String path = uri.getPath();
- if (path.length() < 1) {
- return null;
- }
- int firstSlashIdx = path.indexOf('/', 1);
- if (firstSlashIdx < 0) {
- return null;
- }
- String fsName = path.substring(1, firstSlashIdx);
- path = path.substring(firstSlashIdx);
- boolean isDirectory = path.charAt(path.length() - 1) == '/';
- return new LocalFilesystemURL(uri, fsName, path, isDirectory);
- }
-
- public static LocalFilesystemURL parse(String uri) {
- return parse(Uri.parse(uri));
- }
-
- public String toString() {
- return uri.toString();
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/NoModificationAllowedException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/NoModificationAllowedException.java
deleted file mode 100644
index 627eafb..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/NoModificationAllowedException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova.file;
-
-@SuppressWarnings("serial")
-public class NoModificationAllowedException extends Exception {
-
- public NoModificationAllowedException(String message) {
- super(message);
- }
-
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/PendingRequests.java b/platforms/android/app/src/main/java/org/apache/cordova/file/PendingRequests.java
deleted file mode 100644
index 23d6d73..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/PendingRequests.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.file;
-
-import android.util.SparseArray;
-
-import org.apache.cordova.CallbackContext;
-
-/**
- * Holds pending runtime permission requests
- */
-class PendingRequests {
- private int currentReqId = 0;
- private SparseArray requests = new SparseArray();
-
- /**
- * Creates a request and adds it to the array of pending requests. Each created request gets a
- * unique result code for use with requestPermission()
- * @param rawArgs The raw arguments passed to the plugin
- * @param action The action this request corresponds to (get file, etc.)
- * @param callbackContext The CallbackContext for this plugin call
- * @return The request code that can be used to retrieve the Request object
- */
- public synchronized int createRequest(String rawArgs, int action, CallbackContext callbackContext) {
- Request req = new Request(rawArgs, action, callbackContext);
- requests.put(req.requestCode, req);
- return req.requestCode;
- }
-
- /**
- * Gets the request corresponding to this request code and removes it from the pending requests
- * @param requestCode The request code for the desired request
- * @return The request corresponding to the given request code or null if such a
- * request is not found
- */
- public synchronized Request getAndRemove(int requestCode) {
- Request result = requests.get(requestCode);
- requests.remove(requestCode);
- return result;
- }
-
- /**
- * Holds the options and CallbackContext for a call made to the plugin.
- */
- public class Request {
-
- // Unique int used to identify this request in any Android permission callback
- private int requestCode;
-
- // Action to be performed after permission request result
- private int action;
-
- // Raw arguments passed to plugin
- private String rawArgs;
-
- // The callback context for this plugin request
- private CallbackContext callbackContext;
-
- private Request(String rawArgs, int action, CallbackContext callbackContext) {
- this.rawArgs = rawArgs;
- this.action = action;
- this.callbackContext = callbackContext;
- this.requestCode = currentReqId ++;
- }
-
- public int getAction() {
- return this.action;
- }
-
- public String getRawArgs() {
- return rawArgs;
- }
-
- public CallbackContext getCallbackContext() {
- return callbackContext;
- }
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/file/TypeMismatchException.java b/platforms/android/app/src/main/java/org/apache/cordova/file/TypeMismatchException.java
deleted file mode 100644
index 1315f9a..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/file/TypeMismatchException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-
-package org.apache.cordova.file;
-
-@SuppressWarnings("serial")
-public class TypeMismatchException extends Exception {
-
- public TypeMismatchException(String message) {
- super(message);
- }
-
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/filetransfer/FileProgressResult.java b/platforms/android/app/src/main/java/org/apache/cordova/filetransfer/FileProgressResult.java
deleted file mode 100644
index 76a7b13..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/filetransfer/FileProgressResult.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.filetransfer;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * Encapsulates in-progress status of uploading or downloading a file to a remote server.
- */
-public class FileProgressResult {
-
- private boolean lengthComputable = false; // declares whether total is known
- private long loaded = 0; // bytes sent so far
- private long total = 0; // bytes total, if known
-
- public boolean getLengthComputable() {
- return lengthComputable;
- }
-
- public void setLengthComputable(boolean computable) {
- this.lengthComputable = computable;
- }
-
- public long getLoaded() {
- return loaded;
- }
-
- public void setLoaded(long bytes) {
- this.loaded = bytes;
- }
-
- public long getTotal() {
- return total;
- }
-
- public void setTotal(long bytes) {
- this.total = bytes;
- }
-
- public JSONObject toJSONObject() throws JSONException {
- return new JSONObject(
- "{loaded:" + loaded +
- ",total:" + total +
- ",lengthComputable:" + (lengthComputable ? "true" : "false") + "}");
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/filetransfer/FileTransfer.java b/platforms/android/app/src/main/java/org/apache/cordova/filetransfer/FileTransfer.java
deleted file mode 100644
index 5a3c5d6..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/filetransfer/FileTransfer.java
+++ /dev/null
@@ -1,932 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.filetransfer;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.net.HttpURLConnection;
-import java.net.URLConnection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.Inflater;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaResourceApi;
-import org.apache.cordova.CordovaResourceApi.OpenForReadResult;
-import org.apache.cordova.LOG;
-import org.apache.cordova.PluginManager;
-import org.apache.cordova.PluginResult;
-import org.apache.cordova.Whitelist;
-import org.apache.cordova.file.FileUtils;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import android.net.Uri;
-import android.os.Build;
-import android.webkit.CookieManager;
-
-public class FileTransfer extends CordovaPlugin {
-
- private static final String LOG_TAG = "FileTransfer";
- private static final String LINE_START = "--";
- private static final String LINE_END = "\r\n";
- private static final String BOUNDARY = "+++++";
-
- public static int FILE_NOT_FOUND_ERR = 1;
- public static int INVALID_URL_ERR = 2;
- public static int CONNECTION_ERR = 3;
- public static int ABORTED_ERR = 4;
- public static int NOT_MODIFIED_ERR = 5;
-
- private static HashMap activeRequests = new HashMap();
- private static final int MAX_BUFFER_SIZE = 16 * 1024;
-
- private static final class RequestContext {
- String source;
- String target;
- File targetFile;
- CallbackContext callbackContext;
- HttpURLConnection connection;
- boolean aborted;
- RequestContext(String source, String target, CallbackContext callbackContext) {
- this.source = source;
- this.target = target;
- this.callbackContext = callbackContext;
- }
- void sendPluginResult(PluginResult pluginResult) {
- synchronized (this) {
- if (!aborted) {
- callbackContext.sendPluginResult(pluginResult);
- }
- }
- }
- }
-
- /**
- * Adds an interface method to an InputStream to return the number of bytes
- * read from the raw stream. This is used to track total progress against
- * the HTTP Content-Length header value from the server.
- */
- private static abstract class TrackingInputStream extends FilterInputStream {
- public TrackingInputStream(final InputStream in) {
- super(in);
- }
- public abstract long getTotalRawBytesRead();
- }
-
- private static class ExposedGZIPInputStream extends GZIPInputStream {
- public ExposedGZIPInputStream(final InputStream in) throws IOException {
- super(in);
- }
- public Inflater getInflater() {
- return inf;
- }
- }
-
- /**
- * Provides raw bytes-read tracking for a GZIP input stream. Reports the
- * total number of compressed bytes read from the input, rather than the
- * number of uncompressed bytes.
- */
- private static class TrackingGZIPInputStream extends TrackingInputStream {
- private ExposedGZIPInputStream gzin;
- public TrackingGZIPInputStream(final ExposedGZIPInputStream gzin) throws IOException {
- super(gzin);
- this.gzin = gzin;
- }
- public long getTotalRawBytesRead() {
- return gzin.getInflater().getBytesRead();
- }
- }
-
- /**
- * Provides simple total-bytes-read tracking for an existing InputStream
- */
- private static class SimpleTrackingInputStream extends TrackingInputStream {
- private long bytesRead = 0;
- public SimpleTrackingInputStream(InputStream stream) {
- super(stream);
- }
-
- private int updateBytesRead(int newBytesRead) {
- if (newBytesRead != -1) {
- bytesRead += newBytesRead;
- }
- return newBytesRead;
- }
-
- @Override
- public int read() throws IOException {
- return updateBytesRead(super.read());
- }
-
- // Note: FilterInputStream delegates read(byte[] bytes) to the below method,
- // so we don't override it or else double count (CB-5631).
- @Override
- public int read(byte[] bytes, int offset, int count) throws IOException {
- return updateBytesRead(super.read(bytes, offset, count));
- }
-
- public long getTotalRawBytesRead() {
- return bytesRead;
- }
- }
-
- @Override
- public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
- if (action.equals("upload") || action.equals("download")) {
- String source = args.getString(0);
- String target = args.getString(1);
-
- if (action.equals("upload")) {
- upload(source, target, args, callbackContext);
- } else {
- download(source, target, args, callbackContext);
- }
- return true;
- } else if (action.equals("abort")) {
- String objectId = args.getString(0);
- abort(objectId);
- callbackContext.success();
- return true;
- }
- return false;
- }
-
- private static void addHeadersToRequest(URLConnection connection, JSONObject headers) {
- try {
- for (Iterator> iter = headers.keys(); iter.hasNext(); ) {
- /* RFC 2616 says that non-ASCII characters and control
- * characters are not allowed in header names or values.
- * Additionally, spaces are not allowed in header names.
- * RFC 2046 Quoted-printable encoding may be used to encode
- * arbitrary characters, but we donon- not do that encoding here.
- */
- String headerKey = iter.next().toString();
- String cleanHeaderKey = headerKey.replaceAll("\\n","")
- .replaceAll("\\s+","")
- .replaceAll(":", "")
- .replaceAll("[^\\x20-\\x7E]+", "");
-
- JSONArray headerValues = headers.optJSONArray(headerKey);
- if (headerValues == null) {
- headerValues = new JSONArray();
-
- /* RFC 2616 also says that any amount of consecutive linear
- * whitespace within a header value can be replaced with a
- * single space character, without affecting the meaning of
- * that value.
- */
-
- String headerValue = headers.getString(headerKey);
- String finalValue = headerValue.replaceAll("\\s+", " ").replaceAll("\\n"," ").replaceAll("[^\\x20-\\x7E]+", " ");
- headerValues.put(finalValue);
- }
-
- //Use the clean header key, not the one that we passed in
- connection.setRequestProperty(cleanHeaderKey, 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!
- }
- }
-
- private String getCookies(final String target) {
- boolean gotCookie = false;
- String cookie = null;
- Class webViewClass = webView.getClass();
- try {
- Method gcmMethod = webViewClass.getMethod("getCookieManager");
- Class iccmClass = gcmMethod.getReturnType();
- Method gcMethod = iccmClass.getMethod("getCookie", String.class);
-
- cookie = (String)gcMethod.invoke(
- iccmClass.cast(
- gcmMethod.invoke(webView)
- ), target);
-
- gotCookie = true;
- } catch (NoSuchMethodException e) {
- } catch (IllegalAccessException e) {
- } catch (InvocationTargetException e) {
- } catch (ClassCastException e) {
- }
-
- if (!gotCookie && CookieManager.getInstance() != null) {
- cookie = CookieManager.getInstance().getCookie(target);
- }
-
- return cookie;
- }
-
- /**
- * 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
- * @param target URL of the server to receive the file
- * @param args JSON Array of args
- * @param callbackContext callback id for optional progress reports
- *
- * args[2] fileKey Name of file request parameter
- * args[3] fileName File name to be used on server
- * args[4] mimeType Describes file content type
- * args[5] params key:value pairs of user-defined parameters
- * @return FileUploadResult containing result of upload request
- */
- private void upload(final String source, final String target, JSONArray args, CallbackContext callbackContext) throws JSONException {
- LOG.d(LOG_TAG, "upload " + source + " to " + target);
-
- // Setup the options
- final String fileKey = getArgument(args, 2, "file");
- final String fileName = getArgument(args, 3, "image.jpg");
- final String mimeType = getArgument(args, 4, "image/jpeg");
- final JSONObject params = args.optJSONObject(5) == null ? new JSONObject() : args.optJSONObject(5);
- // Always use chunked mode unless set to false as per API
- final boolean chunkedMode = args.optBoolean(7) || args.isNull(7);
- // Look for headers on the params map for backwards compatibility with older Cordova versions.
- final JSONObject headers = args.optJSONObject(8) == null ? params.optJSONObject("headers") : args.optJSONObject(8);
- final String objectId = args.getString(9);
- final String httpMethod = getArgument(args, 10, "POST");
-
- final CordovaResourceApi resourceApi = webView.getResourceApi();
-
- LOG.d(LOG_TAG, "fileKey: " + fileKey);
- LOG.d(LOG_TAG, "fileName: " + fileName);
- LOG.d(LOG_TAG, "mimeType: " + mimeType);
- LOG.d(LOG_TAG, "params: " + params);
- LOG.d(LOG_TAG, "chunkedMode: " + chunkedMode);
- LOG.d(LOG_TAG, "headers: " + headers);
- LOG.d(LOG_TAG, "objectId: " + objectId);
- LOG.d(LOG_TAG, "httpMethod: " + httpMethod);
-
- final Uri targetUri = resourceApi.remapUri(Uri.parse(target));
-
- int uriType = CordovaResourceApi.getUriType(targetUri);
- final boolean useHttps = uriType == CordovaResourceApi.URI_TYPE_HTTPS;
- if (uriType != CordovaResourceApi.URI_TYPE_HTTP && !useHttps) {
- JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, null, 0, null);
- LOG.e(LOG_TAG, "Unsupported URI: " + targetUri);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
- return;
- }
-
- final RequestContext context = new RequestContext(source, target, callbackContext);
- synchronized (activeRequests) {
- activeRequests.put(objectId, context);
- }
-
- cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- if (context.aborted) {
- return;
- }
-
- // We should call remapUri on background thread otherwise it throws
- // IllegalStateException when trying to remap 'cdvfile://localhost/content/...' URIs
- // via ContentFilesystem (see https://issues.apache.org/jira/browse/CB-9022)
- Uri tmpSrc = Uri.parse(source);
- final Uri sourceUri = resourceApi.remapUri(
- tmpSrc.getScheme() != null ? tmpSrc : Uri.fromFile(new File(source)));
-
- HttpURLConnection conn = null;
- int totalBytes = 0;
- int fixedLength = -1;
- try {
- // Create return object
- FileUploadResult result = new FileUploadResult();
- FileProgressResult progress = new FileProgressResult();
-
- //------------------ CLIENT REQUEST
- // Open a HTTP connection to the URL based on protocol
- conn = resourceApi.createHttpConnection(targetUri);
-
- // Allow Inputs
- conn.setDoInput(true);
-
- // Allow Outputs
- conn.setDoOutput(true);
-
- // Don't use a cached copy.
- conn.setUseCaches(false);
-
- // Use a post method.
- conn.setRequestMethod(httpMethod);
-
- // if we specified a Content-Type header, don't do multipart form upload
- boolean multipartFormUpload = (headers == null) || !headers.has("Content-Type");
- if (multipartFormUpload) {
- conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
- }
-
- // Set the cookies on the response
- String cookie = getCookies(target);
-
- if (cookie != null) {
- conn.setRequestProperty("Cookie", cookie);
- }
-
- // Handle the other headers
- if (headers != null) {
- addHeadersToRequest(conn, headers);
- }
-
- /*
- * 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.
- */
- StringBuilder beforeData = new StringBuilder();
- try {
- for (Iterator> iter = params.keys(); iter.hasNext();) {
- Object key = iter.next();
- if(!String.valueOf(key).equals("headers"))
- {
- beforeData.append(LINE_START).append(BOUNDARY).append(LINE_END);
- beforeData.append("Content-Disposition: form-data; name=\"").append(key.toString()).append('"');
- beforeData.append(LINE_END).append(LINE_END);
- beforeData.append(params.getString(key.toString()));
- beforeData.append(LINE_END);
- }
- }
- } catch (JSONException e) {
- LOG.e(LOG_TAG, e.getMessage(), e);
- }
-
- beforeData.append(LINE_START).append(BOUNDARY).append(LINE_END);
- beforeData.append("Content-Disposition: form-data; name=\"").append(fileKey).append("\";");
- beforeData.append(" filename=\"").append(fileName).append('"').append(LINE_END);
- beforeData.append("Content-Type: ").append(mimeType).append(LINE_END).append(LINE_END);
- byte[] beforeDataBytes = beforeData.toString().getBytes("UTF-8");
- byte[] tailParamsBytes = (LINE_END + LINE_START + BOUNDARY + LINE_START + LINE_END).getBytes("UTF-8");
-
-
- // Get a input stream of the file on the phone
- OpenForReadResult readResult = resourceApi.openForRead(sourceUri);
-
- int stringLength = beforeDataBytes.length + tailParamsBytes.length;
- if (readResult.length >= 0) {
- fixedLength = (int)readResult.length;
- if (multipartFormUpload)
- fixedLength += stringLength;
- progress.setLengthComputable(true);
- progress.setTotal(fixedLength);
- }
- LOG.d(LOG_TAG, "Content Length: " + fixedLength);
- // setFixedLengthStreamingMode causes and OutOfMemoryException on pre-Froyo devices.
- // http://code.google.com/p/android/issues/detail?id=3164
- // It also causes OOM if HTTPS is used, even on newer devices.
- boolean useChunkedMode = chunkedMode || (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO);
- useChunkedMode = useChunkedMode || (fixedLength == -1);
-
- if (useChunkedMode) {
- conn.setChunkedStreamingMode(MAX_BUFFER_SIZE);
- // Although setChunkedStreamingMode sets this header, setting it explicitly here works
- // around an OutOfMemoryException when using https.
- conn.setRequestProperty("Transfer-Encoding", "chunked");
- } else {
- conn.setFixedLengthStreamingMode(fixedLength);
-
- if (useHttps) {
- LOG.w(LOG_TAG, "setFixedLengthStreamingMode could cause OutOfMemoryException - switch to chunkedMode=true to avoid it if this is an issue.");
- }
- }
-
- conn.connect();
-
- OutputStream sendStream = null;
- try {
- sendStream = conn.getOutputStream();
- synchronized (context) {
- if (context.aborted) {
- return;
- }
- context.connection = conn;
- }
-
- if (multipartFormUpload) {
- //We don't want to change encoding, we just want this to write for all Unicode.
- sendStream.write(beforeDataBytes);
- totalBytes += beforeDataBytes.length;
- }
-
- // create a buffer of maximum size
- int bytesAvailable = readResult.inputStream.available();
- int bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
- byte[] buffer = new byte[bufferSize];
-
- // read file and write it into form...
- int bytesRead = readResult.inputStream.read(buffer, 0, bufferSize);
-
- long prevBytesRead = 0;
- while (bytesRead > 0) {
- totalBytes += bytesRead;
- result.setBytesSent(totalBytes);
- sendStream.write(buffer, 0, bytesRead);
- if (totalBytes > prevBytesRead + 102400) {
- prevBytesRead = totalBytes;
- LOG.d(LOG_TAG, "Uploaded " + totalBytes + " of " + fixedLength + " bytes");
- }
- bytesAvailable = readResult.inputStream.available();
- bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
- bytesRead = readResult.inputStream.read(buffer, 0, bufferSize);
-
- // Send a progress event.
- progress.setLoaded(totalBytes);
- PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject());
- progressResult.setKeepCallback(true);
- context.sendPluginResult(progressResult);
- }
-
- if (multipartFormUpload) {
- // send multipart form data necessary after file data...
- sendStream.write(tailParamsBytes);
- totalBytes += tailParamsBytes.length;
- }
- sendStream.flush();
- } finally {
- safeClose(readResult.inputStream);
- safeClose(sendStream);
- }
- synchronized (context) {
- context.connection = null;
- }
- LOG.d(LOG_TAG, "Sent " + totalBytes + " of " + fixedLength);
-
- //------------------ read the SERVER RESPONSE
- String responseString;
- int responseCode = conn.getResponseCode();
- LOG.d(LOG_TAG, "response code: " + responseCode);
- LOG.d(LOG_TAG, "response headers: " + conn.getHeaderFields());
- TrackingInputStream inStream = null;
- try {
- inStream = getInputStream(conn);
- synchronized (context) {
- if (context.aborted) {
- return;
- }
- context.connection = conn;
- }
-
- ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(1024, conn.getContentLength()));
- byte[] buffer = new byte[1024];
- int bytesRead = 0;
- // write bytes to file
- while ((bytesRead = inStream.read(buffer)) > 0) {
- out.write(buffer, 0, bytesRead);
- }
- responseString = out.toString("UTF-8");
- } finally {
- synchronized (context) {
- context.connection = null;
- }
- safeClose(inStream);
- }
-
- LOG.d(LOG_TAG, "got response from server");
- LOG.d(LOG_TAG, responseString.substring(0, Math.min(256, responseString.length())));
-
- // send request and retrieve response
- result.setResponseCode(responseCode);
- result.setResponse(responseString);
-
- context.sendPluginResult(new PluginResult(PluginResult.Status.OK, result.toJSONObject()));
- } catch (FileNotFoundException e) {
- JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target, conn, e);
- LOG.e(LOG_TAG, error.toString(), e);
- context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
- } catch (IOException e) {
- JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, conn, e);
- LOG.e(LOG_TAG, error.toString(), e);
- LOG.e(LOG_TAG, "Failed after uploading " + totalBytes + " of " + fixedLength + " bytes.");
- context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
- } catch (JSONException e) {
- LOG.e(LOG_TAG, e.getMessage(), e);
- context.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
- } catch (Throwable t) {
- // Shouldn't happen, but will
- JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, conn, t);
- LOG.e(LOG_TAG, error.toString(), t);
- context.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
- } finally {
- synchronized (activeRequests) {
- activeRequests.remove(objectId);
- }
- }
- }
- });
- }
-
- private static void safeClose(Closeable stream) {
- if (stream != null) {
- try {
- stream.close();
- } catch (IOException e) {
- }
- }
- }
-
- private static TrackingInputStream getInputStream(URLConnection conn) throws IOException {
- String encoding = conn.getContentEncoding();
- if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
- return new TrackingGZIPInputStream(new ExposedGZIPInputStream(conn.getInputStream()));
- }
- return new SimpleTrackingInputStream(conn.getInputStream());
- }
-
- private static JSONObject createFileTransferError(int errorCode, String source, String target, URLConnection connection, Throwable throwable) {
-
- 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"));
- try {
- String line = reader.readLine();
- while(line != null) {
- bodyBuilder.append(line);
- line = reader.readLine();
- if(line != null) {
- bodyBuilder.append('\n');
- }
- }
- body = bodyBuilder.toString();
- } finally {
- reader.close();
- }
- }
- }
- // IOException can leave connection object in a bad state, so catch all exceptions.
- } catch (Throwable e) {
- LOG.w(LOG_TAG, "Error getting HTTP status code from connection.", e);
- }
- }
-
- return createFileTransferError(errorCode, source, target, body, httpStatus, throwable);
- }
-
- /**
- * Create an error object based on the passed in errorCode
- * @param errorCode the error
- * @return JSONObject containing the error
- */
- private static JSONObject createFileTransferError(int errorCode, String source, String target, String body, Integer httpStatus, Throwable throwable) {
- 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);
- }
- if (throwable != null) {
- String msg = throwable.getMessage();
- if (msg == null || "".equals(msg)) {
- msg = throwable.toString();
- }
- error.put("exception", msg);
- }
- } catch (JSONException e) {
- LOG.e(LOG_TAG, e.getMessage(), e);
- }
- return error;
- }
-
- /**
- * Convenience method to read a parameter from the list of JSON args.
- * @param args the args passed to the Plugin
- * @param position the position to retrieve the arg from
- * @param defaultString the default to be used if the arg does not exist
- * @return String with the retrieved value
- */
- private static String getArgument(JSONArray args, int position, String defaultString) {
- String arg = defaultString;
- if (args.length() > position) {
- arg = args.optString(position);
- if (arg == null || "null".equals(arg)) {
- arg = defaultString;
- }
- }
- return arg;
- }
-
- /**
- * Downloads a file form a given URL and saves it to the specified directory.
- *
- * @param source URL of the server to receive the file
- * @param target Full path of the file on the file system
- */
- private void download(final String source, final String target, JSONArray args, CallbackContext callbackContext) throws JSONException {
- LOG.d(LOG_TAG, "download " + source + " to " + target);
-
- final CordovaResourceApi resourceApi = webView.getResourceApi();
-
- final String objectId = args.getString(3);
- final JSONObject headers = args.optJSONObject(4);
-
- final Uri sourceUri = resourceApi.remapUri(Uri.parse(source));
- int uriType = CordovaResourceApi.getUriType(sourceUri);
- final boolean useHttps = uriType == CordovaResourceApi.URI_TYPE_HTTPS;
- final boolean isLocalTransfer = !useHttps && uriType != CordovaResourceApi.URI_TYPE_HTTP;
- if (uriType == CordovaResourceApi.URI_TYPE_UNKNOWN) {
- JSONObject error = createFileTransferError(INVALID_URL_ERR, source, target, null, 0, null);
- LOG.e(LOG_TAG, "Unsupported URI: " + sourceUri);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
- return;
- }
-
- /* This code exists for compatibility between 3.x and 4.x versions of Cordova.
- * Previously the CordovaWebView class had a method, getWhitelist, which would
- * return a Whitelist object. Since the fixed whitelist is removed in Cordova 4.x,
- * the correct call now is to shouldAllowRequest from the plugin manager.
- */
- Boolean shouldAllowRequest = null;
- if (isLocalTransfer) {
- shouldAllowRequest = true;
- }
- if (shouldAllowRequest == null) {
- try {
- Method gwl = webView.getClass().getMethod("getWhitelist");
- Whitelist whitelist = (Whitelist)gwl.invoke(webView);
- shouldAllowRequest = whitelist.isUrlWhiteListed(source);
- } catch (NoSuchMethodException e) {
- } catch (IllegalAccessException e) {
- } catch (InvocationTargetException e) {
- }
- }
- if (shouldAllowRequest == null) {
- try {
- Method gpm = webView.getClass().getMethod("getPluginManager");
- PluginManager pm = (PluginManager)gpm.invoke(webView);
- Method san = pm.getClass().getMethod("shouldAllowRequest", String.class);
- shouldAllowRequest = (Boolean)san.invoke(pm, source);
- } catch (NoSuchMethodException e) {
- } catch (IllegalAccessException e) {
- } catch (InvocationTargetException e) {
- }
- }
-
- if (!Boolean.TRUE.equals(shouldAllowRequest)) {
- LOG.w(LOG_TAG, "Source URL is not in white list: '" + source + "'");
- JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, null, 401, null);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, error));
- return;
- }
-
-
- final RequestContext context = new RequestContext(source, target, callbackContext);
- synchronized (activeRequests) {
- activeRequests.put(objectId, context);
- }
-
- cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- if (context.aborted) {
- return;
- }
-
- // Accept a path or a URI for the source.
- Uri tmpTarget = Uri.parse(target);
- Uri targetUri = resourceApi.remapUri(
- tmpTarget.getScheme() != null ? tmpTarget : Uri.fromFile(new File(target)));
- HttpURLConnection connection = null;
- File file = null;
- PluginResult result = null;
- TrackingInputStream inputStream = null;
- boolean cached = false;
-
- OutputStream outputStream = null;
- try {
- OpenForReadResult readResult = null;
-
- file = resourceApi.mapUriToFile(targetUri);
- context.targetFile = file;
-
- LOG.d(LOG_TAG, "Download file:" + sourceUri);
-
- FileProgressResult progress = new FileProgressResult();
-
- if (isLocalTransfer) {
- readResult = resourceApi.openForRead(sourceUri);
- if (readResult.length != -1) {
- progress.setLengthComputable(true);
- progress.setTotal(readResult.length);
- }
- inputStream = new SimpleTrackingInputStream(readResult.inputStream);
- } else {
- // connect to server
- // Open a HTTP connection to the URL based on protocol
- connection = resourceApi.createHttpConnection(sourceUri);
- connection.setRequestMethod("GET");
-
- // TODO: Make OkHttp use this CookieManager by default.
- String cookie = getCookies(sourceUri.toString());
-
- if(cookie != null)
- {
- connection.setRequestProperty("cookie", cookie);
- }
-
- // This must be explicitly set for gzip progress tracking to work.
- connection.setRequestProperty("Accept-Encoding", "gzip");
-
- // Handle the other headers
- if (headers != null) {
- addHeadersToRequest(connection, headers);
- }
-
- connection.connect();
- if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
- cached = true;
- connection.disconnect();
- LOG.d(LOG_TAG, "Resource not modified: " + source);
- JSONObject error = createFileTransferError(NOT_MODIFIED_ERR, source, target, connection, null);
- result = new PluginResult(PluginResult.Status.ERROR, error);
- } else {
- if (connection.getContentEncoding() == null || connection.getContentEncoding().equalsIgnoreCase("gzip")) {
- // Only trust content-length header if we understand
- // the encoding -- identity or gzip
- if (connection.getContentLength() != -1) {
- progress.setLengthComputable(true);
- progress.setTotal(connection.getContentLength());
- }
- }
- inputStream = getInputStream(connection);
- }
- }
-
- if (!cached) {
- try {
- synchronized (context) {
- if (context.aborted) {
- return;
- }
- context.connection = connection;
- }
-
- // write bytes to file
- byte[] buffer = new byte[MAX_BUFFER_SIZE];
- int bytesRead = 0;
- outputStream = resourceApi.openOutputStream(targetUri);
- while ((bytesRead = inputStream.read(buffer)) > 0) {
- outputStream.write(buffer, 0, bytesRead);
- // Send a progress event.
- progress.setLoaded(inputStream.getTotalRawBytesRead());
- PluginResult progressResult = new PluginResult(PluginResult.Status.OK, progress.toJSONObject());
- progressResult.setKeepCallback(true);
- context.sendPluginResult(progressResult);
- }
- } finally {
- synchronized (context) {
- context.connection = null;
- }
- safeClose(inputStream);
- safeClose(outputStream);
- }
-
- LOG.d(LOG_TAG, "Saved file: " + target);
-
-
- // create FileEntry object
- Class webViewClass = webView.getClass();
- PluginManager pm = null;
- try {
- Method gpm = webViewClass.getMethod("getPluginManager");
- pm = (PluginManager) gpm.invoke(webView);
- } catch (NoSuchMethodException e) {
- } catch (IllegalAccessException e) {
- } catch (InvocationTargetException e) {
- }
- if (pm == null) {
- try {
- Field pmf = webViewClass.getField("pluginManager");
- pm = (PluginManager)pmf.get(webView);
- } catch (NoSuchFieldException e) {
- } catch (IllegalAccessException e) {
- }
- }
- file = resourceApi.mapUriToFile(targetUri);
- context.targetFile = file;
- FileUtils filePlugin = (FileUtils) pm.getPlugin("File");
- if (filePlugin != null) {
- JSONObject fileEntry = filePlugin.getEntryForFile(file);
- if (fileEntry != null) {
- result = new PluginResult(PluginResult.Status.OK, fileEntry);
- } else {
- JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection, null);
- LOG.e(LOG_TAG, "File plugin cannot represent download path");
- result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
- }
- } else {
- LOG.e(LOG_TAG, "File plugin not found; cannot save downloaded file");
- result = new PluginResult(PluginResult.Status.ERROR, "File plugin not found; cannot save downloaded file");
- }
- }
- } catch (FileNotFoundException e) {
- JSONObject error = createFileTransferError(FILE_NOT_FOUND_ERR, source, target, connection, e);
- LOG.e(LOG_TAG, error.toString(), e);
- result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
- } catch (IOException e) {
- JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection, e);
- LOG.e(LOG_TAG, error.toString(), e);
- result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
- } catch (JSONException e) {
- LOG.e(LOG_TAG, e.getMessage(), e);
- result = new PluginResult(PluginResult.Status.JSON_EXCEPTION);
- } catch (Throwable e) {
- JSONObject error = createFileTransferError(CONNECTION_ERR, source, target, connection, e);
- LOG.e(LOG_TAG, error.toString(), e);
- result = new PluginResult(PluginResult.Status.IO_EXCEPTION, error);
- } finally {
- synchronized (activeRequests) {
- activeRequests.remove(objectId);
- }
-
- if (result == null) {
- result = new PluginResult(PluginResult.Status.ERROR, createFileTransferError(CONNECTION_ERR, source, target, connection, null));
- }
- // Remove incomplete download.
- if (!cached && result.getStatus() != PluginResult.Status.OK.ordinal() && file != null) {
- file.delete();
- }
- context.sendPluginResult(result);
- }
- }
- });
- }
-
- /**
- * Abort an ongoing upload or download.
- */
- private void abort(String objectId) {
- final RequestContext context;
- synchronized (activeRequests) {
- context = activeRequests.remove(objectId);
- }
- if (context != null) {
- // Closing the streams can block, so execute on a background thread.
- cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- synchronized (context) {
- File file = context.targetFile;
- if (file != null) {
- 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, null, -1, null);
- context.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, error));
- context.aborted = true;
- if (context.connection != null) {
- try {
- context.connection.disconnect();
- } catch (Exception e) {
- LOG.e(LOG_TAG, "CB-8431 Catch workaround for fatal exception", e);
- }
- }
- }
- }
- });
- }
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/filetransfer/FileUploadResult.java b/platforms/android/app/src/main/java/org/apache/cordova/filetransfer/FileUploadResult.java
deleted file mode 100644
index c24ea78..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/filetransfer/FileUploadResult.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.filetransfer;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * Encapsulates the result and/or status of uploading a file to a remote server.
- */
-public class FileUploadResult {
-
- private long bytesSent = 0; // bytes sent
- private int responseCode = -1; // HTTP response code
- private String response = null; // HTTP response
- private String objectId = null; // FileTransfer object id
-
- public long getBytesSent() {
- return bytesSent;
- }
-
- public void setBytesSent(long bytes) {
- this.bytesSent = bytes;
- }
-
- public int getResponseCode() {
- return responseCode;
- }
-
- public void setResponseCode(int responseCode) {
- this.responseCode = responseCode;
- }
-
- public String getResponse() {
- return response;
- }
-
- public void setResponse(String response) {
- this.response = response;
- }
-
- public String getObjectId() {
- return objectId;
- }
-
- public void setObjectId(String objectId) {
- this.objectId = objectId;
- }
-
- public JSONObject toJSONObject() throws JSONException {
- return new JSONObject(
- "{bytesSent:" + bytesSent +
- ",responseCode:" + responseCode +
- ",response:" + JSONObject.quote(response) +
- ",objectId:" + JSONObject.quote(objectId) + "}");
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowser.java b/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowser.java
deleted file mode 100644
index 9b3388c..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowser.java
+++ /dev/null
@@ -1,1259 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.inappbrowser;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.Browser;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.drawable.Drawable;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.Color;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.text.InputType;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.webkit.CookieManager;
-import android.webkit.CookieSyncManager;
-import android.webkit.HttpAuthHandler;
-import android.webkit.ValueCallback;
-import android.webkit.WebChromeClient;
-import android.webkit.WebSettings;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.Config;
-import org.apache.cordova.CordovaArgs;
-import org.apache.cordova.CordovaHttpAuthHandler;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.LOG;
-import org.apache.cordova.PluginManager;
-import org.apache.cordova.PluginResult;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.List;
-import java.util.HashMap;
-import java.util.StringTokenizer;
-
-@SuppressLint("SetJavaScriptEnabled")
-public class InAppBrowser extends CordovaPlugin {
-
- private static final String NULL = "null";
- protected static final String LOG_TAG = "InAppBrowser";
- private static final String SELF = "_self";
- private static final String SYSTEM = "_system";
- private static final String EXIT_EVENT = "exit";
- private static final String LOCATION = "location";
- private static final String ZOOM = "zoom";
- private static final String HIDDEN = "hidden";
- 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 CLEAR_ALL_CACHE = "clearcache";
- private static final String CLEAR_SESSION_CACHE = "clearsessioncache";
- private static final String HARDWARE_BACK_BUTTON = "hardwareback";
- private static final String MEDIA_PLAYBACK_REQUIRES_USER_ACTION = "mediaPlaybackRequiresUserAction";
- private static final String SHOULD_PAUSE = "shouldPauseOnSuspend";
- private static final Boolean DEFAULT_HARDWARE_BACK = true;
- private static final String USER_WIDE_VIEW_PORT = "useWideViewPort";
- private static final String TOOLBAR_COLOR = "toolbarcolor";
- private static final String CLOSE_BUTTON_CAPTION = "closebuttoncaption";
- private static final String CLOSE_BUTTON_COLOR = "closebuttoncolor";
- private static final String HIDE_NAVIGATION = "hidenavigationbuttons";
- private static final String NAVIGATION_COLOR = "navigationbuttoncolor";
- private static final String HIDE_URL = "hideurlbar";
- private static final String FOOTER = "footer";
- private static final String FOOTER_COLOR = "footercolor";
-
- private static final List customizableOptions = Arrays.asList(CLOSE_BUTTON_CAPTION, TOOLBAR_COLOR, NAVIGATION_COLOR, CLOSE_BUTTON_COLOR, FOOTER_COLOR);
-
- private InAppBrowserDialog dialog;
- private WebView inAppWebView;
- private EditText edittext;
- private CallbackContext callbackContext;
- private boolean showLocationBar = true;
- private boolean showZoomControls = true;
- private boolean openWindowHidden = false;
- private boolean clearAllCache = false;
- private boolean clearSessionCache = false;
- private boolean hadwareBackButton = true;
- private boolean mediaPlaybackRequiresUserGesture = false;
- private boolean shouldPauseInAppBrowser = false;
- private boolean useWideViewPort = true;
- private ValueCallback mUploadCallback;
- private ValueCallback mUploadCallbackLollipop;
- private final static int FILECHOOSER_REQUESTCODE = 1;
- private final static int FILECHOOSER_REQUESTCODE_LOLLIPOP = 2;
- private String closeButtonCaption = "";
- private String closeButtonColor = "";
- private int toolbarColor = android.graphics.Color.LTGRAY;
- private boolean hideNavigationButtons = false;
- private String navigationButtonColor = "";
- private boolean hideUrlBar = false;
- private boolean showFooter = false;
- private String footerColor = "";
- private String[] allowedSchemes;
-
- /**
- * Executes the request and returns PluginResult.
- *
- * @param action the action to execute.
- * @param args JSONArry of arguments for the plugin.
- * @param callbackContext the callbackContext used when calling back into JavaScript.
- * @return A PluginResult object with a status and message.
- */
- public boolean execute(String action, CordovaArgs args, final CallbackContext callbackContext) throws JSONException {
- if (action.equals("open")) {
- this.callbackContext = callbackContext;
- final String url = args.getString(0);
- String t = args.optString(1);
- if (t == null || t.equals("") || t.equals(NULL)) {
- t = SELF;
- }
- final String target = t;
- final HashMap features = parseFeature(args.optString(2));
-
- LOG.d(LOG_TAG, "target = " + target);
-
- this.cordova.getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- String result = "";
- // SELF
- if (SELF.equals(target)) {
- LOG.d(LOG_TAG, "in self");
- /* This code exists for compatibility between 3.x and 4.x versions of Cordova.
- * Previously the Config class had a static method, isUrlWhitelisted(). That
- * responsibility has been moved to the plugins, with an aggregating method in
- * PluginManager.
- */
- Boolean shouldAllowNavigation = null;
- if (url.startsWith("javascript:")) {
- shouldAllowNavigation = true;
- }
- if (shouldAllowNavigation == null) {
- try {
- Method iuw = Config.class.getMethod("isUrlWhiteListed", String.class);
- shouldAllowNavigation = (Boolean)iuw.invoke(null, url);
- } catch (NoSuchMethodException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- } catch (IllegalAccessException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- } catch (InvocationTargetException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- }
- }
- if (shouldAllowNavigation == null) {
- try {
- Method gpm = webView.getClass().getMethod("getPluginManager");
- PluginManager pm = (PluginManager)gpm.invoke(webView);
- Method san = pm.getClass().getMethod("shouldAllowNavigation", String.class);
- shouldAllowNavigation = (Boolean)san.invoke(pm, url);
- } catch (NoSuchMethodException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- } catch (IllegalAccessException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- } catch (InvocationTargetException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- }
- }
- // load in webview
- if (Boolean.TRUE.equals(shouldAllowNavigation)) {
- LOG.d(LOG_TAG, "loading in webview");
- webView.loadUrl(url);
- }
- //Load the dialer
- else if (url.startsWith(WebView.SCHEME_TEL))
- {
- try {
- LOG.d(LOG_TAG, "loading in dialer");
- 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());
- }
- }
- // load in InAppBrowser
- else {
- LOG.d(LOG_TAG, "loading in InAppBrowser");
- result = showWebPage(url, features);
- }
- }
- // SYSTEM
- else if (SYSTEM.equals(target)) {
- LOG.d(LOG_TAG, "in system");
- result = openExternal(url);
- }
- // BLANK - or anything else
- else {
- LOG.d(LOG_TAG, "in blank");
- result = showWebPage(url, features);
- }
-
- PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, result);
- pluginResult.setKeepCallback(true);
- callbackContext.sendPluginResult(pluginResult);
- }
- });
- }
- else if (action.equals("close")) {
- closeDialog();
- }
- else if (action.equals("injectScriptCode")) {
- String jsWrapper = null;
- if (args.getBoolean(1)) {
- jsWrapper = String.format("(function(){prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')})()", callbackContext.getCallbackId());
- }
- injectDeferredObject(args.getString(0), jsWrapper);
- }
- else if (action.equals("injectScriptFile")) {
- String jsWrapper;
- if (args.getBoolean(1)) {
- jsWrapper = String.format("(function(d) { var c = d.createElement('script'); c.src = %%s; c.onload = function() { prompt('', 'gap-iab://%s'); }; d.body.appendChild(c); })(document)", callbackContext.getCallbackId());
- } else {
- jsWrapper = "(function(d) { var c = d.createElement('script'); c.src = %s; d.body.appendChild(c); })(document)";
- }
- injectDeferredObject(args.getString(0), jsWrapper);
- }
- else if (action.equals("injectStyleCode")) {
- String jsWrapper;
- if (args.getBoolean(1)) {
- jsWrapper = String.format("(function(d) { var c = d.createElement('style'); c.innerHTML = %%s; d.body.appendChild(c); prompt('', 'gap-iab://%s');})(document)", callbackContext.getCallbackId());
- } else {
- jsWrapper = "(function(d) { var c = d.createElement('style'); c.innerHTML = %s; d.body.appendChild(c); })(document)";
- }
- injectDeferredObject(args.getString(0), jsWrapper);
- }
- else if (action.equals("injectStyleFile")) {
- String jsWrapper;
- if (args.getBoolean(1)) {
- jsWrapper = String.format("(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %%s; d.head.appendChild(c); prompt('', 'gap-iab://%s');})(document)", callbackContext.getCallbackId());
- } else {
- jsWrapper = "(function(d) { var c = d.createElement('link'); c.rel='stylesheet'; c.type='text/css'; c.href = %s; d.head.appendChild(c); })(document)";
- }
- injectDeferredObject(args.getString(0), jsWrapper);
- }
- else if (action.equals("show")) {
- this.cordova.getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- dialog.show();
- }
- });
- PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
- pluginResult.setKeepCallback(true);
- this.callbackContext.sendPluginResult(pluginResult);
- }
- else if (action.equals("hide")) {
- this.cordova.getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- dialog.hide();
- }
- });
- PluginResult pluginResult = new PluginResult(PluginResult.Status.OK);
- pluginResult.setKeepCallback(true);
- this.callbackContext.sendPluginResult(pluginResult);
- }
- else {
- return false;
- }
- return true;
- }
-
- /**
- * Called when the view navigates.
- */
- @Override
- public void onReset() {
- closeDialog();
- }
-
- /**
- * Called when the system is about to start resuming a previous activity.
- */
- @Override
- public void onPause(boolean multitasking) {
- if (shouldPauseInAppBrowser) {
- inAppWebView.onPause();
- }
- }
-
- /**
- * Called when the activity will start interacting with the user.
- */
- @Override
- public void onResume(boolean multitasking) {
- if (shouldPauseInAppBrowser) {
- inAppWebView.onResume();
- }
- }
-
- /**
- * Called by AccelBroker when listener is to be shut down.
- * Stop listener.
- */
- public void onDestroy() {
- closeDialog();
- }
-
- /**
- * Inject an object (script or style) into the InAppBrowser WebView.
- *
- * This is a helper method for the inject{Script|Style}{Code|File} API calls, which
- * provides a consistent method for injecting JavaScript code into the document.
- *
- * If a wrapper string is supplied, then the source string will be JSON-encoded (adding
- * quotes) and wrapped using string formatting. (The wrapper string should have a single
- * '%s' marker)
- *
- * @param source The source object (filename or script/style text) to inject into
- * the document.
- * @param jsWrapper A JavaScript string to wrap the source string in, so that the object
- * is properly injected, or null if the source string is JavaScript text
- * which should be executed directly.
- */
- private void injectDeferredObject(String source, String jsWrapper) {
- if (inAppWebView!=null) {
- String scriptToInject;
- if (jsWrapper != null) {
- org.json.JSONArray jsonEsc = new org.json.JSONArray();
- jsonEsc.put(source);
- String jsonRepr = jsonEsc.toString();
- String jsonSourceString = jsonRepr.substring(1, jsonRepr.length()-1);
- scriptToInject = String.format(jsWrapper, jsonSourceString);
- } else {
- scriptToInject = source;
- }
- final String finalScriptToInject = scriptToInject;
- this.cordova.getActivity().runOnUiThread(new Runnable() {
- @SuppressLint("NewApi")
- @Override
- public void run() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- // This action will have the side-effect of blurring the currently focused element
- inAppWebView.loadUrl("javascript:" + finalScriptToInject);
- } else {
- inAppWebView.evaluateJavascript(finalScriptToInject, null);
- }
- }
- });
- } else {
- LOG.d(LOG_TAG, "Can't inject code into the system browser");
- }
- }
-
- /**
- * Put the list of features into a hash map
- *
- * @param optString
- * @return
- */
- private HashMap parseFeature(String optString) {
- if (optString.equals(NULL)) {
- return null;
- } else {
- HashMap map = new HashMap();
- StringTokenizer features = new StringTokenizer(optString, ",");
- StringTokenizer option;
- while(features.hasMoreElements()) {
- option = new StringTokenizer(features.nextToken(), "=");
- if (option.hasMoreElements()) {
- String key = option.nextToken();
- String value = option.nextToken();
- if (!customizableOptions.contains(key)){
- value = value.equals("yes") || value.equals("no") ? value : "yes";
- }
- map.put(key, value);
- }
- }
- return map;
- }
- }
-
- /**
- * Display a new browser with the specified URL.
- *
- * @param url the url to load.
- * @return "" if ok, or error message.
- */
- public String openExternal(String url) {
- try {
- Intent intent = null;
- intent = new Intent(Intent.ACTION_VIEW);
- // Omitting the MIME type for file: URLs causes "No Activity found to handle Intent".
- // Adding the MIME type to http: URLs causes them to not be handled by the downloader.
- Uri uri = Uri.parse(url);
- if ("file".equals(uri.getScheme())) {
- intent.setDataAndType(uri, webView.getResourceApi().getMimeType(uri));
- } else {
- intent.setData(uri);
- }
- intent.putExtra(Browser.EXTRA_APPLICATION_ID, cordova.getActivity().getPackageName());
- this.cordova.getActivity().startActivity(intent);
- return "";
- // not catching FileUriExposedException explicitly because buildtools<24 doesn't know about it
- } catch (java.lang.RuntimeException e) {
- LOG.d(LOG_TAG, "InAppBrowser: Error loading url "+url+":"+ e.toString());
- return e.toString();
- }
- }
-
- /**
- * Closes the dialog
- */
- public void closeDialog() {
- this.cordova.getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- final WebView childView = inAppWebView;
- // The JS protects against multiple calls, so this should happen only when
- // closeDialog() is called by other native code.
- if (childView == null) {
- return;
- }
-
- childView.setWebViewClient(new WebViewClient() {
- // NB: wait for about:blank before dismissing
- public void onPageFinished(WebView view, String url) {
- if (dialog != null) {
- dialog.dismiss();
- dialog = null;
- }
- }
- });
- // NB: From SDK 19: "If you call methods on WebView from any thread
- // other than your app's UI thread, it can cause unexpected results."
- // http://developer.android.com/guide/webapps/migrating.html#Threads
- childView.loadUrl("about:blank");
-
- try {
- JSONObject obj = new JSONObject();
- obj.put("type", EXIT_EVENT);
- sendUpdate(obj, false);
- } catch (JSONException ex) {
- LOG.d(LOG_TAG, "Should never happen");
- }
- }
- });
- }
-
- /**
- * Checks to see if it is possible to go back one page in history, then does so.
- */
- public void goBack() {
- if (this.inAppWebView.canGoBack()) {
- this.inAppWebView.goBack();
- }
- }
-
- /**
- * Can the web browser go back?
- * @return boolean
- */
- public boolean canGoBack() {
- return this.inAppWebView.canGoBack();
- }
-
- /**
- * Has the user set the hardware back button to go back
- * @return boolean
- */
- public boolean hardwareBack() {
- return hadwareBackButton;
- }
-
- /**
- * Checks to see if it is possible to go forward one page in history, then does so.
- */
- private void goForward() {
- if (this.inAppWebView.canGoForward()) {
- this.inAppWebView.goForward();
- }
- }
-
- /**
- * Navigate to the new page
- *
- * @param url to load
- */
- private void navigate(String url) {
- InputMethodManager imm = (InputMethodManager)this.cordova.getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(edittext.getWindowToken(), 0);
-
- if (!url.startsWith("http") && !url.startsWith("file:")) {
- this.inAppWebView.loadUrl("http://" + url);
- } else {
- this.inAppWebView.loadUrl(url);
- }
- this.inAppWebView.requestFocus();
- }
-
-
- /**
- * Should we show the location bar?
- *
- * @return boolean
- */
- private boolean getShowLocationBar() {
- return this.showLocationBar;
- }
-
- private InAppBrowser getInAppBrowser(){
- return this;
- }
-
- /**
- * Display a new browser with the specified URL.
- *
- * @param url the url to load.
- * @param features jsonObject
- */
- public String showWebPage(final String url, HashMap features) {
- // Determine if we should hide the location bar.
- showLocationBar = true;
- showZoomControls = true;
- openWindowHidden = false;
- mediaPlaybackRequiresUserGesture = false;
-
- if (features != null) {
- String show = features.get(LOCATION);
- if (show != null) {
- showLocationBar = show.equals("yes") ? true : false;
- }
- if(showLocationBar) {
- String hideNavigation = features.get(HIDE_NAVIGATION);
- String hideUrl = features.get(HIDE_URL);
- if(hideNavigation != null) hideNavigationButtons = hideNavigation.equals("yes") ? true : false;
- if(hideUrl != null) hideUrlBar = hideUrl.equals("yes") ? true : false;
- }
- String zoom = features.get(ZOOM);
- if (zoom != null) {
- showZoomControls = zoom.equals("yes") ? true : false;
- }
- String hidden = features.get(HIDDEN);
- if (hidden != null) {
- openWindowHidden = hidden.equals("yes") ? true : false;
- }
- String hardwareBack = features.get(HARDWARE_BACK_BUTTON);
- if (hardwareBack != null) {
- hadwareBackButton = hardwareBack.equals("yes") ? true : false;
- } else {
- hadwareBackButton = DEFAULT_HARDWARE_BACK;
- }
- String mediaPlayback = features.get(MEDIA_PLAYBACK_REQUIRES_USER_ACTION);
- if (mediaPlayback != null) {
- mediaPlaybackRequiresUserGesture = mediaPlayback.equals("yes") ? true : false;
- }
- String cache = features.get(CLEAR_ALL_CACHE);
- if (cache != null) {
- clearAllCache = cache.equals("yes") ? true : false;
- } else {
- cache = features.get(CLEAR_SESSION_CACHE);
- if (cache != null) {
- clearSessionCache = cache.equals("yes") ? true : false;
- }
- }
- String shouldPause = features.get(SHOULD_PAUSE);
- if (shouldPause != null) {
- shouldPauseInAppBrowser = shouldPause.equals("yes") ? true : false;
- }
- String wideViewPort = features.get(USER_WIDE_VIEW_PORT);
- if (wideViewPort != null ) {
- useWideViewPort = wideViewPort.equals("yes") ? true : false;
- }
- String closeButtonCaptionSet = features.get(CLOSE_BUTTON_CAPTION);
- if (closeButtonCaptionSet != null) {
- closeButtonCaption = closeButtonCaptionSet;
- }
- String closeButtonColorSet = features.get(CLOSE_BUTTON_COLOR);
- if (closeButtonColorSet != null) {
- closeButtonColor = closeButtonColorSet;
- }
- String toolbarColorSet = features.get(TOOLBAR_COLOR);
- if (toolbarColorSet != null) {
- toolbarColor = android.graphics.Color.parseColor(toolbarColorSet);
- }
- String navigationButtonColorSet = features.get(NAVIGATION_COLOR);
- if (navigationButtonColorSet != null) {
- navigationButtonColor = navigationButtonColorSet;
- }
- String showFooterSet = features.get(FOOTER);
- if (showFooterSet != null) {
- showFooter = showFooterSet.equals("yes") ? true : false;
- }
- String footerColorSet = features.get(FOOTER_COLOR);
- if (footerColorSet != null) {
- footerColor = footerColorSet;
- }
- }
-
- final CordovaWebView thatWebView = this.webView;
-
- // Create dialog in new thread
- Runnable runnable = new Runnable() {
- /**
- * Convert our DIP units to Pixels
- *
- * @return int
- */
- private int dpToPixels(int dipValue) {
- int value = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP,
- (float) dipValue,
- cordova.getActivity().getResources().getDisplayMetrics()
- );
-
- return value;
- }
-
- private View createCloseButton(int id){
- View _close;
- Resources activityRes = cordova.getActivity().getResources();
-
- if (closeButtonCaption != "") {
- // Use TextView for text
- TextView close = new TextView(cordova.getActivity());
- close.setText(closeButtonCaption);
- close.setTextSize(20);
- if (closeButtonColor != "") close.setTextColor(android.graphics.Color.parseColor(closeButtonColor));
- close.setGravity(android.view.Gravity.CENTER_VERTICAL);
- close.setPadding(this.dpToPixels(10), 0, this.dpToPixels(10), 0);
- _close = close;
- }
- else {
- ImageButton close = new ImageButton(cordova.getActivity());
- int closeResId = activityRes.getIdentifier("ic_action_remove", "drawable", cordova.getActivity().getPackageName());
- Drawable closeIcon = activityRes.getDrawable(closeResId);
- if (closeButtonColor != "") close.setColorFilter(android.graphics.Color.parseColor(closeButtonColor));
- close.setImageDrawable(closeIcon);
- close.setScaleType(ImageView.ScaleType.FIT_CENTER);
- if (Build.VERSION.SDK_INT >= 16)
- close.getAdjustViewBounds();
-
- _close = close;
- }
-
- RelativeLayout.LayoutParams closeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
- closeLayoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- _close.setLayoutParams(closeLayoutParams);
-
- if (Build.VERSION.SDK_INT >= 16)
- _close.setBackground(null);
- else
- _close.setBackgroundDrawable(null);
-
- _close.setContentDescription("Close Button");
- _close.setId(Integer.valueOf(id));
- _close.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- closeDialog();
- }
- });
-
- return _close;
- }
-
- @SuppressLint("NewApi")
- public void run() {
-
- // CB-6702 InAppBrowser hangs when opening more than one instance
- if (dialog != null) {
- dialog.dismiss();
- };
-
- // Let's create the main dialog
- dialog = new InAppBrowserDialog(cordova.getActivity(), android.R.style.Theme_NoTitleBar);
- dialog.getWindow().getAttributes().windowAnimations = android.R.style.Animation_Dialog;
- dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
- dialog.setCancelable(true);
- dialog.setInAppBroswer(getInAppBrowser());
-
- // Main container layout
- LinearLayout main = new LinearLayout(cordova.getActivity());
- main.setOrientation(LinearLayout.VERTICAL);
-
- // Toolbar layout
- RelativeLayout toolbar = new RelativeLayout(cordova.getActivity());
- //Please, no more black!
- toolbar.setBackgroundColor(toolbarColor);
- toolbar.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, this.dpToPixels(44)));
- toolbar.setPadding(this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2), this.dpToPixels(2));
- toolbar.setHorizontalGravity(Gravity.LEFT);
- toolbar.setVerticalGravity(Gravity.TOP);
-
- // Action Button Container layout
- RelativeLayout actionButtonContainer = new RelativeLayout(cordova.getActivity());
- actionButtonContainer.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- actionButtonContainer.setHorizontalGravity(Gravity.LEFT);
- actionButtonContainer.setVerticalGravity(Gravity.CENTER_VERTICAL);
- actionButtonContainer.setId(Integer.valueOf(1));
-
- // Back button
- ImageButton back = new ImageButton(cordova.getActivity());
- RelativeLayout.LayoutParams backLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
- backLayoutParams.addRule(RelativeLayout.ALIGN_LEFT);
- back.setLayoutParams(backLayoutParams);
- back.setContentDescription("Back Button");
- back.setId(Integer.valueOf(2));
- Resources activityRes = cordova.getActivity().getResources();
- int backResId = activityRes.getIdentifier("ic_action_previous_item", "drawable", cordova.getActivity().getPackageName());
- Drawable backIcon = activityRes.getDrawable(backResId);
- if (navigationButtonColor != "") back.setColorFilter(android.graphics.Color.parseColor(navigationButtonColor));
- if (Build.VERSION.SDK_INT >= 16)
- back.setBackground(null);
- else
- back.setBackgroundDrawable(null);
- back.setImageDrawable(backIcon);
- back.setScaleType(ImageView.ScaleType.FIT_CENTER);
- back.setPadding(0, this.dpToPixels(10), 0, this.dpToPixels(10));
- if (Build.VERSION.SDK_INT >= 16)
- back.getAdjustViewBounds();
-
- back.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- goBack();
- }
- });
-
- // Forward button
- ImageButton forward = new ImageButton(cordova.getActivity());
- RelativeLayout.LayoutParams forwardLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
- forwardLayoutParams.addRule(RelativeLayout.RIGHT_OF, 2);
- forward.setLayoutParams(forwardLayoutParams);
- forward.setContentDescription("Forward Button");
- forward.setId(Integer.valueOf(3));
- int fwdResId = activityRes.getIdentifier("ic_action_next_item", "drawable", cordova.getActivity().getPackageName());
- Drawable fwdIcon = activityRes.getDrawable(fwdResId);
- if (navigationButtonColor != "") forward.setColorFilter(android.graphics.Color.parseColor(navigationButtonColor));
- if (Build.VERSION.SDK_INT >= 16)
- forward.setBackground(null);
- else
- forward.setBackgroundDrawable(null);
- forward.setImageDrawable(fwdIcon);
- forward.setScaleType(ImageView.ScaleType.FIT_CENTER);
- forward.setPadding(0, this.dpToPixels(10), 0, this.dpToPixels(10));
- if (Build.VERSION.SDK_INT >= 16)
- forward.getAdjustViewBounds();
-
- forward.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- goForward();
- }
- });
-
- // Edit Text Box
- edittext = new EditText(cordova.getActivity());
- RelativeLayout.LayoutParams textLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
- textLayoutParams.addRule(RelativeLayout.RIGHT_OF, 1);
- textLayoutParams.addRule(RelativeLayout.LEFT_OF, 5);
- edittext.setLayoutParams(textLayoutParams);
- edittext.setId(Integer.valueOf(4));
- edittext.setSingleLine(true);
- edittext.setText(url);
- edittext.setInputType(InputType.TYPE_TEXT_VARIATION_URI);
- edittext.setImeOptions(EditorInfo.IME_ACTION_GO);
- edittext.setInputType(InputType.TYPE_NULL); // Will not except input... Makes the text NON-EDITABLE
- edittext.setOnKeyListener(new View.OnKeyListener() {
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- // If the event is a key-down event on the "enter" button
- if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
- navigate(edittext.getText().toString());
- return true;
- }
- return false;
- }
- });
-
-
- // Header Close/Done button
- View close = createCloseButton(5);
- toolbar.addView(close);
-
- // Footer
- RelativeLayout footer = new RelativeLayout(cordova.getActivity());
- int _footerColor;
- if(footerColor != ""){
- _footerColor = Color.parseColor(footerColor);
- }else{
- _footerColor = android.graphics.Color.LTGRAY;
- }
- footer.setBackgroundColor(_footerColor);
- RelativeLayout.LayoutParams footerLayout = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, this.dpToPixels(44));
- footerLayout.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
- footer.setLayoutParams(footerLayout);
- if (closeButtonCaption != "") footer.setPadding(this.dpToPixels(8), this.dpToPixels(8), this.dpToPixels(8), this.dpToPixels(8));
- footer.setHorizontalGravity(Gravity.LEFT);
- footer.setVerticalGravity(Gravity.BOTTOM);
-
- View footerClose = createCloseButton(7);
- footer.addView(footerClose);
-
-
- // WebView
- inAppWebView = new WebView(cordova.getActivity());
- inAppWebView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- inAppWebView.setId(Integer.valueOf(6));
- // File Chooser Implemented ChromeClient
- inAppWebView.setWebChromeClient(new InAppChromeClient(thatWebView) {
- // For Android 5.0+
- public boolean onShowFileChooser (WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
- {
- LOG.d(LOG_TAG, "File Chooser 5.0+");
- // If callback exists, finish it.
- if(mUploadCallbackLollipop != null) {
- mUploadCallbackLollipop.onReceiveValue(null);
- }
- mUploadCallbackLollipop = filePathCallback;
-
- // Create File Chooser Intent
- Intent content = new Intent(Intent.ACTION_GET_CONTENT);
- content.addCategory(Intent.CATEGORY_OPENABLE);
- content.setType("*/*");
-
- // Run cordova startActivityForResult
- cordova.startActivityForResult(InAppBrowser.this, Intent.createChooser(content, "Select File"), FILECHOOSER_REQUESTCODE_LOLLIPOP);
- return true;
- }
-
- // For Android 4.1+
- public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture)
- {
- LOG.d(LOG_TAG, "File Chooser 4.1+");
- // Call file chooser for Android 3.0+
- openFileChooser(uploadMsg, acceptType);
- }
-
- // For Android 3.0+
- public void openFileChooser(ValueCallback uploadMsg, String acceptType)
- {
- LOG.d(LOG_TAG, "File Chooser 3.0+");
- mUploadCallback = uploadMsg;
- Intent content = new Intent(Intent.ACTION_GET_CONTENT);
- content.addCategory(Intent.CATEGORY_OPENABLE);
-
- // run startActivityForResult
- cordova.startActivityForResult(InAppBrowser.this, Intent.createChooser(content, "Select File"), FILECHOOSER_REQUESTCODE);
- }
-
- });
- WebViewClient client = new InAppBrowserClient(thatWebView, edittext);
- inAppWebView.setWebViewClient(client);
- WebSettings settings = inAppWebView.getSettings();
- settings.setJavaScriptEnabled(true);
- settings.setJavaScriptCanOpenWindowsAutomatically(true);
- settings.setBuiltInZoomControls(showZoomControls);
- settings.setPluginState(android.webkit.WebSettings.PluginState.ON);
-
- if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
- settings.setMediaPlaybackRequiresUserGesture(mediaPlaybackRequiresUserGesture);
- }
-
- String overrideUserAgent = preferences.getString("OverrideUserAgent", null);
- String appendUserAgent = preferences.getString("AppendUserAgent", null);
-
- if (overrideUserAgent != null) {
- settings.setUserAgentString(overrideUserAgent);
- }
- if (appendUserAgent != null) {
- settings.setUserAgentString(settings.getUserAgentString() + appendUserAgent);
- }
-
- //Toggle whether this is enabled or not!
- Bundle appSettings = cordova.getActivity().getIntent().getExtras();
- boolean enableDatabase = appSettings == null ? true : 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);
-
- if (clearAllCache) {
- CookieManager.getInstance().removeAllCookie();
- } else if (clearSessionCache) {
- CookieManager.getInstance().removeSessionCookie();
- }
-
- // Enable Thirdparty Cookies on >=Android 5.0 device
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
- CookieManager.getInstance().setAcceptThirdPartyCookies(inAppWebView,true);
- }
-
- inAppWebView.loadUrl(url);
- inAppWebView.setId(Integer.valueOf(6));
- inAppWebView.getSettings().setLoadWithOverviewMode(true);
- inAppWebView.getSettings().setUseWideViewPort(useWideViewPort);
- inAppWebView.requestFocus();
- inAppWebView.requestFocusFromTouch();
-
- // Add the back and forward buttons to our action button container layout
- actionButtonContainer.addView(back);
- actionButtonContainer.addView(forward);
-
- // Add the views to our toolbar if they haven't been disabled
- if (!hideNavigationButtons) toolbar.addView(actionButtonContainer);
- if (!hideUrlBar) toolbar.addView(edittext);
-
- // Don't add the toolbar if its been disabled
- if (getShowLocationBar()) {
- // Add our toolbar to our main view/layout
- main.addView(toolbar);
- }
-
- // Add our webview to our main view/layout
- RelativeLayout webViewLayout = new RelativeLayout(cordova.getActivity());
- webViewLayout.addView(inAppWebView);
- main.addView(webViewLayout);
-
- // Don't add the footer unless it's been enabled
- if (showFooter) {
- webViewLayout.addView(footer);
- }
-
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
- lp.copyFrom(dialog.getWindow().getAttributes());
- lp.width = WindowManager.LayoutParams.MATCH_PARENT;
- lp.height = WindowManager.LayoutParams.MATCH_PARENT;
-
- dialog.setContentView(main);
- dialog.show();
- dialog.getWindow().setAttributes(lp);
- // the goal of openhidden is to load the url and not display it
- // Show() needs to be called to cause the URL to be loaded
- if(openWindowHidden) {
- dialog.hide();
- }
- }
- };
- this.cordova.getActivity().runOnUiThread(runnable);
- return "";
- }
-
- /**
- * 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) {
- 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) {
- if (callbackContext != null) {
- PluginResult result = new PluginResult(status, obj);
- result.setKeepCallback(keepCallback);
- callbackContext.sendPluginResult(result);
- if (!keepCallback) {
- callbackContext = null;
- }
- }
- }
-
- /**
- * Receive File Data from File Chooser
- *
- * @param requestCode the requested code from chromeclient
- * @param resultCode the result code returned from android system
- * @param intent the data from android file chooser
- */
- public void onActivityResult(int requestCode, int resultCode, Intent intent) {
- // For Android >= 5.0
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- LOG.d(LOG_TAG, "onActivityResult (For Android >= 5.0)");
- // If RequestCode or Callback is Invalid
- if(requestCode != FILECHOOSER_REQUESTCODE_LOLLIPOP || mUploadCallbackLollipop == null) {
- super.onActivityResult(requestCode, resultCode, intent);
- return;
- }
- mUploadCallbackLollipop.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
- mUploadCallbackLollipop = null;
- }
- // For Android < 5.0
- else {
- LOG.d(LOG_TAG, "onActivityResult (For Android < 5.0)");
- // If RequestCode or Callback is Invalid
- if(requestCode != FILECHOOSER_REQUESTCODE || mUploadCallback == null) {
- super.onActivityResult(requestCode, resultCode, intent);
- return;
- }
-
- if (null == mUploadCallback) return;
- Uri result = intent == null || resultCode != cordova.getActivity().RESULT_OK ? null : intent.getData();
-
- mUploadCallback.onReceiveValue(result);
- mUploadCallback = null;
- }
- }
-
- /**
- * The webview client receives notifications about appView
- */
- public class InAppBrowserClient extends WebViewClient {
- EditText edittext;
- CordovaWebView webView;
-
- /**
- * Constructor.
- *
- * @param webView
- * @param mEditText
- */
- public InAppBrowserClient(CordovaWebView webView, EditText mEditText) {
- this.webView = webView;
- this.edittext = mEditText;
- }
-
- /**
- * Override the URL that should be loaded
- *
- * This handles a small subset of all the URIs that would be encountered.
- *
- * @param webView
- * @param url
- */
- @Override
- public boolean shouldOverrideUrlLoading(WebView webView, String url) {
- if (url.startsWith(WebView.SCHEME_TEL)) {
- try {
- Intent intent = new Intent(Intent.ACTION_DIAL);
- intent.setData(Uri.parse(url));
- cordova.getActivity().startActivity(intent);
- return true;
- } 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:") || url.startsWith("intent:")) {
- try {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(url));
- cordova.getActivity().startActivity(intent);
- return true;
- } 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);
- return true;
- } catch (android.content.ActivityNotFoundException e) {
- LOG.e(LOG_TAG, "Error sending sms " + url + ":" + e.toString());
- }
- }
- // Test for whitelisted custom scheme names like mycoolapp:// or twitteroauthresponse:// (Twitter Oauth Response)
- else if (!url.startsWith("http:") && !url.startsWith("https:") && url.matches("^[a-z]*://.*?$")) {
- if (allowedSchemes == null) {
- String allowed = preferences.getString("AllowedSchemes", "");
- allowedSchemes = allowed.split(",");
- }
- if (allowedSchemes != null) {
- for (String scheme : allowedSchemes) {
- if (url.startsWith(scheme)) {
- try {
- JSONObject obj = new JSONObject();
- obj.put("type", "customscheme");
- obj.put("url", url);
- sendUpdate(obj, true);
- return true;
- } catch (JSONException ex) {
- LOG.e(LOG_TAG, "Custom Scheme URI passed in has caused a JSON error.");
- }
- }
- }
- }
- }
-
- return false;
- }
-
-
- /*
- * onPageStarted fires the LOAD_START_EVENT
- *
- * @param view
- * @param url
- * @param favicon
- */
- @Override
- public void onPageStarted(WebView view, String url, Bitmap favicon) {
- super.onPageStarted(view, url, favicon);
- String newloc = "";
- if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {
- newloc = url;
- }
- else
- {
- // Assume that everything is HTTP at this point, because if we don't specify,
- // it really should be. Complain loudly about this!!!
- LOG.e(LOG_TAG, "Possible Uncaught/Unknown URI");
- newloc = "http://" + url;
- }
-
- // Update the UI if we haven't already
- if (!newloc.equals(edittext.getText().toString())) {
- edittext.setText(newloc);
- }
-
- try {
- JSONObject obj = new JSONObject();
- obj.put("type", LOAD_START_EVENT);
- obj.put("url", newloc);
- sendUpdate(obj, true);
- } catch (JSONException ex) {
- LOG.e(LOG_TAG, "URI passed in has caused a JSON error.");
- }
- }
-
-
-
- public void onPageFinished(WebView view, String url) {
- super.onPageFinished(view, url);
-
- // CB-10395 InAppBrowser's WebView not storing cookies reliable to local device storage
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
- CookieManager.getInstance().flush();
- } else {
- CookieSyncManager.getInstance().sync();
- }
-
- // https://issues.apache.org/jira/browse/CB-11248
- view.clearFocus();
- view.requestFocus();
-
- try {
- JSONObject obj = new JSONObject();
- obj.put("type", LOAD_STOP_EVENT);
- obj.put("url", url);
-
- sendUpdate(obj, true);
- } catch (JSONException ex) {
- 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");
- }
- }
-
- /**
- * On received http auth request.
- */
- @Override
- public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
-
- // Check if there is some plugin which can resolve this auth challenge
- PluginManager pluginManager = null;
- try {
- Method gpm = webView.getClass().getMethod("getPluginManager");
- pluginManager = (PluginManager)gpm.invoke(webView);
- } catch (NoSuchMethodException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- } catch (IllegalAccessException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- } catch (InvocationTargetException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- }
-
- if (pluginManager == null) {
- try {
- Field pmf = webView.getClass().getField("pluginManager");
- pluginManager = (PluginManager)pmf.get(webView);
- } catch (NoSuchFieldException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- } catch (IllegalAccessException e) {
- LOG.d(LOG_TAG, e.getLocalizedMessage());
- }
- }
-
- if (pluginManager != null && pluginManager.onReceivedHttpAuthRequest(webView, new CordovaHttpAuthHandler(handler), host, realm)) {
- return;
- }
-
- // By default handle 401 like we'd normally do!
- super.onReceivedHttpAuthRequest(view, handler, host, realm);
- }
- }
-}
\ No newline at end of file
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowserDialog.java b/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowserDialog.java
deleted file mode 100644
index e7b212f..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppBrowserDialog.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.inappbrowser;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * Created by Oliver on 22/11/2013.
- */
-public class InAppBrowserDialog extends Dialog {
- Context context;
- InAppBrowser inAppBrowser = null;
-
- public InAppBrowserDialog(Context context, int theme) {
- super(context, theme);
- this.context = context;
- }
-
- public void setInAppBroswer(InAppBrowser browser) {
- this.inAppBrowser = browser;
- }
-
- public void onBackPressed () {
- if (this.inAppBrowser == null) {
- this.dismiss();
- } else {
- // better to go through the in inAppBrowser
- // because it does a clean up
- if (this.inAppBrowser.hardwareBack() && this.inAppBrowser.canGoBack()) {
- this.inAppBrowser.goBack();
- } else {
- this.inAppBrowser.closeDialog();
- }
- }
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppChromeClient.java b/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppChromeClient.java
deleted file mode 100644
index a2145e6..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/inappbrowser/InAppChromeClient.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.inappbrowser;
-
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.LOG;
-import org.apache.cordova.PluginResult;
-import org.json.JSONArray;
-import org.json.JSONException;
-
-import android.webkit.JsPromptResult;
-import android.webkit.WebChromeClient;
-import android.webkit.WebStorage;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.webkit.GeolocationPermissions.Callback;
-
-public class InAppChromeClient extends WebChromeClient {
-
- private CordovaWebView webView;
- private String LOG_TAG = "InAppChromeClient";
- private long MAX_QUOTA = 100 * 1024 * 1024;
-
- public InAppChromeClient(CordovaWebView webView) {
- super();
- this.webView = webView;
- }
- /**
- * Handle database quota exceeded notification.
- *
- * @param url
- * @param databaseIdentifier
- * @param currentQuota
- * @param estimatedSize
- * @param totalUsedQuota
- * @param quotaUpdater
- */
- @Override
- public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize,
- long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater)
- {
- LOG.d(LOG_TAG, "onExceededDatabaseQuota estimatedSize: %d currentQuota: %d totalUsedQuota: %d", estimatedSize, currentQuota, totalUsedQuota);
- quotaUpdater.updateQuota(MAX_QUOTA);
- }
-
- /**
- * 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);
- }
-
- /**
- * Tell the client to display a prompt dialog to the user.
- * If the client returns true, WebView will assume that the client will
- * handle the prompt dialog and call the appropriate JsPromptResult method.
- *
- * The prompt bridge provided for the InAppBrowser is capable of executing any
- * oustanding callback belonging to the InAppBrowser plugin. Care has been
- * taken that other callbacks cannot be triggered, and that no other code
- * execution is possible.
- *
- * To trigger the bridge, the prompt default value should be of the form:
- *
- * gap-iab://
- *
- * where is the string id of the callback to trigger (something
- * like "InAppBrowser0123456789")
- *
- * If present, the prompt message is expected to be a JSON-encoded value to
- * pass to the callback. A JSON_EXCEPTION is returned if the JSON is invalid.
- *
- * @param view
- * @param url
- * @param message
- * @param defaultValue
- * @param result
- */
- @Override
- public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
- // See if the prompt string uses the 'gap-iab' protocol. If so, the remainder should be the id of a callback to execute.
- if (defaultValue != null && defaultValue.startsWith("gap")) {
- if(defaultValue.startsWith("gap-iab://")) {
- PluginResult scriptResult;
- String scriptCallbackId = defaultValue.substring(10);
- if (scriptCallbackId.startsWith("InAppBrowser")) {
- if(message == null || message.length() == 0) {
- scriptResult = new PluginResult(PluginResult.Status.OK, new JSONArray());
- } else {
- try {
- scriptResult = new PluginResult(PluginResult.Status.OK, new JSONArray(message));
- } catch(JSONException e) {
- scriptResult = new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
- }
- }
- this.webView.sendPluginResult(scriptResult, scriptCallbackId);
- result.confirm("");
- return true;
- }
- }
- else
- {
- // Anything else with a gap: prefix should get this message
- LOG.w(LOG_TAG, "InAppBrowser does not support Cordova API calls: " + url + " " + defaultValue);
- result.cancel();
- return true;
- }
- }
- return false;
- }
-
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/splashscreen/SplashScreen.java b/platforms/android/app/src/main/java/org/apache/cordova/splashscreen/SplashScreen.java
deleted file mode 100644
index 6f56c6c..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/splashscreen/SplashScreen.java
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova.splashscreen;
-
-import android.app.Dialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.Configuration;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.os.Handler;
-import android.view.Display;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
-import android.view.animation.Animation;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.DecelerateInterpolator;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaWebView;
-import org.json.JSONArray;
-import org.json.JSONException;
-
-public class SplashScreen extends CordovaPlugin {
- private static final String LOG_TAG = "SplashScreen";
- // Cordova 3.x.x has a copy of this plugin bundled with it (SplashScreenInternal.java).
- // Enable functionality only if running on 4.x.x.
- private static final boolean HAS_BUILT_IN_SPLASH_SCREEN = Integer.valueOf(CordovaWebView.CORDOVA_VERSION.split("\\.")[0]) < 4;
- private static final int DEFAULT_SPLASHSCREEN_DURATION = 3000;
- private static final int DEFAULT_FADE_DURATION = 500;
- private static Dialog splashDialog;
- private static ProgressDialog spinnerDialog;
- private static boolean firstShow = true;
- private static boolean lastHideAfterDelay; // https://issues.apache.org/jira/browse/CB-9094
-
- /**
- * Displays the splash drawable.
- */
- private ImageView splashImageView;
-
- /**
- * Remember last device orientation to detect orientation changes.
- */
- private int orientation;
-
- // Helper to be compile-time compatible with both Cordova 3.x and 4.x.
- private View getView() {
- try {
- return (View)webView.getClass().getMethod("getView").invoke(webView);
- } catch (Exception e) {
- return (View)webView;
- }
- }
-
- private int getSplashId() {
- int drawableId = 0;
- String splashResource = preferences.getString("SplashScreen", "screen");
- if (splashResource != null) {
- drawableId = cordova.getActivity().getResources().getIdentifier(splashResource, "drawable", cordova.getActivity().getClass().getPackage().getName());
- if (drawableId == 0) {
- drawableId = cordova.getActivity().getResources().getIdentifier(splashResource, "drawable", cordova.getActivity().getPackageName());
- }
- }
- return drawableId;
- }
-
- @Override
- protected void pluginInitialize() {
- if (HAS_BUILT_IN_SPLASH_SCREEN) {
- return;
- }
- // Make WebView invisible while loading URL
- // CB-11326 Ensure we're calling this on UI thread
- cordova.getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- getView().setVisibility(View.INVISIBLE);
- }
- });
- int drawableId = getSplashId();
-
- // Save initial orientation.
- orientation = cordova.getActivity().getResources().getConfiguration().orientation;
-
- if (firstShow) {
- boolean autoHide = preferences.getBoolean("AutoHideSplashScreen", true);
- showSplashScreen(autoHide);
- }
-
- if (preferences.getBoolean("SplashShowOnlyFirstTime", true)) {
- firstShow = false;
- }
- }
-
- /**
- * Shorter way to check value of "SplashMaintainAspectRatio" preference.
- */
- private boolean isMaintainAspectRatio () {
- return preferences.getBoolean("SplashMaintainAspectRatio", false);
- }
-
- private int getFadeDuration () {
- int fadeSplashScreenDuration = preferences.getBoolean("FadeSplashScreen", true) ?
- preferences.getInteger("FadeSplashScreenDuration", DEFAULT_FADE_DURATION) : 0;
-
- if (fadeSplashScreenDuration < 30) {
- // [CB-9750] This value used to be in decimal seconds, so we will assume that if someone specifies 10
- // they mean 10 seconds, and not the meaningless 10ms
- fadeSplashScreenDuration *= 1000;
- }
-
- return fadeSplashScreenDuration;
- }
-
- @Override
- public void onPause(boolean multitasking) {
- if (HAS_BUILT_IN_SPLASH_SCREEN) {
- return;
- }
- // hide the splash screen to avoid leaking a window
- this.removeSplashScreen(true);
- }
-
- @Override
- public void onDestroy() {
- if (HAS_BUILT_IN_SPLASH_SCREEN) {
- return;
- }
- // hide the splash screen to avoid leaking a window
- this.removeSplashScreen(true);
- // If we set this to true onDestroy, we lose track when we go from page to page!
- //firstShow = true;
- }
-
- @Override
- public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
- if (action.equals("hide")) {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- webView.postMessage("splashscreen", "hide");
- }
- });
- } else if (action.equals("show")) {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- webView.postMessage("splashscreen", "show");
- }
- });
- } else {
- return false;
- }
-
- callbackContext.success();
- return true;
- }
-
- @Override
- public Object onMessage(String id, Object data) {
- if (HAS_BUILT_IN_SPLASH_SCREEN) {
- return null;
- }
- if ("splashscreen".equals(id)) {
- if ("hide".equals(data.toString())) {
- this.removeSplashScreen(false);
- } else {
- this.showSplashScreen(false);
- }
- } else if ("spinner".equals(id)) {
- if ("stop".equals(data.toString())) {
- getView().setVisibility(View.VISIBLE);
- }
- } else if ("onReceivedError".equals(id)) {
- this.spinnerStop();
- }
- return null;
- }
-
- // Don't add @Override so that plugin still compiles on 3.x.x for a while
- public void onConfigurationChanged(Configuration newConfig) {
- if (newConfig.orientation != orientation) {
- orientation = newConfig.orientation;
-
- // Splash drawable may change with orientation, so reload it.
- if (splashImageView != null) {
- int drawableId = getSplashId();
- if (drawableId != 0) {
- splashImageView.setImageDrawable(cordova.getActivity().getResources().getDrawable(drawableId));
- }
- }
- }
- }
-
- private void removeSplashScreen(final boolean forceHideImmediately) {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- if (splashDialog != null && splashDialog.isShowing()) {
- final int fadeSplashScreenDuration = getFadeDuration();
- // CB-10692 If the plugin is being paused/destroyed, skip the fading and hide it immediately
- if (fadeSplashScreenDuration > 0 && forceHideImmediately == false) {
- AlphaAnimation fadeOut = new AlphaAnimation(1, 0);
- fadeOut.setInterpolator(new DecelerateInterpolator());
- fadeOut.setDuration(fadeSplashScreenDuration);
-
- splashImageView.setAnimation(fadeOut);
- splashImageView.startAnimation(fadeOut);
-
- fadeOut.setAnimationListener(new Animation.AnimationListener() {
- @Override
- public void onAnimationStart(Animation animation) {
- spinnerStop();
- }
-
- @Override
- public void onAnimationEnd(Animation animation) {
- if (splashDialog != null && splashDialog.isShowing()) {
- splashDialog.dismiss();
- splashDialog = null;
- splashImageView = null;
- }
- }
-
- @Override
- public void onAnimationRepeat(Animation animation) {
- }
- });
- } else {
- spinnerStop();
- splashDialog.dismiss();
- splashDialog = null;
- splashImageView = null;
- }
- }
- }
- });
- }
-
- /**
- * Shows the splash screen over the full Activity
- */
- @SuppressWarnings("deprecation")
- private void showSplashScreen(final boolean hideAfterDelay) {
- final int splashscreenTime = preferences.getInteger("SplashScreenDelay", DEFAULT_SPLASHSCREEN_DURATION);
- final int drawableId = getSplashId();
-
- final int fadeSplashScreenDuration = getFadeDuration();
- final int effectiveSplashDuration = Math.max(0, splashscreenTime - fadeSplashScreenDuration);
-
- lastHideAfterDelay = hideAfterDelay;
-
- // Prevent to show the splash dialog if the activity is in the process of finishing
- if (cordova.getActivity().isFinishing()) {
- return;
- }
- // If the splash dialog is showing don't try to show it again
- if (splashDialog != null && splashDialog.isShowing()) {
- return;
- }
- if (drawableId == 0 || (splashscreenTime <= 0 && hideAfterDelay)) {
- return;
- }
-
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- // Get reference to display
- Display display = cordova.getActivity().getWindowManager().getDefaultDisplay();
- Context context = webView.getContext();
-
- // Use an ImageView to render the image because of its flexible scaling options.
- splashImageView = new ImageView(context);
- splashImageView.setImageResource(drawableId);
- LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
- splashImageView.setLayoutParams(layoutParams);
-
- splashImageView.setMinimumHeight(display.getHeight());
- splashImageView.setMinimumWidth(display.getWidth());
-
- // TODO: Use the background color of the webView's parent instead of using the preference.
- splashImageView.setBackgroundColor(preferences.getInteger("backgroundColor", Color.BLACK));
-
- if (isMaintainAspectRatio()) {
- // CENTER_CROP scale mode is equivalent to CSS "background-size:cover"
- splashImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
- }
- else {
- // FIT_XY scales image non-uniformly to fit into image view.
- splashImageView.setScaleType(ImageView.ScaleType.FIT_XY);
- }
-
- // Create and show the dialog
- splashDialog = new Dialog(context, android.R.style.Theme_Translucent_NoTitleBar);
- // check to see if the splash screen should be full screen
- if ((cordova.getActivity().getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN)
- == WindowManager.LayoutParams.FLAG_FULLSCREEN) {
- splashDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- }
- splashDialog.setContentView(splashImageView);
- splashDialog.setCancelable(false);
- splashDialog.show();
-
- if (preferences.getBoolean("ShowSplashScreenSpinner", true)) {
- spinnerStart();
- }
-
- // Set Runnable to remove splash screen just in case
- if (hideAfterDelay) {
- final Handler handler = new Handler();
- handler.postDelayed(new Runnable() {
- public void run() {
- if (lastHideAfterDelay) {
- removeSplashScreen(false);
- }
- }
- }, effectiveSplashDuration);
- }
- }
- });
- }
-
- // Show only spinner in the center of the screen
- private void spinnerStart() {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- spinnerStop();
-
- spinnerDialog = new ProgressDialog(webView.getContext());
- spinnerDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- spinnerDialog = null;
- }
- });
-
- spinnerDialog.setCancelable(false);
- spinnerDialog.setIndeterminate(true);
-
- RelativeLayout centeredLayout = new RelativeLayout(cordova.getActivity());
- centeredLayout.setGravity(Gravity.CENTER);
- centeredLayout.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
-
- ProgressBar progressBar = new ProgressBar(webView.getContext());
- RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
- progressBar.setLayoutParams(layoutParams);
-
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
- String colorName = preferences.getString("SplashScreenSpinnerColor", null);
- if(colorName != null){
- int[][] states = new int[][] {
- new int[] { android.R.attr.state_enabled}, // enabled
- new int[] {-android.R.attr.state_enabled}, // disabled
- new int[] {-android.R.attr.state_checked}, // unchecked
- new int[] { android.R.attr.state_pressed} // pressed
- };
- int progressBarColor = Color.parseColor(colorName);
- int[] colors = new int[] {
- progressBarColor,
- progressBarColor,
- progressBarColor,
- progressBarColor
- };
- ColorStateList colorStateList = new ColorStateList(states, colors);
- progressBar.setIndeterminateTintList(colorStateList);
- }
- }
-
- centeredLayout.addView(progressBar);
-
- spinnerDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
- spinnerDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
-
- spinnerDialog.show();
- spinnerDialog.setContentView(centeredLayout);
- }
- });
- }
-
- private void spinnerStop() {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- if (spinnerDialog != null && spinnerDialog.isShowing()) {
- spinnerDialog.dismiss();
- spinnerDialog = null;
- }
- }
- });
- }
-}
diff --git a/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java b/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java
deleted file mode 100644
index 3656788..0000000
--- a/platforms/android/app/src/main/java/org/apache/cordova/whitelist/WhitelistPlugin.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova.whitelist;
-
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.ConfigXmlParser;
-import org.apache.cordova.LOG;
-import org.apache.cordova.Whitelist;
-import org.xmlpull.v1.XmlPullParser;
-
-import android.content.Context;
-
-public class WhitelistPlugin extends CordovaPlugin {
- private static final String LOG_TAG = "WhitelistPlugin";
- private Whitelist allowedNavigations;
- private Whitelist allowedIntents;
- private Whitelist allowedRequests;
-
- // Used when instantiated via reflection by PluginManager
- public WhitelistPlugin() {
- }
- // These can be used by embedders to allow Java-configuration of whitelists.
- public WhitelistPlugin(Context context) {
- this(new Whitelist(), new Whitelist(), null);
- new CustomConfigXmlParser().parse(context);
- }
- public WhitelistPlugin(XmlPullParser xmlParser) {
- this(new Whitelist(), new Whitelist(), null);
- new CustomConfigXmlParser().parse(xmlParser);
- }
- public WhitelistPlugin(Whitelist allowedNavigations, Whitelist allowedIntents, Whitelist allowedRequests) {
- if (allowedRequests == null) {
- allowedRequests = new Whitelist();
- allowedRequests.addWhiteListEntry("file:///*", false);
- allowedRequests.addWhiteListEntry("data:*", false);
- }
- this.allowedNavigations = allowedNavigations;
- this.allowedIntents = allowedIntents;
- this.allowedRequests = allowedRequests;
- }
- @Override
- public void pluginInitialize() {
- if (allowedNavigations == null) {
- allowedNavigations = new Whitelist();
- allowedIntents = new Whitelist();
- allowedRequests = new Whitelist();
- new CustomConfigXmlParser().parse(webView.getContext());
- }
- }
-
- private class CustomConfigXmlParser extends ConfigXmlParser {
- @Override
- public void handleStartTag(XmlPullParser xml) {
- String strNode = xml.getName();
- if (strNode.equals("content")) {
- String startPage = xml.getAttributeValue(null, "src");
- allowedNavigations.addWhiteListEntry(startPage, false);
- } else if (strNode.equals("allow-navigation")) {
- String origin = xml.getAttributeValue(null, "href");
- if ("*".equals(origin)) {
- allowedNavigations.addWhiteListEntry("http://*/*", false);
- allowedNavigations.addWhiteListEntry("https://*/*", false);
- allowedNavigations.addWhiteListEntry("data:*", false);
- } else {
- allowedNavigations.addWhiteListEntry(origin, false);
- }
- } else if (strNode.equals("allow-intent")) {
- String origin = xml.getAttributeValue(null, "href");
- allowedIntents.addWhiteListEntry(origin, false);
- } else if (strNode.equals("access")) {
- String origin = xml.getAttributeValue(null, "origin");
- String subdomains = xml.getAttributeValue(null, "subdomains");
- boolean external = (xml.getAttributeValue(null, "launch-external") != null);
- if (origin != null) {
- if (external) {
- LOG.w(LOG_TAG, "Found within config.xml. Please use instead.");
- allowedIntents.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
- } else {
- if ("*".equals(origin)) {
- allowedRequests.addWhiteListEntry("http://*/*", false);
- allowedRequests.addWhiteListEntry("https://*/*", false);
- } else {
- allowedRequests.addWhiteListEntry(origin, (subdomains != null) && (subdomains.compareToIgnoreCase("true") == 0));
- }
- }
- }
- }
- }
- @Override
- public void handleEndTag(XmlPullParser xml) {
- }
- }
-
- @Override
- public Boolean shouldAllowNavigation(String url) {
- if (allowedNavigations.isUrlWhiteListed(url)) {
- return true;
- }
- return null; // Default policy
- }
-
- @Override
- public Boolean shouldAllowRequest(String url) {
- if (Boolean.TRUE == shouldAllowNavigation(url)) {
- return true;
- }
- if (allowedRequests.isUrlWhiteListed(url)) {
- return true;
- }
- return null; // Default policy
- }
-
- @Override
- public Boolean shouldOpenExternalUrl(String url) {
- if (allowedIntents.isUrlWhiteListed(url)) {
- return true;
- }
- return null; // Default policy
- }
-
- public Whitelist getAllowedNavigations() {
- return allowedNavigations;
- }
-
- public void setAllowedNavigations(Whitelist allowedNavigations) {
- this.allowedNavigations = allowedNavigations;
- }
-
- public Whitelist getAllowedIntents() {
- return allowedIntents;
- }
-
- public void setAllowedIntents(Whitelist allowedIntents) {
- this.allowedIntents = allowedIntents;
- }
-
- public Whitelist getAllowedRequests() {
- return allowedRequests;
- }
-
- public void setAllowedRequests(Whitelist allowedRequests) {
- this.allowedRequests = allowedRequests;
- }
-}
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/ic_action_next_item.png b/platforms/android/app/src/main/res/drawable-hdpi/ic_action_next_item.png
deleted file mode 100644
index fa469d8..0000000
Binary files a/platforms/android/app/src/main/res/drawable-hdpi/ic_action_next_item.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/ic_action_previous_item.png b/platforms/android/app/src/main/res/drawable-hdpi/ic_action_previous_item.png
deleted file mode 100644
index e861ecc..0000000
Binary files a/platforms/android/app/src/main/res/drawable-hdpi/ic_action_previous_item.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-hdpi/ic_action_remove.png b/platforms/android/app/src/main/res/drawable-hdpi/ic_action_remove.png
deleted file mode 100644
index f889617..0000000
Binary files a/platforms/android/app/src/main/res/drawable-hdpi/ic_action_remove.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-land-hdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-hdpi/screen.png
deleted file mode 100644
index 150564a..0000000
Binary files a/platforms/android/app/src/main/res/drawable-land-hdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-land-ldpi/screen.png b/platforms/android/app/src/main/res/drawable-land-ldpi/screen.png
deleted file mode 100644
index 3052cec..0000000
Binary files a/platforms/android/app/src/main/res/drawable-land-ldpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-land-mdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-mdpi/screen.png
deleted file mode 100644
index 536a819..0000000
Binary files a/platforms/android/app/src/main/res/drawable-land-mdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-land-xhdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-xhdpi/screen.png
deleted file mode 100644
index be50593..0000000
Binary files a/platforms/android/app/src/main/res/drawable-land-xhdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-land-xxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-xxhdpi/screen.png
deleted file mode 100644
index 2903a88..0000000
Binary files a/platforms/android/app/src/main/res/drawable-land-xxhdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-land-xxxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-land-xxxhdpi/screen.png
deleted file mode 100644
index 34a2aad..0000000
Binary files a/platforms/android/app/src/main/res/drawable-land-xxxhdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/ic_action_next_item.png b/platforms/android/app/src/main/res/drawable-mdpi/ic_action_next_item.png
deleted file mode 100644
index 47365a3..0000000
Binary files a/platforms/android/app/src/main/res/drawable-mdpi/ic_action_next_item.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/ic_action_previous_item.png b/platforms/android/app/src/main/res/drawable-mdpi/ic_action_previous_item.png
deleted file mode 100644
index 4ad2df4..0000000
Binary files a/platforms/android/app/src/main/res/drawable-mdpi/ic_action_previous_item.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-mdpi/ic_action_remove.png b/platforms/android/app/src/main/res/drawable-mdpi/ic_action_remove.png
deleted file mode 100644
index e84853e..0000000
Binary files a/platforms/android/app/src/main/res/drawable-mdpi/ic_action_remove.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-port-hdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-hdpi/screen.png
deleted file mode 100644
index fa9efc4..0000000
Binary files a/platforms/android/app/src/main/res/drawable-port-hdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-port-ldpi/screen.png b/platforms/android/app/src/main/res/drawable-port-ldpi/screen.png
deleted file mode 100644
index 80b314a..0000000
Binary files a/platforms/android/app/src/main/res/drawable-port-ldpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-port-mdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-mdpi/screen.png
deleted file mode 100644
index f5181dc..0000000
Binary files a/platforms/android/app/src/main/res/drawable-port-mdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-port-xhdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-xhdpi/screen.png
deleted file mode 100644
index 43df4e8..0000000
Binary files a/platforms/android/app/src/main/res/drawable-port-xhdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-port-xxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-xxhdpi/screen.png
deleted file mode 100644
index bba7ecc..0000000
Binary files a/platforms/android/app/src/main/res/drawable-port-xxhdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-port-xxxhdpi/screen.png b/platforms/android/app/src/main/res/drawable-port-xxxhdpi/screen.png
deleted file mode 100644
index 27e017a..0000000
Binary files a/platforms/android/app/src/main/res/drawable-port-xxxhdpi/screen.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_next_item.png b/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_next_item.png
deleted file mode 100644
index 5f30474..0000000
Binary files a/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_next_item.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_previous_item.png b/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_previous_item.png
deleted file mode 100644
index ed8ac91..0000000
Binary files a/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_previous_item.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_remove.png b/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_remove.png
deleted file mode 100644
index 4cd0458..0000000
Binary files a/platforms/android/app/src/main/res/drawable-xhdpi/ic_action_remove.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_next_item.png b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_next_item.png
deleted file mode 100644
index 51479d8..0000000
Binary files a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_next_item.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_previous_item.png b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_previous_item.png
deleted file mode 100644
index bc8ff12..0000000
Binary files a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_previous_item.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_remove.png b/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_remove.png
deleted file mode 100644
index 331c545..0000000
Binary files a/platforms/android/app/src/main/res/drawable-xxhdpi/ic_action_remove.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/mipmap-hdpi/icon.png b/platforms/android/app/src/main/res/mipmap-hdpi/icon.png
deleted file mode 100644
index f1232b6..0000000
Binary files a/platforms/android/app/src/main/res/mipmap-hdpi/icon.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/mipmap-ldpi/icon.png b/platforms/android/app/src/main/res/mipmap-ldpi/icon.png
deleted file mode 100644
index 25c9f51..0000000
Binary files a/platforms/android/app/src/main/res/mipmap-ldpi/icon.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/mipmap-mdpi/icon.png b/platforms/android/app/src/main/res/mipmap-mdpi/icon.png
deleted file mode 100644
index dae5103..0000000
Binary files a/platforms/android/app/src/main/res/mipmap-mdpi/icon.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/mipmap-xhdpi/icon.png b/platforms/android/app/src/main/res/mipmap-xhdpi/icon.png
deleted file mode 100644
index f8a4e3a..0000000
Binary files a/platforms/android/app/src/main/res/mipmap-xhdpi/icon.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxhdpi/icon.png b/platforms/android/app/src/main/res/mipmap-xxhdpi/icon.png
deleted file mode 100644
index 6edb68f..0000000
Binary files a/platforms/android/app/src/main/res/mipmap-xxhdpi/icon.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/mipmap-xxxhdpi/icon.png b/platforms/android/app/src/main/res/mipmap-xxxhdpi/icon.png
deleted file mode 100644
index 6a18693..0000000
Binary files a/platforms/android/app/src/main/res/mipmap-xxxhdpi/icon.png and /dev/null differ
diff --git a/platforms/android/app/src/main/res/values/strings.xml b/platforms/android/app/src/main/res/values/strings.xml
deleted file mode 100644
index d177188..0000000
--- a/platforms/android/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
- Goober
- @string/app_name
- @string/launcher_name
-
diff --git a/platforms/android/app/src/main/res/xml/config.xml b/platforms/android/app/src/main/res/xml/config.xml
deleted file mode 100644
index 250b260..0000000
--- a/platforms/android/app/src/main/res/xml/config.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Goober
- Goober, a mobile app for pnut.io
- Morgan McMillian
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/platforms/android/app/src/main/res/xml/provider_paths.xml b/platforms/android/app/src/main/res/xml/provider_paths.xml
deleted file mode 100644
index 3785fcc..0000000
--- a/platforms/android/app/src/main/res/xml/provider_paths.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/platforms/android/build.gradle b/platforms/android/build.gradle
deleted file mode 100644
index 569004f..0000000
--- a/platforms/android/build.gradle
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-
-buildscript {
- repositories {
- maven {
- url "https://maven.google.com"
- }
- jcenter()
- }
- dependencies {
-
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
- classpath 'com.android.tools.build:gradle:3.0.1'
- }
-}
-
-allprojects {
- repositories {
- maven {
- url "https://maven.google.com"
- }
- jcenter()
- }
- //This replaces project.properties w.r.t. build settings
- project.ext {
- defaultBuildToolsVersion="27.0.1" //String
- defaultMinSdkVersion=19 //Integer - Minimum requirement is Android 4.4
- defaultTargetSdkVersion=27 //Integer - We ALWAYS target the latest by default
- defaultCompileSdkVersion=27 //Integer - We ALWAYS compile with the latest by default
- }
-}
-
-task clean(type: Delete) {
- delete rootProject.buildDir
-}
diff --git a/platforms/android/cordova/Api.js b/platforms/android/cordova/Api.js
deleted file mode 100644
index ae4d17b..0000000
--- a/platforms/android/cordova/Api.js
+++ /dev/null
@@ -1,411 +0,0 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var path = require('path');
-var Q = require('q');
-
-var AndroidProject = require('./lib/AndroidProject');
-var AndroidStudio = require('./lib/AndroidStudio');
-var PluginManager = require('cordova-common').PluginManager;
-
-var CordovaLogger = require('cordova-common').CordovaLogger;
-var selfEvents = require('cordova-common').events;
-
-var PLATFORM = 'android';
-
-function setupEvents (externalEventEmitter) {
- if (externalEventEmitter) {
- // This will make the platform internal events visible outside
- selfEvents.forwardEventsTo(externalEventEmitter);
- return externalEventEmitter;
- }
-
- // There is no logger if external emitter is not present,
- // so attach a console logger
- CordovaLogger.get().subscribe(selfEvents);
- return selfEvents;
-}
-
-/**
- * Class, that acts as abstraction over particular platform. Encapsulates the
- * platform's properties and methods.
- *
- * Platform that implements own PlatformApi instance _should implement all
- * prototype methods_ of this class to be fully compatible with cordova-lib.
- *
- * The PlatformApi instance also should define the following field:
- *
- * * platform: String that defines a platform name.
- */
-function Api (platform, platformRootDir, events) {
- this.platform = PLATFORM;
- this.root = path.resolve(__dirname, '..');
- this.builder = 'gradle';
-
- setupEvents(events);
-
- var self = this;
-
- this.locations = {
- root: self.root,
- www: path.join(self.root, 'assets/www'),
- res: path.join(self.root, 'res'),
- platformWww: path.join(self.root, 'platform_www'),
- configXml: path.join(self.root, 'res/xml/config.xml'),
- defaultConfigXml: path.join(self.root, 'cordova/defaults.xml'),
- strings: path.join(self.root, 'res/values/strings.xml'),
- manifest: path.join(self.root, 'AndroidManifest.xml'),
- build: path.join(self.root, 'build'),
- javaSrc: path.join(self.root, 'src'),
- // NOTE: Due to platformApi spec we need to return relative paths here
- cordovaJs: 'bin/templates/project/assets/www/cordova.js',
- cordovaJsSrc: 'cordova-js-src'
- };
-
- // XXX Override some locations for Android Studio projects
- if (AndroidStudio.isAndroidStudioProject(self.root) === true) {
- selfEvents.emit('log', 'Android Studio project detected');
- this.builder = 'studio';
- this.android_studio = true;
- this.locations.configXml = path.join(self.root, 'app/src/main/res/xml/config.xml');
- this.locations.strings = path.join(self.root, 'app/src/main/res/values/strings.xml');
- this.locations.manifest = path.join(self.root, 'app/src/main/AndroidManifest.xml');
- // We could have Java Source, we could have other languages
- this.locations.javaSrc = path.join(self.root, 'app/src/main/java/');
- this.locations.www = path.join(self.root, 'app/src/main/assets/www');
- this.locations.res = path.join(self.root, 'app/src/main/res');
- }
-}
-
-/**
- * Installs platform to specified directory and creates a platform project.
- *
- * @param {String} destination Destination directory, where insatll platform to
- * @param {ConfigParser} [config] ConfgiParser instance, used to retrieve
- * project creation options, such as package id and project name.
- * @param {Object} [options] An options object. The most common options are:
- * @param {String} [options.customTemplate] A path to custom template, that
- * should override the default one from platform.
- * @param {Boolean} [options.link] Flag that indicates that platform's
- * sources will be linked to installed platform instead of copying.
- * @param {EventEmitter} [events] An EventEmitter instance that will be used for
- * logging purposes. If no EventEmitter provided, all events will be logged to
- * console
- *
- * @return {Promise} Promise either fulfilled with PlatformApi
- * instance or rejected with CordovaError.
- */
-Api.createPlatform = function (destination, config, options, events) {
- events = setupEvents(events);
- var result;
- try {
- result = require('../../lib/create').create(destination, config, options, events).then(function (destination) {
- var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
- return new PlatformApi(PLATFORM, destination, events);
- });
- } catch (e) {
- events.emit('error', 'createPlatform is not callable from the android project API.');
- throw (e);
- }
- return result;
-};
-
-/**
- * Updates already installed platform.
- *
- * @param {String} destination Destination directory, where platform installed
- * @param {Object} [options] An options object. The most common options are:
- * @param {String} [options.customTemplate] A path to custom template, that
- * should override the default one from platform.
- * @param {Boolean} [options.link] Flag that indicates that platform's
- * sources will be linked to installed platform instead of copying.
- * @param {EventEmitter} [events] An EventEmitter instance that will be used for
- * logging purposes. If no EventEmitter provided, all events will be logged to
- * console
- *
- * @return {Promise} Promise either fulfilled with PlatformApi
- * instance or rejected with CordovaError.
- */
-Api.updatePlatform = function (destination, options, events) {
- events = setupEvents(events);
- var result;
- try {
- result = require('../../lib/create').update(destination, options, events).then(function (destination) {
- var PlatformApi = require(path.resolve(destination, 'cordova/Api'));
- return new PlatformApi('android', destination, events);
- });
- } catch (e) {
- events.emit('error', 'updatePlatform is not callable from the android project API, you will need to do this manually.');
- throw (e);
- }
- return result;
-};
-
-/**
- * Gets a CordovaPlatform object, that represents the platform structure.
- *
- * @return {CordovaPlatform} A structure that contains the description of
- * platform's file structure and other properties of platform.
- */
-Api.prototype.getPlatformInfo = function () {
- var result = {};
- result.locations = this.locations;
- result.root = this.root;
- result.name = this.platform;
- result.version = require('./version');
- result.projectConfig = this._config;
-
- return result;
-};
-
-/**
- * Updates installed platform with provided www assets and new app
- * configuration. This method is required for CLI workflow and will be called
- * each time before build, so the changes, made to app configuration and www
- * code, will be applied to platform.
- *
- * @param {CordovaProject} cordovaProject A CordovaProject instance, that defines a
- * project structure and configuration, that should be applied to platform
- * (contains project's www location and ConfigParser instance for project's
- * config).
- *
- * @return {Promise} Return a promise either fulfilled, or rejected with
- * CordovaError instance.
- */
-Api.prototype.prepare = function (cordovaProject, prepareOptions) {
- return require('./lib/prepare').prepare.call(this, cordovaProject, prepareOptions);
-};
-
-/**
- * Installs a new plugin into platform. This method only copies non-www files
- * (sources, libs, etc.) to platform. It also doesn't resolves the
- * dependencies of plugin. Both of handling of www files, such as assets and
- * js-files and resolving dependencies are the responsibility of caller.
- *
- * @param {PluginInfo} plugin A PluginInfo instance that represents plugin
- * that will be installed.
- * @param {Object} installOptions An options object. Possible options below:
- * @param {Boolean} installOptions.link: Flag that specifies that plugin
- * sources will be symlinked to app's directory instead of copying (if
- * possible).
- * @param {Object} installOptions.variables An object that represents
- * variables that will be used to install plugin. See more details on plugin
- * variables in documentation:
- * https://cordova.apache.org/docs/en/4.0.0/plugin_ref_spec.md.html
- *
- * @return {Promise} Return a promise either fulfilled, or rejected with
- * CordovaError instance.
- */
-Api.prototype.addPlugin = function (plugin, installOptions) {
- var project = AndroidProject.getProjectFile(this.root);
- var self = this;
-
- installOptions = installOptions || {};
- installOptions.variables = installOptions.variables || {};
- // Add PACKAGE_NAME variable into vars
- if (!installOptions.variables.PACKAGE_NAME) {
- installOptions.variables.PACKAGE_NAME = project.getPackageName();
- }
-
- if (this.android_studio === true) {
- installOptions.android_studio = true;
- }
-
- return Q().then(function () {
- // CB-11964: Do a clean when installing the plugin code to get around
- // the Gradle bug introduced by the Android Gradle Plugin Version 2.2
- // TODO: Delete when the next version of Android Gradle plugin comes out
- // Since clean doesn't just clean the build, it also wipes out www, we need
- // to pass additional options.
-
- // Do some basic argument parsing
- var opts = {};
-
- // Skip cleaning prepared files when not invoking via cordova CLI.
- opts.noPrepare = true;
-
- if (!AndroidStudio.isAndroidStudioProject(self.root) && !project.isClean()) {
- return self.clean(opts);
- }
- }).then(function () {
- return PluginManager.get(self.platform, self.locations, project).addPlugin(plugin, installOptions);
- }).then(function () {
- if (plugin.getFrameworks(this.platform).length === 0) return;
- selfEvents.emit('verbose', 'Updating build files since android plugin contained ');
- // This should pick the correct builder, not just get gradle
- require('./lib/builders/builders').getBuilder(this.builder).prepBuildFiles();
- }.bind(this))
- // CB-11022 Return truthy value to prevent running prepare after
- .thenResolve(true);
-};
-
-/**
- * Removes an installed plugin from platform.
- *
- * Since method accepts PluginInfo instance as input parameter instead of plugin
- * id, caller shoud take care of managing/storing PluginInfo instances for
- * future uninstalls.
- *
- * @param {PluginInfo} plugin A PluginInfo instance that represents plugin
- * that will be installed.
- *
- * @return {Promise} Return a promise either fulfilled, or rejected with
- * CordovaError instance.
- */
-Api.prototype.removePlugin = function (plugin, uninstallOptions) {
- var project = AndroidProject.getProjectFile(this.root);
-
- if (uninstallOptions && uninstallOptions.usePlatformWww === true && this.android_studio === true) {
- uninstallOptions.usePlatformWww = false;
- uninstallOptions.android_studio = true;
- }
-
- return PluginManager.get(this.platform, this.locations, project)
- .removePlugin(plugin, uninstallOptions)
- .then(function () {
- if (plugin.getFrameworks(this.platform).length === 0) return;
-
- selfEvents.emit('verbose', 'Updating build files since android plugin contained ');
- require('./lib/builders/builders').getBuilder(this.builder).prepBuildFiles();
- }.bind(this))
- // CB-11022 Return truthy value to prevent running prepare after
- .thenResolve(true);
-};
-
-/**
- * Builds an application package for current platform.
- *
- * @param {Object} buildOptions A build options. This object's structure is
- * highly depends on platform's specific. The most common options are:
- * @param {Boolean} buildOptions.debug Indicates that packages should be
- * built with debug configuration. This is set to true by default unless the
- * 'release' option is not specified.
- * @param {Boolean} buildOptions.release Indicates that packages should be
- * built with release configuration. If not set to true, debug configuration
- * will be used.
- * @param {Boolean} buildOptions.device Specifies that built app is intended
- * to run on device
- * @param {Boolean} buildOptions.emulator: Specifies that built app is
- * intended to run on emulator
- * @param {String} buildOptions.target Specifies the device id that will be
- * used to run built application.
- * @param {Boolean} buildOptions.nobuild Indicates that this should be a
- * dry-run call, so no build artifacts will be produced.
- * @param {String[]} buildOptions.archs Specifies chip architectures which
- * app packages should be built for. List of valid architectures is depends on
- * platform.
- * @param {String} buildOptions.buildConfig The path to build configuration
- * file. The format of this file is depends on platform.
- * @param {String[]} buildOptions.argv Raw array of command-line arguments,
- * passed to `build` command. The purpose of this property is to pass a
- * platform-specific arguments, and eventually let platform define own
- * arguments processing logic.
- *
- * @return {Promise} A promise either fulfilled with an array of build
- * artifacts (application packages) if package was built successfully,
- * or rejected with CordovaError. The resultant build artifact objects is not
- * strictly typed and may conatin arbitrary set of fields as in sample below.
- *
- * {
- * architecture: 'x86',
- * buildType: 'debug',
- * path: '/path/to/build',
- * type: 'app'
- * }
- *
- * The return value in most cases will contain only one item but in some cases
- * there could be multiple items in output array, e.g. when multiple
- * arhcitectures is specified.
- */
-Api.prototype.build = function (buildOptions) {
- var self = this;
- if (this.android_studio) {
- buildOptions.studio = true;
- }
- return require('./lib/check_reqs').run().then(function () {
- return require('./lib/build').run.call(self, buildOptions);
- }).then(function (buildResults) {
- // Cast build result to array of build artifacts
- return buildResults.apkPaths.map(function (apkPath) {
- return {
- buildType: buildResults.buildType,
- buildMethod: buildResults.buildMethod,
- path: apkPath,
- type: 'apk'
- };
- });
- });
-};
-
-/**
- * Builds an application package for current platform and runs it on
- * specified/default device. If no 'device'/'emulator'/'target' options are
- * specified, then tries to run app on default device if connected, otherwise
- * runs the app on emulator.
- *
- * @param {Object} runOptions An options object. The structure is the same
- * as for build options.
- *
- * @return {Promise} A promise either fulfilled if package was built and ran
- * successfully, or rejected with CordovaError.
- */
-Api.prototype.run = function (runOptions) {
- var self = this;
- return require('./lib/check_reqs').run().then(function () {
- return require('./lib/run').run.call(self, runOptions);
- });
-};
-
-/**
- * Cleans out the build artifacts from platform's directory, and also
- * cleans out the platform www directory if called without options specified.
- *
- * @return {Promise} Return a promise either fulfilled, or rejected with
- * CordovaError.
- */
-Api.prototype.clean = function (cleanOptions) {
- var self = this;
- if (this.android_studio) {
- // This will lint, checking for null won't
- if (typeof cleanOptions === 'undefined') {
- cleanOptions = {};
- }
- cleanOptions.studio = true;
- }
-
- return require('./lib/check_reqs').run().then(function () {
- return require('./lib/build').runClean.call(self, cleanOptions);
- }).then(function () {
- return require('./lib/prepare').clean.call(self, cleanOptions);
- });
-};
-
-/**
- * Performs a requirements check for current platform. Each platform defines its
- * own set of requirements, which should be resolved before platform can be
- * built successfully.
- *
- * @return {Promise} Promise, resolved with set of Requirement
- * objects for current platform.
- */
-Api.prototype.requirements = function () {
- return require('./lib/check_reqs').check_all();
-};
-
-module.exports = Api;
diff --git a/platforms/android/cordova/android_sdk_version b/platforms/android/cordova/android_sdk_version
deleted file mode 100755
index 34ed28f..0000000
--- a/platforms/android/cordova/android_sdk_version
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var android_sdk = require('./lib/android_sdk');
-
-android_sdk.print_newest_available_sdk_target().done(null, function(err) {
- console.error(err);
- process.exit(2);
-});
-
-
diff --git a/platforms/android/cordova/android_sdk_version.bat b/platforms/android/cordova/android_sdk_version.bat
deleted file mode 100644
index a6bc104..0000000
--- a/platforms/android/cordova/android_sdk_version.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0android_sdk_version"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'android_sdk_version' script in 'bin' folder, aborting...>&2
- EXIT /B 1
-)
diff --git a/platforms/android/cordova/build b/platforms/android/cordova/build
deleted file mode 100755
index 222e84a..0000000
--- a/platforms/android/cordova/build
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var args = process.argv;
-var Api = require('./Api');
-var nopt = require('nopt');
-var path = require('path');
-
-// Support basic help commands
-if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0)
- require('./lib/build').help();
-
-// Do some basic argument parsing
-var buildOpts = nopt({
- 'verbose' : Boolean,
- 'silent' : Boolean,
- 'debug' : Boolean,
- 'release' : Boolean,
- 'nobuild': Boolean,
- 'buildConfig' : path
-}, { 'd' : '--verbose' });
-
-// Make buildOptions compatible with PlatformApi build method spec
-buildOpts.argv = buildOpts.argv.original;
-
-require('./loggingHelper').adjustLoggerLevel(buildOpts);
-
-new Api().build(buildOpts)
-.catch(function(err) {
- console.error(err.stack);
- process.exit(2);
-});
diff --git a/platforms/android/cordova/build.bat b/platforms/android/cordova/build.bat
deleted file mode 100644
index 46e966a..0000000
--- a/platforms/android/cordova/build.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0build"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'build' script in 'cordova' folder, aborting...>&2
- EXIT /B 1
-)
\ No newline at end of file
diff --git a/platforms/android/cordova/check_reqs b/platforms/android/cordova/check_reqs
deleted file mode 100755
index 372a383..0000000
--- a/platforms/android/cordova/check_reqs
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var check_reqs = require('./lib/check_reqs');
-
-check_reqs.run().done(
- function success() {
- console.log('Looks like your environment fully supports cordova-android development!');
- }, function fail(err) {
- console.log(err);
- process.exit(2);
- }
-);
diff --git a/platforms/android/cordova/check_reqs.bat b/platforms/android/cordova/check_reqs.bat
deleted file mode 100644
index 846dfa1..0000000
--- a/platforms/android/cordova/check_reqs.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0check_reqs"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'check_reqs' script in 'bin' folder, aborting...>&2
- EXIT /B 1
-)
diff --git a/platforms/android/cordova/clean b/platforms/android/cordova/clean
deleted file mode 100755
index 22065cc..0000000
--- a/platforms/android/cordova/clean
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var Api = require('./Api');
-var path = require('path');
-var nopt = require('nopt');
-
-// Support basic help commands
-if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0) {
- console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]));
- console.log('Cleans the project directory.');
- process.exit(0);
-}
-
-// Do some basic argument parsing
-var opts = nopt({
- 'verbose' : Boolean,
- 'silent' : Boolean
-}, { 'd' : '--verbose' });
-
-// Make buildOptions compatible with PlatformApi clean method spec
-opts.argv = opts.argv.original;
-
-// Skip cleaning prepared files when not invoking via cordova CLI.
-opts.noPrepare = true;
-
-require('./loggingHelper').adjustLoggerLevel(opts);
-
-new Api().clean(opts)
-.catch(function(err) {
- console.error(err.stack);
- process.exit(2);
-});
diff --git a/platforms/android/cordova/clean.bat b/platforms/android/cordova/clean.bat
deleted file mode 100644
index 445ef6e..0000000
--- a/platforms/android/cordova/clean.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0clean"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'clean' script in 'cordova' folder, aborting...>&2
- EXIT /B 1
-)
\ No newline at end of file
diff --git a/platforms/android/cordova/defaults.xml b/platforms/android/cordova/defaults.xml
deleted file mode 100644
index 5286ab9..0000000
--- a/platforms/android/cordova/defaults.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
diff --git a/platforms/android/cordova/lib/Adb.js b/platforms/android/cordova/lib/Adb.js
deleted file mode 100644
index 038c67c..0000000
--- a/platforms/android/cordova/lib/Adb.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q');
-var os = require('os');
-var events = require('cordova-common').events;
-var spawn = require('cordova-common').superspawn.spawn;
-var CordovaError = require('cordova-common').CordovaError;
-
-var Adb = {};
-
-function isDevice (line) {
- return line.match(/\w+\tdevice/) && !line.match(/emulator/);
-}
-
-function isEmulator (line) {
- return line.match(/device/) && line.match(/emulator/);
-}
-
-/**
- * Lists available/connected devices and emulators
- *
- * @param {Object} opts Various options
- * @param {Boolean} opts.emulators Specifies whether this method returns
- * emulators only
- *
- * @return {Promise} list of available/connected
- * devices/emulators
- */
-Adb.devices = function (opts) {
- return spawn('adb', ['devices'], {cwd: os.tmpdir()}).then(function (output) {
- return output.split('\n').filter(function (line) {
- // Filter out either real devices or emulators, depending on options
- return (line && opts && opts.emulators) ? isEmulator(line) : isDevice(line);
- }).map(function (line) {
- return line.replace(/\tdevice/, '').replace('\r', '');
- });
- });
-};
-
-Adb.install = function (target, packagePath, opts) {
- events.emit('verbose', 'Installing apk ' + packagePath + ' on target ' + target + '...');
- var args = ['-s', target, 'install'];
- if (opts && opts.replace) args.push('-r');
- return spawn('adb', args.concat(packagePath), {cwd: os.tmpdir()}).then(function (output) {
- // 'adb install' seems to always returns no error, even if installation fails
- // so we catching output to detect installation failure
- if (output.match(/Failure/)) {
- if (output.match(/INSTALL_PARSE_FAILED_NO_CERTIFICATES/)) {
- output += '\n\n' + 'Sign the build using \'-- --keystore\' or \'--buildConfig\'' +
- ' or sign and deploy the unsigned apk manually using Android tools.';
- } else if (output.match(/INSTALL_FAILED_VERSION_DOWNGRADE/)) {
- output += '\n\n' + 'You\'re trying to install apk with a lower versionCode that is already installed.' +
- '\nEither uninstall an app or increment the versionCode.';
- }
-
- return Q.reject(new CordovaError('Failed to install apk to device: ' + output));
- }
- });
-};
-
-Adb.uninstall = function (target, packageId) {
- events.emit('verbose', 'Uninstalling package ' + packageId + ' from target ' + target + '...');
- return spawn('adb', ['-s', target, 'uninstall', packageId], {cwd: os.tmpdir()});
-};
-
-Adb.shell = function (target, shellCommand) {
- events.emit('verbose', 'Running adb shell command "' + shellCommand + '" on target ' + target + '...');
- var args = ['-s', target, 'shell'];
- shellCommand = shellCommand.split(/\s+/);
- return spawn('adb', args.concat(shellCommand), {cwd: os.tmpdir()}).catch(function (output) {
- return Q.reject(new CordovaError('Failed to execute shell command "' +
- shellCommand + '"" on device: ' + output));
- });
-};
-
-Adb.start = function (target, activityName) {
- events.emit('verbose', 'Starting application "' + activityName + '" on target ' + target + '...');
- return Adb.shell(target, 'am start -W -a android.intent.action.MAIN -n' + activityName).catch(function (output) {
- return Q.reject(new CordovaError('Failed to start application "' +
- activityName + '"" on device: ' + output));
- });
-};
-
-module.exports = Adb;
diff --git a/platforms/android/cordova/lib/AndroidManifest.js b/platforms/android/cordova/lib/AndroidManifest.js
deleted file mode 100644
index 5b7077a..0000000
--- a/platforms/android/cordova/lib/AndroidManifest.js
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var fs = require('fs');
-var et = require('elementtree');
-var xml = require('cordova-common').xmlHelpers;
-
-var DEFAULT_ORIENTATION = 'default';
-
-/** Wraps an AndroidManifest file */
-function AndroidManifest (path) {
- this.path = path;
- this.doc = xml.parseElementtreeSync(path);
- if (this.doc.getroot().tag !== 'manifest') {
- throw new Error('AndroidManifest at ' + path + ' has incorrect root node name (expected "manifest")');
- }
-}
-
-AndroidManifest.prototype.getVersionName = function () {
- return this.doc.getroot().attrib['android:versionName'];
-};
-
-AndroidManifest.prototype.setVersionName = function (versionName) {
- this.doc.getroot().attrib['android:versionName'] = versionName;
- return this;
-};
-
-AndroidManifest.prototype.getVersionCode = function () {
- return this.doc.getroot().attrib['android:versionCode'];
-};
-
-AndroidManifest.prototype.setVersionCode = function (versionCode) {
- this.doc.getroot().attrib['android:versionCode'] = versionCode;
- return this;
-};
-
-AndroidManifest.prototype.getPackageId = function () {
- /* jshint -W069 */
- return this.doc.getroot().attrib['package'];
- /* jshint +W069 */
-};
-
-AndroidManifest.prototype.setPackageId = function (pkgId) {
- /* jshint -W069 */
- this.doc.getroot().attrib['package'] = pkgId;
- /* jshint +W069 */
- return this;
-};
-
-AndroidManifest.prototype.getActivity = function () {
- var activity = this.doc.getroot().find('./application/activity');
- return {
- getName: function () {
- return activity.attrib['android:name'];
- },
- setName: function (name) {
- if (!name) {
- delete activity.attrib['android:name'];
- } else {
- activity.attrib['android:name'] = name;
- }
- return this;
- },
- getOrientation: function () {
- return activity.attrib['android:screenOrientation'];
- },
- setOrientation: function (orientation) {
- if (!orientation || orientation.toLowerCase() === DEFAULT_ORIENTATION) {
- delete activity.attrib['android:screenOrientation'];
- } else {
- activity.attrib['android:screenOrientation'] = orientation;
- }
- return this;
- },
- getLaunchMode: function () {
- return activity.attrib['android:launchMode'];
- },
- setLaunchMode: function (launchMode) {
- if (!launchMode) {
- delete activity.attrib['android:launchMode'];
- } else {
- activity.attrib['android:launchMode'] = launchMode;
- }
- return this;
- }
- };
-};
-
-['minSdkVersion', 'maxSdkVersion', 'targetSdkVersion'].forEach(function (sdkPrefName) {
- // Copy variable reference to avoid closure issues
- var prefName = sdkPrefName;
-
- AndroidManifest.prototype['get' + capitalize(prefName)] = function () {
- var usesSdk = this.doc.getroot().find('./uses-sdk');
- return usesSdk && usesSdk.attrib['android:' + prefName];
- };
-
- AndroidManifest.prototype['set' + capitalize(prefName)] = function (prefValue) {
- var usesSdk = this.doc.getroot().find('./uses-sdk');
-
- if (!usesSdk && prefValue) { // if there is no required uses-sdk element, we should create it first
- usesSdk = new et.Element('uses-sdk');
- this.doc.getroot().append(usesSdk);
- }
-
- if (prefValue) {
- usesSdk.attrib['android:' + prefName] = prefValue;
- }
-
- return this;
- };
-});
-
-AndroidManifest.prototype.getDebuggable = function () {
- return this.doc.getroot().find('./application').attrib['android:debuggable'] === 'true';
-};
-
-AndroidManifest.prototype.setDebuggable = function (value) {
- var application = this.doc.getroot().find('./application');
- if (value) {
- application.attrib['android:debuggable'] = 'true';
- } else {
- // The default value is "false", so we can remove attribute at all.
- delete application.attrib['android:debuggable'];
- }
- return this;
-};
-
-/**
- * Writes manifest to disk syncronously. If filename is specified, then manifest
- * will be written to that file
- *
- * @param {String} [destPath] File to write manifest to. If omitted,
- * manifest will be written to file it has been read from.
- */
-AndroidManifest.prototype.write = function (destPath) {
- fs.writeFileSync(destPath || this.path, this.doc.write({indent: 4}), 'utf-8');
-};
-
-module.exports = AndroidManifest;
-
-function capitalize (str) {
- return str.charAt(0).toUpperCase() + str.slice(1);
-}
diff --git a/platforms/android/cordova/lib/AndroidProject.js b/platforms/android/cordova/lib/AndroidProject.js
deleted file mode 100644
index bf55cad..0000000
--- a/platforms/android/cordova/lib/AndroidProject.js
+++ /dev/null
@@ -1,209 +0,0 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var fs = require('fs');
-var path = require('path');
-var properties_parser = require('properties-parser');
-var AndroidManifest = require('./AndroidManifest');
-var AndroidStudio = require('./AndroidStudio');
-var pluginHandlers = require('./pluginHandlers');
-
-var projectFileCache = {};
-
-function addToPropertyList (projectProperties, key, value) {
- var i = 1;
- while (projectProperties.get(key + '.' + i)) { i++; }
-
- projectProperties.set(key + '.' + i, value);
- projectProperties.dirty = true;
-}
-
-function removeFromPropertyList (projectProperties, key, value) {
- var i = 1;
- var currentValue;
- while ((currentValue = projectProperties.get(key + '.' + i))) {
- if (currentValue === value) {
- while ((currentValue = projectProperties.get(key + '.' + (i + 1)))) {
- projectProperties.set(key + '.' + i, currentValue);
- i++;
- }
- projectProperties.set(key + '.' + i);
- break;
- }
- i++;
- }
- projectProperties.dirty = true;
-}
-
-function getRelativeLibraryPath (parentDir, subDir) {
- var libraryPath = path.relative(parentDir, subDir);
- return (path.sep === '\\') ? libraryPath.replace(/\\/g, '/') : libraryPath;
-}
-
-function AndroidProject (projectDir) {
- this._propertiesEditors = {};
- this._subProjectDirs = {};
- this._dirty = false;
- this.projectDir = projectDir;
- this.platformWww = path.join(this.projectDir, 'platform_www');
- this.www = path.join(this.projectDir, 'assets/www');
- if (AndroidStudio.isAndroidStudioProject(projectDir) === true) {
- this.www = path.join(this.projectDir, 'app/src/main/assets/www');
- }
-}
-
-AndroidProject.getProjectFile = function (projectDir) {
- if (!projectFileCache[projectDir]) {
- projectFileCache[projectDir] = new AndroidProject(projectDir);
- }
-
- return projectFileCache[projectDir];
-};
-
-AndroidProject.purgeCache = function (projectDir) {
- if (projectDir) {
- delete projectFileCache[projectDir];
- } else {
- projectFileCache = {};
- }
-};
-
-/**
- * Reads the package name out of the Android Manifest file
- *
- * @param {String} projectDir The absolute path to the directory containing the project
- *
- * @return {String} The name of the package
- */
-AndroidProject.prototype.getPackageName = function () {
- var manifestPath = path.join(this.projectDir, 'AndroidManifest.xml');
- if (AndroidStudio.isAndroidStudioProject(this.projectDir) === true) {
- manifestPath = path.join(this.projectDir, 'app/src/main/AndroidManifest.xml');
- }
- return new AndroidManifest(manifestPath).getPackageId();
-};
-
-AndroidProject.prototype.getCustomSubprojectRelativeDir = function (plugin_id, src) {
- // All custom subprojects are prefixed with the last portion of the package id.
- // This is to avoid collisions when opening multiple projects in Eclipse that have subprojects with the same name.
- var packageName = this.getPackageName();
- var lastDotIndex = packageName.lastIndexOf('.');
- var prefix = packageName.substring(lastDotIndex + 1);
- var subRelativeDir = path.join(plugin_id, prefix + '-' + path.basename(src));
- return subRelativeDir;
-};
-
-AndroidProject.prototype.addSubProject = function (parentDir, subDir) {
- var parentProjectFile = path.resolve(parentDir, 'project.properties');
- var subProjectFile = path.resolve(subDir, 'project.properties');
- var parentProperties = this._getPropertiesFile(parentProjectFile);
- // TODO: Setting the target needs to happen only for pre-3.7.0 projects
- if (fs.existsSync(subProjectFile)) {
- var subProperties = this._getPropertiesFile(subProjectFile);
- subProperties.set('target', parentProperties.get('target'));
- subProperties.dirty = true;
- this._subProjectDirs[subDir] = true;
- }
- addToPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
-
- this._dirty = true;
-};
-
-AndroidProject.prototype.removeSubProject = function (parentDir, subDir) {
- var parentProjectFile = path.resolve(parentDir, 'project.properties');
- var parentProperties = this._getPropertiesFile(parentProjectFile);
- removeFromPropertyList(parentProperties, 'android.library.reference', getRelativeLibraryPath(parentDir, subDir));
- delete this._subProjectDirs[subDir];
- this._dirty = true;
-};
-
-AndroidProject.prototype.addGradleReference = function (parentDir, subDir) {
- var parentProjectFile = path.resolve(parentDir, 'project.properties');
- var parentProperties = this._getPropertiesFile(parentProjectFile);
- addToPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
- this._dirty = true;
-};
-
-AndroidProject.prototype.removeGradleReference = function (parentDir, subDir) {
- var parentProjectFile = path.resolve(parentDir, 'project.properties');
- var parentProperties = this._getPropertiesFile(parentProjectFile);
- removeFromPropertyList(parentProperties, 'cordova.gradle.include', getRelativeLibraryPath(parentDir, subDir));
- this._dirty = true;
-};
-
-AndroidProject.prototype.addSystemLibrary = function (parentDir, value) {
- var parentProjectFile = path.resolve(parentDir, 'project.properties');
- var parentProperties = this._getPropertiesFile(parentProjectFile);
- addToPropertyList(parentProperties, 'cordova.system.library', value);
- this._dirty = true;
-};
-
-AndroidProject.prototype.removeSystemLibrary = function (parentDir, value) {
- var parentProjectFile = path.resolve(parentDir, 'project.properties');
- var parentProperties = this._getPropertiesFile(parentProjectFile);
- removeFromPropertyList(parentProperties, 'cordova.system.library', value);
- this._dirty = true;
-};
-
-AndroidProject.prototype.write = function () {
- if (!this._dirty) {
- return;
- }
- this._dirty = false;
-
- for (var filename in this._propertiesEditors) {
- var editor = this._propertiesEditors[filename];
- if (editor.dirty) {
- fs.writeFileSync(filename, editor.toString());
- editor.dirty = false;
- }
- }
-};
-
-AndroidProject.prototype._getPropertiesFile = function (filename) {
- if (!this._propertiesEditors[filename]) {
- if (fs.existsSync(filename)) {
- this._propertiesEditors[filename] = properties_parser.createEditor(filename);
- } else {
- this._propertiesEditors[filename] = properties_parser.createEditor();
- }
- }
-
- return this._propertiesEditors[filename];
-};
-
-AndroidProject.prototype.getInstaller = function (type) {
- return pluginHandlers.getInstaller(type);
-};
-
-AndroidProject.prototype.getUninstaller = function (type) {
- return pluginHandlers.getUninstaller(type);
-};
-
-/*
- * This checks if an Android project is clean or has old build artifacts
- */
-
-AndroidProject.prototype.isClean = function () {
- var build_path = path.join(this.projectDir, 'build');
- // If the build directory doesn't exist, it's clean
- return !(fs.existsSync(build_path));
-};
-
-module.exports = AndroidProject;
diff --git a/platforms/android/cordova/lib/AndroidStudio.js b/platforms/android/cordova/lib/AndroidStudio.js
deleted file mode 100644
index 68d4d8f..0000000
--- a/platforms/android/cordova/lib/AndroidStudio.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * This is a simple routine that checks if project is an Android Studio Project
- *
- * @param {String} root Root folder of the project
- */
-
-/* jshint esnext: false */
-
-module.exports.isAndroidStudioProject = function isAndroidStudioProject (root) {
- return true;
-};
diff --git a/platforms/android/cordova/lib/android_sdk.js b/platforms/android/cordova/lib/android_sdk.js
deleted file mode 100755
index 148f9f3..0000000
--- a/platforms/android/cordova/lib/android_sdk.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q');
-var superspawn = require('cordova-common').superspawn;
-
-var suffix_number_regex = /(\d+)$/;
-// Used for sorting Android targets, example strings to sort:
-// android-19
-// android-L
-// Google Inc.:Google APIs:20
-// Google Inc.:Glass Development Kit Preview:20
-// The idea is to sort based on largest "suffix" number - meaning the bigger
-// the number at the end, the more recent the target, the closer to the
-// start of the array.
-function sort_by_largest_numerical_suffix (a, b) {
- var suffix_a = a.match(suffix_number_regex);
- var suffix_b = b.match(suffix_number_regex);
- if (suffix_a && suffix_b) {
- // If the two targets being compared have suffixes, return less than
- // zero, or greater than zero, based on which suffix is larger.
- return (parseInt(suffix_a[1]) > parseInt(suffix_b[1]) ? -1 : 1);
- } else {
- // If no suffix numbers were detected, leave the order as-is between
- // elements a and b.
- return 0;
- }
-}
-
-module.exports.print_newest_available_sdk_target = function () {
- return module.exports.list_targets().then(function (targets) {
- targets.sort(sort_by_largest_numerical_suffix);
- console.log(targets[0]);
- });
-};
-
-module.exports.version_string_to_api_level = {
- '4.0': 14,
- '4.0.3': 15,
- '4.1': 16,
- '4.2': 17,
- '4.3': 18,
- '4.4': 19,
- '4.4W': 20,
- '5.0': 21,
- '5.1': 22,
- '6.0': 23,
- '7.0': 24,
- '7.1.1': 25,
- '8.0': 26
-};
-
-function parse_targets (output) {
- var target_out = output.split('\n');
- var targets = [];
- for (var i = target_out.length - 1; i >= 0; i--) {
- if (target_out[i].match(/id:/)) { // if "id:" is in the line...
- targets.push(target_out[i].match(/"(.+)"/)[1]); // .. match whatever is in quotes.
- }
- }
- return targets;
-}
-
-module.exports.list_targets_with_android = function () {
- return superspawn.spawn('android', ['list', 'target']).then(parse_targets);
-};
-
-module.exports.list_targets_with_avdmanager = function () {
- return superspawn.spawn('avdmanager', ['list', 'target']).then(parse_targets);
-};
-
-module.exports.list_targets = function () {
- return module.exports.list_targets_with_avdmanager().catch(function (err) {
- // If there's an error, like avdmanager could not be found, we can try
- // as a last resort, to run `android`, in case this is a super old
- // SDK installation.
- if (err && (err.code === 'ENOENT' || (err.stderr && err.stderr.match(/not recognized/)))) {
- return module.exports.list_targets_with_android();
- } else throw err;
- }).then(function (targets) {
- if (targets.length === 0) {
- return Q.reject(new Error('No android targets (SDKs) installed!'));
- }
- return targets;
- });
-};
diff --git a/platforms/android/cordova/lib/build.js b/platforms/android/cordova/lib/build.js
deleted file mode 100644
index e33cfae..0000000
--- a/platforms/android/cordova/lib/build.js
+++ /dev/null
@@ -1,294 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var Q = require('q');
-var path = require('path');
-var fs = require('fs');
-var nopt = require('nopt');
-
-var Adb = require('./Adb');
-
-var builders = require('./builders/builders');
-var events = require('cordova-common').events;
-var spawn = require('cordova-common').superspawn.spawn;
-var CordovaError = require('cordova-common').CordovaError;
-
-function parseOpts (options, resolvedTarget, projectRoot) {
- options = options || {};
- options.argv = nopt({
- gradle: Boolean,
- studio: Boolean,
- prepenv: Boolean,
- versionCode: String,
- minSdkVersion: String,
- gradleArg: [String, Array],
- keystore: path,
- alias: String,
- storePassword: String,
- password: String,
- keystoreType: String
- }, {}, options.argv, 0);
-
- // Android Studio Build method is the default
- var ret = {
- buildType: options.release ? 'release' : 'debug',
- buildMethod: process.env.ANDROID_BUILD || 'studio',
- prepEnv: options.argv.prepenv,
- arch: resolvedTarget && resolvedTarget.arch,
- extraArgs: []
- };
-
- if (options.argv.gradle || options.argv.studio) {
- ret.buildMethod = options.argv.studio ? 'studio' : 'gradle';
- }
-
- // This comes from cordova/run
- if (options.studio) ret.buildMethod = 'studio';
- if (options.gradle) ret.buildMethod = 'gradle';
-
- if (options.nobuild) ret.buildMethod = 'none';
-
- if (options.argv.versionCode) { ret.extraArgs.push('-PcdvVersionCode=' + options.argv.versionCode); }
-
- if (options.argv.minSdkVersion) { ret.extraArgs.push('-PcdvMinSdkVersion=' + options.argv.minSdkVersion); }
-
- if (options.argv.gradleArg) {
- ret.extraArgs = ret.extraArgs.concat(options.argv.gradleArg);
- }
-
- var packageArgs = {};
-
- if (options.argv.keystore) { packageArgs.keystore = path.relative(projectRoot, path.resolve(options.argv.keystore)); }
-
- ['alias', 'storePassword', 'password', 'keystoreType'].forEach(function (flagName) {
- if (options.argv[flagName]) { packageArgs[flagName] = options.argv[flagName]; }
- });
-
- var buildConfig = options.buildConfig;
-
- // If some values are not specified as command line arguments - use build config to supplement them.
- // Command line arguemnts have precedence over build config.
- if (buildConfig) {
- if (!fs.existsSync(buildConfig)) {
- throw new Error('Specified build config file does not exist: ' + buildConfig);
- }
- events.emit('log', 'Reading build config file: ' + path.resolve(buildConfig));
- var buildjson = fs.readFileSync(buildConfig, 'utf8');
- var config = JSON.parse(buildjson.replace(/^\ufeff/, '')); // Remove BOM
- if (config.android && config.android[ret.buildType]) {
- var androidInfo = config.android[ret.buildType];
- if (androidInfo.keystore && !packageArgs.keystore) {
- if (androidInfo.keystore.substr(0, 1) === '~') {
- androidInfo.keystore = process.env.HOME + androidInfo.keystore.substr(1);
- }
- packageArgs.keystore = path.resolve(path.dirname(buildConfig), androidInfo.keystore);
- events.emit('log', 'Reading the keystore from: ' + packageArgs.keystore);
- }
-
- ['alias', 'storePassword', 'password', 'keystoreType'].forEach(function (key) {
- packageArgs[key] = packageArgs[key] || androidInfo[key];
- });
- }
- }
-
- if (packageArgs.keystore && packageArgs.alias) {
- ret.packageInfo = new PackageInfo(packageArgs.keystore, packageArgs.alias, packageArgs.storePassword,
- packageArgs.password, packageArgs.keystoreType);
- }
-
- if (!ret.packageInfo) {
- if (Object.keys(packageArgs).length > 0) {
- events.emit('warn', '\'keystore\' and \'alias\' need to be specified to generate a signed archive.');
- }
- }
-
- return ret;
-}
-
-/*
- * Builds the project with the specifed options
- * Returns a promise.
- */
-module.exports.runClean = function (options) {
- var opts = parseOpts(options, null, this.root);
- var builder = builders.getBuilder(opts.buildMethod);
- return builder.prepEnv(opts).then(function () {
- return builder.clean(opts);
- });
-};
-
-/**
- * Builds the project with the specifed options.
- *
- * @param {BuildOptions} options A set of options. See PlatformApi.build
- * method documentation for reference.
- * @param {Object} optResolvedTarget A deployment target. Used to pass
- * target architecture from upstream 'run' call. TODO: remove this option in
- * favor of setting buildOptions.archs field.
- *
- * @return {Promise} Promise, resolved with built packages
- * information.
- */
-module.exports.run = function (options, optResolvedTarget) {
- var opts = parseOpts(options, optResolvedTarget, this.root);
- console.log(opts.buildMethod);
- var builder = builders.getBuilder(opts.buildMethod);
- return builder.prepEnv(opts).then(function () {
- if (opts.prepEnv) {
- events.emit('verbose', 'Build file successfully prepared.');
- return;
- }
- return builder.build(opts).then(function () {
- var apkPaths = builder.findOutputApks(opts.buildType, opts.arch);
- events.emit('log', 'Built the following apk(s): \n\t' + apkPaths.join('\n\t'));
- return {
- apkPaths: apkPaths,
- buildType: opts.buildType,
- buildMethod: opts.buildMethod
- };
- });
- });
-};
-
-/*
- * Detects the architecture of a device/emulator
- * Returns "arm" or "x86".
- */
-module.exports.detectArchitecture = function (target) {
- function helper () {
- return Adb.shell(target, 'cat /proc/cpuinfo').then(function (output) {
- return /intel/i.exec(output) ? 'x86' : 'arm';
- });
- }
- // It sometimes happens (at least on OS X), that this command will hang forever.
- // To fix it, either unplug & replug device, or restart adb server.
- return helper().timeout(1000, new CordovaError('Device communication timed out. Try unplugging & replugging the device.')).then(null, function (err) {
- if (/timed out/.exec('' + err)) {
- // adb kill-server doesn't seem to do the trick.
- // Could probably find a x-platform version of killall, but I'm not actually
- // sure that this scenario even happens on non-OSX machines.
- events.emit('verbose', 'adb timed out while detecting device/emulator architecture. Killing adb and trying again.');
- return spawn('killall', ['adb']).then(function () {
- return helper().then(null, function () {
- // The double kill is sadly often necessary, at least on mac.
- events.emit('warn', 'adb timed out a second time while detecting device/emulator architecture. Killing adb and trying again.');
- return spawn('killall', ['adb']).then(function () {
- return helper().then(null, function () {
- return Q.reject(new CordovaError('adb timed out a third time while detecting device/emulator architecture. Try unplugging & replugging the device.'));
- });
- });
- });
- }, function () {
- // For non-killall OS's.
- return Q.reject(err);
- });
- }
- throw err;
- });
-};
-
-module.exports.findBestApkForArchitecture = function (buildResults, arch) {
- var paths = buildResults.apkPaths.filter(function (p) {
- var apkName = path.basename(p);
- if (buildResults.buildType === 'debug') {
- return /-debug/.exec(apkName);
- }
- return !/-debug/.exec(apkName);
- });
- var archPattern = new RegExp('-' + arch);
- var hasArchPattern = /-x86|-arm/;
- for (var i = 0; i < paths.length; ++i) {
- var apkName = path.basename(paths[i]);
- if (hasArchPattern.exec(apkName)) {
- if (archPattern.exec(apkName)) {
- return paths[i];
- }
- } else {
- return paths[i];
- }
- }
- throw new Error('Could not find apk architecture: ' + arch + ' build-type: ' + buildResults.buildType);
-};
-
-function PackageInfo (keystore, alias, storePassword, password, keystoreType) {
- this.keystore = {
- 'name': 'key.store',
- 'value': keystore
- };
- this.alias = {
- 'name': 'key.alias',
- 'value': alias
- };
- if (storePassword) {
- this.storePassword = {
- 'name': 'key.store.password',
- 'value': storePassword
- };
- }
- if (password) {
- this.password = {
- 'name': 'key.alias.password',
- 'value': password
- };
- }
- if (keystoreType) {
- this.keystoreType = {
- 'name': 'key.store.type',
- 'value': keystoreType
- };
- }
-}
-
-PackageInfo.prototype = {
- toProperties: function () {
- var self = this;
- var result = '';
- Object.keys(self).forEach(function (key) {
- result += self[key].name;
- result += '=';
- result += self[key].value.replace(/\\/g, '\\\\');
- result += '\n';
- });
- return result;
- }
-};
-
-module.exports.help = function () {
- console.log('Usage: ' + path.relative(process.cwd(), path.join('../build')) + ' [flags] [Signed APK flags]');
- console.log('Flags:');
- console.log(' \'--debug\': will build project in debug mode (default)');
- console.log(' \'--release\': will build project for release');
- console.log(' \'--ant\': will build project with ant');
- console.log(' \'--gradle\': will build project with gradle (default)');
- console.log(' \'--nobuild\': will skip build process (useful when using run command)');
- console.log(' \'--prepenv\': don\'t build, but copy in build scripts where necessary');
- console.log(' \'--versionCode=#\': Override versionCode for this build. Useful for uploading multiple APKs. Requires --gradle.');
- console.log(' \'--minSdkVersion=#\': Override minSdkVersion for this build. Useful for uploading multiple APKs. Requires --gradle.');
- console.log(' \'--gradleArg=\': Extra args to pass to the gradle command. Use one flag per arg. Ex. --gradleArg=-PcdvBuildMultipleApks=true');
- console.log('');
- console.log('Signed APK flags (overwrites debug/release-signing.proprties) :');
- console.log(' \'--keystore=\': Key store used to build a signed archive. (Required)');
- console.log(' \'--alias=\': Alias for the key store. (Required)');
- console.log(' \'--storePassword=\': Password for the key store. (Optional - prompted)');
- console.log(' \'--password=\': Password for the key. (Optional - prompted)');
- console.log(' \'--keystoreType\': Type of the keystore. (Optional)');
- process.exit(0);
-};
diff --git a/platforms/android/cordova/lib/builders/GenericBuilder.js b/platforms/android/cordova/lib/builders/GenericBuilder.js
deleted file mode 100644
index 892aa38..0000000
--- a/platforms/android/cordova/lib/builders/GenericBuilder.js
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-/* eslint no-self-assign: 0 */
-/* eslint no-unused-vars: 0 */
-
-var Q = require('q');
-var fs = require('fs');
-var path = require('path');
-var shell = require('shelljs');
-var events = require('cordova-common').events;
-
-function GenericBuilder (projectDir) {
- this.root = projectDir || path.resolve(__dirname, '../../..');
- this.binDirs = {
- studio: path.join(this.root, 'app', 'build', 'outputs', 'apk'),
- gradle: path.join(this.root, 'build', 'outputs', 'apk')
- };
-}
-
-GenericBuilder.prototype.prepEnv = function () {
- return Q();
-};
-
-GenericBuilder.prototype.build = function () {
- events.emit('log', 'Skipping build...');
- return Q(null);
-};
-
-GenericBuilder.prototype.clean = function () {
- return Q();
-};
-
-GenericBuilder.prototype.findOutputApks = function (build_type, arch) {
- var self = this;
- return Object.keys(this.binDirs).reduce(function (result, builderName) {
- var binDir = self.binDirs[builderName];
- return result.concat(findOutputApksHelper(binDir, build_type, builderName === 'ant' ? null : arch));
- }, []).sort(apkSorter);
-};
-
-module.exports = GenericBuilder;
-
-function apkSorter (fileA, fileB) {
- // De-prioritize arch specific builds
- var archSpecificRE = /-x86|-arm/;
- if (archSpecificRE.exec(fileA)) {
- return 1;
- } else if (archSpecificRE.exec(fileB)) {
- return -1;
- }
-
- // De-prioritize unsigned builds
- var unsignedRE = /-unsigned/;
- if (unsignedRE.exec(fileA)) {
- return 1;
- } else if (unsignedRE.exec(fileB)) {
- return -1;
- }
-
- var timeDiff = fs.statSync(fileB).mtime - fs.statSync(fileA).mtime;
- return timeDiff === 0 ? fileA.length - fileB.length : timeDiff;
-}
-
-function findOutputApksHelper (dir, build_type, arch) {
- var shellSilent = shell.config.silent;
- shell.config.silent = true;
-
- // list directory recursively
- var ret = shell.ls('-R', dir).map(function (file) {
- // ls does not include base directory
- return path.join(dir, file);
- }).filter(function (file) {
- // find all APKs
- return file.match(/\.apk?$/i);
- }).filter(function (candidate) {
- var apkName = path.basename(candidate);
- // Need to choose between release and debug .apk.
- if (build_type === 'debug') {
- return /-debug/.exec(apkName) && !/-unaligned|-unsigned/.exec(apkName);
- }
- if (build_type === 'release') {
- return /-release/.exec(apkName) && !/-unaligned/.exec(apkName);
- }
- return true;
- }).sort(apkSorter);
-
- shellSilent = shellSilent;
-
- if (ret.length === 0) {
- return ret;
- }
- // Assume arch-specific build if newest apk has -x86 or -arm.
- var archSpecific = !!/-x86|-arm/.exec(path.basename(ret[0]));
- // And show only arch-specific ones (or non-arch-specific)
- ret = ret.filter(function (p) {
- /* jshint -W018 */
- return !!/-x86|-arm/.exec(path.basename(p)) === archSpecific;
- /* jshint +W018 */
- });
-
- if (archSpecific && ret.length > 1 && arch) {
- ret = ret.filter(function (p) {
- return path.basename(p).indexOf('-' + arch) !== -1;
- });
- }
-
- return ret;
-}
diff --git a/platforms/android/cordova/lib/builders/GradleBuilder.js b/platforms/android/cordova/lib/builders/GradleBuilder.js
deleted file mode 100644
index b955db1..0000000
--- a/platforms/android/cordova/lib/builders/GradleBuilder.js
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q');
-var fs = require('fs');
-var util = require('util');
-var path = require('path');
-var shell = require('shelljs');
-var superspawn = require('cordova-common').superspawn;
-var CordovaError = require('cordova-common').CordovaError;
-var events = require('cordova-common').events;
-var check_reqs = require('../check_reqs');
-
-var GenericBuilder = require('./GenericBuilder');
-
-var MARKER = 'YOUR CHANGES WILL BE ERASED!';
-var SIGNING_PROPERTIES = '-signing.properties';
-var TEMPLATE =
- '# This file is automatically generated.\n' +
- '# Do not modify this file -- ' + MARKER + '\n';
-
-function GradleBuilder (projectRoot) {
- GenericBuilder.call(this, projectRoot);
-
- this.binDirs = { gradle: this.binDirs.gradle };
-}
-
-util.inherits(GradleBuilder, GenericBuilder);
-
-GradleBuilder.prototype.getArgs = function (cmd, opts) {
- if (cmd === 'release') {
- cmd = 'cdvBuildRelease';
- } else if (cmd === 'debug') {
- cmd = 'cdvBuildDebug';
- }
- var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
- if (opts.arch) {
- args.push('-PcdvBuildArch=' + opts.arch);
- }
-
- // 10 seconds -> 6 seconds
- args.push('-Dorg.gradle.daemon=true');
- // to allow dex in process
- args.push('-Dorg.gradle.jvmargs=-Xmx2048m');
- // allow NDK to be used - required by Gradle 1.5 plugin
- args.push('-Pandroid.useDeprecatedNdk=true');
- args.push.apply(args, opts.extraArgs);
- // Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
- // args.push('-Dorg.gradle.parallel=true');
- return args;
-};
-
-/*
- * This returns a promise
- */
-
-GradleBuilder.prototype.runGradleWrapper = function (gradle_cmd, gradle_file) {
- var gradlePath = path.join(this.root, 'gradlew');
- gradle_file = path.join(this.root, (gradle_file || 'wrapper.gradle'));
- if (fs.existsSync(gradlePath)) {
- // Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
- } else {
- return superspawn.spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', gradle_file], { stdio: 'pipe' })
- .progress(function (stdio) {
- suppressJavaOptionsInfo(stdio);
- });
- }
-};
-
-/*
- * We need to kill this in a fire.
- */
-
-GradleBuilder.prototype.readProjectProperties = function () {
- function findAllUniq (data, r) {
- var s = {};
- var m;
- while ((m = r.exec(data))) {
- s[m[1]] = 1;
- }
- return Object.keys(s);
- }
-
- var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
- return {
- libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
- gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
- systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
- };
-};
-
-GradleBuilder.prototype.extractRealProjectNameFromManifest = function () {
- var manifestPath = path.join(this.root, 'AndroidManifest.xml');
- var manifestData = fs.readFileSync(manifestPath, 'utf8');
- var m = /= 0) {
- return check_reqs.check_android_target(error).then(function () {
- // If due to some odd reason - check_android_target succeeds
- // we should still fail here.
- return Q.reject(error);
- });
- }
- return Q.reject(error);
- });
-};
-
-GradleBuilder.prototype.clean = function (opts) {
- var builder = this;
- var wrapper = path.join(this.root, 'gradlew');
- var args = builder.getArgs('clean', opts);
- return Q().then(function () {
- return superspawn.spawn(wrapper, args, { stdio: 'inherit' });
- }).then(function () {
- shell.rm('-rf', path.join(builder.root, 'out'));
-
- ['debug', 'release'].forEach(function (config) {
- var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
- if (isAutoGenerated(propertiesFilePath)) {
- shell.rm('-f', propertiesFilePath);
- }
- });
- });
-};
-
-module.exports = GradleBuilder;
-
-function suppressJavaOptionsInfo (stdio) {
- if (stdio.stderr) {
- /*
- * Workaround for the issue with Java printing some unwanted information to
- * stderr instead of stdout.
- * This function suppresses 'Picked up _JAVA_OPTIONS' message from being
- * printed to stderr. See https://issues.apache.org/jira/browse/CB-9971 for
- * explanation.
- */
- var suppressThisLine = /^Picked up _JAVA_OPTIONS: /i.test(stdio.stderr.toString());
- if (suppressThisLine) {
- return;
- }
- process.stderr.write(stdio.stderr);
- } else {
- process.stdout.write(stdio.stdout);
- }
-}
-
-function isAutoGenerated (file) {
- return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
-}
diff --git a/platforms/android/cordova/lib/builders/StudioBuilder.js b/platforms/android/cordova/lib/builders/StudioBuilder.js
deleted file mode 100644
index 1689e16..0000000
--- a/platforms/android/cordova/lib/builders/StudioBuilder.js
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var Q = require('q');
-var fs = require('fs');
-var util = require('util');
-var path = require('path');
-var shell = require('shelljs');
-var spawn = require('cordova-common').superspawn.spawn;
-var events = require('cordova-common').events;
-var CordovaError = require('cordova-common').CordovaError;
-var check_reqs = require('../check_reqs');
-
-var GenericBuilder = require('./GenericBuilder');
-
-var MARKER = 'YOUR CHANGES WILL BE ERASED!';
-var SIGNING_PROPERTIES = '-signing.properties';
-var TEMPLATE =
- '# This file is automatically generated.\n' +
- '# Do not modify this file -- ' + MARKER + '\n';
-
-function StudioBuilder (projectRoot) {
- GenericBuilder.call(this, projectRoot);
-
- this.binDirs = {gradle: this.binDirs.studio};
-}
-
-util.inherits(StudioBuilder, GenericBuilder);
-
-StudioBuilder.prototype.getArgs = function (cmd, opts) {
- if (cmd === 'release') {
- cmd = 'cdvBuildRelease';
- } else if (cmd === 'debug') {
- cmd = 'cdvBuildDebug';
- }
- var args = [cmd, '-b', path.join(this.root, 'build.gradle')];
- if (opts.arch) {
- args.push('-PcdvBuildArch=' + opts.arch);
- }
-
- // 10 seconds -> 6 seconds
- args.push('-Dorg.gradle.daemon=true');
- // to allow dex in process
- args.push('-Dorg.gradle.jvmargs=-Xmx2048m');
- // allow NDK to be used - required by Gradle 1.5 plugin
- // args.push('-Pandroid.useDeprecatedNdk=true');
- args.push.apply(args, opts.extraArgs);
- // Shaves another 100ms, but produces a "try at own risk" warning. Not worth it (yet):
- // args.push('-Dorg.gradle.parallel=true');
- return args;
-};
-
-/*
- * This returns a promise
- */
-
-StudioBuilder.prototype.runGradleWrapper = function (gradle_cmd) {
- var gradlePath = path.join(this.root, 'gradlew');
- var wrapperGradle = path.join(this.root, 'wrapper.gradle');
- if (fs.existsSync(gradlePath)) {
- // Literally do nothing, for some reason this works, while !fs.existsSync didn't on Windows
- } else {
- return spawn(gradle_cmd, ['-p', this.root, 'wrapper', '-b', wrapperGradle], {stdio: 'inherit'});
- }
-};
-
-StudioBuilder.prototype.readProjectProperties = function () {
-
- function findAllUniq (data, r) {
- var s = {};
- var m;
- while ((m = r.exec(data))) {
- s[m[1]] = 1;
- }
- return Object.keys(s);
- }
-
- var data = fs.readFileSync(path.join(this.root, 'project.properties'), 'utf8');
- return {
- libs: findAllUniq(data, /^\s*android\.library\.reference\.\d+=(.*)(?:\s|$)/mg),
- gradleIncludes: findAllUniq(data, /^\s*cordova\.gradle\.include\.\d+=(.*)(?:\s|$)/mg),
- systemLibs: findAllUniq(data, /^\s*cordova\.system\.library\.\d+=(.*)(?:\s|$)/mg)
- };
-};
-
-StudioBuilder.prototype.extractRealProjectNameFromManifest = function () {
- var manifestPath = path.join(this.root, 'app', 'src', 'main', 'AndroidManifest.xml');
- var manifestData = fs.readFileSync(manifestPath, 'utf8');
- var m = /= 0) {
- return check_reqs.check_android_target(error).then(function () {
- // If due to some odd reason - check_android_target succeeds
- // we should still fail here.
- return Q.reject(error);
- });
- }
- return Q.reject(error);
- });
-};
-
-StudioBuilder.prototype.clean = function (opts) {
- var builder = this;
- var wrapper = path.join(this.root, 'gradlew');
- var args = builder.getArgs('clean', opts);
- return Q().then(function () {
- return spawn(wrapper, args, {stdio: 'inherit'});
- })
- .then(function () {
- shell.rm('-rf', path.join(builder.root, 'out'));
-
- ['debug', 'release'].forEach(function (config) {
- var propertiesFilePath = path.join(builder.root, config + SIGNING_PROPERTIES);
- if (isAutoGenerated(propertiesFilePath)) {
- shell.rm('-f', propertiesFilePath);
- }
- });
- });
-};
-
-module.exports = StudioBuilder;
-
-function isAutoGenerated (file) {
- return fs.existsSync(file) && fs.readFileSync(file, 'utf8').indexOf(MARKER) > 0;
-}
diff --git a/platforms/android/cordova/lib/builders/builders.js b/platforms/android/cordova/lib/builders/builders.js
deleted file mode 100644
index aedf9be..0000000
--- a/platforms/android/cordova/lib/builders/builders.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-var CordovaError = require('cordova-common').CordovaError;
-
-var knownBuilders = {
- gradle: 'GradleBuilder',
- studio: 'StudioBuilder',
- none: 'GenericBuilder'
-};
-
-/**
- * Helper method that instantiates and returns a builder for specified build
- * type.
- *
- * @param {String} builderType Builder name to construct and return. Must
- * be one of 'ant', 'gradle' or 'none'
- *
- * @return {Builder} A builder instance for specified build type.
- */
-module.exports.getBuilder = function (builderType, projectRoot) {
- if (!knownBuilders[builderType]) { throw new CordovaError('Builder ' + builderType + ' is not supported.'); }
-
- try {
- var Builder = require('./' + knownBuilders[builderType]);
- return new Builder(projectRoot);
- } catch (err) {
- throw new CordovaError('Failed to instantiate ' + knownBuilders[builderType] + ' builder: ' + err);
- }
-};
diff --git a/platforms/android/cordova/lib/check_reqs.js b/platforms/android/cordova/lib/check_reqs.js
deleted file mode 100644
index d9c5f99..0000000
--- a/platforms/android/cordova/lib/check_reqs.js
+++ /dev/null
@@ -1,424 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-/* jshint sub:true */
-
-var shelljs = require('shelljs');
-var child_process = require('child_process');
-var Q = require('q');
-var path = require('path');
-var fs = require('fs');
-var os = require('os');
-var REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
-var PROJECT_ROOT = path.join(__dirname, '..', '..');
-var CordovaError = require('cordova-common').CordovaError;
-var superspawn = require('cordova-common').superspawn;
-var android_sdk = require('./android_sdk');
-
-function forgivingWhichSync (cmd) {
- try {
- return fs.realpathSync(shelljs.which(cmd));
- } catch (e) {
- return '';
- }
-}
-
-module.exports.isWindows = function () {
- return (os.platform() === 'win32');
-};
-
-module.exports.isDarwin = function () {
- return (os.platform() === 'darwin');
-};
-
-// Get valid target from framework/project.properties if run from this repo
-// Otherwise get target from project.properties file within a generated cordova-android project
-module.exports.get_target = function () {
- function extractFromFile (filePath) {
- var target = shelljs.grep(/\btarget=/, filePath);
- if (!target) {
- throw new Error('Could not find android target within: ' + filePath);
- }
- return target.split('=')[1].trim();
- }
- var repo_file = path.join(REPO_ROOT, 'framework', 'project.properties');
- if (fs.existsSync(repo_file)) {
- return extractFromFile(repo_file);
- }
- var project_file = path.join(PROJECT_ROOT, 'project.properties');
- if (fs.existsSync(project_file)) {
- // if no target found, we're probably in a project and project.properties is in PROJECT_ROOT.
- return extractFromFile(project_file);
- }
- throw new Error('Could not find android target in either ' + repo_file + ' nor ' + project_file);
-};
-
-// Returns a promise. Called only by build and clean commands.
-module.exports.check_ant = function () {
- return superspawn.spawn('ant', ['-version']).then(function (output) {
- // Parse Ant version from command output
- return /version ((?:\d+\.)+(?:\d+))/i.exec(output)[1];
- }).catch(function (err) {
- if (err) {
- throw new CordovaError('Failed to run `ant -version`. Make sure you have `ant` on your $PATH.');
- }
- });
-};
-
-module.exports.get_gradle_wrapper = function () {
- var androidStudioPath;
- var i = 0;
- var foundStudio = false;
- var program_dir;
- // OK, This hack only works on Windows, not on Mac OS or Linux. We will be deleting this eventually!
- if (module.exports.isWindows()) {
-
- var result = child_process.spawnSync(path.join(__dirname, 'getASPath.bat'));
- // console.log('result.stdout =' + result.stdout.toString());
- // console.log('result.stderr =' + result.stderr.toString());
-
- if (result.stderr.toString().length > 0) {
- var androidPath = path.join(process.env['ProgramFiles'], 'Android') + '/';
- if (fs.existsSync(androidPath)) {
- program_dir = fs.readdirSync(androidPath);
- while (i < program_dir.length && !foundStudio) {
- if (program_dir[i].startsWith('Android Studio')) {
- foundStudio = true;
- androidStudioPath = path.join(process.env['ProgramFiles'], 'Android', program_dir[i], 'gradle');
- } else { ++i; }
- }
- }
- } else {
- // console.log('got android studio path from registry');
- // remove the (os independent) new line char at the end of stdout
- // add gradle to match the above.
- androidStudioPath = path.join(result.stdout.toString().split('\r\n')[0], 'gradle');
- }
- }
-
- if (androidStudioPath !== null && fs.existsSync(androidStudioPath)) {
- var dirs = fs.readdirSync(androidStudioPath);
- if (dirs[0].split('-')[0] === 'gradle') {
- return path.join(androidStudioPath, dirs[0], 'bin', 'gradle');
- }
- } else {
- // OK, let's try to check for Gradle!
- return forgivingWhichSync('gradle');
- }
-};
-
-// Returns a promise. Called only by build and clean commands.
-module.exports.check_gradle = function () {
- var sdkDir = process.env['ANDROID_HOME'];
- var d = Q.defer();
- if (!sdkDir) {
- return Q.reject(new CordovaError('Could not find gradle wrapper within Android SDK. Could not find Android SDK directory.\n' +
- 'Might need to install Android SDK or set up \'ANDROID_HOME\' env variable.'));
- }
-
- var gradlePath = module.exports.get_gradle_wrapper();
- if (gradlePath.length !== 0) { d.resolve(gradlePath); } else {
- d.reject(new CordovaError('Could not find an installed version of Gradle either in Android Studio,\n' +
- 'or on your system to install the gradle wrapper. Please include gradle \n' +
- 'in your path, or install Android Studio'));
- }
- return d.promise;
-};
-
-// Returns a promise.
-module.exports.check_java = function () {
- var javacPath = forgivingWhichSync('javac');
- var hasJavaHome = !!process.env['JAVA_HOME'];
- return Q().then(function () {
- if (hasJavaHome) {
- // Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
- if (!javacPath) {
- process.env['PATH'] += path.delimiter + path.join(process.env['JAVA_HOME'], 'bin');
- }
- } else {
- if (javacPath) {
- // OS X has a command for finding JAVA_HOME.
- var find_java = '/usr/libexec/java_home';
- var default_java_error_msg = 'Failed to find \'JAVA_HOME\' environment variable. Try setting it manually.';
- if (fs.existsSync(find_java)) {
- return superspawn.spawn(find_java).then(function (stdout) {
- process.env['JAVA_HOME'] = stdout.trim();
- }).catch(function (err) {
- if (err) {
- throw new CordovaError(default_java_error_msg);
- }
- });
- } else {
- // See if we can derive it from javac's location.
- // fs.realpathSync is require on Ubuntu, which symplinks from /usr/bin -> JDK
- var maybeJavaHome = path.dirname(path.dirname(javacPath));
- if (fs.existsSync(path.join(maybeJavaHome, 'lib', 'tools.jar'))) {
- process.env['JAVA_HOME'] = maybeJavaHome;
- } else {
- throw new CordovaError(default_java_error_msg);
- }
- }
- } else if (module.exports.isWindows()) {
- // Try to auto-detect java in the default install paths.
- var oldSilent = shelljs.config.silent;
- shelljs.config.silent = true;
- var firstJdkDir =
- shelljs.ls(process.env['ProgramFiles'] + '\\java\\jdk*')[0] ||
- shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
- shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
- shelljs.config.silent = oldSilent;
- if (firstJdkDir) {
- // shelljs always uses / in paths.
- firstJdkDir = firstJdkDir.replace(/\//g, path.sep);
- if (!javacPath) {
- process.env['PATH'] += path.delimiter + path.join(firstJdkDir, 'bin');
- }
- process.env['JAVA_HOME'] = firstJdkDir;
- }
- }
- }
- }).then(function () {
- return Q.denodeify(child_process.exec)('javac -version')
- .then(outputs => {
- // outputs contains two entries: stdout and stderr
- // Java <= 8 writes version info to stderr, Java >= 9 to stdout
- const output = outputs.join('').trim();
- const match = /javac\s+([\d.]+)/i.exec(output);
- return match && match[1];
- }, () => {
- var msg =
- 'Failed to run "javac -version", make sure that you have a JDK installed.\n' +
- 'You can get it from: http://www.oracle.com/technetwork/java/javase/downloads.\n';
- if (process.env['JAVA_HOME']) {
- msg += 'Your JAVA_HOME is invalid: ' + process.env['JAVA_HOME'] + '\n';
- }
- throw new CordovaError(msg);
- });
- });
-};
-
-// Returns a promise.
-module.exports.check_android = function () {
- return Q().then(function () {
- var androidCmdPath = forgivingWhichSync('android');
- var adbInPath = forgivingWhichSync('adb');
- var avdmanagerInPath = forgivingWhichSync('avdmanager');
- var hasAndroidHome = !!process.env['ANDROID_HOME'] && fs.existsSync(process.env['ANDROID_HOME']);
- function maybeSetAndroidHome (value) {
- if (!hasAndroidHome && fs.existsSync(value)) {
- hasAndroidHome = true;
- process.env['ANDROID_HOME'] = value;
- }
- }
- // First ensure ANDROID_HOME is set
- // If we have no hints (nothing in PATH), try a few default locations
- if (!hasAndroidHome && !androidCmdPath && !adbInPath && !avdmanagerInPath) {
- if (module.exports.isWindows()) {
- // Android Studio 1.0 installer
- maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'sdk'));
- maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'sdk'));
- // Android Studio pre-1.0 installer
- maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-studio', 'sdk'));
- maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-studio', 'sdk'));
- // Stand-alone installer
- maybeSetAndroidHome(path.join(process.env['LOCALAPPDATA'], 'Android', 'android-sdk'));
- maybeSetAndroidHome(path.join(process.env['ProgramFiles'], 'Android', 'android-sdk'));
- } else if (module.exports.isDarwin()) {
- // Android Studio 1.0 installer
- maybeSetAndroidHome(path.join(process.env['HOME'], 'Library', 'Android', 'sdk'));
- // Android Studio pre-1.0 installer
- maybeSetAndroidHome('/Applications/Android Studio.app/sdk');
- // Stand-alone zip file that user might think to put under /Applications
- maybeSetAndroidHome('/Applications/android-sdk-macosx');
- maybeSetAndroidHome('/Applications/android-sdk');
- }
- if (process.env['HOME']) {
- // Stand-alone zip file that user might think to put under their home directory
- maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk-macosx'));
- maybeSetAndroidHome(path.join(process.env['HOME'], 'android-sdk'));
- }
- }
- if (!hasAndroidHome) {
- // If we dont have ANDROID_HOME, but we do have some tools on the PATH, try to infer from the tooling PATH.
- var parentDir, grandParentDir;
- if (androidCmdPath) {
- parentDir = path.dirname(androidCmdPath);
- grandParentDir = path.dirname(parentDir);
- if (path.basename(parentDir) === 'tools' || fs.existsSync(path.join(grandParentDir, 'tools', 'android'))) {
- maybeSetAndroidHome(grandParentDir);
- } else {
- throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
- 'Detected \'android\' command at ' + parentDir + ' but no \'tools\' directory found near.\n' +
- 'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools directory.');
- }
- }
- if (adbInPath) {
- parentDir = path.dirname(adbInPath);
- grandParentDir = path.dirname(parentDir);
- if (path.basename(parentDir) === 'platform-tools') {
- maybeSetAndroidHome(grandParentDir);
- } else {
- throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
- 'Detected \'adb\' command at ' + parentDir + ' but no \'platform-tools\' directory found near.\n' +
- 'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'platform-tools directory.');
- }
- }
- if (avdmanagerInPath) {
- parentDir = path.dirname(avdmanagerInPath);
- grandParentDir = path.dirname(parentDir);
- if (path.basename(parentDir) === 'bin' && path.basename(grandParentDir) === 'tools') {
- maybeSetAndroidHome(path.dirname(grandParentDir));
- } else {
- throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
- 'Detected \'avdmanager\' command at ' + parentDir + ' but no \'tools' + path.sep + 'bin\' directory found near.\n' +
- 'Try reinstall Android SDK or update your PATH to include valid path to SDK' + path.sep + 'tools' + path.sep + 'bin directory.');
- }
- }
- }
- if (!process.env['ANDROID_HOME']) {
- throw new CordovaError('Failed to find \'ANDROID_HOME\' environment variable. Try setting it manually.\n' +
- 'Failed to find \'android\' command in your \'PATH\'. Try update your \'PATH\' to include path to valid SDK directory.');
- }
- if (!fs.existsSync(process.env['ANDROID_HOME'])) {
- throw new CordovaError('\'ANDROID_HOME\' environment variable is set to non-existent path: ' + process.env['ANDROID_HOME'] +
- '\nTry update it manually to point to valid SDK directory.');
- }
- // Next let's make sure relevant parts of the SDK tooling is in our PATH
- if (hasAndroidHome && !androidCmdPath) {
- process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools');
- }
- if (hasAndroidHome && !adbInPath) {
- process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'platform-tools');
- }
- if (hasAndroidHome && !avdmanagerInPath) {
- process.env['PATH'] += path.delimiter + path.join(process.env['ANDROID_HOME'], 'tools', 'bin');
- }
- return hasAndroidHome;
- });
-};
-
-// TODO: is this actually needed?
-module.exports.getAbsoluteAndroidCmd = function () {
- var cmd = forgivingWhichSync('android');
- if (cmd.length === 0) {
- cmd = forgivingWhichSync('sdkmanager');
- }
- if (module.exports.isWindows()) {
- return '"' + cmd + '"';
- }
- return cmd.replace(/(\s)/g, '\\$1');
-};
-
-module.exports.check_android_target = function (originalError) {
- // valid_target can look like:
- // android-19
- // android-L
- // Google Inc.:Google APIs:20
- // Google Inc.:Glass Development Kit Preview:20
- var desired_api_level = module.exports.get_target();
- return android_sdk.list_targets().then(function (targets) {
- if (targets.indexOf(desired_api_level) >= 0) {
- return targets;
- }
- var androidCmd = module.exports.getAbsoluteAndroidCmd();
- var msg = 'Please install Android target / API level: "' + desired_api_level + '".\n\n' +
- 'Hint: Open the SDK manager by running: ' + androidCmd + '\n' +
- 'You will require:\n' +
- '1. "SDK Platform" for API level ' + desired_api_level + '\n' +
- '2. "Android SDK Platform-tools (latest)\n' +
- '3. "Android SDK Build-tools" (latest)';
- if (originalError) {
- msg = originalError + '\n' + msg;
- }
- throw new CordovaError(msg);
- });
-};
-
-// Returns a promise.
-module.exports.run = function () {
- return Q.all([this.check_java(), this.check_android()]).then(function (values) {
- console.log('ANDROID_HOME=' + process.env['ANDROID_HOME']);
- console.log('JAVA_HOME=' + process.env['JAVA_HOME']);
-
- if (!String(values[0]).startsWith('1.8.')) {
- throw new CordovaError('Requirements check failed for JDK 1.8');
- }
-
- if (!values[1]) {
- throw new CordovaError('Requirements check failed for Android SDK');
- }
- });
-};
-
-/**
- * Object thar represents one of requirements for current platform.
- * @param {String} id The unique identifier for this requirements.
- * @param {String} name The name of requirements. Human-readable field.
- * @param {String} version The version of requirement installed. In some cases could be an array of strings
- * (for example, check_android_target returns an array of android targets installed)
- * @param {Boolean} installed Indicates whether the requirement is installed or not
- */
-var Requirement = function (id, name, version, installed) {
- this.id = id;
- this.name = name;
- this.installed = installed || false;
- this.metadata = {
- version: version
- };
-};
-
-/**
- * Methods that runs all checks one by one and returns a result of checks
- * as an array of Requirement objects. This method intended to be used by cordova-lib check_reqs method
- *
- * @return Promise Array of requirements. Due to implementation, promise is always fulfilled.
- */
-module.exports.check_all = function () {
-
- var requirements = [
- new Requirement('java', 'Java JDK'),
- new Requirement('androidSdk', 'Android SDK'),
- new Requirement('androidTarget', 'Android target'),
- new Requirement('gradle', 'Gradle')
- ];
-
- var checkFns = [
- this.check_java,
- this.check_android,
- this.check_android_target,
- this.check_gradle
- ];
-
- // Then execute requirement checks one-by-one
- return checkFns.reduce(function (promise, checkFn, idx) {
- // Update each requirement with results
- var requirement = requirements[idx];
- return promise.then(checkFn).then(function (version) {
- requirement.installed = true;
- requirement.metadata.version = version;
- }, function (err) {
- requirement.metadata.reason = err instanceof Error ? err.message : err;
- });
- }, Q()).then(function () {
- // When chain is completed, return requirements array to upstream API
- return requirements;
- });
-};
diff --git a/platforms/android/cordova/lib/device.js b/platforms/android/cordova/lib/device.js
deleted file mode 100644
index 84b5094..0000000
--- a/platforms/android/cordova/lib/device.js
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var Q = require('q');
-var build = require('./build');
-var path = require('path');
-var Adb = require('./Adb');
-var AndroidManifest = require('./AndroidManifest');
-var spawn = require('cordova-common').superspawn.spawn;
-var CordovaError = require('cordova-common').CordovaError;
-var events = require('cordova-common').events;
-
-/**
- * Returns a promise for the list of the device ID's found
- * @param lookHarder When true, try restarting adb if no devices are found.
- */
-module.exports.list = function (lookHarder) {
- return Adb.devices().then(function (list) {
- if (list.length === 0 && lookHarder) {
- // adb kill-server doesn't seem to do the trick.
- // Could probably find a x-platform version of killall, but I'm not actually
- // sure that this scenario even happens on non-OSX machines.
- return spawn('killall', ['adb']).then(function () {
- events.emit('verbose', 'Restarting adb to see if more devices are detected.');
- return Adb.devices();
- }, function () {
- // For non-killall OS's.
- return list;
- });
- }
- return list;
- });
-};
-
-module.exports.resolveTarget = function (target) {
- return this.list(true).then(function (device_list) {
- if (!device_list || !device_list.length) {
- return Q.reject(new CordovaError('Failed to deploy to device, no devices found.'));
- }
- // default device
- target = target || device_list[0];
-
- if (device_list.indexOf(target) < 0) {
- return Q.reject('ERROR: Unable to find target \'' + target + '\'.');
- }
-
- return build.detectArchitecture(target).then(function (arch) {
- return { target: target, arch: arch, isEmulator: false };
- });
- });
-};
-
-/*
- * Installs a previously built application on the device
- * and launches it.
- * Returns a promise.
- */
-module.exports.install = function (target, buildResults) {
- return Q().then(function () {
- if (target && typeof target === 'object') {
- return target;
- }
- return module.exports.resolveTarget(target);
- }).then(function (resolvedTarget) {
- var apk_path = build.findBestApkForArchitecture(buildResults, resolvedTarget.arch);
- var manifest = new AndroidManifest(path.join(__dirname, '../../app/src/main/AndroidManifest.xml'));
- var pkgName = manifest.getPackageId();
- var launchName = pkgName + '/.' + manifest.getActivity().getName();
- events.emit('log', 'Using apk: ' + apk_path);
- events.emit('log', 'Package name: ' + pkgName);
-
- return Adb.install(resolvedTarget.target, apk_path, {replace: true}).catch(function (error) {
- // CB-9557 CB-10157 only uninstall and reinstall app if the one that
- // is already installed on device was signed w/different certificate
- if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
-
- events.emit('warn', 'Uninstalling app from device and reinstalling it again because the ' +
- 'installed app already signed with different key');
-
- // This promise is always resolved, even if 'adb uninstall' fails to uninstall app
- // or the app doesn't installed at all, so no error catching needed.
- return Adb.uninstall(resolvedTarget.target, pkgName).then(function () {
- return Adb.install(resolvedTarget.target, apk_path, {replace: true});
- });
- }).then(function () {
- // unlock screen
- return Adb.shell(resolvedTarget.target, 'input keyevent 82');
- }).then(function () {
- return Adb.start(resolvedTarget.target, launchName);
- }).then(function () {
- events.emit('log', 'LAUNCH SUCCESS');
- });
- });
-};
diff --git a/platforms/android/cordova/lib/emulator.js b/platforms/android/cordova/lib/emulator.js
deleted file mode 100644
index 63ed302..0000000
--- a/platforms/android/cordova/lib/emulator.js
+++ /dev/null
@@ -1,534 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-/* jshint sub:true */
-
-var android_versions = require('android-versions');
-var retry = require('./retry');
-var build = require('./build');
-var path = require('path');
-var Adb = require('./Adb');
-var AndroidManifest = require('./AndroidManifest');
-var events = require('cordova-common').events;
-var superspawn = require('cordova-common').superspawn;
-var CordovaError = require('cordova-common').CordovaError;
-var shelljs = require('shelljs');
-var android_sdk = require('./android_sdk');
-var check_reqs = require('./check_reqs');
-
-var Q = require('q');
-var os = require('os');
-var fs = require('fs');
-var child_process = require('child_process');
-
-// constants
-var ONE_SECOND = 1000; // in milliseconds
-var ONE_MINUTE = 60 * ONE_SECOND; // in milliseconds
-var INSTALL_COMMAND_TIMEOUT = 5 * ONE_MINUTE; // in milliseconds
-var NUM_INSTALL_RETRIES = 3;
-var CHECK_BOOTED_INTERVAL = 3 * ONE_SECOND; // in milliseconds
-var EXEC_KILL_SIGNAL = 'SIGKILL';
-
-function forgivingWhichSync (cmd) {
- try {
- return fs.realpathSync(shelljs.which(cmd));
- } catch (e) {
- return '';
- }
-}
-
-module.exports.list_images_using_avdmanager = function () {
- return superspawn.spawn('avdmanager', ['list', 'avd']).then(function (output) {
- var response = output.split('\n');
- var emulator_list = [];
- for (var i = 1; i < response.length; i++) {
- // To return more detailed information use img_obj
- var img_obj = {};
- if (response[i].match(/Name:\s/)) {
- img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
- if (response[i + 1].match(/Device:\s/)) {
- i++;
- img_obj['device'] = response[i].split('Device: ')[1].replace('\r', '');
- }
- if (response[i + 1].match(/Path:\s/)) {
- i++;
- img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
- }
- if (response[i + 1].match(/Target:\s/)) {
- i++;
- if (response[i + 1].match(/ABI:\s/)) {
- img_obj['abi'] = response[i + 1].split('ABI: ')[1].replace('\r', '');
- }
- // This next conditional just aims to match the old output of `android list avd`
- // We do so so that we don't have to change the logic when parsing for the
- // best emulator target to spawn (see below in `best_image`)
- // This allows us to transitionally support both `android` and `avdmanager` binaries,
- // depending on what SDK version the user has
- if (response[i + 1].match(/Based\son:\s/)) {
- img_obj['target'] = response[i + 1].split('Based on:')[1];
- if (img_obj['target'].match(/Tag\/ABI:\s/)) {
- img_obj['target'] = img_obj['target'].split('Tag/ABI:')[0].replace('\r', '').trim();
- if (img_obj['target'].indexOf('(') > -1) {
- img_obj['target'] = img_obj['target'].substr(0, img_obj['target'].indexOf('(') - 1).trim();
- }
- }
- var version_string = img_obj['target'].replace(/Android\s+/, '');
-
- var api_level = android_sdk.version_string_to_api_level[version_string];
- if (api_level) {
- img_obj['target'] += ' (API level ' + api_level + ')';
- }
- }
- }
- if (response[i + 1].match(/Skin:\s/)) {
- i++;
- img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
- }
-
- emulator_list.push(img_obj);
- }
- /* To just return a list of names use this
- if (response[i].match(/Name:\s/)) {
- emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
- } */
-
- }
- return emulator_list;
- });
-};
-
-module.exports.list_images_using_android = function () {
- return superspawn.spawn('android', ['list', 'avd']).then(function (output) {
- var response = output.split('\n');
- var emulator_list = [];
- for (var i = 1; i < response.length; i++) {
- // To return more detailed information use img_obj
- var img_obj = {};
- if (response[i].match(/Name:\s/)) {
- img_obj['name'] = response[i].split('Name: ')[1].replace('\r', '');
- if (response[i + 1].match(/Device:\s/)) {
- i++;
- img_obj['device'] = response[i].split('Device: ')[1].replace('\r', '');
- }
- if (response[i + 1].match(/Path:\s/)) {
- i++;
- img_obj['path'] = response[i].split('Path: ')[1].replace('\r', '');
- }
- if (response[i + 1].match(/\(API\slevel\s/) || (response[i + 2] && response[i + 2].match(/\(API\slevel\s/))) {
- i++;
- var secondLine = response[i + 1].match(/\(API\slevel\s/) ? response[i + 1] : '';
- img_obj['target'] = (response[i] + secondLine).split('Target: ')[1].replace('\r', '');
- }
- if (response[i + 1].match(/ABI:\s/)) {
- i++;
- img_obj['abi'] = response[i].split('ABI: ')[1].replace('\r', '');
- }
- if (response[i + 1].match(/Skin:\s/)) {
- i++;
- img_obj['skin'] = response[i].split('Skin: ')[1].replace('\r', '');
- }
-
- emulator_list.push(img_obj);
- }
- /* To just return a list of names use this
- if (response[i].match(/Name:\s/)) {
- emulator_list.push(response[i].split('Name: ')[1].replace('\r', '');
- } */
-
- }
- return emulator_list;
- });
-};
-
-/**
- * Returns a Promise for a list of emulator images in the form of objects
- * {
- name : ,
- device : ,
- path : ,
- target : ,
- abi : ,
- skin :
- }
- */
-module.exports.list_images = function () {
- return Q.fcall(function () {
- if (forgivingWhichSync('avdmanager')) {
- return module.exports.list_images_using_avdmanager();
- } else if (forgivingWhichSync('android')) {
- return module.exports.list_images_using_android();
- } else {
- return Q().then(function () {
- throw new CordovaError('Could not find either `android` or `avdmanager` on your $PATH! Are you sure the Android SDK is installed and available?');
- });
- }
- }).then(function (avds) {
- // In case we're missing the Android OS version string from the target description, add it.
- return avds.map(function (avd) {
- if (avd.target && avd.target.indexOf('Android API') > -1 && avd.target.indexOf('API level') < 0) {
- var api_level = avd.target.match(/\d+/);
- if (api_level) {
- var level = android_versions.get(api_level);
- if (level) {
- avd.target = 'Android ' + level.semver + ' (API level ' + api_level + ')';
- }
- }
- }
- return avd;
- });
- });
-};
-
-/**
- * Will return the closest avd to the projects target
- * or undefined if no avds exist.
- * Returns a promise.
- */
-module.exports.best_image = function () {
- return this.list_images().then(function (images) {
- // Just return undefined if there is no images
- if (images.length === 0) return;
-
- var closest = 9999;
- var best = images[0];
- var project_target = parseInt(check_reqs.get_target().replace('android-', ''));
- for (var i in images) {
- var target = images[i].target;
- if (target && target.indexOf('API level') > -1) {
- var num = parseInt(target.split('(API level ')[1].replace(')', ''));
- if (num === project_target) {
- return images[i];
- } else if (project_target - num < closest && project_target > num) {
- closest = project_target - num;
- best = images[i];
- }
- }
- }
- return best;
- });
-};
-
-// Returns a promise.
-module.exports.list_started = function () {
- return Adb.devices({emulators: true});
-};
-
-// Returns a promise.
-// TODO: we should remove this, there's a more robust method under android_sdk.js
-module.exports.list_targets = function () {
- return superspawn.spawn('android', ['list', 'targets'], {cwd: os.tmpdir()}).then(function (output) {
- var target_out = output.split('\n');
- var targets = [];
- for (var i = target_out.length; i >= 0; i--) {
- if (target_out[i].match(/id:/)) {
- targets.push(targets[i].split(' ')[1]);
- }
- }
- return targets;
- });
-};
-
-/*
- * Gets unused port for android emulator, between 5554 and 5584
- * Returns a promise.
- */
-module.exports.get_available_port = function () {
- var self = this;
-
- return self.list_started().then(function (emulators) {
- for (var p = 5584; p >= 5554; p -= 2) {
- if (emulators.indexOf('emulator-' + p) === -1) {
- events.emit('verbose', 'Found available port: ' + p);
- return p;
- }
- }
- throw new CordovaError('Could not find an available avd port');
- });
-};
-
-/*
- * Starts an emulator with the given ID,
- * and returns the started ID of that emulator.
- * If no ID is given it will use the first image available,
- * if no image is available it will error out (maybe create one?).
- * If no boot timeout is given or the value is negative it will wait forever for
- * the emulator to boot
- *
- * Returns a promise.
- */
-module.exports.start = function (emulator_ID, boot_timeout) {
- var self = this;
-
- return Q().then(function () {
- if (emulator_ID) return Q(emulator_ID);
-
- return self.best_image().then(function (best) {
- if (best && best.name) {
- events.emit('warn', 'No emulator specified, defaulting to ' + best.name);
- return best.name;
- }
-
- var androidCmd = check_reqs.getAbsoluteAndroidCmd();
- return Q.reject(new CordovaError('No emulator images (avds) found.\n' +
- '1. Download desired System Image by running: ' + androidCmd + ' sdk\n' +
- '2. Create an AVD by running: ' + androidCmd + ' avd\n' +
- 'HINT: For a faster emulator, use an Intel System Image and install the HAXM device driver\n'));
- });
- }).then(function (emulatorId) {
- return self.get_available_port().then(function (port) {
- // Figure out the directory the emulator binary runs in, and set the cwd to that directory.
- // Workaround for https://code.google.com/p/android/issues/detail?id=235461
- var emulator_dir = path.dirname(shelljs.which('emulator'));
- var args = ['-avd', emulatorId, '-port', port];
- // Don't wait for it to finish, since the emulator will probably keep running for a long time.
- child_process
- .spawn('emulator', args, { stdio: 'inherit', detached: true, cwd: emulator_dir })
- .unref();
-
- // wait for emulator to start
- events.emit('log', 'Waiting for emulator to start...');
- return self.wait_for_emulator(port);
- });
- }).then(function (emulatorId) {
- if (!emulatorId) { return Q.reject(new CordovaError('Failed to start emulator')); }
-
- // wait for emulator to boot up
- process.stdout.write('Waiting for emulator to boot (this may take a while)...');
- return self.wait_for_boot(emulatorId, boot_timeout).then(function (success) {
- if (success) {
- events.emit('log', 'BOOT COMPLETE');
- // unlock screen
- return Adb.shell(emulatorId, 'input keyevent 82').then(function () {
- // return the new emulator id for the started emulators
- return emulatorId;
- });
- } else {
- // We timed out waiting for the boot to happen
- return null;
- }
- });
- });
-};
-
-/*
- * Waits for an emulator to boot on a given port.
- * Returns this emulator's ID in a promise.
- */
-module.exports.wait_for_emulator = function (port) {
- var self = this;
- return Q().then(function () {
- var emulator_id = 'emulator-' + port;
- return Adb.shell(emulator_id, 'getprop dev.bootcomplete').then(function (output) {
- if (output.indexOf('1') >= 0) {
- return emulator_id;
- }
- return self.wait_for_emulator(port);
- }, function (error) {
- if ((error && error.message &&
- (error.message.indexOf('not found') > -1)) ||
- (error.message.indexOf('device offline') > -1) ||
- (error.message.indexOf('device still connecting') > -1)) {
- // emulator not yet started, continue waiting
- return self.wait_for_emulator(port);
- } else {
- // something unexpected has happened
- throw error;
- }
- });
- });
-};
-
-/*
- * Waits for the core android process of the emulator to start. Returns a
- * promise that resolves to a boolean indicating success. Not specifying a
- * time_remaining or passing a negative value will cause it to wait forever
- */
-module.exports.wait_for_boot = function (emulator_id, time_remaining) {
- var self = this;
- return Adb.shell(emulator_id, 'ps').then(function (output) {
- if (output.match(/android\.process\.acore/)) {
- return true;
- } else if (time_remaining === 0) {
- return false;
- } else {
- process.stdout.write('.');
-
- // Check at regular intervals
- return Q.delay(time_remaining < CHECK_BOOTED_INTERVAL ? time_remaining : CHECK_BOOTED_INTERVAL).then(function () {
- var updated_time = time_remaining >= 0 ? Math.max(time_remaining - CHECK_BOOTED_INTERVAL, 0) : time_remaining;
- return self.wait_for_boot(emulator_id, updated_time);
- });
- }
- });
-};
-
-/*
- * Create avd
- * TODO : Enter the stdin input required to complete the creation of an avd.
- * Returns a promise.
- */
-module.exports.create_image = function (name, target) {
- console.log('Creating new avd named ' + name);
- if (target) {
- return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', target]).then(null, function (error) {
- console.error('ERROR : Failed to create emulator image : ');
- console.error(' Do you have the latest android targets including ' + target + '?');
- console.error(error);
- });
- } else {
- console.log('WARNING : Project target not found, creating avd with a different target but the project may fail to install.');
- // TODO: there's a more robust method for finding targets in android_sdk.js
- return superspawn.spawn('android', ['create', 'avd', '--name', name, '--target', this.list_targets()[0]]).then(function () {
- // TODO: This seems like another error case, even though it always happens.
- console.error('ERROR : Unable to create an avd emulator, no targets found.');
- console.error('Ensure you have targets available by running the "android" command');
- return Q.reject();
- }, function (error) {
- console.error('ERROR : Failed to create emulator image : ');
- console.error(error);
- });
- }
-};
-
-module.exports.resolveTarget = function (target) {
- return this.list_started().then(function (emulator_list) {
- if (emulator_list.length < 1) {
- return Q.reject('No running Android emulators found, please start an emulator before deploying your project.');
- }
-
- // default emulator
- target = target || emulator_list[0];
- if (emulator_list.indexOf(target) < 0) {
- return Q.reject('Unable to find target \'' + target + '\'. Failed to deploy to emulator.');
- }
-
- return build.detectArchitecture(target).then(function (arch) {
- return {target: target, arch: arch, isEmulator: true};
- });
- });
-};
-
-/*
- * Installs a previously built application on the emulator and launches it.
- * If no target is specified, then it picks one.
- * If no started emulators are found, error out.
- * Returns a promise.
- */
-module.exports.install = function (givenTarget, buildResults) {
-
- var target;
- // We need to find the proper path to the Android Manifest
- var manifestPath = path.join(__dirname, '..', '..', 'app', 'src', 'main', 'AndroidManifest.xml');
- if (buildResults.buildMethod === 'gradle') {
- manifestPath = path.join(__dirname, '../../AndroidManifest.xml');
- }
- var manifest = new AndroidManifest(manifestPath);
- var pkgName = manifest.getPackageId();
-
- // resolve the target emulator
- return Q().then(function () {
- if (givenTarget && typeof givenTarget === 'object') {
- return givenTarget;
- } else {
- return module.exports.resolveTarget(givenTarget);
- }
-
- // set the resolved target
- }).then(function (resolvedTarget) {
- target = resolvedTarget;
-
- // install the app
- }).then(function () {
- // This promise is always resolved, even if 'adb uninstall' fails to uninstall app
- // or the app doesn't installed at all, so no error catching needed.
- return Q.when().then(function () {
-
- var apk_path = build.findBestApkForArchitecture(buildResults, target.arch);
- var execOptions = {
- cwd: os.tmpdir(),
- timeout: INSTALL_COMMAND_TIMEOUT, // in milliseconds
- killSignal: EXEC_KILL_SIGNAL
- };
-
- events.emit('log', 'Using apk: ' + apk_path);
- events.emit('log', 'Package name: ' + pkgName);
- events.emit('verbose', 'Installing app on emulator...');
-
- // A special function to call adb install in specific environment w/ specific options.
- // Introduced as a part of fix for http://issues.apache.org/jira/browse/CB-9119
- // to workaround sporadic emulator hangs
- function adbInstallWithOptions (target, apk, opts) {
- events.emit('verbose', 'Installing apk ' + apk + ' on ' + target + '...');
-
- var command = 'adb -s ' + target + ' install -r "' + apk + '"';
- return Q.promise(function (resolve, reject) {
- child_process.exec(command, opts, function (err, stdout, stderr) {
- if (err) reject(new CordovaError('Error executing "' + command + '": ' + stderr));
- // adb does not return an error code even if installation fails. Instead it puts a specific
- // message to stdout, so we have to use RegExp matching to detect installation failure.
- else if (/Failure/.test(stdout)) {
- if (stdout.match(/INSTALL_PARSE_FAILED_NO_CERTIFICATES/)) {
- stdout += 'Sign the build using \'-- --keystore\' or \'--buildConfig\'' +
- ' or sign and deploy the unsigned apk manually using Android tools.';
- } else if (stdout.match(/INSTALL_FAILED_VERSION_DOWNGRADE/)) {
- stdout += 'You\'re trying to install apk with a lower versionCode that is already installed.' +
- '\nEither uninstall an app or increment the versionCode.';
- }
-
- reject(new CordovaError('Failed to install apk to emulator: ' + stdout));
- } else resolve(stdout);
- });
- });
- }
-
- function installPromise () {
- return adbInstallWithOptions(target.target, apk_path, execOptions).catch(function (error) {
- // CB-9557 CB-10157 only uninstall and reinstall app if the one that
- // is already installed on device was signed w/different certificate
- if (!/INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES/.test(error.toString())) { throw error; }
-
- events.emit('warn', 'Uninstalling app from device and reinstalling it because the ' +
- 'currently installed app was signed with different key');
-
- // This promise is always resolved, even if 'adb uninstall' fails to uninstall app
- // or the app doesn't installed at all, so no error catching needed.
- return Adb.uninstall(target.target, pkgName).then(function () {
- return adbInstallWithOptions(target.target, apk_path, execOptions);
- });
- });
- }
-
- return retry.retryPromise(NUM_INSTALL_RETRIES, installPromise).then(function (output) {
- events.emit('log', 'INSTALL SUCCESS');
- });
- });
- // unlock screen
- }).then(function () {
-
- events.emit('verbose', 'Unlocking screen...');
- return Adb.shell(target.target, 'input keyevent 82');
- }).then(function () {
- Adb.start(target.target, pkgName + '/.' + manifest.getActivity().getName());
- // report success or failure
- }).then(function (output) {
- events.emit('log', 'LAUNCH SUCCESS');
- });
-};
diff --git a/platforms/android/cordova/lib/getASPath.bat b/platforms/android/cordova/lib/getASPath.bat
deleted file mode 100644
index 14dad43..0000000
--- a/platforms/android/cordova/lib/getASPath.bat
+++ /dev/null
@@ -1,3 +0,0 @@
-@ECHO OFF
-for /f "tokens=2*" %%a in ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Android Studio" /v Path') do set "ASPath=%%~b"
-ECHO %ASPath%
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/install-device b/platforms/android/cordova/lib/install-device
deleted file mode 100755
index fc4b784..0000000
--- a/platforms/android/cordova/lib/install-device
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var device = require('./device'),
- args = process.argv;
-
-if(args.length > 2) {
- var install_target;
- if (args[2].substring(0, 9) == '--target=') {
- install_target = args[2].substring(9, args[2].length);
- device.install(install_target).done(null, function(err) {
- console.error('ERROR: ' + err);
- process.exit(2);
- });
- } else {
- console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
- process.exit(2);
- }
-} else {
- device.install().done(null, function(err) {
- console.error('ERROR: ' + err);
- process.exit(2);
- });
-}
diff --git a/platforms/android/cordova/lib/install-device.bat b/platforms/android/cordova/lib/install-device.bat
deleted file mode 100644
index 109b470..0000000
--- a/platforms/android/cordova/lib/install-device.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0install-device"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'install-device' script in 'cordova\lib' folder, aborting...>&2
- EXIT /B 1
-)
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/install-emulator b/platforms/android/cordova/lib/install-emulator
deleted file mode 100755
index aa2a34f..0000000
--- a/platforms/android/cordova/lib/install-emulator
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var emulator = require('./emulator'),
- args = process.argv;
-
-var install_target;
-if(args.length > 2) {
- if (args[2].substring(0, 9) == '--target=') {
- install_target = args[2].substring(9, args[2].length);
- } else {
- console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
- process.exit(2);
- }
-}
-
-emulator.install(install_target).done(null, function(err) {
- console.error('ERROR: ' + err);
- process.exit(2);
-});
diff --git a/platforms/android/cordova/lib/install-emulator.bat b/platforms/android/cordova/lib/install-emulator.bat
deleted file mode 100644
index a28c23a..0000000
--- a/platforms/android/cordova/lib/install-emulator.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0install-emulator"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'install-emulator' script in 'cordova\lib' folder, aborting...>&2
- EXIT /B 1
-)
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/list-devices b/platforms/android/cordova/lib/list-devices
deleted file mode 100755
index 8e22c7f..0000000
--- a/platforms/android/cordova/lib/list-devices
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var devices = require('./device');
-
-// Usage support for when args are given
-require('./check_reqs').check_android().then(function() {
- devices.list().done(function(device_list) {
- device_list && device_list.forEach(function(dev) {
- console.log(dev);
- });
- }, function(err) {
- console.error('ERROR: ' + err);
- process.exit(2);
- });
-});
diff --git a/platforms/android/cordova/lib/list-devices.bat b/platforms/android/cordova/lib/list-devices.bat
deleted file mode 100644
index ad5f03e..0000000
--- a/platforms/android/cordova/lib/list-devices.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0list-devices"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'list-devices' script in 'cordova\lib' folder, aborting...>&2
- EXIT /B 1
-)
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/list-emulator-images b/platforms/android/cordova/lib/list-emulator-images
deleted file mode 100755
index 25e5c81..0000000
--- a/platforms/android/cordova/lib/list-emulator-images
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var emulators = require('./emulator');
-
-// Usage support for when args are given
-require('./check_reqs').check_android().then(function() {
- emulators.list_images().done(function(emulator_list) {
- emulator_list && emulator_list.forEach(function(emu) {
- console.log(emu.name);
- });
- }, function(err) {
- console.error('ERROR: ' + err);
- process.exit(2);
- });
-});
diff --git a/platforms/android/cordova/lib/list-emulator-images.bat b/platforms/android/cordova/lib/list-emulator-images.bat
deleted file mode 100644
index 616ffb7..0000000
--- a/platforms/android/cordova/lib/list-emulator-images.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0list-emulator-images"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'list-emulator-images' script in 'cordova\lib' folder, aborting...>&2
- EXIT /B 1
-)
diff --git a/platforms/android/cordova/lib/list-started-emulators b/platforms/android/cordova/lib/list-started-emulators
deleted file mode 100755
index 43ebda2..0000000
--- a/platforms/android/cordova/lib/list-started-emulators
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var emulators = require('./emulator');
-
-// Usage support for when args are given
-require('./check_reqs').check_android().then(function() {
- emulators.list_started().done(function(emulator_list) {
- emulator_list && emulator_list.forEach(function(emu) {
- console.log(emu);
- });
- }, function(err) {
- console.error('ERROR: ' + err);
- process.exit(2);
- });
-});
diff --git a/platforms/android/cordova/lib/list-started-emulators.bat b/platforms/android/cordova/lib/list-started-emulators.bat
deleted file mode 100644
index eed02a5..0000000
--- a/platforms/android/cordova/lib/list-started-emulators.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0list-started-emulators"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'list-started-emulators' script in 'cordova\lib' folder, aborting...>&2
- EXIT /B 1
-)
\ No newline at end of file
diff --git a/platforms/android/cordova/lib/log.js b/platforms/android/cordova/lib/log.js
deleted file mode 100644
index ef2dd5c..0000000
--- a/platforms/android/cordova/lib/log.js
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var path = require('path');
-var os = require('os');
-var Q = require('q');
-var child_process = require('child_process');
-var ROOT = path.join(__dirname, '..', '..');
-
-/*
- * Starts running logcat in the shell.
- * Returns a promise.
- */
-module.exports.run = function () {
- var d = Q.defer();
- var adb = child_process.spawn('adb', ['logcat'], {cwd: os.tmpdir()});
-
- adb.stdout.on('data', function (data) {
- var lines = data ? data.toString().split('\n') : [];
- var out = lines.filter(function (x) { return x.indexOf('nativeGetEnabledTags') < 0; });
- console.log(out.join('\n'));
- });
-
- adb.stderr.on('data', console.error);
- adb.on('close', function (code) {
- if (code > 0) {
- d.reject('Failed to run logcat command.');
- } else d.resolve();
- });
-
- return d.promise;
-};
-
-module.exports.help = function () {
- console.log('Usage: ' + path.relative(process.cwd(), path.join(ROOT, 'cordova', 'log')));
- console.log('Gives the logcat output on the command line.');
- process.exit(0);
-};
diff --git a/platforms/android/cordova/lib/plugin-build.gradle b/platforms/android/cordova/lib/plugin-build.gradle
deleted file mode 100644
index fdef1f7..0000000
--- a/platforms/android/cordova/lib/plugin-build.gradle
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-// GENERATED FILE! DO NOT EDIT!
-
-buildscript {
- repositories {
- maven {
- url "https://maven.google.com"
- }
- jcenter()
- }
-
- // Switch the Android Gradle plugin version requirement depending on the
- // installed version of Gradle. This dependency is documented at
- // http://tools.android.com/tech-docs/new-build-system/version-compatibility
- // and https://issues.apache.org/jira/browse/CB-8143
- dependencies {
- classpath 'com.android.tools.build:gradle:1.0.0+'
- }
-}
-
-apply plugin: 'com.android.library'
-
-dependencies {
- compile fileTree(dir: 'libs', include: '*.jar')
- debugCompile project(path: ":CordovaLib", configuration: "debug")
- releaseCompile project(path: ":CordovaLib", configuration: "release")
-}
-
-android {
- compileSdkVersion cdvCompileSdkVersion
- buildToolsVersion cdvBuildToolsVersion
- publishNonDefault true
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_6
- targetCompatibility JavaVersion.VERSION_1_6
- }
-
- sourceSets {
- main {
- manifest.srcFile 'AndroidManifest.xml'
- java.srcDirs = ['src']
- resources.srcDirs = ['src']
- aidl.srcDirs = ['src']
- renderscript.srcDirs = ['src']
- res.srcDirs = ['res']
- assets.srcDirs = ['assets']
- jniLibs.srcDirs = ['libs']
- }
- }
-}
-
-if (file('build-extras.gradle').exists()) {
- apply from: 'build-extras.gradle'
-}
diff --git a/platforms/android/cordova/lib/pluginHandlers.js b/platforms/android/cordova/lib/pluginHandlers.js
deleted file mode 100644
index a3ebed0..0000000
--- a/platforms/android/cordova/lib/pluginHandlers.js
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Licensed 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.
- *
-*/
-
-/* jshint unused: vars */
-
-var fs = require('fs');
-var path = require('path');
-var shell = require('shelljs');
-var events = require('cordova-common').events;
-var CordovaError = require('cordova-common').CordovaError;
-
-var handlers = {
- 'source-file': {
- install: function (obj, plugin, project, options) {
- if (!obj.src) throw new CordovaError(generateAttributeError('src', 'source-file', plugin.id));
- if (!obj.targetDir) throw new CordovaError(generateAttributeError('target-dir', 'source-file', plugin.id));
-
- var dest = path.join(obj.targetDir, path.basename(obj.src));
-
- // TODO: This code needs to be replaced, since the core plugins need to be re-mapped to a different location in
- // a later plugins release. This is for legacy plugins to work with Cordova.
-
- if (options && options.android_studio === true) {
- dest = studioPathRemap(obj);
- }
-
- if (options && options.force) {
- copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
- } else {
- copyNewFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
- }
- },
- uninstall: function (obj, plugin, project, options) {
- var dest = path.join(obj.targetDir, path.basename(obj.src));
-
- if (options && options.android_studio === true) {
- dest = studioPathRemap(obj);
- }
-
- // TODO: Add Koltin extension to uninstall, since they are handled like Java files
- if (obj.src.endsWith('java')) {
- deleteJava(project.projectDir, dest);
- } else {
- // Just remove the file, not the whole parent directory
- removeFile(project.projectDir, dest);
- }
- }
- },
- 'lib-file': {
- install: function (obj, plugin, project, options) {
- var dest = path.join('libs', path.basename(obj.src));
- if (options && options.android_studio === true) {
- dest = path.join('app/libs', path.basename(obj.src));
- }
- copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
- },
- uninstall: function (obj, plugin, project, options) {
- var dest = path.join('libs', path.basename(obj.src));
- if (options && options.android_studio === true) {
- dest = path.join('app/libs', path.basename(obj.src));
- }
- removeFile(project.projectDir, dest);
- }
- },
- 'resource-file': {
- install: function (obj, plugin, project, options) {
- var dest = path.normalize(obj.target);
- if (options && options.android_studio === true) {
- dest = path.join('app/src/main', dest);
- }
- copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
- },
- uninstall: function (obj, plugin, project, options) {
- var dest = path.normalize(obj.target);
- if (options && options.android_studio === true) {
- dest = path.join('app/src/main', dest);
- }
- removeFile(project.projectDir, dest);
- }
- },
- 'framework': {
- install: function (obj, plugin, project, options) {
- var src = obj.src;
- if (!src) throw new CordovaError(generateAttributeError('src', 'framework', plugin.id));
-
- events.emit('verbose', 'Installing Android library: ' + src);
- var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
- var subDir;
-
- if (obj.custom) {
- var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
- copyNewFile(plugin.dir, src, project.projectDir, subRelativeDir, !!(options && options.link));
- subDir = path.resolve(project.projectDir, subRelativeDir);
- } else {
- obj.type = 'sys';
- subDir = src;
- }
-
- if (obj.type === 'gradleReference') {
- project.addGradleReference(parentDir, subDir);
- } else if (obj.type === 'sys') {
- project.addSystemLibrary(parentDir, subDir);
- } else {
- project.addSubProject(parentDir, subDir);
- }
- },
- uninstall: function (obj, plugin, project, options) {
- var src = obj.src;
- if (!src) throw new CordovaError(generateAttributeError('src', 'framework', plugin.id));
-
- events.emit('verbose', 'Uninstalling Android library: ' + src);
- var parentDir = obj.parent ? path.resolve(project.projectDir, obj.parent) : project.projectDir;
- var subDir;
-
- if (obj.custom) {
- var subRelativeDir = project.getCustomSubprojectRelativeDir(plugin.id, src);
- removeFile(project.projectDir, subRelativeDir);
- subDir = path.resolve(project.projectDir, subRelativeDir);
- // If it's the last framework in the plugin, remove the parent directory.
- var parDir = path.dirname(subDir);
- if (fs.existsSync(parDir) && fs.readdirSync(parDir).length === 0) {
- fs.rmdirSync(parDir);
- }
- } else {
- obj.type = 'sys';
- subDir = src;
- }
-
- if (obj.type === 'gradleReference') {
- project.removeGradleReference(parentDir, subDir);
- } else if (obj.type === 'sys') {
- project.removeSystemLibrary(parentDir, subDir);
- } else {
- project.removeSubProject(parentDir, subDir);
- }
- }
- },
- asset: {
- install: function (obj, plugin, project, options) {
- if (!obj.src) {
- throw new CordovaError(generateAttributeError('src', 'asset', plugin.id));
- }
- if (!obj.target) {
- throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));
- }
-
- copyFile(plugin.dir, obj.src, project.www, obj.target);
- if (options && options.usePlatformWww) {
- // CB-11022 copy file to both directories if usePlatformWww is specified
- copyFile(plugin.dir, obj.src, project.platformWww, obj.target);
- }
- },
- uninstall: function (obj, plugin, project, options) {
- var target = obj.target || obj.src;
-
- if (!target) throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));
-
- removeFileF(path.resolve(project.www, target));
- removeFileF(path.resolve(project.www, 'plugins', plugin.id));
- if (options && options.usePlatformWww) {
- // CB-11022 remove file from both directories if usePlatformWww is specified
- removeFileF(path.resolve(project.platformWww, target));
- removeFileF(path.resolve(project.platformWww, 'plugins', plugin.id));
- }
- }
- },
- 'js-module': {
- install: function (obj, plugin, project, options) {
- // Copy the plugin's files into the www directory.
- var moduleSource = path.resolve(plugin.dir, obj.src);
- var moduleName = plugin.id + '.' + (obj.name || path.basename(obj.src, path.extname(obj.src)));
-
- // Read in the file, prepend the cordova.define, and write it back out.
- var scriptContent = fs.readFileSync(moduleSource, 'utf-8').replace(/^\ufeff/, ''); // Window BOM
- if (moduleSource.match(/.*\.json$/)) {
- scriptContent = 'module.exports = ' + scriptContent;
- }
- scriptContent = 'cordova.define("' + moduleName + '", function(require, exports, module) {\n' + scriptContent + '\n});\n';
-
- var wwwDest = path.resolve(project.www, 'plugins', plugin.id, obj.src);
- shell.mkdir('-p', path.dirname(wwwDest));
- fs.writeFileSync(wwwDest, scriptContent, 'utf-8');
-
- if (options && options.usePlatformWww) {
- // CB-11022 copy file to both directories if usePlatformWww is specified
- var platformWwwDest = path.resolve(project.platformWww, 'plugins', plugin.id, obj.src);
- shell.mkdir('-p', path.dirname(platformWwwDest));
- fs.writeFileSync(platformWwwDest, scriptContent, 'utf-8');
- }
- },
- uninstall: function (obj, plugin, project, options) {
- var pluginRelativePath = path.join('plugins', plugin.id, obj.src);
- removeFileAndParents(project.www, pluginRelativePath);
- if (options && options.usePlatformWww) {
- // CB-11022 remove file from both directories if usePlatformWww is specified
- removeFileAndParents(project.platformWww, pluginRelativePath);
- }
- }
- }
-};
-
-module.exports.getInstaller = function (type) {
- if (handlers[type] && handlers[type].install) {
- return handlers[type].install;
- }
-
- events.emit('verbose', '<' + type + '> is not supported for android plugins');
-};
-
-module.exports.getUninstaller = function (type) {
- if (handlers[type] && handlers[type].uninstall) {
- return handlers[type].uninstall;
- }
-
- events.emit('verbose', '<' + type + '> is not supported for android plugins');
-};
-
-function copyFile (plugin_dir, src, project_dir, dest, link) {
- src = path.resolve(plugin_dir, src);
- if (!fs.existsSync(src)) throw new CordovaError('"' + src + '" not found!');
-
- // check that src path is inside plugin directory
- var real_path = fs.realpathSync(src);
- var real_plugin_path = fs.realpathSync(plugin_dir);
- if (real_path.indexOf(real_plugin_path) !== 0) { throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); }
-
- dest = path.resolve(project_dir, dest);
-
- // check that dest path is located in project directory
- if (dest.indexOf(project_dir) !== 0) { throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project'); }
-
- shell.mkdir('-p', path.dirname(dest));
- if (link) {
- symlinkFileOrDirTree(src, dest);
- } else if (fs.statSync(src).isDirectory()) {
- // XXX shelljs decides to create a directory when -R|-r is used which sucks. http://goo.gl/nbsjq
- shell.cp('-Rf', src + '/*', dest);
- } else {
- shell.cp('-f', src, dest);
- }
-}
-
-// Same as copy file but throws error if target exists
-function copyNewFile (plugin_dir, src, project_dir, dest, link) {
- var target_path = path.resolve(project_dir, dest);
- if (fs.existsSync(target_path)) { throw new CordovaError('"' + target_path + '" already exists!'); }
-
- copyFile(plugin_dir, src, project_dir, dest, !!link);
-}
-
-function symlinkFileOrDirTree (src, dest) {
- if (fs.existsSync(dest)) {
- shell.rm('-Rf', dest);
- }
-
- if (fs.statSync(src).isDirectory()) {
- shell.mkdir('-p', dest);
- fs.readdirSync(src).forEach(function (entry) {
- symlinkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
- });
- } else {
- fs.symlinkSync(path.relative(fs.realpathSync(path.dirname(dest)), src), dest);
- }
-}
-
-// checks if file exists and then deletes. Error if doesn't exist
-function removeFile (project_dir, src) {
- var file = path.resolve(project_dir, src);
- shell.rm('-Rf', file);
-}
-
-// deletes file/directory without checking
-function removeFileF (file) {
- shell.rm('-Rf', file);
-}
-
-// Sometimes we want to remove some java, and prune any unnecessary empty directories
-function deleteJava (project_dir, destFile) {
- removeFileAndParents(project_dir, destFile, 'src');
-}
-
-function removeFileAndParents (baseDir, destFile, stopper) {
- stopper = stopper || '.';
- var file = path.resolve(baseDir, destFile);
- if (!fs.existsSync(file)) return;
-
- removeFileF(file);
-
- // check if directory is empty
- var curDir = path.dirname(file);
-
- while (curDir !== path.resolve(baseDir, stopper)) {
- if (fs.existsSync(curDir) && fs.readdirSync(curDir).length === 0) {
- fs.rmdirSync(curDir);
- curDir = path.resolve(curDir, '..');
- } else {
- // directory not empty...do nothing
- break;
- }
- }
-}
-
-function generateAttributeError (attribute, element, id) {
- return 'Required attribute "' + attribute + '" not specified in <' + element + '> element from plugin: ' + id;
-}
-
-function studioPathRemap (obj) {
- // If a Java file is using the new directory structure, don't penalize it
- if (!obj.targetDir.includes('app/src/main')) {
- if (obj.src.endsWith('.java')) {
- return path.join('app/src/main/java', obj.targetDir.substring(4), path.basename(obj.src));
- } else {
- // For all other files, add 'app/src/main' to the targetDir if it didn't have it already
- return path.join('app/src/main', obj.targetDir, path.basename(obj.src));
- }
- }
-
-}
diff --git a/platforms/android/cordova/lib/prepare.js b/platforms/android/cordova/lib/prepare.js
deleted file mode 100644
index ac63f8a..0000000
--- a/platforms/android/cordova/lib/prepare.js
+++ /dev/null
@@ -1,480 +0,0 @@
-/**
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-/* eslint no-useless-escape: 0 */
-
-var Q = require('q');
-var fs = require('fs');
-var path = require('path');
-var shell = require('shelljs');
-var events = require('cordova-common').events;
-var AndroidManifest = require('./AndroidManifest');
-var checkReqs = require('./check_reqs');
-var xmlHelpers = require('cordova-common').xmlHelpers;
-var CordovaError = require('cordova-common').CordovaError;
-var ConfigParser = require('cordova-common').ConfigParser;
-var FileUpdater = require('cordova-common').FileUpdater;
-var PlatformJson = require('cordova-common').PlatformJson;
-var PlatformMunger = require('cordova-common').ConfigChanges.PlatformMunger;
-var PluginInfoProvider = require('cordova-common').PluginInfoProvider;
-
-module.exports.prepare = function (cordovaProject, options) {
- var self = this;
-
- var platformJson = PlatformJson.load(this.locations.root, this.platform);
- var munger = new PlatformMunger(this.platform, this.locations.root, platformJson, new PluginInfoProvider());
-
- this._config = updateConfigFilesFrom(cordovaProject.projectConfig, munger, this.locations);
-
- // Update own www dir with project's www assets and plugins' assets and js-files
- return Q.when(updateWww(cordovaProject, this.locations)).then(function () {
- // update project according to config.xml changes.
- return updateProjectAccordingTo(self._config, self.locations);
- }).then(function () {
- updateIcons(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
- updateSplashes(cordovaProject, path.relative(cordovaProject.root, self.locations.res));
- updateFileResources(cordovaProject, path.relative(cordovaProject.root, self.locations.root));
- }).then(function () {
- events.emit('verbose', 'Prepared android project successfully');
- });
-};
-
-module.exports.clean = function (options) {
- // A cordovaProject isn't passed into the clean() function, because it might have
- // been called from the platform shell script rather than the CLI. Check for the
- // noPrepare option passed in by the non-CLI clean script. If that's present, or if
- // there's no config.xml found at the project root, then don't clean prepared files.
- var projectRoot = path.resolve(this.root, '../..');
- if ((options && options.noPrepare) || !fs.existsSync(this.locations.configXml) ||
- !fs.existsSync(this.locations.configXml)) {
- return Q();
- }
-
- var projectConfig = new ConfigParser(this.locations.configXml);
-
- var self = this;
- return Q().then(function () {
- cleanWww(projectRoot, self.locations);
- cleanIcons(projectRoot, projectConfig, path.relative(projectRoot, self.locations.res));
- cleanSplashes(projectRoot, projectConfig, path.relative(projectRoot, self.locations.res));
- cleanFileResources(projectRoot, projectConfig, path.relative(projectRoot, self.locations.root));
- });
-};
-
-/**
- * Updates config files in project based on app's config.xml and config munge,
- * generated by plugins.
- *
- * @param {ConfigParser} sourceConfig A project's configuration that will
- * be merged into platform's config.xml
- * @param {ConfigChanges} configMunger An initialized ConfigChanges instance
- * for this platform.
- * @param {Object} locations A map of locations for this platform
- *
- * @return {ConfigParser} An instance of ConfigParser, that
- * represents current project's configuration. When returned, the
- * configuration is already dumped to appropriate config.xml file.
- */
-function updateConfigFilesFrom (sourceConfig, configMunger, locations) {
- events.emit('verbose', 'Generating platform-specific config.xml from defaults for android at ' + locations.configXml);
-
- // First cleanup current config and merge project's one into own
- // Overwrite platform config.xml with defaults.xml.
- shell.cp('-f', locations.defaultConfigXml, locations.configXml);
-
- // Then apply config changes from global munge to all config files
- // in project (including project's config)
- configMunger.reapply_global_munge().save_all();
-
- events.emit('verbose', 'Merging project\'s config.xml into platform-specific android config.xml');
- // Merge changes from app's config.xml into platform's one
- var config = new ConfigParser(locations.configXml);
- xmlHelpers.mergeXml(sourceConfig.doc.getroot(),
- config.doc.getroot(), 'android', /* clobber= */true);
-
- config.write();
- return config;
-}
-
-/**
- * Logs all file operations via the verbose event stream, indented.
- */
-function logFileOp (message) {
- events.emit('verbose', ' ' + message);
-}
-
-/**
- * Updates platform 'www' directory by replacing it with contents of
- * 'platform_www' and app www. Also copies project's overrides' folder into
- * the platform 'www' folder
- *
- * @param {Object} cordovaProject An object which describes cordova project.
- * @param {Object} destinations An object that contains destination
- * paths for www files.
- */
-function updateWww (cordovaProject, destinations) {
- var sourceDirs = [
- path.relative(cordovaProject.root, cordovaProject.locations.www),
- path.relative(cordovaProject.root, destinations.platformWww)
- ];
-
- // If project contains 'merges' for our platform, use them as another overrides
- var merges_path = path.join(cordovaProject.root, 'merges', 'android');
- if (fs.existsSync(merges_path)) {
- events.emit('verbose', 'Found "merges/android" folder. Copying its contents into the android project.');
- sourceDirs.push(path.join('merges', 'android'));
- }
-
- var targetDir = path.relative(cordovaProject.root, destinations.www);
- events.emit(
- 'verbose', 'Merging and updating files from [' + sourceDirs.join(', ') + '] to ' + targetDir);
- FileUpdater.mergeAndUpdateDir(
- sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);
-}
-
-/**
- * Cleans all files from the platform 'www' directory.
- */
-function cleanWww (projectRoot, locations) {
- var targetDir = path.relative(projectRoot, locations.www);
- events.emit('verbose', 'Cleaning ' + targetDir);
-
- // No source paths are specified, so mergeAndUpdateDir() will clear the target directory.
- FileUpdater.mergeAndUpdateDir(
- [], targetDir, { rootDir: projectRoot, all: true }, logFileOp);
-}
-
-/**
- * Updates project structure and AndroidManifest according to project's configuration.
- *
- * @param {ConfigParser} platformConfig A project's configuration that will
- * be used to update project
- * @param {Object} locations A map of locations for this platform
- */
-function updateProjectAccordingTo (platformConfig, locations) {
- // Update app name by editing res/values/strings.xml
- var strings = xmlHelpers.parseElementtreeSync(locations.strings);
-
- var name = platformConfig.name();
- strings.find('string[@name="app_name"]').text = name.replace(/\'/g, '\\\'');
-
- var shortName = platformConfig.shortName && platformConfig.shortName();
- if (shortName && shortName !== name) {
- strings.find('string[@name="launcher_name"]').text = shortName.replace(/\'/g, '\\\'');
- }
-
- fs.writeFileSync(locations.strings, strings.write({indent: 4}), 'utf-8');
- events.emit('verbose', 'Wrote out android application name "' + name + '" to ' + locations.strings);
-
- // Java packages cannot support dashes
- var androidPkgName = (platformConfig.android_packageName() || platformConfig.packageName()).replace(/-/g, '_');
-
- var manifest = new AndroidManifest(locations.manifest);
- var manifestId = manifest.getPackageId();
-
- manifest.getActivity()
- .setOrientation(platformConfig.getPreference('orientation'))
- .setLaunchMode(findAndroidLaunchModePreference(platformConfig));
-
- manifest.setVersionName(platformConfig.version())
- .setVersionCode(platformConfig.android_versionCode() || default_versionCode(platformConfig.version()))
- .setPackageId(androidPkgName)
- .setMinSdkVersion(platformConfig.getPreference('android-minSdkVersion', 'android'))
- .setMaxSdkVersion(platformConfig.getPreference('android-maxSdkVersion', 'android'))
- .setTargetSdkVersion(platformConfig.getPreference('android-targetSdkVersion', 'android'))
- .write();
-
- // Java file paths shouldn't be hard coded
- var javaPattern = path.join(locations.javaSrc, manifestId.replace(/\./g, '/'), '*.java');
- var java_files = shell.ls(javaPattern).filter(function (f) {
- return shell.grep(/extends\s+CordovaActivity/g, f);
- });
-
- if (java_files.length === 0) {
- throw new CordovaError('No Java files found that extend CordovaActivity.');
- } else if (java_files.length > 1) {
- events.emit('log', 'Multiple candidate Java files that extend CordovaActivity found. Guessing at the first one, ' + java_files[0]);
- }
-
- var destFile = path.join(locations.root, 'app', 'src', 'main', 'java', androidPkgName.replace(/\./g, '/'), path.basename(java_files[0]));
- shell.mkdir('-p', path.dirname(destFile));
- shell.sed(/package [\w\.]*;/, 'package ' + androidPkgName + ';', java_files[0]).to(destFile);
- events.emit('verbose', 'Wrote out Android package name "' + androidPkgName + '" to ' + destFile);
-
- var removeOrigPkg = checkReqs.isWindows() || checkReqs.isDarwin() ?
- manifestId.toUpperCase() !== androidPkgName.toUpperCase() :
- manifestId !== androidPkgName;
-
- if (removeOrigPkg) {
- // If package was name changed we need to remove old java with main activity
- shell.rm('-Rf', java_files[0]);
- // remove any empty directories
- var currentDir = path.dirname(java_files[0]);
- var sourcesRoot = path.resolve(locations.root, 'src');
- while (currentDir !== sourcesRoot) {
- if (fs.existsSync(currentDir) && fs.readdirSync(currentDir).length === 0) {
- fs.rmdirSync(currentDir);
- currentDir = path.resolve(currentDir, '..');
- } else {
- break;
- }
- }
- }
-}
-
-// Consturct the default value for versionCode as
-// PATCH + MINOR * 100 + MAJOR * 10000
-// see http://developer.android.com/tools/publishing/versioning.html
-function default_versionCode (version) {
- var nums = version.split('-')[0].split('.');
- var versionCode = 0;
- if (+nums[0]) {
- versionCode += +nums[0] * 10000;
- }
- if (+nums[1]) {
- versionCode += +nums[1] * 100;
- }
- if (+nums[2]) {
- versionCode += +nums[2];
- }
-
- events.emit('verbose', 'android-versionCode not found in config.xml. Generating a code based on version in config.xml (' + version + '): ' + versionCode);
- return versionCode;
-}
-
-function getImageResourcePath (resourcesDir, type, density, name, sourceName) {
- if (/\.9\.png$/.test(sourceName)) {
- name = name.replace(/\.png$/, '.9.png');
- }
- var resourcePath = path.join(resourcesDir, (density ? type + '-' + density : type), name);
- return resourcePath;
-}
-
-function updateSplashes (cordovaProject, platformResourcesDir) {
- var resources = cordovaProject.projectConfig.getSplashScreens('android');
-
- // if there are "splash" elements in config.xml
- if (resources.length === 0) {
- events.emit('verbose', 'This app does not have splash screens defined');
- return;
- }
-
- var resourceMap = mapImageResources(cordovaProject.root, platformResourcesDir, 'drawable', 'screen.png');
-
- var hadMdpi = false;
- resources.forEach(function (resource) {
- if (!resource.density) {
- return;
- }
- if (resource.density === 'mdpi') {
- hadMdpi = true;
- }
- var targetPath = getImageResourcePath(
- platformResourcesDir, 'drawable', resource.density, 'screen.png', path.basename(resource.src));
- resourceMap[targetPath] = resource.src;
- });
-
- // There's no "default" drawable, so assume default == mdpi.
- if (!hadMdpi && resources.defaultResource) {
- var targetPath = getImageResourcePath(
- platformResourcesDir, 'drawable', 'mdpi', 'screen.png', path.basename(resources.defaultResource.src));
- resourceMap[targetPath] = resources.defaultResource.src;
- }
-
- events.emit('verbose', 'Updating splash screens at ' + platformResourcesDir);
- FileUpdater.updatePaths(
- resourceMap, { rootDir: cordovaProject.root }, logFileOp);
-}
-
-function cleanSplashes (projectRoot, projectConfig, platformResourcesDir) {
- var resources = projectConfig.getSplashScreens('android');
- if (resources.length > 0) {
- var resourceMap = mapImageResources(projectRoot, platformResourcesDir, 'drawable', 'screen.png');
- events.emit('verbose', 'Cleaning splash screens at ' + platformResourcesDir);
-
- // No source paths are specified in the map, so updatePaths() will delete the target files.
- FileUpdater.updatePaths(
- resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
- }
-}
-
-function updateIcons (cordovaProject, platformResourcesDir) {
- var icons = cordovaProject.projectConfig.getIcons('android');
-
- // if there are icon elements in config.xml
- if (icons.length === 0) {
- events.emit('verbose', 'This app does not have launcher icons defined');
- return;
- }
-
- var resourceMap = mapImageResources(cordovaProject.root, platformResourcesDir, 'mipmap', 'icon.png');
-
- var android_icons = {};
- var default_icon;
- // http://developer.android.com/design/style/iconography.html
- var sizeToDensityMap = {
- 36: 'ldpi',
- 48: 'mdpi',
- 72: 'hdpi',
- 96: 'xhdpi',
- 144: 'xxhdpi',
- 192: 'xxxhdpi'
- };
- // find the best matching icon for a given density or size
- // @output android_icons
- var parseIcon = function (icon, icon_size) {
- // do I have a platform icon for that density already
- var density = icon.density || sizeToDensityMap[icon_size];
- if (!density) {
- // invalid icon defition ( or unsupported size)
- return;
- }
- var previous = android_icons[density];
- if (previous && previous.platform) {
- return;
- }
- android_icons[density] = icon;
- };
-
- // iterate over all icon elements to find the default icon and call parseIcon
- for (var i = 0; i < icons.length; i++) {
- var icon = icons[i];
- var size = icon.width;
- if (!size) {
- size = icon.height;
- }
- if (!size && !icon.density) {
- if (default_icon) {
- events.emit('verbose', 'Found extra default icon: ' + icon.src + ' (ignoring in favor of ' + default_icon.src + ')');
- } else {
- default_icon = icon;
- }
- } else {
- parseIcon(icon, size);
- }
- }
-
- // The source paths for icons and splashes are relative to
- // project's config.xml location, so we use it as base path.
- for (var density in android_icons) {
- var targetPath = getImageResourcePath(
- platformResourcesDir, 'mipmap', density, 'icon.png', path.basename(android_icons[density].src));
- resourceMap[targetPath] = android_icons[density].src;
- }
-
- // There's no "default" drawable, so assume default == mdpi.
- if (default_icon && !android_icons.mdpi) {
- var defaultTargetPath = getImageResourcePath(
- platformResourcesDir, 'mipmap', 'mdpi', 'icon.png', path.basename(default_icon.src));
- resourceMap[defaultTargetPath] = default_icon.src;
- }
-
- events.emit('verbose', 'Updating icons at ' + platformResourcesDir);
- FileUpdater.updatePaths(
- resourceMap, { rootDir: cordovaProject.root }, logFileOp);
-}
-
-function cleanIcons (projectRoot, projectConfig, platformResourcesDir) {
- var icons = projectConfig.getIcons('android');
- if (icons.length > 0) {
- var resourceMap = mapImageResources(projectRoot, platformResourcesDir, 'mipmap', 'icon.png');
- events.emit('verbose', 'Cleaning icons at ' + platformResourcesDir);
-
- // No source paths are specified in the map, so updatePaths() will delete the target files.
- FileUpdater.updatePaths(
- resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
- }
-}
-
-/**
- * Gets a map containing resources of a specified name from all drawable folders in a directory.
- */
-function mapImageResources (rootDir, subDir, type, resourceName) {
- var pathMap = {};
- shell.ls(path.join(rootDir, subDir, type + '-*')).forEach(function (drawableFolder) {
- var imagePath = path.join(subDir, path.basename(drawableFolder), resourceName);
- pathMap[imagePath] = null;
- });
- return pathMap;
-}
-
-function updateFileResources (cordovaProject, platformDir) {
- var files = cordovaProject.projectConfig.getFileResources('android');
-
- // if there are resource-file elements in config.xml
- if (files.length === 0) {
- events.emit('verbose', 'This app does not have additional resource files defined');
- return;
- }
-
- var resourceMap = {};
- files.forEach(function (res) {
- var targetPath = path.join(platformDir, res.target);
- resourceMap[targetPath] = res.src;
- });
-
- events.emit('verbose', 'Updating resource files at ' + platformDir);
- FileUpdater.updatePaths(
- resourceMap, { rootDir: cordovaProject.root }, logFileOp);
-}
-
-function cleanFileResources (projectRoot, projectConfig, platformDir) {
- var files = projectConfig.getFileResources('android', true);
- if (files.length > 0) {
- events.emit('verbose', 'Cleaning resource files at ' + platformDir);
-
- var resourceMap = {};
- files.forEach(function (res) {
- var filePath = path.join(platformDir, res.target);
- resourceMap[filePath] = null;
- });
-
- FileUpdater.updatePaths(
- resourceMap, {
- rootDir: projectRoot, all: true}, logFileOp);
- }
-}
-
-/**
- * Gets and validates 'AndroidLaunchMode' prepference from config.xml. Returns
- * preference value and warns if it doesn't seems to be valid
- *
- * @param {ConfigParser} platformConfig A configParser instance for
- * platform.
- *
- * @return {String} Preference's value from config.xml or
- * default value, if there is no such preference. The default value is
- * 'singleTop'
- */
-function findAndroidLaunchModePreference (platformConfig) {
- var launchMode = platformConfig.getPreference('AndroidLaunchMode');
- if (!launchMode) {
- // Return a default value
- return 'singleTop';
- }
-
- var expectedValues = ['standard', 'singleTop', 'singleTask', 'singleInstance'];
- var valid = expectedValues.indexOf(launchMode) >= 0;
- if (!valid) {
- // Note: warn, but leave the launch mode as developer wanted, in case the list of options changes in the future
- events.emit('warn', 'Unrecognized value for AndroidLaunchMode preference: ' +
- launchMode + '. Expected values are: ' + expectedValues.join(', '));
- }
-
- return launchMode;
-}
diff --git a/platforms/android/cordova/lib/retry.js b/platforms/android/cordova/lib/retry.js
deleted file mode 100644
index c464b9d..0000000
--- a/platforms/android/cordova/lib/retry.js
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-/* jshint node: true */
-
-'use strict';
-
-var events = require('cordova-common').events;
-
-/*
- * Retry a promise-returning function a number of times, propagating its
- * results on success or throwing its error on a failed final attempt.
- *
- * @arg {Number} attemts_left - The number of times to retry the passed call.
- * @arg {Function} promiseFunction - A function that returns a promise.
- * @arg {...} - Arguments to pass to promiseFunction.
- *
- * @returns {Promise}
- */
-module.exports.retryPromise = function (attemts_left, promiseFunction) {
-
- // NOTE:
- // get all trailing arguments, by skipping the first two (attemts_left and
- // promiseFunction) because they shouldn't get passed to promiseFunction
- var promiseFunctionArguments = Array.prototype.slice.call(arguments, 2);
-
- return promiseFunction.apply(undefined, promiseFunctionArguments).then(
-
- // on success pass results through
- function onFulfilled (value) {
- return value;
- },
-
- // on rejection either retry, or throw the error
- function onRejected (error) {
-
- attemts_left -= 1;
-
- if (attemts_left < 1) {
- throw error;
- }
-
- events.emit('verbose', 'A retried call failed. Retrying ' + attemts_left + ' more time(s).');
-
- // retry call self again with the same arguments, except attemts_left is now lower
- var fullArguments = [attemts_left, promiseFunction].concat(promiseFunctionArguments);
- return module.exports.retryPromise.apply(undefined, fullArguments);
- }
- );
-};
diff --git a/platforms/android/cordova/lib/run.js b/platforms/android/cordova/lib/run.js
deleted file mode 100644
index 4d7927c..0000000
--- a/platforms/android/cordova/lib/run.js
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-/* jshint loopfunc:true */
-
-var path = require('path');
-var build = require('./build');
-var emulator = require('./emulator');
-var device = require('./device');
-var Q = require('q');
-var events = require('cordova-common').events;
-
-function getInstallTarget (runOptions) {
- var install_target;
- if (runOptions.target) {
- install_target = runOptions.target;
- } else if (runOptions.device) {
- install_target = '--device';
- } else if (runOptions.emulator) {
- install_target = '--emulator';
- }
-
- return install_target;
-}
-
-/**
- * Runs the application on a device if available. If no device is found, it will
- * use a started emulator. If no started emulators are found it will attempt
- * to start an avd. If no avds are found it will error out.
- *
- * @param {Object} runOptions various run/build options. See Api.js build/run
- * methods for reference.
- *
- * @return {Promise}
- */
-module.exports.run = function (runOptions) {
-
- var self = this;
- var install_target = getInstallTarget(runOptions);
-
- return Q().then(function () {
- if (!install_target) {
- // no target given, deploy to device if available, otherwise use the emulator.
- return device.list().then(function (device_list) {
- if (device_list.length > 0) {
- events.emit('warn', 'No target specified, deploying to device \'' + device_list[0] + '\'.');
- install_target = device_list[0];
- } else {
- events.emit('warn', 'No target specified and no devices found, deploying to emulator');
- install_target = '--emulator';
- }
- });
- }
- }).then(function () {
- if (install_target === '--device') {
- return device.resolveTarget(null);
- } else if (install_target === '--emulator') {
- // Give preference to any already started emulators. Else, start one.
- return emulator.list_started().then(function (started) {
- return started && started.length > 0 ? started[0] : emulator.start();
- }).then(function (emulatorId) {
- return emulator.resolveTarget(emulatorId);
- });
- }
- // They specified a specific device/emulator ID.
- return device.list().then(function (devices) {
- if (devices.indexOf(install_target) > -1) {
- return device.resolveTarget(install_target);
- }
- return emulator.list_started().then(function (started_emulators) {
- if (started_emulators.indexOf(install_target) > -1) {
- return emulator.resolveTarget(install_target);
- }
- return emulator.list_images().then(function (avds) {
- // if target emulator isn't started, then start it.
- for (var avd in avds) {
- if (avds[avd].name === install_target) {
- return emulator.start(install_target).then(function (emulatorId) {
- return emulator.resolveTarget(emulatorId);
- });
- }
- }
- return Q.reject('Target \'' + install_target + '\' not found, unable to run project');
- });
- });
- });
- }).then(function (resolvedTarget) {
- // Better just call self.build, but we're doing some processing of
- // build results (according to platformApi spec) so they are in different
- // format than emulator.install expects.
- // TODO: Update emulator/device.install to handle this change
- return build.run.call(self, runOptions, resolvedTarget).then(function (buildResults) {
- if (resolvedTarget && resolvedTarget.isEmulator) {
- return emulator.wait_for_boot(resolvedTarget.target).then(function () {
- return emulator.install(resolvedTarget, buildResults);
- });
- }
- return device.install(resolvedTarget, buildResults);
- });
- });
-};
-
-module.exports.help = function () {
- console.log('Usage: ' + path.relative(process.cwd(), process.argv[1]) + ' [options]');
- console.log('Build options :');
- console.log(' --debug : Builds project in debug mode');
- console.log(' --release : Builds project in release mode');
- console.log(' --nobuild : Runs the currently built project without recompiling');
- console.log('Deploy options :');
- console.log(' --device : Will deploy the built project to a device');
- console.log(' --emulator : Will deploy the built project to an emulator if one exists');
- console.log(' --target= : Installs to the target with the specified id.');
- process.exit(0);
-};
diff --git a/platforms/android/cordova/lib/start-emulator b/platforms/android/cordova/lib/start-emulator
deleted file mode 100755
index f96bdc3..0000000
--- a/platforms/android/cordova/lib/start-emulator
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var emulator = require('./emulator'),
- args = process.argv;
-
-var install_target;
-if(args.length > 2) {
- if (args[2].substring(0, 9) == '--target=') {
- install_target = args[2].substring(9, args[2].length);
- } else {
- console.error('ERROR : argument \'' + args[2] + '\' not recognized.');
- process.exit(2);
- }
-}
-
-emulator.start(install_target).done(null, function(err) {
- console.error('ERROR: ' + err);
- process.exit(2);
-});
-
diff --git a/platforms/android/cordova/lib/start-emulator.bat b/platforms/android/cordova/lib/start-emulator.bat
deleted file mode 100644
index 6c237ea..0000000
--- a/platforms/android/cordova/lib/start-emulator.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0start-emulator"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'start-emulator' script in 'cordova\lib' folder, aborting...>&2
- EXIT /B 1
-)
\ No newline at end of file
diff --git a/platforms/android/cordova/log b/platforms/android/cordova/log
deleted file mode 100755
index 47f0605..0000000
--- a/platforms/android/cordova/log
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var log = require('./lib/log'),
- reqs = require('./lib/check_reqs'),
- args = process.argv;
-
-// Usage support for when args are given
-if(args.length > 2) {
- log.help();
-} else {
- reqs.run().done(function() {
- return log.run();
- }, function(err) {
- console.error('ERROR: ' + err);
- process.exit(2);
- });
-}
diff --git a/platforms/android/cordova/log.bat b/platforms/android/cordova/log.bat
deleted file mode 100644
index 4b2b434..0000000
--- a/platforms/android/cordova/log.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0log"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'log' script in 'cordova' folder, aborting...>&2
- EXIT /B 1
-)
\ No newline at end of file
diff --git a/platforms/android/cordova/loggingHelper.js b/platforms/android/cordova/loggingHelper.js
deleted file mode 100644
index 32b2ee0..0000000
--- a/platforms/android/cordova/loggingHelper.js
+++ /dev/null
@@ -1,18 +0,0 @@
-var CordovaLogger = require('cordova-common').CordovaLogger;
-
-module.exports = {
- adjustLoggerLevel: function (opts) {
- if (opts instanceof Array) {
- opts.silent = opts.indexOf('--silent') !== -1;
- opts.verbose = opts.indexOf('--verbose') !== -1;
- }
-
- if (opts.silent) {
- CordovaLogger.get().setLevel('error');
- }
-
- if (opts.verbose) {
- CordovaLogger.get().setLevel('verbose');
- }
- }
-};
diff --git a/platforms/android/cordova/run b/platforms/android/cordova/run
deleted file mode 100755
index 9544c1d..0000000
--- a/platforms/android/cordova/run
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-var Api = require('./Api');
-var nopt = require('nopt');
-var path = require('path');
-
-// Support basic help commands
-if(['--help', '/?', '-h', 'help', '-help', '/help'].indexOf(process.argv[2]) >= 0)
- require('./lib/run').help();
-
-// Do some basic argument parsing
-var runOpts = nopt({
- 'verbose' : Boolean,
- 'silent' : Boolean,
- 'debug' : Boolean,
- 'release' : Boolean,
- 'nobuild': Boolean,
- 'buildConfig' : path,
- 'archs' : String,
- 'device' : Boolean,
- 'emulator': Boolean,
- 'target' : String
-}, { 'd' : '--verbose' });
-
-// Make runOptions compatible with PlatformApi run method spec
-runOpts.argv = runOpts.argv.remain;
-
-require('./loggingHelper').adjustLoggerLevel(runOpts);
-
-new Api().run(runOpts)
-.catch(function(err) {
- console.error(err, err.stack);
- process.exit(2);
-});
diff --git a/platforms/android/cordova/run.bat b/platforms/android/cordova/run.bat
deleted file mode 100644
index b0bc28b..0000000
--- a/platforms/android/cordova/run.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0run"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'run' script in 'cordova' folder, aborting...>&2
- EXIT /B 1
-)
\ No newline at end of file
diff --git a/platforms/android/cordova/version b/platforms/android/cordova/version
deleted file mode 100755
index 6f490b8..0000000
--- a/platforms/android/cordova/version
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env node
-
-/*
- 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.
-*/
-
-// Coho updates this line:
-var VERSION = "7.1.2";
-
-module.exports.version = VERSION;
-
-if (!module.parent) {
- console.log(VERSION);
-}
diff --git a/platforms/android/cordova/version.bat b/platforms/android/cordova/version.bat
deleted file mode 100644
index 3610c17..0000000
--- a/platforms/android/cordova/version.bat
+++ /dev/null
@@ -1,26 +0,0 @@
-:: Licensed to the Apache Software Foundation (ASF) under one
-:: or more contributor license agreements. See the NOTICE file
-:: distributed with this work for additional information
-:: regarding copyright ownership. The ASF licenses this file
-:: to you under the Apache License, Version 2.0 (the
-:: "License"); you may not use this file except in compliance
-:: with the License. You may obtain a copy of the License at
-::
-:: http://www.apache.org/licenses/LICENSE-2.0
-::
-:: Unless required by applicable law or agreed to in writing,
-:: software distributed under the License is distributed on an
-:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-:: KIND, either express or implied. See the License for the
-:: specific language governing permissions and limitations
-:: under the License.
-
-@ECHO OFF
-SET script_path="%~dp0version"
-IF EXIST %script_path% (
- node %script_path% %*
-) ELSE (
- ECHO.
- ECHO ERROR: Could not find 'version' script in 'cordova' folder, aborting...>&2
- EXIT /B 1
-)
diff --git a/platforms/android/platform_www/cordova-js-src/android/nativeapiprovider.js b/platforms/android/platform_www/cordova-js-src/android/nativeapiprovider.js
deleted file mode 100644
index 2e9aa67..0000000
--- a/platforms/android/platform_www/cordova-js-src/android/nativeapiprovider.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-
-/**
- * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
- */
-
-var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
-var currentApi = nativeApi;
-
-module.exports = {
- get: function() { return currentApi; },
- setPreferPrompt: function(value) {
- currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
- },
- // Used only by tests.
- set: function(value) {
- currentApi = value;
- }
-};
diff --git a/platforms/android/platform_www/cordova-js-src/android/promptbasednativeapi.js b/platforms/android/platform_www/cordova-js-src/android/promptbasednativeapi.js
deleted file mode 100644
index f7fb6bc..0000000
--- a/platforms/android/platform_www/cordova-js-src/android/promptbasednativeapi.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
-*/
-
-/**
- * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
- * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
- */
-
-module.exports = {
- exec: function(bridgeSecret, service, action, callbackId, argsJson) {
- return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
- },
- setNativeToJsBridgeMode: function(bridgeSecret, value) {
- prompt(value, 'gap_bridge_mode:' + bridgeSecret);
- },
- retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
- return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
- }
-};
diff --git a/platforms/android/platform_www/cordova-js-src/exec.js b/platforms/android/platform_www/cordova-js-src/exec.js
deleted file mode 100644
index f73d87a..0000000
--- a/platforms/android/platform_www/cordova-js-src/exec.js
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
- * Execute a cordova command. It is up to the native side whether this action
- * is synchronous or asynchronous. The native side can return:
- * Synchronous: PluginResult object as a JSON string
- * Asynchronous: Empty string ""
- * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
- * depending upon the result of the action.
- *
- * @param {Function} success The success callback
- * @param {Function} fail The fail callback
- * @param {String} service The name of the service to use
- * @param {String} action Action to be run in cordova
- * @param {String[]} [args] Zero or more arguments to pass to the method
- */
-var cordova = require('cordova'),
- nativeApiProvider = require('cordova/android/nativeapiprovider'),
- utils = require('cordova/utils'),
- base64 = require('cordova/base64'),
- channel = require('cordova/channel'),
- jsToNativeModes = {
- PROMPT: 0,
- JS_OBJECT: 1
- },
- nativeToJsModes = {
- // Polls for messages using the JS->Native bridge.
- POLLING: 0,
- // For LOAD_URL to be viable, it would need to have a work-around for
- // the bug where the soft-keyboard gets dismissed when a message is sent.
- LOAD_URL: 1,
- // For the ONLINE_EVENT to be viable, it would need to intercept all event
- // listeners (both through addEventListener and window.ononline) as well
- // as set the navigator property itself.
- ONLINE_EVENT: 2,
- EVAL_BRIDGE: 3
- },
- jsToNativeBridgeMode, // Set lazily.
- nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE,
- pollEnabled = false,
- bridgeSecret = -1;
-
-var messagesFromNative = [];
-var isProcessing = false;
-var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
-var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
-
-function androidExec(success, fail, service, action, args) {
- if (bridgeSecret < 0) {
- // If we ever catch this firing, we'll need to queue up exec()s
- // and fire them once we get a secret. For now, I don't think
- // it's possible for exec() to be called since plugins are parsed but
- // not run until until after onNativeReady.
- throw new Error('exec() called without bridgeSecret');
- }
- // Set default bridge modes if they have not already been set.
- // By default, we use the failsafe, since addJavascriptInterface breaks too often
- if (jsToNativeBridgeMode === undefined) {
- androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
- }
-
- // If args is not provided, default to an empty array
- args = args || [];
-
- // Process any ArrayBuffers in the args into a string.
- for (var i = 0; i < args.length; i++) {
- if (utils.typeName(args[i]) == 'ArrayBuffer') {
- args[i] = base64.fromArrayBuffer(args[i]);
- }
- }
-
- var callbackId = service + cordova.callbackId++,
- argsJson = JSON.stringify(args);
- if (success || fail) {
- cordova.callbacks[callbackId] = {success:success, fail:fail};
- }
-
- var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
- // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
- // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
- if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
- androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
- androidExec(success, fail, service, action, args);
- androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
- } else if (msgs) {
- messagesFromNative.push(msgs);
- // Always process async to avoid exceptions messing up stack.
- nextTick(processMessages);
- }
-}
-
-androidExec.init = function() {
- //CB-11828
- //This failsafe checks the version of Android and if it's Jellybean, it switches it to
- //using the Online Event bridge for communicating from Native to JS
- //
- //It's ugly, but it's necessary.
- var check = navigator.userAgent.toLowerCase().match(/android\s[0-9].[0-9]/);
- var version_code = check && check[0].match(/4.[0-3].*/);
- if (version_code != null && nativeToJsBridgeMode == nativeToJsModes.EVAL_BRIDGE) {
- nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT;
- }
-
- bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
- channel.onNativeReady.fire();
-};
-
-function pollOnceFromOnlineEvent() {
- pollOnce(true);
-}
-
-function pollOnce(opt_fromOnlineEvent) {
- if (bridgeSecret < 0) {
- // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
- // We know there's nothing to retrieve, so no need to poll.
- return;
- }
- var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
- if (msgs) {
- messagesFromNative.push(msgs);
- // Process sync since we know we're already top-of-stack.
- processMessages();
- }
-}
-
-function pollingTimerFunc() {
- if (pollEnabled) {
- pollOnce();
- setTimeout(pollingTimerFunc, 50);
- }
-}
-
-function hookOnlineApis() {
- function proxyEvent(e) {
- cordova.fireWindowEvent(e.type);
- }
- // The network module takes care of firing online and offline events.
- // It currently fires them only on document though, so we bridge them
- // to window here (while first listening for exec()-releated online/offline
- // events).
- window.addEventListener('online', pollOnceFromOnlineEvent, false);
- window.addEventListener('offline', pollOnceFromOnlineEvent, false);
- cordova.addWindowEventHandler('online');
- cordova.addWindowEventHandler('offline');
- document.addEventListener('online', proxyEvent, false);
- document.addEventListener('offline', proxyEvent, false);
-}
-
-hookOnlineApis();
-
-androidExec.jsToNativeModes = jsToNativeModes;
-androidExec.nativeToJsModes = nativeToJsModes;
-
-androidExec.setJsToNativeBridgeMode = function(mode) {
- if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
- mode = jsToNativeModes.PROMPT;
- }
- nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
- jsToNativeBridgeMode = mode;
-};
-
-androidExec.setNativeToJsBridgeMode = function(mode) {
- if (mode == nativeToJsBridgeMode) {
- return;
- }
- if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
- pollEnabled = false;
- }
-
- nativeToJsBridgeMode = mode;
- // Tell the native side to switch modes.
- // Otherwise, it will be set by androidExec.init()
- if (bridgeSecret >= 0) {
- nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
- }
-
- if (mode == nativeToJsModes.POLLING) {
- pollEnabled = true;
- setTimeout(pollingTimerFunc, 1);
- }
-};
-
-function buildPayload(payload, message) {
- var payloadKind = message.charAt(0);
- if (payloadKind == 's') {
- payload.push(message.slice(1));
- } else if (payloadKind == 't') {
- payload.push(true);
- } else if (payloadKind == 'f') {
- payload.push(false);
- } else if (payloadKind == 'N') {
- payload.push(null);
- } else if (payloadKind == 'n') {
- payload.push(+message.slice(1));
- } else if (payloadKind == 'A') {
- var data = message.slice(1);
- payload.push(base64.toArrayBuffer(data));
- } else if (payloadKind == 'S') {
- payload.push(window.atob(message.slice(1)));
- } else if (payloadKind == 'M') {
- var multipartMessages = message.slice(1);
- while (multipartMessages !== "") {
- var spaceIdx = multipartMessages.indexOf(' ');
- var msgLen = +multipartMessages.slice(0, spaceIdx);
- var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
- multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
- buildPayload(payload, multipartMessage);
- }
- } else {
- payload.push(JSON.parse(message));
- }
-}
-
-// Processes a single message, as encoded by NativeToJsMessageQueue.java.
-function processMessage(message) {
- var firstChar = message.charAt(0);
- if (firstChar == 'J') {
- // This is deprecated on the .java side. It doesn't work with CSP enabled.
- eval(message.slice(1));
- } else if (firstChar == 'S' || firstChar == 'F') {
- var success = firstChar == 'S';
- var keepCallback = message.charAt(1) == '1';
- var spaceIdx = message.indexOf(' ', 2);
- var status = +message.slice(2, spaceIdx);
- var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
- var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
- var payloadMessage = message.slice(nextSpaceIdx + 1);
- var payload = [];
- buildPayload(payload, payloadMessage);
- cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
- } else {
- console.log("processMessage failed: invalid message: " + JSON.stringify(message));
- }
-}
-
-function processMessages() {
- // Check for the reentrant case.
- if (isProcessing) {
- return;
- }
- if (messagesFromNative.length === 0) {
- return;
- }
- isProcessing = true;
- try {
- var msg = popMessageFromQueue();
- // The Java side can send a * message to indicate that it
- // still has messages waiting to be retrieved.
- if (msg == '*' && messagesFromNative.length === 0) {
- nextTick(pollOnce);
- return;
- }
- processMessage(msg);
- } finally {
- isProcessing = false;
- if (messagesFromNative.length > 0) {
- nextTick(processMessages);
- }
- }
-}
-
-function popMessageFromQueue() {
- var messageBatch = messagesFromNative.shift();
- if (messageBatch == '*') {
- return '*';
- }
-
- var spaceIdx = messageBatch.indexOf(' ');
- var msgLen = +messageBatch.slice(0, spaceIdx);
- var message = messageBatch.substr(spaceIdx + 1, msgLen);
- messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
- if (messageBatch) {
- messagesFromNative.unshift(messageBatch);
- }
- return message;
-}
-
-module.exports = androidExec;
diff --git a/platforms/android/platform_www/cordova-js-src/platform.js b/platforms/android/platform_www/cordova-js-src/platform.js
deleted file mode 100644
index 2bfd024..0000000
--- a/platforms/android/platform_www/cordova-js-src/platform.js
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-// The last resume event that was received that had the result of a plugin call.
-var lastResumeEvent = null;
-
-module.exports = {
- id: 'android',
- bootstrap: function() {
- var channel = require('cordova/channel'),
- cordova = require('cordova'),
- exec = require('cordova/exec'),
- modulemapper = require('cordova/modulemapper');
-
- // Get the shared secret needed to use the bridge.
- exec.init();
-
- // TODO: Extract this as a proper plugin.
- modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
-
- var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
-
- // Inject a listener for the backbutton on the document.
- var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
- backButtonChannel.onHasSubscribersChange = function() {
- // If we just attached the first handler or detached the last handler,
- // let native know we need to override the back button.
- exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
- };
-
- // Add hardware MENU and SEARCH button handlers
- cordova.addDocumentEventHandler('menubutton');
- cordova.addDocumentEventHandler('searchbutton');
-
- function bindButtonChannel(buttonName) {
- // generic button bind used for volumeup/volumedown buttons
- var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
- volumeButtonChannel.onHasSubscribersChange = function() {
- exec(null, null, APP_PLUGIN_NAME, "overrideButton", [buttonName, this.numHandlers == 1]);
- };
- }
- // Inject a listener for the volume buttons on the document.
- bindButtonChannel('volumeup');
- bindButtonChannel('volumedown');
-
- // The resume event is not "sticky", but it is possible that the event
- // will contain the result of a plugin call. We need to ensure that the
- // plugin result is delivered even after the event is fired (CB-10498)
- var cordovaAddEventListener = document.addEventListener;
-
- document.addEventListener = function(evt, handler, capture) {
- cordovaAddEventListener(evt, handler, capture);
-
- if (evt === 'resume' && lastResumeEvent) {
- handler(lastResumeEvent);
- }
- };
-
- // Let native code know we are all done on the JS side.
- // Native code will then un-hide the WebView.
- channel.onCordovaReady.subscribe(function() {
- exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
- exec(null, null, APP_PLUGIN_NAME, "show", []);
- });
- }
-};
-
-function onMessageFromNative(msg) {
- var cordova = require('cordova');
- var action = msg.action;
-
- switch (action)
- {
- // Button events
- case 'backbutton':
- case 'menubutton':
- case 'searchbutton':
- // App life cycle events
- case 'pause':
- // Volume events
- case 'volumedownbutton':
- case 'volumeupbutton':
- cordova.fireDocumentEvent(action);
- break;
- case 'resume':
- if(arguments.length > 1 && msg.pendingResult) {
- if(arguments.length === 2) {
- msg.pendingResult.result = arguments[1];
- } else {
- // The plugin returned a multipart message
- var res = [];
- for(var i = 1; i < arguments.length; i++) {
- res.push(arguments[i]);
- }
- msg.pendingResult.result = res;
- }
-
- // Save the plugin result so that it can be delivered to the js
- // even if they miss the initial firing of the event
- lastResumeEvent = msg;
- }
- cordova.fireDocumentEvent(action, msg);
- break;
- default:
- throw new Error('Unknown event action ' + action);
- }
-}
diff --git a/platforms/android/platform_www/cordova-js-src/plugin/android/app.js b/platforms/android/platform_www/cordova-js-src/plugin/android/app.js
deleted file mode 100644
index 22cf96e..0000000
--- a/platforms/android/platform_www/cordova-js-src/plugin/android/app.js
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var exec = require('cordova/exec');
-var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
-
-module.exports = {
- /**
- * Clear the resource cache.
- */
- clearCache:function() {
- exec(null, null, APP_PLUGIN_NAME, "clearCache", []);
- },
-
- /**
- * Load the url into the webview or into new browser instance.
- *
- * @param url The URL to load
- * @param props Properties that can be passed in to the activity:
- * wait: int => wait msec before loading URL
- * loadingDialog: "Title,Message" => display a native loading dialog
- * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
- * clearHistory: boolean => clear webview history (default=false)
- * openExternal: boolean => open in a new browser (default=false)
- *
- * Example:
- * navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
- */
- loadUrl:function(url, props) {
- exec(null, null, APP_PLUGIN_NAME, "loadUrl", [url, props]);
- },
-
- /**
- * Cancel loadUrl that is waiting to be loaded.
- */
- cancelLoadUrl:function() {
- exec(null, null, APP_PLUGIN_NAME, "cancelLoadUrl", []);
- },
-
- /**
- * Clear web history in this web view.
- * Instead of BACK button loading the previous web page, it will exit the app.
- */
- clearHistory:function() {
- exec(null, null, APP_PLUGIN_NAME, "clearHistory", []);
- },
-
- /**
- * Go to previous page displayed.
- * This is the same as pressing the backbutton on Android device.
- */
- backHistory:function() {
- exec(null, null, APP_PLUGIN_NAME, "backHistory", []);
- },
-
- /**
- * Override the default behavior of the Android back button.
- * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
- *
- * Note: The user should not have to call this method. Instead, when the user
- * registers for the "backbutton" event, this is automatically done.
- *
- * @param override T=override, F=cancel override
- */
- overrideBackbutton:function(override) {
- exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [override]);
- },
-
- /**
- * Override the default behavior of the Android volume button.
- * If overridden, when the volume button is pressed, the "volume[up|down]button"
- * JavaScript event will be fired.
- *
- * Note: The user should not have to call this method. Instead, when the user
- * registers for the "volume[up|down]button" event, this is automatically done.
- *
- * @param button volumeup, volumedown
- * @param override T=override, F=cancel override
- */
- overrideButton:function(button, override) {
- exec(null, null, APP_PLUGIN_NAME, "overrideButton", [button, override]);
- },
-
- /**
- * Exit and terminate the application.
- */
- exitApp:function() {
- return exec(null, null, APP_PLUGIN_NAME, "exitApp", []);
- }
-};
diff --git a/platforms/android/platform_www/cordova.js b/platforms/android/platform_www/cordova.js
deleted file mode 100644
index a9f8bb0..0000000
--- a/platforms/android/platform_www/cordova.js
+++ /dev/null
@@ -1,2189 +0,0 @@
-// Platform: android
-// 9e8e1b716252c4a08abcd31a13013b868d6f4141
-/*
- 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.
-*/
-;(function() {
-var PLATFORM_VERSION_BUILD_LABEL = '7.1.2';
-// file: src/scripts/require.js
-
-/* jshint -W079 */
-/* jshint -W020 */
-
-var require;
-var define;
-
-(function () {
- var modules = {};
- // Stack of moduleIds currently being built.
- var requireStack = [];
- // Map of module ID -> index into requireStack of modules currently being built.
- var inProgressModules = {};
- var SEPARATOR = '.';
-
- function build (module) {
- var factory = module.factory;
- var localRequire = function (id) {
- var resultantId = id;
- // Its a relative path, so lop off the last portion and add the id (minus "./")
- if (id.charAt(0) === '.') {
- resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
- }
- return require(resultantId);
- };
- module.exports = {};
- delete module.factory;
- factory(localRequire, module.exports, module);
- return module.exports;
- }
-
- require = function (id) {
- if (!modules[id]) {
- throw 'module ' + id + ' not found';
- } else if (id in inProgressModules) {
- var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
- throw 'Cycle in require graph: ' + cycle;
- }
- if (modules[id].factory) {
- try {
- inProgressModules[id] = requireStack.length;
- requireStack.push(id);
- return build(modules[id]);
- } finally {
- delete inProgressModules[id];
- requireStack.pop();
- }
- }
- return modules[id].exports;
- };
-
- define = function (id, factory) {
- if (modules[id]) {
- throw 'module ' + id + ' already defined';
- }
-
- modules[id] = {
- id: id,
- factory: factory
- };
- };
-
- define.remove = function (id) {
- delete modules[id];
- };
-
- define.moduleMap = modules;
-})();
-
-// Export for use in node
-if (typeof module === 'object' && typeof require === 'function') {
- module.exports.require = require;
- module.exports.define = define;
-}
-
-// file: src/cordova.js
-define("cordova", function(require, exports, module) {
-
-// Workaround for Windows 10 in hosted environment case
-// http://www.w3.org/html/wg/drafts/html/master/browsers.html#named-access-on-the-window-object
-if (window.cordova && !(window.cordova instanceof HTMLElement)) { // eslint-disable-line no-undef
- throw new Error('cordova already defined');
-}
-
-var channel = require('cordova/channel');
-var platform = require('cordova/platform');
-
-/**
- * Intercept calls to addEventListener + removeEventListener and handle deviceready,
- * resume, and pause events.
- */
-var m_document_addEventListener = document.addEventListener;
-var m_document_removeEventListener = document.removeEventListener;
-var m_window_addEventListener = window.addEventListener;
-var m_window_removeEventListener = window.removeEventListener;
-
-/**
- * Houses custom event handlers to intercept on document + window event listeners.
- */
-var documentEventHandlers = {};
-var windowEventHandlers = {};
-
-document.addEventListener = function (evt, handler, capture) {
- var e = evt.toLowerCase();
- if (typeof documentEventHandlers[e] !== 'undefined') {
- documentEventHandlers[e].subscribe(handler);
- } else {
- m_document_addEventListener.call(document, evt, handler, capture);
- }
-};
-
-window.addEventListener = function (evt, handler, capture) {
- var e = evt.toLowerCase();
- if (typeof windowEventHandlers[e] !== 'undefined') {
- windowEventHandlers[e].subscribe(handler);
- } else {
- m_window_addEventListener.call(window, evt, handler, capture);
- }
-};
-
-document.removeEventListener = function (evt, handler, capture) {
- var e = evt.toLowerCase();
- // If unsubscribing from an event that is handled by a plugin
- if (typeof documentEventHandlers[e] !== 'undefined') {
- documentEventHandlers[e].unsubscribe(handler);
- } else {
- m_document_removeEventListener.call(document, evt, handler, capture);
- }
-};
-
-window.removeEventListener = function (evt, handler, capture) {
- var e = evt.toLowerCase();
- // If unsubscribing from an event that is handled by a plugin
- if (typeof windowEventHandlers[e] !== 'undefined') {
- windowEventHandlers[e].unsubscribe(handler);
- } else {
- m_window_removeEventListener.call(window, evt, handler, capture);
- }
-};
-
-function createEvent (type, data) {
- var event = document.createEvent('Events');
- event.initEvent(type, false, false);
- if (data) {
- for (var i in data) {
- if (data.hasOwnProperty(i)) {
- event[i] = data[i];
- }
- }
- }
- return event;
-}
-
-/* eslint-disable no-undef */
-var cordova = {
- define: define,
- require: require,
- version: PLATFORM_VERSION_BUILD_LABEL,
- platformVersion: PLATFORM_VERSION_BUILD_LABEL,
- platformId: platform.id,
-
- /* eslint-enable no-undef */
-
- /**
- * Methods to add/remove your own addEventListener hijacking on document + window.
- */
- addWindowEventHandler: function (event) {
- return (windowEventHandlers[event] = channel.create(event));
- },
- addStickyDocumentEventHandler: function (event) {
- return (documentEventHandlers[event] = channel.createSticky(event));
- },
- addDocumentEventHandler: function (event) {
- return (documentEventHandlers[event] = channel.create(event));
- },
- removeWindowEventHandler: function (event) {
- delete windowEventHandlers[event];
- },
- removeDocumentEventHandler: function (event) {
- delete documentEventHandlers[event];
- },
- /**
- * Retrieve original event handlers that were replaced by Cordova
- *
- * @return object
- */
- getOriginalHandlers: function () {
- return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
- 'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
- },
- /**
- * Method to fire event from native code
- * bNoDetach is required for events which cause an exception which needs to be caught in native code
- */
- fireDocumentEvent: function (type, data, bNoDetach) {
- var evt = createEvent(type, data);
- if (typeof documentEventHandlers[type] !== 'undefined') {
- if (bNoDetach) {
- documentEventHandlers[type].fire(evt);
- } else {
- setTimeout(function () {
- // Fire deviceready on listeners that were registered before cordova.js was loaded.
- if (type === 'deviceready') {
- document.dispatchEvent(evt);
- }
- documentEventHandlers[type].fire(evt);
- }, 0);
- }
- } else {
- document.dispatchEvent(evt);
- }
- },
- fireWindowEvent: function (type, data) {
- var evt = createEvent(type, data);
- if (typeof windowEventHandlers[type] !== 'undefined') {
- setTimeout(function () {
- windowEventHandlers[type].fire(evt);
- }, 0);
- } else {
- window.dispatchEvent(evt);
- }
- },
-
- /**
- * Plugin callback mechanism.
- */
- // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
- // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
- callbackId: Math.floor(Math.random() * 2000000000),
- callbacks: {},
- callbackStatus: {
- NO_RESULT: 0,
- OK: 1,
- CLASS_NOT_FOUND_EXCEPTION: 2,
- ILLEGAL_ACCESS_EXCEPTION: 3,
- INSTANTIATION_EXCEPTION: 4,
- MALFORMED_URL_EXCEPTION: 5,
- IO_EXCEPTION: 6,
- INVALID_ACTION: 7,
- JSON_EXCEPTION: 8,
- ERROR: 9
- },
-
- /**
- * Called by native code when returning successful result from an action.
- */
- callbackSuccess: function (callbackId, args) {
- cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
- },
-
- /**
- * Called by native code when returning error result from an action.
- */
- callbackError: function (callbackId, args) {
- // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
- // Derive success from status.
- cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
- },
-
- /**
- * Called by native code when returning the result from an action.
- */
- callbackFromNative: function (callbackId, isSuccess, status, args, keepCallback) {
- try {
- var callback = cordova.callbacks[callbackId];
- if (callback) {
- if (isSuccess && status === cordova.callbackStatus.OK) {
- callback.success && callback.success.apply(null, args);
- } else if (!isSuccess) {
- callback.fail && callback.fail.apply(null, args);
- }
- /*
- else
- Note, this case is intentionally not caught.
- this can happen if isSuccess is true, but callbackStatus is NO_RESULT
- which is used to remove a callback from the list without calling the callbacks
- typically keepCallback is false in this case
- */
- // Clear callback if not expecting any more results
- if (!keepCallback) {
- delete cordova.callbacks[callbackId];
- }
- }
- } catch (err) {
- var msg = 'Error in ' + (isSuccess ? 'Success' : 'Error') + ' callbackId: ' + callbackId + ' : ' + err;
- console && console.log && console.log(msg);
- console && console.log && err.stack && console.log(err.stack);
- cordova.fireWindowEvent('cordovacallbackerror', { 'message': msg });
- throw err;
- }
- },
- addConstructor: function (func) {
- channel.onCordovaReady.subscribe(function () {
- try {
- func();
- } catch (e) {
- console.log('Failed to run constructor: ' + e);
- }
- });
- }
-};
-
-module.exports = cordova;
-
-});
-
-// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/android/nativeapiprovider.js
-define("cordova/android/nativeapiprovider", function(require, exports, module) {
-
-/**
- * Exports the ExposedJsApi.java object if available, otherwise exports the PromptBasedNativeApi.
- */
-
-var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
-var currentApi = nativeApi;
-
-module.exports = {
- get: function() { return currentApi; },
- setPreferPrompt: function(value) {
- currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi;
- },
- // Used only by tests.
- set: function(value) {
- currentApi = value;
- }
-};
-
-});
-
-// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/android/promptbasednativeapi.js
-define("cordova/android/promptbasednativeapi", function(require, exports, module) {
-
-/**
- * Implements the API of ExposedJsApi.java, but uses prompt() to communicate.
- * This is used pre-JellyBean, where addJavascriptInterface() is disabled.
- */
-
-module.exports = {
- exec: function(bridgeSecret, service, action, callbackId, argsJson) {
- return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));
- },
- setNativeToJsBridgeMode: function(bridgeSecret, value) {
- prompt(value, 'gap_bridge_mode:' + bridgeSecret);
- },
- retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) {
- return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret);
- }
-};
-
-});
-
-// file: src/common/argscheck.js
-define("cordova/argscheck", function(require, exports, module) {
-
-var utils = require('cordova/utils');
-
-var moduleExports = module.exports;
-
-var typeMap = {
- 'A': 'Array',
- 'D': 'Date',
- 'N': 'Number',
- 'S': 'String',
- 'F': 'Function',
- 'O': 'Object'
-};
-
-function extractParamName (callee, argIndex) {
- return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
-}
-
-function checkArgs (spec, functionName, args, opt_callee) {
- if (!moduleExports.enableChecks) {
- return;
- }
- var errMsg = null;
- var typeName;
- for (var i = 0; i < spec.length; ++i) {
- var c = spec.charAt(i);
- var cUpper = c.toUpperCase();
- var arg = args[i];
- // Asterix means allow anything.
- if (c === '*') {
- continue;
- }
- typeName = utils.typeName(arg);
- if ((arg === null || arg === undefined) && c === cUpper) {
- continue;
- }
- if (typeName !== typeMap[cUpper]) {
- errMsg = 'Expected ' + typeMap[cUpper];
- break;
- }
- }
- if (errMsg) {
- errMsg += ', but got ' + typeName + '.';
- errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
- // Don't log when running unit tests.
- if (typeof jasmine === 'undefined') {
- console.error(errMsg);
- }
- throw TypeError(errMsg);
- }
-}
-
-function getValue (value, defaultValue) {
- return value === undefined ? defaultValue : value;
-}
-
-moduleExports.checkArgs = checkArgs;
-moduleExports.getValue = getValue;
-moduleExports.enableChecks = true;
-
-});
-
-// file: src/common/base64.js
-define("cordova/base64", function(require, exports, module) {
-
-var base64 = exports;
-
-base64.fromArrayBuffer = function (arrayBuffer) {
- var array = new Uint8Array(arrayBuffer);
- return uint8ToBase64(array);
-};
-
-base64.toArrayBuffer = function (str) {
- var decodedStr = typeof atob !== 'undefined' ? atob(str) : Buffer.from(str, 'base64').toString('binary'); // eslint-disable-line no-undef
- var arrayBuffer = new ArrayBuffer(decodedStr.length);
- var array = new Uint8Array(arrayBuffer);
- for (var i = 0, len = decodedStr.length; i < len; i++) {
- array[i] = decodedStr.charCodeAt(i);
- }
- return arrayBuffer;
-};
-
-// ------------------------------------------------------------------------------
-
-/* This code is based on the performance tests at http://jsperf.com/b64tests
- * This 12-bit-at-a-time algorithm was the best performing version on all
- * platforms tested.
- */
-
-var b64_6bit = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-var b64_12bit;
-
-var b64_12bitTable = function () {
- b64_12bit = [];
- for (var i = 0; i < 64; i++) {
- for (var j = 0; j < 64; j++) {
- b64_12bit[i * 64 + j] = b64_6bit[i] + b64_6bit[j];
- }
- }
- b64_12bitTable = function () { return b64_12bit; };
- return b64_12bit;
-};
-
-function uint8ToBase64 (rawData) {
- var numBytes = rawData.byteLength;
- var output = '';
- var segment;
- var table = b64_12bitTable();
- for (var i = 0; i < numBytes - 2; i += 3) {
- segment = (rawData[i] << 16) + (rawData[i + 1] << 8) + rawData[i + 2];
- output += table[segment >> 12];
- output += table[segment & 0xfff];
- }
- if (numBytes - i === 2) {
- segment = (rawData[i] << 16) + (rawData[i + 1] << 8);
- output += table[segment >> 12];
- output += b64_6bit[(segment & 0xfff) >> 6];
- output += '=';
- } else if (numBytes - i === 1) {
- segment = (rawData[i] << 16);
- output += table[segment >> 12];
- output += '==';
- }
- return output;
-}
-
-});
-
-// file: src/common/builder.js
-define("cordova/builder", function(require, exports, module) {
-
-var utils = require('cordova/utils');
-
-function each (objects, func, context) {
- for (var prop in objects) {
- if (objects.hasOwnProperty(prop)) {
- func.apply(context, [objects[prop], prop]);
- }
- }
-}
-
-function clobber (obj, key, value) {
- exports.replaceHookForTesting(obj, key);
- var needsProperty = false;
- try {
- obj[key] = value;
- } catch (e) {
- needsProperty = true;
- }
- // Getters can only be overridden by getters.
- if (needsProperty || obj[key] !== value) {
- utils.defineGetter(obj, key, function () {
- return value;
- });
- }
-}
-
-function assignOrWrapInDeprecateGetter (obj, key, value, message) {
- if (message) {
- utils.defineGetter(obj, key, function () {
- console.log(message);
- delete obj[key];
- clobber(obj, key, value);
- return value;
- });
- } else {
- clobber(obj, key, value);
- }
-}
-
-function include (parent, objects, clobber, merge) {
- each(objects, function (obj, key) {
- try {
- var result = obj.path ? require(obj.path) : {};
-
- if (clobber) {
- // Clobber if it doesn't exist.
- if (typeof parent[key] === 'undefined') {
- assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
- } else if (typeof obj.path !== 'undefined') {
- // If merging, merge properties onto parent, otherwise, clobber.
- if (merge) {
- recursiveMerge(parent[key], result);
- } else {
- assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
- }
- }
- result = parent[key];
- } else {
- // Overwrite if not currently defined.
- if (typeof parent[key] === 'undefined') {
- assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
- } else {
- // Set result to what already exists, so we can build children into it if they exist.
- result = parent[key];
- }
- }
-
- if (obj.children) {
- include(result, obj.children, clobber, merge);
- }
- } catch (e) {
- utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
- }
- });
-}
-
-/**
- * Merge properties from one object onto another recursively. Properties from
- * the src object will overwrite existing target property.
- *
- * @param target Object to merge properties into.
- * @param src Object to merge properties from.
- */
-function recursiveMerge (target, src) {
- for (var prop in src) {
- if (src.hasOwnProperty(prop)) {
- if (target.prototype && target.prototype.constructor === target) {
- // If the target object is a constructor override off prototype.
- clobber(target.prototype, prop, src[prop]);
- } else {
- if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
- recursiveMerge(target[prop], src[prop]);
- } else {
- clobber(target, prop, src[prop]);
- }
- }
- }
- }
-}
-
-exports.buildIntoButDoNotClobber = function (objects, target) {
- include(target, objects, false, false);
-};
-exports.buildIntoAndClobber = function (objects, target) {
- include(target, objects, true, false);
-};
-exports.buildIntoAndMerge = function (objects, target) {
- include(target, objects, true, true);
-};
-exports.recursiveMerge = recursiveMerge;
-exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
-exports.replaceHookForTesting = function () {};
-
-});
-
-// file: src/common/channel.js
-define("cordova/channel", function(require, exports, module) {
-
-var utils = require('cordova/utils');
-var nextGuid = 1;
-
-/**
- * Custom pub-sub "channel" that can have functions subscribed to it
- * This object is used to define and control firing of events for
- * cordova initialization, as well as for custom events thereafter.
- *
- * The order of events during page load and Cordova startup is as follows:
- *
- * onDOMContentLoaded* Internal event that is received when the web page is loaded and parsed.
- * onNativeReady* Internal event that indicates the Cordova native side is ready.
- * onCordovaReady* Internal event fired when all Cordova JavaScript objects have been created.
- * onDeviceReady* User event fired to indicate that Cordova is ready
- * onResume User event fired to indicate a start/resume lifecycle event
- * onPause User event fired to indicate a pause lifecycle event
- *
- * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
- * All listeners that subscribe after the event is fired will be executed right away.
- *
- * The only Cordova events that user code should register for are:
- * deviceready Cordova native code is initialized and Cordova APIs can be called from JavaScript
- * pause App has moved to background
- * resume App has returned to foreground
- *
- * Listeners can be registered as:
- * document.addEventListener("deviceready", myDeviceReadyListener, false);
- * document.addEventListener("resume", myResumeListener, false);
- * document.addEventListener("pause", myPauseListener, false);
- *
- * The DOM lifecycle events should be used for saving and restoring state
- * window.onload
- * window.onunload
- *
- */
-
-/**
- * Channel
- * @constructor
- * @param type String the channel name
- */
-var Channel = function (type, sticky) {
- this.type = type;
- // Map of guid -> function.
- this.handlers = {};
- // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
- this.state = sticky ? 1 : 0;
- // Used in sticky mode to remember args passed to fire().
- this.fireArgs = null;
- // Used by onHasSubscribersChange to know if there are any listeners.
- this.numHandlers = 0;
- // Function that is called when the first listener is subscribed, or when
- // the last listener is unsubscribed.
- this.onHasSubscribersChange = null;
-};
-var channel = {
- /**
- * Calls the provided function only after all of the channels specified
- * have been fired. All channels must be sticky channels.
- */
- join: function (h, c) {
- var len = c.length;
- var i = len;
- var f = function () {
- if (!(--i)) h();
- };
- for (var j = 0; j < len; j++) {
- if (c[j].state === 0) {
- throw Error('Can only use join with sticky channels.');
- }
- c[j].subscribe(f);
- }
- if (!len) h();
- },
- /* eslint-disable no-return-assign */
- create: function (type) {
- return channel[type] = new Channel(type, false);
- },
- createSticky: function (type) {
- return channel[type] = new Channel(type, true);
- },
- /* eslint-enable no-return-assign */
- /**
- * cordova Channels that must fire before "deviceready" is fired.
- */
- deviceReadyChannelsArray: [],
- deviceReadyChannelsMap: {},
-
- /**
- * Indicate that a feature needs to be initialized before it is ready to be used.
- * This holds up Cordova's "deviceready" event until the feature has been initialized
- * and Cordova.initComplete(feature) is called.
- *
- * @param feature {String} The unique feature name
- */
- waitForInitialization: function (feature) {
- if (feature) {
- var c = channel[feature] || this.createSticky(feature);
- this.deviceReadyChannelsMap[feature] = c;
- this.deviceReadyChannelsArray.push(c);
- }
- },
-
- /**
- * Indicate that initialization code has completed and the feature is ready to be used.
- *
- * @param feature {String} The unique feature name
- */
- initializationComplete: function (feature) {
- var c = this.deviceReadyChannelsMap[feature];
- if (c) {
- c.fire();
- }
- }
-};
-
-function checkSubscriptionArgument (argument) {
- if (typeof argument !== 'function' && typeof argument.handleEvent !== 'function') {
- throw new Error(
- 'Must provide a function or an EventListener object ' +
- 'implementing the handleEvent interface.'
- );
- }
-}
-
-/**
- * Subscribes the given function to the channel. Any time that
- * Channel.fire is called so too will the function.
- * Optionally specify an execution context for the function
- * and a guid that can be used to stop subscribing to the channel.
- * Returns the guid.
- */
-Channel.prototype.subscribe = function (eventListenerOrFunction, eventListener) {
- checkSubscriptionArgument(eventListenerOrFunction);
- var handleEvent, guid;
-
- if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
- // Received an EventListener object implementing the handleEvent interface
- handleEvent = eventListenerOrFunction.handleEvent;
- eventListener = eventListenerOrFunction;
- } else {
- // Received a function to handle event
- handleEvent = eventListenerOrFunction;
- }
-
- if (this.state === 2) {
- handleEvent.apply(eventListener || this, this.fireArgs);
- return;
- }
-
- guid = eventListenerOrFunction.observer_guid;
- if (typeof eventListener === 'object') {
- handleEvent = utils.close(eventListener, handleEvent);
- }
-
- if (!guid) {
- // First time any channel has seen this subscriber
- guid = '' + nextGuid++;
- }
- handleEvent.observer_guid = guid;
- eventListenerOrFunction.observer_guid = guid;
-
- // Don't add the same handler more than once.
- if (!this.handlers[guid]) {
- this.handlers[guid] = handleEvent;
- this.numHandlers++;
- if (this.numHandlers === 1) {
- this.onHasSubscribersChange && this.onHasSubscribersChange();
- }
- }
-};
-
-/**
- * Unsubscribes the function with the given guid from the channel.
- */
-Channel.prototype.unsubscribe = function (eventListenerOrFunction) {
- checkSubscriptionArgument(eventListenerOrFunction);
- var handleEvent, guid, handler;
-
- if (eventListenerOrFunction && typeof eventListenerOrFunction === 'object') {
- // Received an EventListener object implementing the handleEvent interface
- handleEvent = eventListenerOrFunction.handleEvent;
- } else {
- // Received a function to handle event
- handleEvent = eventListenerOrFunction;
- }
-
- guid = handleEvent.observer_guid;
- handler = this.handlers[guid];
- if (handler) {
- delete this.handlers[guid];
- this.numHandlers--;
- if (this.numHandlers === 0) {
- this.onHasSubscribersChange && this.onHasSubscribersChange();
- }
- }
-};
-
-/**
- * Calls all functions subscribed to this channel.
- */
-Channel.prototype.fire = function (e) {
- var fail = false; // eslint-disable-line no-unused-vars
- var fireArgs = Array.prototype.slice.call(arguments);
- // Apply stickiness.
- if (this.state === 1) {
- this.state = 2;
- this.fireArgs = fireArgs;
- }
- if (this.numHandlers) {
- // Copy the values first so that it is safe to modify it from within
- // callbacks.
- var toCall = [];
- for (var item in this.handlers) {
- toCall.push(this.handlers[item]);
- }
- for (var i = 0; i < toCall.length; ++i) {
- toCall[i].apply(this, fireArgs);
- }
- if (this.state === 2 && this.numHandlers) {
- this.numHandlers = 0;
- this.handlers = {};
- this.onHasSubscribersChange && this.onHasSubscribersChange();
- }
- }
-};
-
-// defining them here so they are ready super fast!
-// DOM event that is received when the web page is loaded and parsed.
-channel.createSticky('onDOMContentLoaded');
-
-// Event to indicate the Cordova native side is ready.
-channel.createSticky('onNativeReady');
-
-// Event to indicate that all Cordova JavaScript objects have been created
-// and it's time to run plugin constructors.
-channel.createSticky('onCordovaReady');
-
-// Event to indicate that all automatically loaded JS plugins are loaded and ready.
-// FIXME remove this
-channel.createSticky('onPluginsReady');
-
-// Event to indicate that Cordova is ready
-channel.createSticky('onDeviceReady');
-
-// Event to indicate a resume lifecycle event
-channel.create('onResume');
-
-// Event to indicate a pause lifecycle event
-channel.create('onPause');
-
-// Channels that must fire before "deviceready" is fired.
-channel.waitForInitialization('onCordovaReady');
-channel.waitForInitialization('onDOMContentLoaded');
-
-module.exports = channel;
-
-});
-
-// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/exec.js
-define("cordova/exec", function(require, exports, module) {
-
-/**
- * Execute a cordova command. It is up to the native side whether this action
- * is synchronous or asynchronous. The native side can return:
- * Synchronous: PluginResult object as a JSON string
- * Asynchronous: Empty string ""
- * If async, the native side will cordova.callbackSuccess or cordova.callbackError,
- * depending upon the result of the action.
- *
- * @param {Function} success The success callback
- * @param {Function} fail The fail callback
- * @param {String} service The name of the service to use
- * @param {String} action Action to be run in cordova
- * @param {String[]} [args] Zero or more arguments to pass to the method
- */
-var cordova = require('cordova'),
- nativeApiProvider = require('cordova/android/nativeapiprovider'),
- utils = require('cordova/utils'),
- base64 = require('cordova/base64'),
- channel = require('cordova/channel'),
- jsToNativeModes = {
- PROMPT: 0,
- JS_OBJECT: 1
- },
- nativeToJsModes = {
- // Polls for messages using the JS->Native bridge.
- POLLING: 0,
- // For LOAD_URL to be viable, it would need to have a work-around for
- // the bug where the soft-keyboard gets dismissed when a message is sent.
- LOAD_URL: 1,
- // For the ONLINE_EVENT to be viable, it would need to intercept all event
- // listeners (both through addEventListener and window.ononline) as well
- // as set the navigator property itself.
- ONLINE_EVENT: 2,
- EVAL_BRIDGE: 3
- },
- jsToNativeBridgeMode, // Set lazily.
- nativeToJsBridgeMode = nativeToJsModes.EVAL_BRIDGE,
- pollEnabled = false,
- bridgeSecret = -1;
-
-var messagesFromNative = [];
-var isProcessing = false;
-var resolvedPromise = typeof Promise == 'undefined' ? null : Promise.resolve();
-var nextTick = resolvedPromise ? function(fn) { resolvedPromise.then(fn); } : function(fn) { setTimeout(fn); };
-
-function androidExec(success, fail, service, action, args) {
- if (bridgeSecret < 0) {
- // If we ever catch this firing, we'll need to queue up exec()s
- // and fire them once we get a secret. For now, I don't think
- // it's possible for exec() to be called since plugins are parsed but
- // not run until until after onNativeReady.
- throw new Error('exec() called without bridgeSecret');
- }
- // Set default bridge modes if they have not already been set.
- // By default, we use the failsafe, since addJavascriptInterface breaks too often
- if (jsToNativeBridgeMode === undefined) {
- androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
- }
-
- // If args is not provided, default to an empty array
- args = args || [];
-
- // Process any ArrayBuffers in the args into a string.
- for (var i = 0; i < args.length; i++) {
- if (utils.typeName(args[i]) == 'ArrayBuffer') {
- args[i] = base64.fromArrayBuffer(args[i]);
- }
- }
-
- var callbackId = service + cordova.callbackId++,
- argsJson = JSON.stringify(args);
- if (success || fail) {
- cordova.callbacks[callbackId] = {success:success, fail:fail};
- }
-
- var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
- // If argsJson was received by Java as null, try again with the PROMPT bridge mode.
- // This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
- if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "@Null arguments.") {
- androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
- androidExec(success, fail, service, action, args);
- androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
- } else if (msgs) {
- messagesFromNative.push(msgs);
- // Always process async to avoid exceptions messing up stack.
- nextTick(processMessages);
- }
-}
-
-androidExec.init = function() {
- //CB-11828
- //This failsafe checks the version of Android and if it's Jellybean, it switches it to
- //using the Online Event bridge for communicating from Native to JS
- //
- //It's ugly, but it's necessary.
- var check = navigator.userAgent.toLowerCase().match(/android\s[0-9].[0-9]/);
- var version_code = check && check[0].match(/4.[0-3].*/);
- if (version_code != null && nativeToJsBridgeMode == nativeToJsModes.EVAL_BRIDGE) {
- nativeToJsBridgeMode = nativeToJsModes.ONLINE_EVENT;
- }
-
- bridgeSecret = +prompt('', 'gap_init:' + nativeToJsBridgeMode);
- channel.onNativeReady.fire();
-};
-
-function pollOnceFromOnlineEvent() {
- pollOnce(true);
-}
-
-function pollOnce(opt_fromOnlineEvent) {
- if (bridgeSecret < 0) {
- // This can happen when the NativeToJsMessageQueue resets the online state on page transitions.
- // We know there's nothing to retrieve, so no need to poll.
- return;
- }
- var msgs = nativeApiProvider.get().retrieveJsMessages(bridgeSecret, !!opt_fromOnlineEvent);
- if (msgs) {
- messagesFromNative.push(msgs);
- // Process sync since we know we're already top-of-stack.
- processMessages();
- }
-}
-
-function pollingTimerFunc() {
- if (pollEnabled) {
- pollOnce();
- setTimeout(pollingTimerFunc, 50);
- }
-}
-
-function hookOnlineApis() {
- function proxyEvent(e) {
- cordova.fireWindowEvent(e.type);
- }
- // The network module takes care of firing online and offline events.
- // It currently fires them only on document though, so we bridge them
- // to window here (while first listening for exec()-releated online/offline
- // events).
- window.addEventListener('online', pollOnceFromOnlineEvent, false);
- window.addEventListener('offline', pollOnceFromOnlineEvent, false);
- cordova.addWindowEventHandler('online');
- cordova.addWindowEventHandler('offline');
- document.addEventListener('online', proxyEvent, false);
- document.addEventListener('offline', proxyEvent, false);
-}
-
-hookOnlineApis();
-
-androidExec.jsToNativeModes = jsToNativeModes;
-androidExec.nativeToJsModes = nativeToJsModes;
-
-androidExec.setJsToNativeBridgeMode = function(mode) {
- if (mode == jsToNativeModes.JS_OBJECT && !window._cordovaNative) {
- mode = jsToNativeModes.PROMPT;
- }
- nativeApiProvider.setPreferPrompt(mode == jsToNativeModes.PROMPT);
- jsToNativeBridgeMode = mode;
-};
-
-androidExec.setNativeToJsBridgeMode = function(mode) {
- if (mode == nativeToJsBridgeMode) {
- return;
- }
- if (nativeToJsBridgeMode == nativeToJsModes.POLLING) {
- pollEnabled = false;
- }
-
- nativeToJsBridgeMode = mode;
- // Tell the native side to switch modes.
- // Otherwise, it will be set by androidExec.init()
- if (bridgeSecret >= 0) {
- nativeApiProvider.get().setNativeToJsBridgeMode(bridgeSecret, mode);
- }
-
- if (mode == nativeToJsModes.POLLING) {
- pollEnabled = true;
- setTimeout(pollingTimerFunc, 1);
- }
-};
-
-function buildPayload(payload, message) {
- var payloadKind = message.charAt(0);
- if (payloadKind == 's') {
- payload.push(message.slice(1));
- } else if (payloadKind == 't') {
- payload.push(true);
- } else if (payloadKind == 'f') {
- payload.push(false);
- } else if (payloadKind == 'N') {
- payload.push(null);
- } else if (payloadKind == 'n') {
- payload.push(+message.slice(1));
- } else if (payloadKind == 'A') {
- var data = message.slice(1);
- payload.push(base64.toArrayBuffer(data));
- } else if (payloadKind == 'S') {
- payload.push(window.atob(message.slice(1)));
- } else if (payloadKind == 'M') {
- var multipartMessages = message.slice(1);
- while (multipartMessages !== "") {
- var spaceIdx = multipartMessages.indexOf(' ');
- var msgLen = +multipartMessages.slice(0, spaceIdx);
- var multipartMessage = multipartMessages.substr(spaceIdx + 1, msgLen);
- multipartMessages = multipartMessages.slice(spaceIdx + msgLen + 1);
- buildPayload(payload, multipartMessage);
- }
- } else {
- payload.push(JSON.parse(message));
- }
-}
-
-// Processes a single message, as encoded by NativeToJsMessageQueue.java.
-function processMessage(message) {
- var firstChar = message.charAt(0);
- if (firstChar == 'J') {
- // This is deprecated on the .java side. It doesn't work with CSP enabled.
- eval(message.slice(1));
- } else if (firstChar == 'S' || firstChar == 'F') {
- var success = firstChar == 'S';
- var keepCallback = message.charAt(1) == '1';
- var spaceIdx = message.indexOf(' ', 2);
- var status = +message.slice(2, spaceIdx);
- var nextSpaceIdx = message.indexOf(' ', spaceIdx + 1);
- var callbackId = message.slice(spaceIdx + 1, nextSpaceIdx);
- var payloadMessage = message.slice(nextSpaceIdx + 1);
- var payload = [];
- buildPayload(payload, payloadMessage);
- cordova.callbackFromNative(callbackId, success, status, payload, keepCallback);
- } else {
- console.log("processMessage failed: invalid message: " + JSON.stringify(message));
- }
-}
-
-function processMessages() {
- // Check for the reentrant case.
- if (isProcessing) {
- return;
- }
- if (messagesFromNative.length === 0) {
- return;
- }
- isProcessing = true;
- try {
- var msg = popMessageFromQueue();
- // The Java side can send a * message to indicate that it
- // still has messages waiting to be retrieved.
- if (msg == '*' && messagesFromNative.length === 0) {
- nextTick(pollOnce);
- return;
- }
- processMessage(msg);
- } finally {
- isProcessing = false;
- if (messagesFromNative.length > 0) {
- nextTick(processMessages);
- }
- }
-}
-
-function popMessageFromQueue() {
- var messageBatch = messagesFromNative.shift();
- if (messageBatch == '*') {
- return '*';
- }
-
- var spaceIdx = messageBatch.indexOf(' ');
- var msgLen = +messageBatch.slice(0, spaceIdx);
- var message = messageBatch.substr(spaceIdx + 1, msgLen);
- messageBatch = messageBatch.slice(spaceIdx + msgLen + 1);
- if (messageBatch) {
- messagesFromNative.unshift(messageBatch);
- }
- return message;
-}
-
-module.exports = androidExec;
-
-});
-
-// file: src/common/exec/proxy.js
-define("cordova/exec/proxy", function(require, exports, module) {
-
-// internal map of proxy function
-var CommandProxyMap = {};
-
-module.exports = {
-
- // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
- add: function (id, proxyObj) {
- console.log('adding proxy for ' + id);
- CommandProxyMap[id] = proxyObj;
- return proxyObj;
- },
-
- // cordova.commandProxy.remove("Accelerometer");
- remove: function (id) {
- var proxy = CommandProxyMap[id];
- delete CommandProxyMap[id];
- CommandProxyMap[id] = null;
- return proxy;
- },
-
- get: function (service, action) {
- return (CommandProxyMap[service] ? CommandProxyMap[service][action] : null);
- }
-};
-
-});
-
-// file: src/common/init.js
-define("cordova/init", function(require, exports, module) {
-
-var channel = require('cordova/channel');
-var cordova = require('cordova');
-var modulemapper = require('cordova/modulemapper');
-var platform = require('cordova/platform');
-var pluginloader = require('cordova/pluginloader');
-var utils = require('cordova/utils');
-
-var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];
-
-function logUnfiredChannels (arr) {
- for (var i = 0; i < arr.length; ++i) {
- if (arr[i].state !== 2) {
- console.log('Channel not fired: ' + arr[i].type);
- }
- }
-}
-
-window.setTimeout(function () {
- if (channel.onDeviceReady.state !== 2) {
- console.log('deviceready has not fired after 5 seconds.');
- logUnfiredChannels(platformInitChannelsArray);
- logUnfiredChannels(channel.deviceReadyChannelsArray);
- }
-}, 5000);
-
-// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
-// We replace it so that properties that can't be clobbered can instead be overridden.
-function replaceNavigator (origNavigator) {
- var CordovaNavigator = function () {};
- CordovaNavigator.prototype = origNavigator;
- var newNavigator = new CordovaNavigator();
- // This work-around really only applies to new APIs that are newer than Function.bind.
- // Without it, APIs such as getGamepads() break.
- if (CordovaNavigator.bind) {
- for (var key in origNavigator) {
- if (typeof origNavigator[key] === 'function') {
- newNavigator[key] = origNavigator[key].bind(origNavigator);
- } else {
- (function (k) {
- utils.defineGetterSetter(newNavigator, key, function () {
- return origNavigator[k];
- });
- })(key);
- }
- }
- }
- return newNavigator;
-}
-
-if (window.navigator) {
- window.navigator = replaceNavigator(window.navigator);
-}
-
-if (!window.console) {
- window.console = {
- log: function () {}
- };
-}
-if (!window.console.warn) {
- window.console.warn = function (msg) {
- this.log('warn: ' + msg);
- };
-}
-
-// Register pause, resume and deviceready channels as events on document.
-channel.onPause = cordova.addDocumentEventHandler('pause');
-channel.onResume = cordova.addDocumentEventHandler('resume');
-channel.onActivated = cordova.addDocumentEventHandler('activated');
-channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
-
-// Listen for DOMContentLoaded and notify our channel subscribers.
-if (document.readyState === 'complete' || document.readyState === 'interactive') {
- channel.onDOMContentLoaded.fire();
-} else {
- document.addEventListener('DOMContentLoaded', function () {
- channel.onDOMContentLoaded.fire();
- }, false);
-}
-
-// _nativeReady is global variable that the native side can set
-// to signify that the native code is ready. It is a global since
-// it may be called before any cordova JS is ready.
-if (window._nativeReady) {
- channel.onNativeReady.fire();
-}
-
-modulemapper.clobbers('cordova', 'cordova');
-modulemapper.clobbers('cordova/exec', 'cordova.exec');
-modulemapper.clobbers('cordova/exec', 'Cordova.exec');
-
-// Call the platform-specific initialization.
-platform.bootstrap && platform.bootstrap();
-
-// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
-// The delay allows the attached modules to be defined before the plugin loader looks for them.
-setTimeout(function () {
- pluginloader.load(function () {
- channel.onPluginsReady.fire();
- });
-}, 0);
-
-/**
- * Create all cordova objects once native side is ready.
- */
-channel.join(function () {
- modulemapper.mapModules(window);
-
- platform.initialize && platform.initialize();
-
- // Fire event to notify that all objects are created
- channel.onCordovaReady.fire();
-
- // Fire onDeviceReady event once page has fully loaded, all
- // constructors have run and cordova info has been received from native
- // side.
- channel.join(function () {
- require('cordova').fireDocumentEvent('deviceready');
- }, channel.deviceReadyChannelsArray);
-
-}, platformInitChannelsArray);
-
-});
-
-// file: src/common/init_b.js
-define("cordova/init_b", function(require, exports, module) {
-
-var channel = require('cordova/channel');
-var cordova = require('cordova');
-var modulemapper = require('cordova/modulemapper');
-var platform = require('cordova/platform');
-var pluginloader = require('cordova/pluginloader');
-var utils = require('cordova/utils');
-
-var platformInitChannelsArray = [channel.onDOMContentLoaded, channel.onNativeReady, channel.onPluginsReady];
-
-// setting exec
-cordova.exec = require('cordova/exec');
-
-function logUnfiredChannels (arr) {
- for (var i = 0; i < arr.length; ++i) {
- if (arr[i].state !== 2) {
- console.log('Channel not fired: ' + arr[i].type);
- }
- }
-}
-
-window.setTimeout(function () {
- if (channel.onDeviceReady.state !== 2) {
- console.log('deviceready has not fired after 5 seconds.');
- logUnfiredChannels(platformInitChannelsArray);
- logUnfiredChannels(channel.deviceReadyChannelsArray);
- }
-}, 5000);
-
-// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
-// We replace it so that properties that can't be clobbered can instead be overridden.
-function replaceNavigator (origNavigator) {
- var CordovaNavigator = function () {};
- CordovaNavigator.prototype = origNavigator;
- var newNavigator = new CordovaNavigator();
- // This work-around really only applies to new APIs that are newer than Function.bind.
- // Without it, APIs such as getGamepads() break.
- if (CordovaNavigator.bind) {
- for (var key in origNavigator) {
- if (typeof origNavigator[key] === 'function') {
- newNavigator[key] = origNavigator[key].bind(origNavigator);
- } else {
- (function (k) {
- utils.defineGetterSetter(newNavigator, key, function () {
- return origNavigator[k];
- });
- })(key);
- }
- }
- }
- return newNavigator;
-}
-if (window.navigator) {
- window.navigator = replaceNavigator(window.navigator);
-}
-
-if (!window.console) {
- window.console = {
- log: function () {}
- };
-}
-if (!window.console.warn) {
- window.console.warn = function (msg) {
- this.log('warn: ' + msg);
- };
-}
-
-// Register pause, resume and deviceready channels as events on document.
-channel.onPause = cordova.addDocumentEventHandler('pause');
-channel.onResume = cordova.addDocumentEventHandler('resume');
-channel.onActivated = cordova.addDocumentEventHandler('activated');
-channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
-
-// Listen for DOMContentLoaded and notify our channel subscribers.
-if (document.readyState === 'complete' || document.readyState === 'interactive') {
- channel.onDOMContentLoaded.fire();
-} else {
- document.addEventListener('DOMContentLoaded', function () {
- channel.onDOMContentLoaded.fire();
- }, false);
-}
-
-// _nativeReady is global variable that the native side can set
-// to signify that the native code is ready. It is a global since
-// it may be called before any cordova JS is ready.
-if (window._nativeReady) {
- channel.onNativeReady.fire();
-}
-
-// Call the platform-specific initialization.
-platform.bootstrap && platform.bootstrap();
-
-// Wrap in a setTimeout to support the use-case of having plugin JS appended to cordova.js.
-// The delay allows the attached modules to be defined before the plugin loader looks for them.
-setTimeout(function () {
- pluginloader.load(function () {
- channel.onPluginsReady.fire();
- });
-}, 0);
-
-/**
- * Create all cordova objects once native side is ready.
- */
-channel.join(function () {
- modulemapper.mapModules(window);
-
- platform.initialize && platform.initialize();
-
- // Fire event to notify that all objects are created
- channel.onCordovaReady.fire();
-
- // Fire onDeviceReady event once page has fully loaded, all
- // constructors have run and cordova info has been received from native
- // side.
- channel.join(function () {
- require('cordova').fireDocumentEvent('deviceready');
- }, channel.deviceReadyChannelsArray);
-
-}, platformInitChannelsArray);
-
-});
-
-// file: src/common/modulemapper.js
-define("cordova/modulemapper", function(require, exports, module) {
-
-var builder = require('cordova/builder');
-var moduleMap = define.moduleMap; // eslint-disable-line no-undef
-var symbolList;
-var deprecationMap;
-
-exports.reset = function () {
- symbolList = [];
- deprecationMap = {};
-};
-
-function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
- if (!(moduleName in moduleMap)) {
- throw new Error('Module ' + moduleName + ' does not exist.');
- }
- symbolList.push(strategy, moduleName, symbolPath);
- if (opt_deprecationMessage) {
- deprecationMap[symbolPath] = opt_deprecationMessage;
- }
-}
-
-// Note: Android 2.3 does have Function.bind().
-exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
- addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
-};
-
-exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
- addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
-};
-
-exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
- addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
-};
-
-exports.runs = function (moduleName) {
- addEntry('r', moduleName, null);
-};
-
-function prepareNamespace (symbolPath, context) {
- if (!symbolPath) {
- return context;
- }
- var parts = symbolPath.split('.');
- var cur = context;
- for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
- cur = cur[part] = cur[part] || {};
- }
- return cur;
-}
-
-exports.mapModules = function (context) {
- var origSymbols = {};
- context.CDV_origSymbols = origSymbols;
- for (var i = 0, len = symbolList.length; i < len; i += 3) {
- var strategy = symbolList[i];
- var moduleName = symbolList[i + 1];
- var module = require(moduleName);
- //
- if (strategy === 'r') {
- continue;
- }
- var symbolPath = symbolList[i + 2];
- var lastDot = symbolPath.lastIndexOf('.');
- var namespace = symbolPath.substr(0, lastDot);
- var lastName = symbolPath.substr(lastDot + 1);
-
- var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
- var parentObj = prepareNamespace(namespace, context);
- var target = parentObj[lastName];
-
- if (strategy === 'm' && target) {
- builder.recursiveMerge(target, module);
- } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
- if (!(symbolPath in origSymbols)) {
- origSymbols[symbolPath] = target;
- }
- builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
- }
- }
-};
-
-exports.getOriginalSymbol = function (context, symbolPath) {
- var origSymbols = context.CDV_origSymbols;
- if (origSymbols && (symbolPath in origSymbols)) {
- return origSymbols[symbolPath];
- }
- var parts = symbolPath.split('.');
- var obj = context;
- for (var i = 0; i < parts.length; ++i) {
- obj = obj && obj[parts[i]];
- }
- return obj;
-};
-
-exports.reset();
-
-});
-
-// file: src/common/modulemapper_b.js
-define("cordova/modulemapper_b", function(require, exports, module) {
-
-var builder = require('cordova/builder');
-var symbolList = [];
-var deprecationMap;
-
-exports.reset = function () {
- symbolList = [];
- deprecationMap = {};
-};
-
-function addEntry (strategy, moduleName, symbolPath, opt_deprecationMessage) {
- symbolList.push(strategy, moduleName, symbolPath);
- if (opt_deprecationMessage) {
- deprecationMap[symbolPath] = opt_deprecationMessage;
- }
-}
-
-// Note: Android 2.3 does have Function.bind().
-exports.clobbers = function (moduleName, symbolPath, opt_deprecationMessage) {
- addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
-};
-
-exports.merges = function (moduleName, symbolPath, opt_deprecationMessage) {
- addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
-};
-
-exports.defaults = function (moduleName, symbolPath, opt_deprecationMessage) {
- addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
-};
-
-exports.runs = function (moduleName) {
- addEntry('r', moduleName, null);
-};
-
-function prepareNamespace (symbolPath, context) {
- if (!symbolPath) {
- return context;
- }
- var parts = symbolPath.split('.');
- var cur = context;
- for (var i = 0, part; part = parts[i]; ++i) { // eslint-disable-line no-cond-assign
- cur = cur[part] = cur[part] || {};
- }
- return cur;
-}
-
-exports.mapModules = function (context) {
- var origSymbols = {};
- context.CDV_origSymbols = origSymbols;
- for (var i = 0, len = symbolList.length; i < len; i += 3) {
- var strategy = symbolList[i];
- var moduleName = symbolList[i + 1];
- var module = require(moduleName);
- //
- if (strategy === 'r') {
- continue;
- }
- var symbolPath = symbolList[i + 2];
- var lastDot = symbolPath.lastIndexOf('.');
- var namespace = symbolPath.substr(0, lastDot);
- var lastName = symbolPath.substr(lastDot + 1);
-
- var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
- var parentObj = prepareNamespace(namespace, context);
- var target = parentObj[lastName];
-
- if (strategy === 'm' && target) {
- builder.recursiveMerge(target, module);
- } else if ((strategy === 'd' && !target) || (strategy !== 'd')) {
- if (!(symbolPath in origSymbols)) {
- origSymbols[symbolPath] = target;
- }
- builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
- }
- }
-};
-
-exports.getOriginalSymbol = function (context, symbolPath) {
- var origSymbols = context.CDV_origSymbols;
- if (origSymbols && (symbolPath in origSymbols)) {
- return origSymbols[symbolPath];
- }
- var parts = symbolPath.split('.');
- var obj = context;
- for (var i = 0; i < parts.length; ++i) {
- obj = obj && obj[parts[i]];
- }
- return obj;
-};
-
-exports.reset();
-
-});
-
-// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/platform.js
-define("cordova/platform", function(require, exports, module) {
-
-// The last resume event that was received that had the result of a plugin call.
-var lastResumeEvent = null;
-
-module.exports = {
- id: 'android',
- bootstrap: function() {
- var channel = require('cordova/channel'),
- cordova = require('cordova'),
- exec = require('cordova/exec'),
- modulemapper = require('cordova/modulemapper');
-
- // Get the shared secret needed to use the bridge.
- exec.init();
-
- // TODO: Extract this as a proper plugin.
- modulemapper.clobbers('cordova/plugin/android/app', 'navigator.app');
-
- var APP_PLUGIN_NAME = Number(cordova.platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
-
- // Inject a listener for the backbutton on the document.
- var backButtonChannel = cordova.addDocumentEventHandler('backbutton');
- backButtonChannel.onHasSubscribersChange = function() {
- // If we just attached the first handler or detached the last handler,
- // let native know we need to override the back button.
- exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [this.numHandlers == 1]);
- };
-
- // Add hardware MENU and SEARCH button handlers
- cordova.addDocumentEventHandler('menubutton');
- cordova.addDocumentEventHandler('searchbutton');
-
- function bindButtonChannel(buttonName) {
- // generic button bind used for volumeup/volumedown buttons
- var volumeButtonChannel = cordova.addDocumentEventHandler(buttonName + 'button');
- volumeButtonChannel.onHasSubscribersChange = function() {
- exec(null, null, APP_PLUGIN_NAME, "overrideButton", [buttonName, this.numHandlers == 1]);
- };
- }
- // Inject a listener for the volume buttons on the document.
- bindButtonChannel('volumeup');
- bindButtonChannel('volumedown');
-
- // The resume event is not "sticky", but it is possible that the event
- // will contain the result of a plugin call. We need to ensure that the
- // plugin result is delivered even after the event is fired (CB-10498)
- var cordovaAddEventListener = document.addEventListener;
-
- document.addEventListener = function(evt, handler, capture) {
- cordovaAddEventListener(evt, handler, capture);
-
- if (evt === 'resume' && lastResumeEvent) {
- handler(lastResumeEvent);
- }
- };
-
- // Let native code know we are all done on the JS side.
- // Native code will then un-hide the WebView.
- channel.onCordovaReady.subscribe(function() {
- exec(onMessageFromNative, null, APP_PLUGIN_NAME, 'messageChannel', []);
- exec(null, null, APP_PLUGIN_NAME, "show", []);
- });
- }
-};
-
-function onMessageFromNative(msg) {
- var cordova = require('cordova');
- var action = msg.action;
-
- switch (action)
- {
- // Button events
- case 'backbutton':
- case 'menubutton':
- case 'searchbutton':
- // App life cycle events
- case 'pause':
- // Volume events
- case 'volumedownbutton':
- case 'volumeupbutton':
- cordova.fireDocumentEvent(action);
- break;
- case 'resume':
- if(arguments.length > 1 && msg.pendingResult) {
- if(arguments.length === 2) {
- msg.pendingResult.result = arguments[1];
- } else {
- // The plugin returned a multipart message
- var res = [];
- for(var i = 1; i < arguments.length; i++) {
- res.push(arguments[i]);
- }
- msg.pendingResult.result = res;
- }
-
- // Save the plugin result so that it can be delivered to the js
- // even if they miss the initial firing of the event
- lastResumeEvent = msg;
- }
- cordova.fireDocumentEvent(action, msg);
- break;
- default:
- throw new Error('Unknown event action ' + action);
- }
-}
-
-});
-
-// file: /Users/brodybits/Documents/cordova/cordova-android/cordova-js-src/plugin/android/app.js
-define("cordova/plugin/android/app", function(require, exports, module) {
-
-var exec = require('cordova/exec');
-var APP_PLUGIN_NAME = Number(require('cordova').platformVersion.split('.')[0]) >= 4 ? 'CoreAndroid' : 'App';
-
-module.exports = {
- /**
- * Clear the resource cache.
- */
- clearCache:function() {
- exec(null, null, APP_PLUGIN_NAME, "clearCache", []);
- },
-
- /**
- * Load the url into the webview or into new browser instance.
- *
- * @param url The URL to load
- * @param props Properties that can be passed in to the activity:
- * wait: int => wait msec before loading URL
- * loadingDialog: "Title,Message" => display a native loading dialog
- * loadUrlTimeoutValue: int => time in msec to wait before triggering a timeout error
- * clearHistory: boolean => clear webview history (default=false)
- * openExternal: boolean => open in a new browser (default=false)
- *
- * Example:
- * navigator.app.loadUrl("http://server/myapp/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
- */
- loadUrl:function(url, props) {
- exec(null, null, APP_PLUGIN_NAME, "loadUrl", [url, props]);
- },
-
- /**
- * Cancel loadUrl that is waiting to be loaded.
- */
- cancelLoadUrl:function() {
- exec(null, null, APP_PLUGIN_NAME, "cancelLoadUrl", []);
- },
-
- /**
- * Clear web history in this web view.
- * Instead of BACK button loading the previous web page, it will exit the app.
- */
- clearHistory:function() {
- exec(null, null, APP_PLUGIN_NAME, "clearHistory", []);
- },
-
- /**
- * Go to previous page displayed.
- * This is the same as pressing the backbutton on Android device.
- */
- backHistory:function() {
- exec(null, null, APP_PLUGIN_NAME, "backHistory", []);
- },
-
- /**
- * Override the default behavior of the Android back button.
- * If overridden, when the back button is pressed, the "backKeyDown" JavaScript event will be fired.
- *
- * Note: The user should not have to call this method. Instead, when the user
- * registers for the "backbutton" event, this is automatically done.
- *
- * @param override T=override, F=cancel override
- */
- overrideBackbutton:function(override) {
- exec(null, null, APP_PLUGIN_NAME, "overrideBackbutton", [override]);
- },
-
- /**
- * Override the default behavior of the Android volume button.
- * If overridden, when the volume button is pressed, the "volume[up|down]button"
- * JavaScript event will be fired.
- *
- * Note: The user should not have to call this method. Instead, when the user
- * registers for the "volume[up|down]button" event, this is automatically done.
- *
- * @param button volumeup, volumedown
- * @param override T=override, F=cancel override
- */
- overrideButton:function(button, override) {
- exec(null, null, APP_PLUGIN_NAME, "overrideButton", [button, override]);
- },
-
- /**
- * Exit and terminate the application.
- */
- exitApp:function() {
- return exec(null, null, APP_PLUGIN_NAME, "exitApp", []);
- }
-};
-
-});
-
-// file: src/common/pluginloader.js
-define("cordova/pluginloader", function(require, exports, module) {
-
-var modulemapper = require('cordova/modulemapper');
-
-// Helper function to inject a