Skip to content

Commit

Permalink
Quick fix to use SDK versions from AndroidManifest
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher J. Brody committed Jan 21, 2019
1 parent 715ce2f commit c386f2d
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 17 deletions.
47 changes: 41 additions & 6 deletions bin/templates/cordova/lib/builders/ProjectBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,29 @@ class ProjectBuilder {
};
}

extractRealProjectNameFromManifest () {
getAndroidManifestInfo () {
var manifestPath = path.join(this.root, 'app', 'src', 'main', 'AndroidManifest.xml');
var manifestData = fs.readFileSync(manifestPath, 'utf8');
var m = /<manifest[\s\S]*?package\s*=\s*"(.*?)"/i.exec(manifestData);
if (!m) {
throw new CordovaError('Could not find package name in ' + manifestPath);
}

var packageName = m[1];
var lastDotIndex = packageName.lastIndexOf('.');
return packageName.substring(lastDotIndex + 1);
const m2 = /<uses-sdk[\s\S]*?android:minSdkVersion\s*=\s*"(.*?)"/i.exec(manifestData);
if (!m2) {
throw new CordovaError('Could not find android:minSdkVersion in ' + manifestPath);
}

const m3 = /<uses-sdk[\s\S]*?android:targetSdkVersion\s*=\s*"(.*?)"/i.exec(manifestData);
if (!m3) {
throw new CordovaError('Could not find android:targetSdkVersion in ' + manifestPath);
}

return {
packageName: m[1],
minSdkVersion: parseInt(m2[1], 10),
targetSdkVersion: parseInt(m3[1], 10)
};
}

// Makes the project buildable, minus the gradle wrapper.
Expand Down Expand Up @@ -128,7 +140,13 @@ class ProjectBuilder {
checkAndCopy(subProjects[i], this.root);
}
}
var name = this.extractRealProjectNameFromManifest();

const androidManifestInfo = this.getAndroidManifestInfo();

const packageName = androidManifestInfo.packageName;
const lastDotIndex = packageName.lastIndexOf('.');
const name = packageName.substring(lastDotIndex + 1);

