Merge branch 'master' into 4.0.x (SplashScreen breakout)

Conflicts:
	framework/src/org/apache/cordova/CordovaActivity.java
	framework/src/org/apache/cordova/CordovaWebView.java
This commit is contained in:
Andrew Grieve 2014-12-10 16:09:22 -05:00
commit 87cdc5ad1c
5 changed files with 93 additions and 222 deletions

View File

@ -239,7 +239,8 @@ var builders = {
// If the gradle distribution URL is set, make sure it points to version 1.12.
// If it's not set, do nothing, assuming that we're using a future version of gradle that we don't want to mess with.
var distributionUrlRegex = '/^distributionUrl=.*$/';
// For some reason, using ^ and $ don't work. This does the job, though.
var distributionUrlRegex = /distributionUrl.*zip/;
var distributionUrl = 'distributionUrl=http\\://services.gradle.org/distributions/gradle-1.12-all.zip';
var gradleWrapperPropertiesPath = path.join(projectPath, 'gradle', 'wrapper', 'gradle-wrapper.properties');
shell.sed('-i', distributionUrlRegex, distributionUrl, gradleWrapperPropertiesPath);
@ -398,12 +399,44 @@ module.exports.run = function(options, optResolvedTarget) {
* Returns "arm" or "x86".
*/
module.exports.detectArchitecture = function(target) {
return exec('adb -s ' + target + ' shell cat /proc/cpuinfo')
.then(function(output) {
if (/intel/i.exec(output)) {
return 'x86';
function helper() {
return exec('adb -s ' + target + ' shell cat /proc/cpuinfo')
.then(function(output) {
if (/intel/i.exec(output)) {
return 'x86';
}
return '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, '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.
return exec('killall adb')
.then(function() {
console.log('adb seems hung. retrying.');
return helper()
.then(null, function() {
// The double kill is sadly often necessary, at least on mac.
console.log('Now device not found... restarting adb again.');
return exec('killall adb')
.then(function() {
return helper()
.then(null, function() {
return Q.reject('USB is flakey. Try unplugging & replugging the device.');
});
});
});
}, function() {
// For non-killall OS's.
return Q.reject(err);
})
}
return 'arm';
throw err;
});
};

View File

@ -28,23 +28,43 @@ var exec = require('./exec'),
/**
* 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() {
return exec('adb devices')
.then(function(output) {
var response = output.split('\n');
var device_list = [];
for (var i = 1; i < response.length; i++) {
if (response[i].match(/\w+\tdevice/) && !response[i].match(/emulator/)) {
device_list.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
module.exports.list = function(lookHarder) {
function helper() {
return exec('adb devices')
.then(function(output) {
var response = output.split('\n');
var device_list = [];
for (var i = 1; i < response.length; i++) {
if (response[i].match(/\w+\tdevice/) && !response[i].match(/emulator/)) {
device_list.push(response[i].replace(/\tdevice/, '').replace('\r', ''));
}
}
return device_list;
});
}
return helper()
.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 exec('killall adb')
.then(function() {
console.log('Restarting adb to see if more devices are detected.');
return helper();
}, function() {
// For non-killall OS's.
return list;
});
}
return device_list;
return list;
});
}
module.exports.resolveTarget = function(target) {
return this.list()
return this.list(true)
.then(function(device_list) {
if (!device_list || !device_list.length) {
return Q.reject('ERROR: Failed to deploy to device, no devices found.');

View File

@ -31,8 +31,18 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.0+'
// 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
if (gradle.gradleVersion >= "2.1") {
dependencies {
classpath 'com.android.tools.build:gradle:0.14.0+'
}
} else {
dependencies {
classpath 'com.android.tools.build:gradle:0.12.0+'
}
}
}

View File

@ -124,8 +124,9 @@ public class AndroidWebView extends WebView implements CordovaWebView {
pluginManager = new PluginManager(this, this.cordova, pluginEntries);
resourceApi = new CordovaResourceApi(this.getContext(), pluginManager);
bridge = new CordovaBridge(pluginManager, new NativeToJsMessageQueue(this, cordova), this.cordova.getActivity().getPackageName());
pluginManager.addService("App", "org.apache.cordova.CoreAndroid");
initWebViewSettings();
pluginManager.addService("App", "org.apache.cordova.CoreAndroid");
pluginManager.init();
if (this.viewClient == null) {
setWebViewClient(Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH ?
@ -304,8 +305,11 @@ public class AndroidWebView extends WebView implements CordovaWebView {
recreatePlugins = recreatePlugins || (loadedUrl == null);
if (recreatePlugins) {
// Don't re-initialize on first load.
if (loadedUrl != null) {
this.pluginManager.init();
}
this.loadedUrl = url;
this.pluginManager.init();
}
// Create a timeout timer for loadUrl

View File

@ -25,16 +25,12 @@ import java.util.Locale;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.LOG;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -42,7 +38,6 @@ import android.graphics.Color;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
@ -92,7 +87,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
// The webview for our app
protected CordovaWebView appView;
protected ProgressDialog spinnerDialog = null;
private final ExecutorService threadPool = Executors.newCachedThreadPool();
private static int ACTIVITY_STARTING = 0;
@ -108,10 +102,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* The variables below are used to cache some of the activity properties.
*/
// Draw a splash screen using an image located in the drawable resource directory.
// This is not the same as calling super.loadSplashscreen(url)
protected int splashscreen = 0;
// LoadUrl timeout value in msec (default of 20 sec)
protected int loadUrlTimeoutValue = 20000;
@ -213,8 +203,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
ViewGroup.LayoutParams.MATCH_PARENT,
1.0F));
// Add web view but make it invisible while loading URL
appView.getView().setVisibility(View.INVISIBLE);
// need to remove appView from any existing parent before invoking root.addView(appView)
ViewParent parent = appView.getView().getParent();
if ((parent != null) && (parent != root)) {
@ -264,7 +252,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
e.printStackTrace();
}
}
if (ret == null) {
// If all else fails, return a default WebView
ret = new AndroidWebView(this);
@ -276,82 +264,15 @@ public class CordovaActivity extends Activity implements CordovaInterface {
/**
* Load the url into the webview.
*/
public void loadUrl(String url, int splashscreenTime) {
public void loadUrl(String url) {
if (appView == null) {
init();
}
String splash = preferences.getString("SplashScreen", null);
if(splashscreenTime > 0 && splash != null)
{
this.splashscreen = getResources().getIdentifier(splash, "drawable", getClass().getPackage().getName());;
if(this.splashscreen != 0)
{
this.showSplashScreen(splashscreenTime);
}
}
// If keepRunning
this.keepRunning = preferences.getBoolean("KeepRunning", true);
//Check if the view is attached to anything
if(appView.getView().getParent() != null)
{
// Then load the spinner
this.loadSpinner();
}
//Load the correct splashscreen
if(this.splashscreen != 0)
{
appView.getPluginManager().postMessage("splashscreen", "show");
}
this.appView.loadUrlIntoView(url, true);
}
/**
* Load the url into the webview after waiting for period of time.
* This is used to display the splashscreen for certain amount of time.
*
* @param url
* @param time The number of ms to wait before loading webview
*/
public void loadUrl(final String url) {
if (appView == null) {
init();
}
this.loadUrl(url, preferences.getInteger("SplashScreenDelay", 3000));
}
/*
* Load the spinner
*/
void loadSpinner() {
// If loadingDialog property, then show the App loading dialog for first page of app
String loading = null;
if ((this.appView == null) || !this.appView.canGoBack()) {
loading = preferences.getString("LoadingDialog", null);
}
else {
loading = preferences.getString("LoadingPageDialog", null);
}
if (loading != null) {
String title = "";
String message = "Loading Application...";
if (loading.length() > 0) {
int comma = loading.indexOf(',');
if (comma > 0) {
title = loading.substring(0, comma);
message = loading.substring(comma + 1);
}
else {
title = "";
message = loading;
}
}
this.spinnerStart(title, message);
}
appView.loadUrlIntoView(url, true);
}
/**
@ -375,9 +296,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
{
this.appView.handlePause(this.keepRunning);
}
// hide the splash screen to avoid leaking a window
this.removeSplashScreen();
}
/**
@ -432,9 +350,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
LOG.d(TAG, "CordovaActivity.onDestroy()");
super.onDestroy();
// hide the splash screen to avoid leaking a window
this.removeSplashScreen();
if (this.appView != null) {
appView.handleDestroy();
}
@ -443,36 +358,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
}
}
/**
* Show the spinner. Must be called from the UI thread.
*
* @param title Title of the dialog
* @param message The message of the dialog
*/
public void spinnerStart(final String title, final String message) {
if (this.spinnerDialog != null) {
this.spinnerDialog.dismiss();
this.spinnerDialog = null;
}
final CordovaActivity me = this;
this.spinnerDialog = ProgressDialog.show(CordovaActivity.this, title, message, true, true,
new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
me.spinnerDialog = null;
}
});
}
/**
* Stop spinner - Must be called from UI thread
*/
public void spinnerStop() {
if (this.spinnerDialog != null && this.spinnerDialog.isShowing()) {
this.spinnerDialog.dismiss();
this.spinnerDialog = null;
}
}
/**
* End this activity by calling finish for activity
*/
@ -561,8 +446,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
// Load URL on UI thread
me.runOnUiThread(new Runnable() {
public void run() {
// Stop "app loading" spinner if showing
me.spinnerStop();
me.appView.showWebPage(errorUrl, false, true, null);
}
});
@ -638,64 +521,6 @@ public class CordovaActivity extends Activity implements CordovaInterface {
return true;
}
protected Dialog splashDialog;
/**
* Removes the Dialog that displays the splash screen
*/
public void removeSplashScreen() {
if (splashDialog != null && splashDialog.isShowing()) {
splashDialog.dismiss();
splashDialog = null;
}
}
/**
* Shows the splash screen over the full Activity
*/
@SuppressWarnings("deprecation")
protected void showSplashScreen(final int time) {
final CordovaActivity that = this;
Runnable runnable = new Runnable() {
public void run() {
// Get reference to display
Display display = getWindowManager().getDefaultDisplay();
// Create the layout for the dialog
LinearLayout root = new LinearLayout(that.getActivity());
root.setMinimumHeight(display.getHeight());
root.setMinimumWidth(display.getWidth());
root.setOrientation(LinearLayout.VERTICAL);
root.setBackgroundColor(preferences.getInteger("backgroundColor", Color.BLACK));
root.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT, 0.0F));
root.setBackgroundResource(that.splashscreen);
// Create and show the dialog
splashDialog = new Dialog(that, android.R.style.Theme_Translucent_NoTitleBar);
// check to see if the splash screen should be full screen
if ((getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN)
== WindowManager.LayoutParams.FLAG_FULLSCREEN) {
splashDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
splashDialog.setContentView(root);
splashDialog.setCancelable(false);
splashDialog.show();
// Set Runnable to remove splash screen just in case
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
removeSplashScreen();
}
}, time);
}
};
this.runOnUiThread(runnable);
}
/**
* Called when a message is sent to plugin.
*
@ -708,28 +533,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
LOG.d(TAG, "onMessage(" + id + "," + data + ")");
}
if ("splashscreen".equals(id)) {
if ("hide".equals(data.toString())) {
this.removeSplashScreen();
}
else {
// If the splash dialog is showing don't try to show it again
if (this.splashDialog == null || !this.splashDialog.isShowing()) {
String splashResource = preferences.getString("SplashScreen", null);
if (splashResource != null) {
splashscreen = getResources().getIdentifier(splashResource, "drawable", getClass().getPackage().getName());
}
this.showSplashScreen(preferences.getInteger("SplashScreenDelay", 3000));
}
}
}
else if ("spinner".equals(id)) {
if ("stop".equals(data.toString())) {
this.spinnerStop();
this.appView.getView().setVisibility(View.VISIBLE);
}
}
else if ("onReceivedError".equals(id)) {
if ("onReceivedError".equals(id)) {
JSONObject d = (JSONObject) data;
try {
this.onReceivedError(d.getInt("errorCode"), d.getString("description"), d.getString("url"));