Compare commits

...

20 Commits

Author SHA1 Message Date
Joe Bowser
f3885692d9 Updating RELASENOTES.md, this is in a weird spot, since you need the branch to exist to generate the notes 2015-01-21 08:25:37 -08:00
shingotoda
d7fc37d365 CB-8317 Make it work to load about:blank and to dispatch exit message (close #149) 2015-01-20 19:46:20 -05:00
Andrew Grieve
c3bdebdb83 CB-8026 Remove default target value from gradle file
Wasn't being used anyways, and it still referenced android-19
This also switches to using a Properties object rather than a RegEx
for parsing project.properties
2015-01-20 15:04:49 -05:00
Andrew Grieve
9514a3ed94 Move cordova.gradle from project template to CordovaLib
Make it easier to share with tests project.
Also, one less file in the project template is a good thing.
2015-01-20 15:04:46 -05:00
Andrew Grieve
050dd088cf gradle: Fix incorrect buildTools dependencies in framework's build.gradle
(although it didn't seem to hurt anything?)
2015-01-20 10:50:38 -05:00
Marcus Pridham
26f0401fda CB-8328 Allow plugins to handle certificate challenges (close #150)
This is a new API for Lollipop
2015-01-19 22:21:10 -05:00
sgrebnov
e4e04927b6 CB-8201 Add support for auth dialogs into Cordova Android 2015-01-19 22:21:05 -05:00
Andrew Grieve
6b3ef11715 Adds cdvPrintProps gradle task: dumps out all cdv properties
Useful for debugging.
2015-01-19 22:05:30 -05:00
Andrew Grieve
cf0fdf5ac0 CB-8255 Pass arch to gradle regardless of cdvBuildMultipleApks
This also pushes the "which target to build" logic into gradle, since
build.js doesn't actually know the value of `cdvBuildMultipleApks`.
2015-01-19 22:05:26 -05:00
Andrew Grieve
33614d1273 CB-8255 Fix cordova/build --gradleVar=--foo=bar stripping off =bar 2015-01-19 22:05:24 -05:00
Andrew Grieve
1f735935b9 Fix cordova/build not printing out all gradle args in console message 2015-01-19 22:05:23 -05:00
Andrew Grieve
8c14e33bb6 Fix cordova/run not finding apk when multi-arch is specified but only arch-independent apk exists 2015-01-19 22:05:22 -05:00
Andrew Grieve
7375154228 Fix exception for unknown flag in cordova/run 2015-01-19 22:05:21 -05:00
Andrew Grieve
1427c13504 Allow --ant, --gradle for cordova/run 2015-01-19 22:05:18 -05:00
Andrew Grieve
5538a231a8 CB-8017 Add support for <input type=file> for Lollipop
Also refactors a bit to remove related special-case code from CordovaActivity
2015-01-19 16:23:20 -05:00
Andrew Grieve
9be110683b CB-8329 Cancel outstanding ActivityResult requests when a new startActivityForResult occurs 2015-01-19 16:23:19 -05:00
Andrew Grieve
cfc36140bc CB-8280 android: Don't apply SplashScreenDelay when .show() is called explicitly 2015-01-19 13:42:35 -05:00
Murat Sutunc
72e947e5c7 CB-4914 Fix build whitespace issue 2015-01-13 10:00:04 -05:00
Joe Bowser
7320ce8ea7 Set VERSION to 3.7.0 (via coho) 2015-01-12 14:55:48 -08:00
Joe Bowser
3e07f26bc4 Update JS snapshot to version 3.7.0 (via coho) 2015-01-12 14:55:48 -08:00
23 changed files with 634 additions and 135 deletions

View File

@@ -20,6 +20,87 @@
-->
## Release Notes for Cordova (Android) ##
### Release 3.7.0 (January 2015) ###
* CB-8328 Allow plugins to handle certificate challenges (close #150)
* CB-8201 Add support for auth dialogs into Cordova Android
* CB-8255 Pass `arch` to gradle regardless of `cdvBuildMultipleApks`
* CB-8255 Fix `cordova/build --gradleVar=--foo=bar` stripping off `=bar`
* CB-8017 Add support for `<input type=file>` for Lollipop
* CB-8329 Cancel outstanding ActivityResult requests when a new startActivityForResult occurs
* CB-8280 android: Don't apply SplashScreenDelay when .show() is called explicitly
* CB-4914 Fix build whitespace issue
* CB-8210 Remove unused onDestroy channel (close #146)
* CB-8026: Bumping up Android Version and setting it up to allow third-party cookies. This might change later.
* CB-8255 Use properties rather than environment variables for gradle settings
* CB-8210 Drop events from native that occur before start-up
* CB-8210 Use PluginResult for various events from native (close #144)
* CB-8168 Add support for `cordova/run --list` (closes #139)
* CB-8210 Use PluginResult instead of sendJavascript() for keyboard events (close #142)
* CB-8228 Gradle: Allow plugins to use Maven dependencies
* CB-8229 Gradle: Add CordovaLib as a dependency to all plugin sub-projects
* CB-7980 Add --minSdkVersion and --versionCode flags to cordova/build command
* CB-7980: Add 9 to versionCode for minSdk 20+ if not multiarch
* CB-8204: Reinstate link tasks to avoid gradle build failures
* CB-8143 Use gradle 2.2.1 instead of 1.12 to appease Android Studio 1.0 warning-on-startup
* CB-8143 Use gradle plugin 1.0.0 for Android Studio 1.0.0
* CB-8202 Fix gradle build signing when passwords provided interactively
* CB-8176 Update Android SDK search path for Android Studio 1.0
* CB-8079 Use activity class package name, but fallback to application package name when looking for splash screen drawable
* CB-8147 Have corodva/build warn about unrecognized flags rather than fail
* CB-7881 Android tooling shouldn't lock application directory
* CB-3679 Move splashscreen logic into splashscreen plugin
* CB-8143: Use the correct Android Gradle plugin for the installed Gradle version
* CB-8119 Restart adb when we detect it's hung
* CB-8112 Turn off mediaPlaybackRequiresUserGesture
* CB-6153 Add a preference for controlling hardware button audio stream (DefaultVolumeStream)
* CB-8081 Allow gradle builds to use Java 6 instead of requiring 7
* CB-8031 Fix race condition that shows as ConcurrentModificationException
* CB-7976 Use webView's context rather than Activity's context for intent receiver
* CB-7974 Cancel timeout timer if view is destroyed
* CB-7940 Disable exec bridge if bridgeSecret is wrong
* CB-7758: Allow content-url-hosted pages to access the bridge
* CB-7726 fix typo in gitignore: ant-built -> ant-build
* Replacing Math.random() with something a little more random.
* CB-6511 Fixes build for android when app name contains unicode characters.
* CB-7707 Added multipart PluginResult (close #125)
* CB-7714 Teach check_reqs about brew's install location for android SDK
* Fix --shared flag of create script (broke in recent gradle changes)
* Update .gitignore to ignore /framework/build and /node_modules
* CB-6837 Fix leaked window when hitting back button while alert being rendered
* CB-7674: Added sleep to avoid null error after most recent change to not break API
* CB-7674 move preference activation back into onCreate()
* CB-7634 Detect JAVA_HOME properly on Ubuntu
* CB-7410 update the docs to match the actual title
* CB-7512 Use a standard build.gradle for all plugins
* CB-7512 Make gradle build only a single config for sub-libraries (release vs debug)
* CB-7579 Fix run script's ability to use non-arch-specific APKs
* CB-7512 Fix gradle asking for release password when building for debug
* CB-7493 Adds test-build command to package.json
* CB-3445: Make minSdkVersion and base versionCode settable through env vars
* CB-7512 Make key password optional & prompt for it when missing
* CB-7512 Fix gradle not copying all archs to out/ (broken by prev commit)
* CB-7512 Use aligned apk rather than unaligned apk when sorting
* CB-7512 Speed up gradle builds by building debug or release (not both)
* CB-7512 Add gradle environment vars for signing apks
* CB-7512 Change gradle android plugins from 0.10 -> 0.12
* CB-7536 check_reqs: windows tweaks + sdk manager error message
* CB-7499, support RTL text direction
* CB-7554 Use x86 apk when deploying to an intel device / emulator
* CB-7512: Fix logic for detecting SDK directory
* CB-7536 Tweak Android SDK not installed error message.
* CB-7536 Tweak error messages for missing JDK / SDK / AVDs
* CB-7511 Auto-detect android sdk when using stand-alone sdk installer
* CB-7512: Copy cordova.gradle file to project root on build
* CB-7330 Don't run check_reqs for bin/create.
* CB-7512: Read android target from project.properties if possible
* CB-7512: Determine SDK and build tools version dynamcally at build time
* CB-7463: Adding licence to project template gradle file
* CB-7511 Auto-detect Android SDK when Android Studio is installed
* CB-7463: Looked at the Apache BigTop git, gradle uses C-style comments
* CB-7463: Adding licences. I don't know what the gradle syntax is for comments, that still needs to be done.
* CB-7460: Fixing bug with KitKat where the background colour would override the CSS colours on the application
### 3.6.4 (Sept 30, 2014) ###
* Set VERSION to 3.6.4 (via coho)

View File

@@ -1 +1 @@
3.7.0-dev
3.7.0

View File

@@ -72,6 +72,7 @@ function copyJsAndLibrary(projectPath, shared, projectName) {
shell.cp('-f', path.join(ROOT, 'framework', 'AndroidManifest.xml'), nestedCordovaLibPath);
shell.cp('-f', path.join(ROOT, 'framework', 'project.properties'), nestedCordovaLibPath);
shell.cp('-f', path.join(ROOT, 'framework', 'build.gradle'), nestedCordovaLibPath);
shell.cp('-f', path.join(ROOT, 'framework', 'cordova.gradle'), nestedCordovaLibPath);
shell.cp('-r', path.join(ROOT, 'framework', 'src'), nestedCordovaLibPath);
// Create an eclipse project file and set the name of it to something unique.
// Without this, you can't import multiple CordovaLib projects into the same workspace.
@@ -122,7 +123,6 @@ function copyBuildRules(projectPath) {
shell.cp('-f', path.join(srcDir, 'custom_rules.xml'), projectPath);
shell.cp('-f', path.join(srcDir, 'build.gradle'), projectPath);
shell.cp('-f', path.join(srcDir, 'cordova.gradle'), projectPath);
}
function copyScripts(projectPath) {

View File

@@ -69,11 +69,13 @@ function findOutputApksHelper(dir, build_type, arch) {
if (ret.length === 0) {
return ret;
}
// Assume arch-specific build if newest api has -x86 or -arm.
var archSpecific = !!/-x86|-arm/.exec(ret[0]);
// And show only arch-specific ones (or non-arch-specific)
ret = ret.filter(function(p) {
return !!/-x86|-arm/.exec(p) == archSpecific;
});
if (arch) {
if (arch && ret.length > 1) {
ret = ret.filter(function(p) {
return p.indexOf('-' + arch) != -1;
});
@@ -175,20 +177,16 @@ var builders = {
},
gradle: {
getArgs: function(cmd, arch, extraArgs) {
if (arch == 'arm' && cmd == 'debug') {
cmd = 'assembleArmv7Debug';
} else if (arch == 'arm' && cmd == 'release') {
cmd = 'assembleArmv7Release';
} else if (arch == 'x86' && cmd == 'debug') {
cmd = 'assembleX86Debug';
} else if (arch == 'x86' && cmd == 'release') {
cmd = 'assembleX86Release';
if (cmd == 'release') {
cmd = 'cdvBuildRelease';
} else if (cmd == 'debug') {
cmd = 'assembleDebug';
} else if (cmd == 'release') {
cmd = 'assembleRelease';
cmd = 'cdvBuildDebug';
}
var args = [cmd, '-b', path.join(ROOT, 'build.gradle')];
if (arch) {
args.push('-PcdvBuildArch=' + arch);
}
// 10 seconds -> 6 seconds
args.push('-Dorg.gradle.daemon=true');
args.push.apply(args, extraArgs);
@@ -260,7 +258,7 @@ var builders = {
var wrapper = path.join(ROOT, 'gradlew');
var args = this.getArgs(build_type == 'debug' ? 'debug' : 'release', arch, extraArgs);
return Q().then(function() {
console.log('Running: ' + wrapper + ' ' + extraArgs.join(' '));
console.log('Running: ' + wrapper + ' ' + args.concat(extraArgs).join(' '));
return spawn(wrapper, args);
});
},
@@ -270,7 +268,7 @@ var builders = {
var wrapper = path.join(ROOT, 'gradlew');
var args = builder.getArgs('clean', null, extraArgs);
return Q().then(function() {
console.log('Running: ' + wrapper + ' ' + extraArgs.join(' '));
console.log('Running: ' + wrapper + ' ' + args.concat(extraArgs).join(' '));
return spawn(wrapper, args);
});
},
@@ -319,8 +317,8 @@ function parseOpts(options, resolvedTarget) {
for (var i=0; options && (i < options.length); ++i) {
if (/^--/.exec(options[i])) {
var keyValue = options[i].substring(2).split('=');
var flagName = keyValue[0];
var flagValue = keyValue[1];
var flagName = keyValue.shift();
var flagValue = keyValue.join('=');
if (multiValueArgs[flagName] && !flagValue) {
flagValue = options[i + 1];
++i;
@@ -359,10 +357,7 @@ function parseOpts(options, resolvedTarget) {
}
}
var multiApk = ret.buildMethod == 'gradle' && process.env['BUILD_MULTIPLE_APKS'];
if (multiApk && !/0|false|no/i.exec(multiApk)) {
ret.arch = resolvedTarget && resolvedTarget.arch;
}
ret.arch = resolvedTarget && resolvedTarget.arch;
return ret;
}

View File

@@ -39,7 +39,7 @@ var path = require('path'),
var list = false;
for (var i=2; i<args.length; i++) {
if (/^--(debug|release|nobuild|versionCode=|minSdkVersion=|gradleArg=)/.exec(args[i])) {
if (/^--(debug|release|ant|gradle|nobuild|versionCode=|minSdkVersion=|gradleArg=)/.exec(args[i])) {
buildFlags.push(args[i]);
} else if (args[i] == '--device') {
install_target = '--device';
@@ -50,7 +50,7 @@ var path = require('path'),
} else if (args[i] == '--list') {
list = true;
} else {
console.warn('Option \'' + options[i] + '\' not recognized (ignoring).');
console.warn('Option \'' + args[i] + '\' not recognized (ignoring).');
}
}

View File

@@ -26,13 +26,15 @@ var isWindows = process.platform.slice(0, 3) == 'win';
// Takes a command and optional current working directory.
module.exports = function(cmd, args, opt_cwd) {
var d = Q.defer();
var opts = { cwd: opt_cwd, stdio: 'inherit' };
try {
// Work around spawn not being able to find .bat files.
if (isWindows) {
args.unshift('/s', '/c', cmd);
cmd = 'cmd';
args = [['/s', '/c', '"' + [cmd].concat(args).map(function(a){if (/^[^"].* .*[^"]/.test(a)) return '"' + a + '"'; return a;}).join(' ')+'"'].join(' ')];
cmd = 'cmd';
opts.windowsVerbatimArguments = true;
}
var child = child_process.spawn(cmd, args, {cwd: opt_cwd, stdio: 'inherit'});
var child = child_process.spawn(cmd, args, opts);
child.on('exit', function(code) {
if (code) {
d.reject('Error code ' + code + ' for command: ' + cmd + ' with args: ' + args);
@@ -45,5 +47,4 @@ module.exports = function(cmd, args, opt_cwd) {
d.reject(e);
}
return d.promise;
}
};

View File

@@ -20,6 +20,6 @@
*/
// Coho updates this line:
var VERSION = "3.7.0-dev";
var VERSION = "3.7.0";
console.log(VERSION);

View File

@@ -57,14 +57,14 @@ task wrapper(type: Wrapper) {
// 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: 'cordova.gradle'
apply from: 'CordovaLib/cordova.gradle'
// The value for android.compileSdkVersion.
if (!project.hasProperty('cdvCompileSdkVersion')) {
cdvCompileSdkVersion = privateHelpers.getProjectTarget('android-19')
cdvCompileSdkVersion = privateHelpers.getProjectTarget()
}
// The value for android.buildToolsVersion.
if (!project.hasProperty('cdvBuildToolsVersion')) {
cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools('19.1.0')
cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
}
// Sets the versionCode to the given value.
if (!project.hasProperty('cdvVersionCode')) {
@@ -86,6 +86,10 @@ ext {
if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
cdvDebugSigningPropertiesFile = null
}
// Set by build.js script.
if (!project.hasProperty('cdvBuildArch')) {
cdvBuildArch = null
}
}
def hasBuildExtras = file('build-extras.gradle').exists()
@@ -93,6 +97,44 @@ if (hasBuildExtras) {
apply from: 'build-extras.gradle'
}
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('cdvMinSdkVersion=' + cdvMinSdkVersion)
println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
println('cdvBuildArch=' + cdvBuildArch)
println('computedVersionCode=' + android.defaultConfig.versionCode)
if (android.productFlavors.has('armv7')) {
println('computedArmv7VersionCode=' + android.productFlavors.armv7.versionCode)
}
if (android.productFlavors.has('x86')) {
println('computedx86VersionCode=' + android.productFlavors.x86.versionCode)
}
}
// PLUGIN GRADLE EXTENSIONS START
// PLUGIN GRADLE EXTENSIONS END
@@ -207,27 +249,20 @@ gradle.taskGraph.whenReady { taskGraph ->
}
}
def ensureValueExists(filePath, props, key) {
if (props.get(key) == null) {
throw new GradleException(filePath + ': Missing key required "' + key + '"')
}
return props.get(key)
}
def addSigningProps(propsFilePath, signingConfig) {
def propsFile = file(propsFilePath)
def props = new Properties()
propsFile.withReader { reader ->
props.load(reader)
}
def storeFile = new File(ensureValueExists(propsFilePath, props, 'storeFile'))
def storeFile = new File(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 = ensureValueExists(propsFilePath, props, 'keyAlias')
signingConfig.keyAlias = privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
signingConfig.keyPassword = props.get('keyPassword', signingConfig.keyPassword)
signingConfig.storeFile = storeFile
signingConfig.storePassword = props.get('storePassword', signingConfig.storePassword)

View File

@@ -1,5 +1,5 @@
// Platform: android
// ee7b91f28e3780afb44222a2d950ccc1bebd0b87
// 24ab6855470f2dc0662624b597c98585e56a1666
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -19,7 +19,7 @@
under the License.
*/
;(function() {
var PLATFORM_VERSION_BUILD_LABEL = '3.7.0-dev';
var PLATFORM_VERSION_BUILD_LABEL = '3.7.0';
// file: src/scripts/require.js
/*jshint -W079 */

View File

@@ -23,23 +23,21 @@ buildscript {
mavenCentral()
}
dependencies {
// 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.2") {
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0+'
}
} else 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+'
}
// 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.2") {
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0+'
}
} else 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

@@ -20,16 +20,19 @@
import java.util.regex.Pattern
import groovy.swing.SwingBuilder
String getProjectTarget(String defaultTarget) {
def manifestFile = file("project.properties")
def pattern = Pattern.compile("target\\s*=\\s*(.*)")
def matcher = pattern.matcher(manifestFile.getText())
if (matcher.find()) {
matcher.group(1)
} else {
defaultTarget
String doEnsureValueExists(filePath, props, key) {
if (props.get(key) == null) {
throw new GradleException(filePath + ': Missing key required "' + key + '"')
}
return props.get(key)
}
String doGetProjectTarget() {
def props = new Properties()
file('project.properties').withReader { reader ->
props.load(reader)
}
return doEnsureValueExists('project.properties', props, 'target')
}
String[] getAvailableBuildTools() {
@@ -39,7 +42,7 @@ String[] getAvailableBuildTools() {
.sort { a, b -> compareVersions(b, a) }
}
String findLatestInstalledBuildTools(String minBuildToolsVersion) {
String doFindLatestInstalledBuildTools(String minBuildToolsVersion) {
def availableBuildToolsVersions
try {
availableBuildToolsVersions = getAvailableBuildTools()
@@ -117,7 +120,7 @@ String getAndroidSdkDir() {
androidSdkDir
}
def extractIntFromManifest(name) {
def doExtractIntFromManifest(name) {
def manifestFile = file(android.sourceSets.main.manifest.srcFile)
def pattern = Pattern.compile(name + "=\"(\\d+)\"")
def matcher = pattern.matcher(manifestFile.getText())
@@ -125,7 +128,7 @@ def extractIntFromManifest(name) {
return Integer.parseInt(matcher.group(1))
}
def promptForPassword(msg) {
def doPromptForPassword(msg) {
if (System.console() == null) {
def ret = null
new SwingBuilder().edt {
@@ -153,9 +156,10 @@ def promptForPassword(msg) {
ext {
// These helpers are shared, but are not guaranteed to be stable / unchanged.
privateHelpers = {}
privateHelpers.getProjectTarget = { defaultValue -> getProjectTarget(defaultValue) }
privateHelpers.findLatestInstalledBuildTools = { defaultValue -> findLatestInstalledBuildTools(defaultValue) }
privateHelpers.extractIntFromManifest = { name -> extractIntFromManifest(name) }
privateHelpers.promptForPassword = { msg -> promptForPassword(msg) }
privateHelpers.getProjectTarget = { doGetProjectTarget() }
privateHelpers.findLatestInstalledBuildTools = { doFindLatestInstalledBuildTools('19.1.0') }
privateHelpers.extractIntFromManifest = { name -> doExtractIntFromManifest(name) }
privateHelpers.promptForPassword = { msg -> doPromptForPassword(msg) }
privateHelpers.ensureValueExists = { filePath, props, key -> doEnsureValueExists(filePath, props, key) }
}

View File

@@ -36,7 +36,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
@@ -48,7 +47,6 @@ import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.ValueCallback;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
@@ -103,7 +101,8 @@ public class CordovaActivity extends Activity implements CordovaInterface {
private int activityState = 0; // 0=starting, 1=running (after 1st resume), 2=shutting down
// Plugin to call when activity result is received
protected CordovaPlugin activityResultCallback = null;
protected int activityResultRequestCode;
protected CordovaPlugin activityResultCallback;
protected boolean activityResultKeepRunning;
/*
@@ -666,7 +665,7 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* @param requestCode The request code that is passed to callback to identify the activity
*/
public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
this.activityResultCallback = command;
setActivityResultCallback(command);
this.activityResultKeepRunning = this.keepRunning;
// If multitasking turned on, then disable it for activities that return results
@@ -674,8 +673,19 @@ public class CordovaActivity extends Activity implements CordovaInterface {
this.keepRunning = false;
}
// Start activity
super.startActivityForResult(intent, requestCode);
try {
startActivityForResult(intent, requestCode);
} catch (RuntimeException e) { // E.g.: ActivityNotFoundException
activityResultCallback = null;
throw e;
}
}
@Override
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
// Capture requestCode here so that it is captured in the setActivityResultCallback() case.
activityResultRequestCode = requestCode;
super.startActivityForResult(intent, requestCode, options);
}
/**
@@ -685,37 +695,34 @@ public class CordovaActivity extends Activity implements CordovaInterface {
* @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 data An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
* @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");
LOG.d(TAG, "Incoming Result. Request code = " + requestCode);
super.onActivityResult(requestCode, resultCode, intent);
Log.d(TAG, "Request code = " + requestCode);
if (appView != null && requestCode == CordovaChromeClient.FILECHOOSER_RESULTCODE) {
ValueCallback<Uri> mUploadMessage = this.appView.getWebChromeClient().getValueCallback();
Log.d(TAG, "did we get here?");
if (null == mUploadMessage)
return;
Uri result = intent == null || resultCode != Activity.RESULT_OK ? null : intent.getData();
Log.d(TAG, "result = " + result);
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
CordovaPlugin callback = this.activityResultCallback;
if(callback == null && initCallbackClass != null) {
// The application was restarted, but had defined an initial callback
// before being shut down.
this.activityResultCallback = appView.pluginManager.getPlugin(initCallbackClass);
callback = this.activityResultCallback;
callback = appView.pluginManager.getPlugin(initCallbackClass);
}
if(callback != null) {
initCallbackClass = null;
activityResultCallback = null;
if (callback != null) {
LOG.d(TAG, "We have a callback to send this result to");
callback.onActivityResult(requestCode, resultCode, intent);
} else {
LOG.w(TAG, "Got an activity result, but no plugin was registered to receive it.");
}
}
public void setActivityResultCallback(CordovaPlugin plugin) {
// Cancel any previously pending activity.
if (activityResultCallback != null) {
activityResultCallback.onActivityResult(activityResultRequestCode, Activity.RESULT_CANCELED, null);
}
this.activityResultCallback = plugin;
}

View File

@@ -22,10 +22,14 @@ import org.apache.cordova.CordovaInterface;
import org.apache.cordova.LOG;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
@@ -67,10 +71,7 @@ public class CordovaChromeClient extends WebChromeClient {
//Keep track of last AlertDialog showed
private AlertDialog lastHandledDialog;
// File Chooser
public ValueCallback<Uri> mUploadMessage;
@Deprecated
public CordovaChromeClient(CordovaInterface cordova) {
this.cordova = cordova;
@@ -309,7 +310,10 @@ public class CordovaChromeClient extends WebChromeClient {
}
return mVideoProgressView;
}
// <input type=file> 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<Uri> uploadMsg) {
this.openFileChooser(uploadMsg, "*/*");
}
@@ -318,20 +322,41 @@ public class CordovaChromeClient extends WebChromeClient {
this.openFileChooser(uploadMsg, acceptType, null);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture)
public void openFileChooser(final ValueCallback<Uri> uploadMsg, String acceptType, String capture)
{
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
this.cordova.getActivity().startActivityForResult(Intent.createChooser(i, "File Browser"),
FILECHOOSER_RESULTCODE);
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
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(TAG, "Receive file chooser URL: " + result);
uploadMsg.onReceiveValue(result);
}
}, intent, FILECHOOSER_RESULTCODE);
}
public ValueCallback<Uri> getValueCallback() {
return this.mUploadMessage;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onShowFileChooser(WebView webView, final ValueCallback<Uri[]> filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) {
Intent intent = fileChooserParams.createIntent();
try {
cordova.startActivityForResult(new CordovaPlugin() {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
Uri[] result = WebChromeClient.FileChooserParams.parseResult(resultCode, intent);
Log.d(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;
}
public void destroyLastDialog(){
if(lastHandledDialog != null){
lastHandledDialog.cancel();

View File

@@ -0,0 +1,96 @@
/*
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.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
*/
public void cancel()
{
request.cancel();
}
/*
* Returns the host name of the server requesting the certificate.
*/
public String getHost()
{
return request.getHost();
}
/*
* Returns the acceptable types of asymmetric keys (can be null).
*/
public String[] getKeyTypes()
{
return request.getKeyTypes();
}
/*
* Returns the port number of the server requesting the certificate.
*/
public int getPort()
{
return request.getPort();
}
/*
* Returns the acceptable certificate issuers for the certificate matching the private key (can be null).
*/
public Principal[] getPrincipals()
{
return request.getPrincipals();
}
/*
* Ignore the request for now. Do not remember user's choice.
*/
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
*/
public void proceed(PrivateKey privateKey, X509Certificate[] chain)
{
request.proceed(privateKey, chain);
}
}

View File

@@ -0,0 +1,51 @@
/*
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);
}
}

View File

@@ -198,4 +198,34 @@ public class CordovaPlugin {
*/
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;
}
}

View File

@@ -62,7 +62,7 @@ import android.widget.FrameLayout;
public class CordovaWebView extends WebView {
public static final String TAG = "CordovaWebView";
public static final String CORDOVA_VERSION = "3.7.0-dev";
public static final String CORDOVA_VERSION = "3.7.0";
private HashSet<Integer> boundKeyCodes = new HashSet<Integer>();
@@ -454,7 +454,7 @@ public class CordovaWebView extends WebView {
if (LOG.isLoggable(LOG.DEBUG) && !url.startsWith("javascript:")) {
LOG.d(TAG, ">>> loadUrlNow()");
}
if (url.startsWith("file://") || url.startsWith("javascript:") || internalWhitelist.isUrlWhiteListed(url)) {
if (url.startsWith("file://") || url.startsWith("javascript:") || url.startsWith("about:") || internalWhitelist.isUrlWhiteListed(url)) {
super.loadUrl(url);
}
}

View File

@@ -21,7 +21,6 @@ package org.apache.cordova;
import java.util.Hashtable;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.LOG;
import org.json.JSONException;
import org.json.JSONObject;
@@ -33,6 +32,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.net.http.SslError;
import android.view.View;
import android.webkit.ClientCertRequest;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
@@ -115,15 +115,45 @@ public class CordovaWebViewClient extends WebViewClient {
@Override
public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm) {
// Get the authentication token
// Get the authentication token (if specified)
AuthenticationToken token = this.getAuthenticationToken(host, realm);
if (token != null) {
handler.proceed(token.getUserName(), token.getPassword());
return;
}
else {
// Handle 401 like we'd normally do!
super.onReceivedHttpAuthRequest(view, handler, host, realm);
// Check if there is some plugin which can resolve this auth challenge
PluginManager pluginManager = this.appView.pluginManager;
if (pluginManager != null && pluginManager.onReceivedHttpAuthRequest(this.appView, new CordovaHttpAuthHandler(handler), host, realm)) {
this.appView.loadUrlTimeout++;
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(21)
public void onReceivedClientCertRequest (WebView view, ClientCertRequest request)
{
// Check if there is some plugin which can resolve this certificate request
PluginManager pluginManager = this.appView.pluginManager;
if (pluginManager != null && pluginManager.onReceivedClientCertRequest(this.appView, new CordovaClientCertRequest(request))) {
this.appView.loadUrlTimeout++;
return;
}
// By default pass to WebViewClient
super.onReceivedClientCertRequest(view, request);
}
/**
@@ -163,8 +193,8 @@ public class CordovaWebViewClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// Ignore excessive calls.
if (!isCurrentlyLoading) {
// Ignore excessive calls, if url is not about:blank (CB-8317).
if (!isCurrentlyLoading && !url.startsWith("about:")) {
return;
}
isCurrentlyLoading = false;

View File

@@ -0,0 +1,66 @@
/*
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);
}

View File

@@ -0,0 +1,38 @@
/*
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);
}

View File

@@ -242,6 +242,46 @@ public class PluginManager {
}
}
/**
* 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(view, 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(view, request)) {
return true;
}
}
return false;
}
/**
* Called when the activity will start interacting with the user.
*

View File

@@ -63,7 +63,7 @@ public class SplashScreenInternal extends CordovaPlugin {
firstShow = false;
loadSpinner();
showSplashScreen();
showSplashScreen(true);
}
@Override
@@ -115,7 +115,7 @@ public class SplashScreenInternal extends CordovaPlugin {
if ("hide".equals(data.toString())) {
this.removeSplashScreen();
} else {
this.showSplashScreen();
this.showSplashScreen(false);
}
} else if ("spinner".equals(id)) {
if ("stop".equals(data.toString())) {
@@ -143,7 +143,7 @@ public class SplashScreenInternal extends CordovaPlugin {
* Shows the splash screen over the full Activity
*/
@SuppressWarnings("deprecation")
private void showSplashScreen() {
private void showSplashScreen(final boolean hideAfterDelay) {
final int splashscreenTime = preferences.getInteger("SplashScreenDelay", 3000);
final int drawableId = preferences.getInteger("SplashDrawableId", 0);
@@ -151,7 +151,7 @@ public class SplashScreenInternal extends CordovaPlugin {
if (this.splashDialog != null && splashDialog.isShowing()) {
return;
}
if (drawableId == 0 || splashscreenTime <= 0) {
if (drawableId == 0 || (splashscreenTime <= 0 && hideAfterDelay)) {
return;
}
@@ -187,12 +187,14 @@ public class SplashScreenInternal extends CordovaPlugin {
splashDialog.show();
// Set Runnable to remove splash screen just in case
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
removeSplashScreen();
}
}, splashscreenTime);
if (hideAfterDelay) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
removeSplashScreen();
}
}, splashscreenTime);
}
}
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "cordova-android",
"version": "3.7.0-dev",
"version": "3.7.0",
"description": "cordova-android release",
"main": "bin/create",
"repository": {