diff --git a/bin/templates/cordova/lib/pluginHandlers.js b/bin/templates/cordova/lib/pluginHandlers.js index a3ebed0e..aaee3b3e 100644 --- a/bin/templates/cordova/lib/pluginHandlers.js +++ b/bin/templates/cordova/lib/pluginHandlers.js @@ -34,7 +34,7 @@ var handlers = { // a later plugins release. This is for legacy plugins to work with Cordova. if (options && options.android_studio === true) { - dest = studioPathRemap(obj); + dest = getInstallDestination(obj); } if (options && options.force) { @@ -47,7 +47,7 @@ var handlers = { var dest = path.join(obj.targetDir, path.basename(obj.src)); if (options && options.android_studio === true) { - dest = studioPathRemap(obj); + dest = getInstallDestination(obj); } // TODO: Add Koltin extension to uninstall, since they are handled like Java files @@ -317,15 +317,29 @@ 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)); +function getInstallDestination (obj) { + var APP_MAIN_PREFIX = 'app/src/main'; + + if (obj.targetDir.includes('app')) { + // If any source file is using the new app directory structure, + // don't penalize it + return path.join(obj.targetDir, path.basename(obj.src)); + } else if (obj.src.endsWith('.java')) { + return path.join(APP_MAIN_PREFIX, 'java', obj.targetDir.substring(4), path.basename(obj.src)); + } else if (obj.src.endsWith('.aidl')) { + return path.join(APP_MAIN_PREFIX, 'aidl', obj.targetDir.substring(4), path.basename(obj.src)); + } else if (obj.targetDir.includes('libs')) { + if (obj.src.endsWith('.so')) { + return path.join(APP_MAIN_PREFIX, 'jniLibs', obj.targetDir.substring(5), 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)); + return path.join('app', obj.targetDir, path.basename(obj.src)); } + } else if (obj.targetDir.includes('src/main')) { + return path.join('app', obj.targetDir, path.basename(obj.src)); + } else { + // For all other source files not using the new app directory structure, + // add 'app/src/main' to the targetDir + return path.join(APP_MAIN_PREFIX, obj.targetDir, path.basename(obj.src)); } } diff --git a/bin/templates/project/app/build.gradle b/bin/templates/project/app/build.gradle index b47fdf94..4830dd93 100644 --- a/bin/templates/project/app/build.gradle +++ b/bin/templates/project/app/build.gradle @@ -69,7 +69,7 @@ ext { if (!project.hasProperty('cdvBuildMultipleApks')) { cdvBuildMultipleApks = null } - // Whether to append a 0 "abi digit" to versionCode when only a single APK is build + // Whether to append a 0 "abi digit" to versionCode when only a single APK is build if (!project.hasProperty('cdvVersionCodeForceAbiDigit')) { cdvVersionCodeForceAbiDigit = null } @@ -93,11 +93,16 @@ ext { // PLUGIN GRADLE EXTENSIONS START // PLUGIN GRADLE EXTENSIONS END -def hasBuildExtras = file('build-extras.gradle').exists() -if (hasBuildExtras) { +def hasBuildExtras1 = file('build-extras.gradle').exists() +if (hasBuildExtras1) { apply from: 'build-extras.gradle' } +def hasBuildExtras2 = file('../build-extras.gradle').exists() +if (hasBuildExtras2) { + apply from: '../build-extras.gradle' +} + // Set property defaults after extension .gradle files. if (ext.cdvCompileSdkVersion == null) { ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget() @@ -117,7 +122,7 @@ if (ext.cdvReleaseSigningPropertiesFile == null && file('../release-signing.prop // 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.cdvMinSdkVersion = cdvMinSdkVersion == null ? defaultMinSdkVersion : Integer.parseInt('' + cdvMinSdkVersion) ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode) def computeBuildTargetName(debugBuild) { @@ -174,10 +179,11 @@ android { 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. + // 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" diff --git a/cordova-js-src/exec.js b/cordova-js-src/exec.js index f73d87a1..39e8c97e 100644 --- a/cordova-js-src/exec.js +++ b/cordova-js-src/exec.js @@ -109,17 +109,6 @@ function androidExec(success, fail, service, action, args) { } 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(); }; diff --git a/spec/fixtures/org.test.plugins.dummyplugin/plugin.xml b/spec/fixtures/org.test.plugins.dummyplugin/plugin.xml index a40df2b2..4e2ebcc6 100644 --- a/spec/fixtures/org.test.plugins.dummyplugin/plugin.xml +++ b/spec/fixtures/org.test.plugins.dummyplugin/plugin.xml @@ -70,6 +70,18 @@ + + + + + + + + + diff --git a/spec/fixtures/org.test.plugins.dummyplugin/src/android/DummyPlugin2.java b/spec/fixtures/org.test.plugins.dummyplugin/src/android/DummyPlugin2.java new file mode 100644 index 00000000..c2dd0f73 --- /dev/null +++ b/spec/fixtures/org.test.plugins.dummyplugin/src/android/DummyPlugin2.java @@ -0,0 +1 @@ +./org.test.plugins.dummyplugin/src/android/DummyPlugin2.java diff --git a/spec/fixtures/org.test.plugins.dummyplugin/src/android/TestAar.aar b/spec/fixtures/org.test.plugins.dummyplugin/src/android/TestAar.aar new file mode 100644 index 00000000..ce401543 --- /dev/null +++ b/spec/fixtures/org.test.plugins.dummyplugin/src/android/TestAar.aar @@ -0,0 +1 @@ +./org.test.plugins.dummyplugin/src/android/TestAar.aar diff --git a/spec/fixtures/org.test.plugins.dummyplugin/src/android/jniLibs/x86/libnative.so b/spec/fixtures/org.test.plugins.dummyplugin/src/android/jniLibs/x86/libnative.so new file mode 100644 index 00000000..421376db --- /dev/null +++ b/spec/fixtures/org.test.plugins.dummyplugin/src/android/jniLibs/x86/libnative.so @@ -0,0 +1 @@ +dummy diff --git a/spec/fixtures/org.test.plugins.dummyplugin/src/android/myapi.aidl b/spec/fixtures/org.test.plugins.dummyplugin/src/android/myapi.aidl new file mode 100644 index 00000000..421376db --- /dev/null +++ b/spec/fixtures/org.test.plugins.dummyplugin/src/android/myapi.aidl @@ -0,0 +1 @@ +dummy diff --git a/spec/fixtures/org.test.plugins.dummyplugin/src/android/mysettings.xml b/spec/fixtures/org.test.plugins.dummyplugin/src/android/mysettings.xml new file mode 100644 index 00000000..421376db --- /dev/null +++ b/spec/fixtures/org.test.plugins.dummyplugin/src/android/mysettings.xml @@ -0,0 +1 @@ +dummy diff --git a/spec/fixtures/org.test.plugins.dummyplugin/src/android/other.extension b/spec/fixtures/org.test.plugins.dummyplugin/src/android/other.extension new file mode 100644 index 00000000..421376db --- /dev/null +++ b/spec/fixtures/org.test.plugins.dummyplugin/src/android/other.extension @@ -0,0 +1 @@ +dummy diff --git a/spec/fixtures/org.test.plugins.dummyplugin/src/android/testaar2.aar b/spec/fixtures/org.test.plugins.dummyplugin/src/android/testaar2.aar new file mode 100644 index 00000000..421376db --- /dev/null +++ b/spec/fixtures/org.test.plugins.dummyplugin/src/android/testaar2.aar @@ -0,0 +1 @@ +dummy diff --git a/spec/fixtures/org.test.plugins.dummyplugin/src/android/testjar2.jar b/spec/fixtures/org.test.plugins.dummyplugin/src/android/testjar2.jar new file mode 100644 index 00000000..421376db Binary files /dev/null and b/spec/fixtures/org.test.plugins.dummyplugin/src/android/testjar2.jar differ diff --git a/spec/unit/pluginHandlers/handlers.spec.js b/spec/unit/pluginHandlers/handlers.spec.js index edc8f43b..97e77dce 100644 --- a/spec/unit/pluginHandlers/handlers.spec.js +++ b/spec/unit/pluginHandlers/handlers.spec.js @@ -108,6 +108,67 @@ describe('android project handler', function () { android['source-file'].install(valid_source[0], dummyPluginInfo, dummyProject); }).toThrow(new Error('"' + target + '" already exists!')); }); + + // TODO: renumber these tests and other tests below + it('Test#00a6 : should allow installing sources with new app target-dir scheme', function () { + android['source-file'].install(valid_source[1], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(copyFileSpy) + .toHaveBeenCalledWith(dummyplugin, 'src/android/DummyPlugin2.java', temp, path.join('app/src/main/src/com/phonegap/plugins/dummyplugin/DummyPlugin2.java'), false); + }); + + it('Test#006b : should allow installing jar lib file from sources with new app target-dir scheme', function () { + android['source-file'].install(valid_source[2], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(copyFileSpy) + .toHaveBeenCalledWith(dummyplugin, 'src/android/TestLib.jar', temp, path.join('app/libs/TestLib.jar'), false); + }); + + it('Test#006c : should allow installing aar lib file from sources with new app target-dir scheme', function () { + android['source-file'].install(valid_source[3], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(copyFileSpy) + .toHaveBeenCalledWith(dummyplugin, 'src/android/TestAar.aar', temp, path.join('app/libs/TestAar.aar'), false); + }); + + it('Test#006d : should allow installing xml file from sources with old target-dir scheme', function () { + android['source-file'].install(valid_source[4], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, + 'src/android/mysettings.xml', temp, + path.join('app/src/main/res/xml/mysettings.xml'), false); + }); + + it('Test#006e : should allow installing file with other extension from sources with old target-dir scheme', function () { + android['source-file'].install(valid_source[5], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, + 'src/android/other.extension', temp, + path.join('app/src/main/res/values/other.extension'), false); + }); + + it('Test#006f : should allow installing aidl file from sources with old target-dir scheme (GH-547)', function () { + android['source-file'].install(valid_source[6], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, + 'src/android/myapi.aidl', temp, + path.join('app/src/main/aidl/com/mytest/myapi.aidl'), false); + }); + + it('Test#006g : should allow installing aar lib file from sources with old target-dir scheme (GH-547)', function () { + android['source-file'].install(valid_source[7], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, + 'src/android/testaar2.aar', temp, + path.join('app/libs/testaar2.aar'), false); + }); + + it('Test#006h : should allow installing jar lib file from sources with old target-dir scheme (GH-547)', function () { + android['source-file'].install(valid_source[8], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, + 'src/android/testjar2.jar', temp, + path.join('app/libs/testjar2.jar'), false); + }); + + it('Test#006i : should allow installing .so lib file from sources with old target-dir scheme (GH-547)', function () { + android['source-file'].install(valid_source[9], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(copyFileSpy).toHaveBeenCalledWith(dummyplugin, + 'src/android/jniLibs/x86/libnative.so', temp, + path.join('app/src/main/jniLibs/x86/libnative.so'), false); + }); }); describe('of elements', function () { @@ -263,6 +324,60 @@ describe('android project handler', function () { android['source-file'].uninstall(valid_source[0], dummyPluginInfo, dummyProject, {android_studio: true}); expect(deleteJavaSpy).toHaveBeenCalledWith(temp, path.join('app/src/main/java/com/phonegap/plugins/dummyplugin/DummyPlugin.java')); }); + + it('Test#019a : should remove stuff by calling common.deleteJava for Android Studio projects, with specific app target-dir', function () { + android['source-file'].install(valid_source[1], dummyPluginInfo, dummyProject, {android_studio: true}); + android['source-file'].uninstall(valid_source[1], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(deleteJavaSpy).toHaveBeenCalledWith(temp, path.join('app/src/main/src/com/phonegap/plugins/dummyplugin/DummyPlugin2.java')); + }); + + it('Test#019b : should remove stuff by calling common.removeFile for Android Studio projects, of jar with new app target-dir scheme', function () { + android['source-file'].install(valid_source[2], dummyPluginInfo, dummyProject, {android_studio: true}); + android['source-file'].uninstall(valid_source[2], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/libs/TestLib.jar')); + }); + + it('Test#019c : should remove stuff by calling common.removeFile for Android Studio projects, of aar with new app target-dir scheme', function () { + android['source-file'].install(valid_source[3], dummyPluginInfo, dummyProject, {android_studio: true}); + android['source-file'].uninstall(valid_source[3], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/libs/TestAar.aar')); + }); + + it('Test#019d : should remove stuff by calling common.removeFile for Android Studio projects, of xml with old target-dir scheme', function () { + android['source-file'].install(valid_source[4], dummyPluginInfo, dummyProject, {android_studio: true}); + android['source-file'].uninstall(valid_source[4], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/src/main/res/xml/mysettings.xml')); + }); + + it('Test#019e : should remove stuff by calling common.removeFile for Android Studio projects, of file with other extension with old target-dir scheme', function () { + android['source-file'].install(valid_source[5], dummyPluginInfo, dummyProject, {android_studio: true}); + android['source-file'].uninstall(valid_source[5], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/src/main/res/values/other.extension')); + }); + + it('Test#019f : should remove stuff by calling common.removeFile for Android Studio projects, of aidl with old target-dir scheme (GH-547)', function () { + android['source-file'].install(valid_source[6], dummyPluginInfo, dummyProject, {android_studio: true}); + android['source-file'].uninstall(valid_source[6], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/src/main/aidl/com/mytest/myapi.aidl')); + }); + + it('Test#019g : should remove stuff by calling common.removeFile for Android Studio projects, of aar with old target-dir scheme (GH-547)', function () { + android['source-file'].install(valid_source[7], dummyPluginInfo, dummyProject, {android_studio: true}); + android['source-file'].uninstall(valid_source[7], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/libs/testaar2.aar')); + }); + + it('Test#019h : should remove stuff by calling common.removeFile for Android Studio projects, of jar with old target-dir scheme (GH-547)', function () { + android['source-file'].install(valid_source[8], dummyPluginInfo, dummyProject, {android_studio: true}); + android['source-file'].uninstall(valid_source[8], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/libs/testjar2.jar')); + }); + + it('Test#019i : should remove stuff by calling common.removeFile for Android Studio projects, of .so lib file with old target-dir scheme (GH-547)', function () { + android['source-file'].install(valid_source[9], dummyPluginInfo, dummyProject, {android_studio: true}); + android['source-file'].uninstall(valid_source[9], dummyPluginInfo, dummyProject, {android_studio: true}); + expect(removeFileSpy).toHaveBeenCalledWith(temp, path.join('app/src/main/jniLibs/x86/libnative.so')); + }); }); describe('of elements', function () {