fix(android): move MainActivity.java to folder that tracks the app package name (widget id) (#1154)

* move mainactivity.java

* unit test for moving mainactivity.java

* fix new unit test

* eslint fixes

* add explicit elementtree npm dependency

Co-authored-by: David Wedgbury <david.wedgbury@telent.com>
This commit is contained in:
wedgberto 2022-05-18 15:11:31 +01:00 committed by GitHub
parent bd0c8ce639
commit cb494ff9b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 165 additions and 17 deletions

View File

@ -23,7 +23,6 @@ const nopt = require('nopt');
const glob = require('fast-glob');
const events = require('cordova-common').events;
const AndroidManifest = require('./AndroidManifest');
const checkReqs = require('./check_reqs');
const xmlHelpers = require('cordova-common').xmlHelpers;
const CordovaError = require('cordova-common').CordovaError;
const ConfigParser = require('cordova-common').ConfigParser;
@ -308,24 +307,20 @@ function updateProjectAccordingTo (platformConfig, locations) {
const destFile = java_files[0];
// var destFile = path.join(locations.root, 'app', 'src', 'main', 'java', androidPkgName.replace(/\./g, '/'), path.basename(java_files[0]));
// fs.ensureDirSync(path.dirname(destFile));
// events.emit('verbose', java_files[0]);
// events.emit('verbose', destFile);
// console.log(locations);
// fs.copySync(java_files[0], destFile);
utils.replaceFileContents(destFile, /package [\w.]*;/, 'package ' + androidPkgName + ';');
events.emit('verbose', 'Wrote out Android package name "' + androidPkgName + '" to ' + destFile);
const removeOrigPkg = checkReqs.isWindows() || checkReqs.isDarwin()
? manifestId.toUpperCase() !== androidPkgName.toUpperCase()
: manifestId !== androidPkgName;
if (removeOrigPkg) {
// if package name has changed, path to MainActivity.java has to track it
const newDestFile = path.join(locations.root, 'app', 'src', 'main', 'java', androidPkgName.replace(/\./g, '/'), path.basename(destFile));
if (newDestFile.toLowerCase() !== destFile.toLowerCase()) {
// If package was name changed we need to create new java with main activity in path matching new package name
fs.ensureDirSync(path.dirname(newDestFile));
events.emit('verbose', `copy ${destFile} to ${newDestFile}`);
fs.copySync(destFile, newDestFile);
utils.replaceFileContents(newDestFile, /package [\w.]*;/, 'package ' + androidPkgName + ';');
events.emit('verbose', 'Wrote out Android package name "' + androidPkgName + '" to ' + newDestFile);
// If package was name changed we need to remove old java with main activity
fs.removeSync(java_files[0]);
events.emit('verbose', `remove ${destFile}`);
fs.removeSync(destFile);
// remove any empty directories
let currentDir = path.dirname(java_files[0]);
let currentDir = path.dirname(destFile);
const sourcesRoot = path.resolve(locations.root, 'src');
while (currentDir !== sourcesRoot) {
if (fs.existsSync(currentDir) && fs.readdirSync(currentDir).length === 0) {

1
package-lock.json generated
View File

@ -24,6 +24,7 @@
"devDependencies": {
"@cordova/eslint-config": "^4.0.0",
"cordova-js": "^6.1.0",
"elementtree": "^0.1.7",
"jasmine": "^4.1.0",
"jasmine-spec-reporter": "^7.0.0",
"nyc": "^15.1.0",

View File

@ -38,6 +38,7 @@
"devDependencies": {
"@cordova/eslint-config": "^4.0.0",
"cordova-js": "^6.1.0",
"elementtree": "^0.1.7",
"jasmine": "^4.1.0",
"jasmine-spec-reporter": "^7.0.0",
"nyc": "^15.1.0",

View File

@ -21,6 +21,8 @@ const rewire = require('rewire');
const path = require('path');
const CordovaError = require('cordova-common').CordovaError;
const GradlePropertiesParser = require('../../lib/config/GradlePropertiesParser');
const utils = require('../../lib/utils');
const et = require('elementtree');
const PATH_RESOURCE = path.join('platforms', 'android', 'app', 'src', 'main', 'res');
@ -810,6 +812,155 @@ describe('prepare', () => {
});
});
describe('relocate CordovaActivity class java file', () => {
// Rewire
let Api;
let api;
let prepare;
// Spies
let replaceFileContents;
let ensureDirSyncSpy;
let copySyncSpy;
let removeSyncSpy;
// Mock Data
let cordovaProject;
let options;
let packageName;
let initialJavaActivityPath;
beforeEach(() => {
Api = rewire('../../lib/Api');
prepare = rewire('../../lib/prepare');
cordovaProject = {
root: '/mock',
projectConfig: {
path: '/mock/config.xml',
cdvNamespacePrefix: 'cdv',
shortName: () => 'rn',
name: () => 'rename',
android_versionCode: jasmine.createSpy('android_versionCode'),
android_packageName: () => packageName,
packageName: () => packageName,
getPreference: jasmine.createSpy('getPreference'),
version: () => '1.0.0'
},
locations: {
plugins: '/mock/plugins',
www: '/mock/www',
strings: '/mock/res/values/strings.xml'
}
};
api = new Api('android', cordovaProject.root);
initialJavaActivityPath = path.join(api.locations.javaSrc, 'com/company/product/MainActivity.java');
options = {
options: {}
};
Api.__set__('ConfigParser',
jasmine.createSpy('ConfigParser')
.and.returnValue(cordovaProject.projectConfig)
);
Api.__set__('prepare', prepare.prepare);
prepare.__set__('updateWww', jasmine.createSpy('updateWww'));
prepare.__set__('updateIcons', jasmine.createSpy('updateIcons').and.returnValue(Promise.resolve()));
prepare.__set__('updateSplashes', jasmine.createSpy('updateSplashes').and.returnValue(Promise.resolve()));
prepare.__set__('updateFileResources', jasmine.createSpy('updateFileResources').and.returnValue(Promise.resolve()));
prepare.__set__('updateConfigFilesFrom',
jasmine.createSpy('updateConfigFilesFrom')
.and.returnValue(cordovaProject.projectConfig
));
prepare.__set__('glob', {
sync: jasmine.createSpy('sync').and.returnValue({
filter: jasmine.createSpy('filter').and.returnValue([
initialJavaActivityPath
])
})
});
// prepare.__set__('events', {
// emit: function () {
// console.log(arguments);
// }
// });
spyOn(GradlePropertiesParser.prototype, 'configure');
replaceFileContents = spyOn(utils, 'replaceFileContents');
prepare.__set__('AndroidManifest', jasmine.createSpy('AndroidManifest').and.returnValue({
getPackageId: () => packageName,
getActivity: jasmine.createSpy('getActivity').and.returnValue({
setOrientation: jasmine.createSpy('setOrientation').and.returnValue({
setLaunchMode: jasmine.createSpy('setLaunchValue')
})
}),
setVersionName: jasmine.createSpy('setVersionName').and.returnValue({
setVersionCode: jasmine.createSpy('setVersionCode').and.returnValue({
setPackageId: jasmine.createSpy('setPackageId').and.returnValue({
write: jasmine.createSpy('write')
})
})
})
}));
prepare.__set__('xmlHelpers', {
parseElementtreeSync: jasmine.createSpy('parseElementtreeSync').and.returnValue(et.parse(`<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- App label shown within list of installed apps, battery & network usage screens. -->
<string name="app_name">__NAME__</string>
<!-- App label shown on the launcher. -->
<string name="launcher_name">@string/app_name</string>
<!-- App label shown on the task switcher. -->
<string name="activity_name">@string/launcher_name</string>
</resources>
`))
});
ensureDirSyncSpy = jasmine.createSpy('ensureDirSync');
copySyncSpy = jasmine.createSpy('copySync');
removeSyncSpy = jasmine.createSpy('removeSync');
prepare.__set__('fs', {
writeFileSync: jasmine.createSpy('writeFileSync'),
writeJSONSync: jasmine.createSpy('writeJSONSync'),
ensureDirSync: ensureDirSyncSpy,
copySync: copySyncSpy,
removeSync: removeSyncSpy,
existsSync: jasmine.createSpy('existsSync')
});
});
it('moves main activity class java file to path that tracks the package name when package name changed', async () => {
packageName = 'com.company.renamed';
const renamedPath = path.join(api.locations.javaSrc, packageName.replace(/\./g, '/'));
const renamedJavaActivityPath = path.join(renamedPath, 'MainActivity.java');
await api.prepare(cordovaProject, options).then(() => {
expect(replaceFileContents).toHaveBeenCalledWith(renamedJavaActivityPath, /package [\w.]*;/, 'package ' + packageName + ';');
expect(ensureDirSyncSpy).toHaveBeenCalledWith(renamedPath);
expect(copySyncSpy).toHaveBeenCalledWith(initialJavaActivityPath, renamedJavaActivityPath);
expect(removeSyncSpy).toHaveBeenCalledWith(initialJavaActivityPath);
});
});
it('doesn\'t move main activity class java file when package name not changed', async () => {
packageName = 'com.company.product';
await api.prepare(cordovaProject, options).then(() => {
expect(replaceFileContents).toHaveBeenCalledTimes(0);
expect(ensureDirSyncSpy).toHaveBeenCalledTimes(0);
expect(copySyncSpy).toHaveBeenCalledTimes(0);
expect(removeSyncSpy).toHaveBeenCalledTimes(0);
});
});
});
describe('updateSplashes method', function () {
// Mock Data
let cordovaProject;