// Remove the proj.id/name- prefix from projects: https://issues.apache.org/jira/browse/CB-9149
var settingsGradlePaths = subProjects.map(function (p) {
var realDir = p.replace(/[/\\]/g, ':');
Expand All @@ -144,7 +162,24 @@ class ProjectBuilder {
'// GENERATED FILE - DO NOT EDIT\n' +
'include ":"\n' + settingsGradlePaths.join(''));

// Update dependencies within build.gradle.
// Update SDK versions within root build.gradle - quick fix:
let rootGradle = fs.readFileSync(path.join(this.root, 'build.gradle'), 'utf8');
rootGradle = rootGradle.replace(
/(defaultMinSdkVersion)\s*=\s*\d+\s*\/\//,
'$1=' + androidManifestInfo.minSdkVersion + ' //');
// Note that we are using the configured targetSdkVersion
// to update both defaultCompileSdkVersion and
// defaultTargetSdkVersion in the root build.gradle
rootGradle = rootGradle.replace(
/(defaultTargetSdkVersion)\s*=\s*\d+\s*\/\//,
'$1=' + androidManifestInfo.targetSdkVersion + ' //');
rootGradle = rootGradle.replace(
/(defaultCompileSdkVersion)\s*=\s*\d+\s*\/\//,
'$1=' + androidManifestInfo.targetSdkVersion + ' //');
// and store it (in the root grade):
fs.writeFileSync(path.join(this.root, 'build.gradle'), rootGradle);

// Update dependencies within app/build.gradle.
var buildGradle = fs.readFileSync(path.join(this.root, 'app', 'build.gradle'), 'utf8');
var depsList = '';
var root = this.root;
Expand Down
10 changes: 10 additions & 0 deletions bin/templates/project/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ if (hasBuildExtras2) {
apply from: '../build-extras.gradle'
}

// Needed for quick fix below:
def customCompileSdkVersion = cdvCompileSdkVersion;

// Set property defaults after extension .gradle files.
if (ext.cdvCompileSdkVersion == null) {
ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget()
Expand All @@ -124,6 +127,10 @@ ext.cdvVersionCodeForceAbiDigit = cdvVersionCodeForceAbiDigit == null ? false :
ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? defaultMinSdkVersion : Integer.parseInt('' + cdvMinSdkVersion)
ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)

// Quick fix:
def appTargetSdkVersion =
(customCompileSdkVersion == null) ? defaultTargetSdkVersion : Integer.parseInt('' + cdvCompileSdkVersion)

def computeBuildTargetName(debugBuild) {
def ret = 'assemble'
if (cdvBuildMultipleApks && cdvBuildArch) {
Expand Down Expand Up @@ -170,6 +177,9 @@ android {
if (cdvMinSdkVersion != null) {
minSdkVersion cdvMinSdkVersion
}

// Quick fix:
targetSdkVersion appTargetSdkVersion
}

lintOptions {
Expand Down
6 changes: 3 additions & 3 deletions bin/templates/project/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ allprojects {
//This replaces project.properties w.r.t. build settings
project.ext {
defaultBuildToolsVersion="28.0.3" //String
defaultMinSdkVersion=19 //Integer - Minimum requirement is Android 4.4
defaultTargetSdkVersion=28 //Integer - We ALWAYS target the latest by default
defaultCompileSdkVersion=28 //Integer - We ALWAYS compile with the latest by default
defaultMinSdkVersion=19 //Integer - updated from app/AndroidManifest.xml, minimum requirement should be Android 4.4
defaultTargetSdkVersion=28 //Integer - updated from app/AndroidManifest.xml, should target the latest by default
defaultCompileSdkVersion=28 //Integer - updated from app/AndroidManifest.xml, should target the latest by default
}
}

Expand Down
64 changes: 56 additions & 8 deletions spec/unit/builders/ProjectBuilder.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,26 +88,74 @@ describe('ProjectBuilder', () => {
});
});

describe('extractRealProjectNameFromManifest', () => {
describe('getAndroidManifestInfo', () => {
it('should get the project name from the Android Manifest', () => {
const projectName = 'unittestproject';
const projectId = `io.cordova.${projectName}`;
const manifest = `<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="${projectId}"></manifest>`;
const manifest =
`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="${projectId}">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28"/>
</manifest>`;

spyOn(fs, 'readFileSync').and.returnValue(manifest);

expect(builder.extractRealProjectNameFromManifest()).toBe(projectName);
expect(builder.getAndroidManifestInfo().packageName).toBe(projectId);
});

it('should get the min & target SDK versions from the Android Manifest', () => {
const projectName = 'unittestproject';
const projectId = `io.cordova.${projectName}`;
const manifest =
`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="${projectId}">
<uses-sdk android:minSdkVersion="22" android:targetSdkVersion="25"/>
</manifest>`;

spyOn(fs, 'readFileSync').and.returnValue(manifest);

expect(builder.getAndroidManifestInfo().minSdkVersion).toBe(22);
expect(builder.getAndroidManifestInfo().targetSdkVersion).toBe(25);
});

it('should throw an error if there is no package in the Android manifest', () => {
const manifest = `<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"></manifest>`;
const manifest =
`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28"/>
</manifest>`;

spyOn(fs, 'readFileSync').and.returnValue(manifest);

expect(() => builder.getAndroidManifestInfo()).toThrow(jasmine.any(CordovaError));
});

it('should throw an error if there is no android:minSdkVersion in the Android manifest', () => {
const projectName = 'unittestproject';
const projectId = `io.cordova.${projectName}`;
const manifest =
`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="${projectId}">
<uses-sdk android:targetSdkVersion="25"/>
</manifest>`;

spyOn(fs, 'readFileSync').and.returnValue(manifest);

expect(() => builder.getAndroidManifestInfo()).toThrow(jasmine.any(CordovaError));
});

it('should throw an error if there is no android:targetSdkVersion in the Android manifest', () => {
const projectName = 'unittestproject';
const projectId = `io.cordova.${projectName}`;
const manifest =
`<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="${projectId}">
<uses-sdk android:minSdkVersion="19"/>
</manifest>`;

spyOn(fs, 'readFileSync').and.returnValue(manifest);

expect(() => builder.extractRealProjectNameFromManifest()).toThrow(jasmine.any(CordovaError));
expect(() => builder.getAndroidManifestInfo()).toThrow(jasmine.any(CordovaError));
});
});

Expand Down

0 comments on commit c386f2d

Please sign in to comment.