Skip to content

Commit f19c34a

Browse files
committed
fix(resources-update-command): make prepare and run backward-compatible
1 parent a899190 commit f19c34a

File tree

3 files changed

+90
-69
lines changed

3 files changed

+90
-69
lines changed

lib/services/android-project-service.ts

Lines changed: 70 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import * as semver from "semver";
55
import * as projectServiceBaseLib from "./platform-project-service-base";
66
import { DeviceAndroidDebugBridge } from "../common/mobile/android/device-android-debug-bridge";
77
import { attachAwaitDetach } from "../common/helpers";
8-
import { EOL } from "os";
98
import { Configurations } from "../common/constants";
109
import { SpawnOptions } from "child_process";
1110

@@ -36,7 +35,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
3635
private $injector: IInjector,
3736
private $pluginVariablesService: IPluginVariablesService,
3837
private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
39-
private $npm: INodePackageManager) {
38+
private $npm: INodePackageManager,
39+
private $projectV4MigrationService: IProjectV4MigrationService) {
4040
super($fs, $projectDataService);
4141
this._androidProjectPropertiesManagers = Object.create(null);
4242
this.isAndroidStudioTemplate = false;
@@ -116,18 +116,32 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
116116
return Promise.resolve(true);
117117
}
118118

119-
public getAppResourcesDestinationDirectoryPath(projectData: IProjectData, frameworkVersion?: string): string {
120-
if (this.canUseGradle(projectData, frameworkVersion)) {
121-
const resourcePath: string[] = [constants.SRC_DIR, constants.MAIN_DIR, constants.RESOURCES_DIR];
122-
if (this.isAndroidStudioTemplate) {
123-
resourcePath.unshift(constants.APP_FOLDER_NAME);
124-
}
119+
public getAppResourcesDestinationDirectoryPath(projectData: IProjectData): string {
120+
const appResourcesDirStructureHasMigrated = this.$projectV4MigrationService.hasMigrated(projectData.getAppResourcesDirectoryPath());
121+
122+
if (appResourcesDirStructureHasMigrated) {
123+
return this.getAppResourcesDestinationDirectoryPathUpdatedAppResourcesDirStructure(projectData);
124+
} else {
125+
return this.getAppResourcesDestinationDirectoryPathOldAppResourcesDirStructure(projectData);
126+
}
127+
}
128+
129+
private getAppResourcesDestinationDirectoryPathOldAppResourcesDirStructure(projectData: IProjectData): string {
130+
const resourcePath: string[] = [constants.SRC_DIR, constants.MAIN_DIR, constants.RESOURCES_DIR];
131+
if (this.isAndroidStudioTemplate) {
132+
resourcePath.unshift(constants.APP_FOLDER_NAME);
133+
}
125134

126-
return path.join(this.getPlatformData(projectData).projectRoot, ...resourcePath);
135+
return path.join(this.getPlatformData(projectData).projectRoot, ...resourcePath);
136+
}
127137

138+
private getAppResourcesDestinationDirectoryPathUpdatedAppResourcesDirStructure(projectData: IProjectData): string {
139+
const resourcePath: string[] = [constants.SRC_DIR];
140+
if (this.isAndroidStudioTemplate) {
141+
resourcePath.unshift(constants.APP_FOLDER_NAME);
128142
}
129143

130-
return path.join(this.getPlatformData(projectData).projectRoot, constants.RESOURCES_DIR);
144+
return path.join(this.getPlatformData(projectData).projectRoot, ...resourcePath);
131145
}
132146

133147
public async validate(projectData: IProjectData): Promise<void> {
@@ -182,7 +196,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
182196
this.copy(this.getPlatformData(projectData).projectRoot, frameworkDir, "gradlew gradlew.bat", "-f");
183197
}
184198

185-
this.cleanResValues(targetSdkVersion, projectData, frameworkVersion);
199+
this.cleanResValues(targetSdkVersion, projectData);
186200

187201
const npmConfig: INodePackageManagerInstallOptions = {
188202
save: true,
@@ -218,8 +232,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
218232
}
219233
}
220234

221-
private cleanResValues(targetSdkVersion: number, projectData: IProjectData, frameworkVersion: string): void {
222-
const resDestinationDir = this.getAppResourcesDestinationDirectoryPath(projectData, frameworkVersion);
235+
private cleanResValues(targetSdkVersion: number, projectData: IProjectData): void {
236+
const resDestinationDir = this.getAppResourcesDestinationDirectoryPath(projectData);
223237
const directoriesInResFolder = this.$fs.readDirectory(resDestinationDir);
224238
const directoriesToClean = directoriesInResFolder
225239
.map(dir => {
@@ -243,16 +257,24 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
243257
public async interpolateData(projectData: IProjectData, platformSpecificData: IPlatformSpecificData): Promise<void> {
244258
// Interpolate the apilevel and package
245259
this.interpolateConfigurationFile(projectData, platformSpecificData);
260+
const appResourcesDirectoryPath = projectData.getAppResourcesDirectoryPath();
261+
262+
let stringsFilePath: string;
263+
264+
if (!this.$projectV4MigrationService.hasMigrated(appResourcesDirectoryPath)) {
265+
stringsFilePath = path.join(this.getAppResourcesDestinationDirectoryPath(projectData), 'values', 'strings.xml');
266+
} else {
267+
stringsFilePath = path.join(this.getAppResourcesDestinationDirectoryPath(projectData), "main", "res", 'values', 'strings.xml');
268+
}
246269

247-
const stringsFilePath = path.join(this.getAppResourcesDestinationDirectoryPath(projectData), 'values', 'strings.xml');
248270
shell.sed('-i', /__NAME__/, projectData.projectName, stringsFilePath);
249271
shell.sed('-i', /__TITLE_ACTIVITY__/, projectData.projectName, stringsFilePath);
250272

251273
const gradleSettingsFilePath = path.join(this.getPlatformData(projectData).projectRoot, "settings.gradle");
252274
shell.sed('-i', /__PROJECT_NAME__/, this.getProjectNameFromId(projectData), gradleSettingsFilePath);
253275

254276
// will replace applicationId in app/App_Resources/Android/app.gradle if it has not been edited by the user
255-
const userAppGradleFilePath = path.join(projectData.getAppResourcesDirectoryPath(), this.$devicePlatformsConstants.Android, "app.gradle");
277+
const userAppGradleFilePath = path.join(appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, "app.gradle");
256278

257279
try {
258280
shell.sed('-i', /__PACKAGE__/, projectData.projectId, userAppGradleFilePath);
@@ -300,33 +322,28 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
300322
}
301323

302324
public async buildProject(projectRoot: string, projectData: IProjectData, buildConfig: IBuildConfig): Promise<void> {
303-
if (this.canUseGradle(projectData)) {
304-
const buildOptions = this.getBuildOptions(buildConfig, projectData);
305-
if (this.$logger.getLevel() === "TRACE") {
306-
buildOptions.unshift("--stacktrace");
307-
buildOptions.unshift("--debug");
308-
}
309-
if (buildConfig.release) {
310-
buildOptions.unshift("assembleRelease");
311-
} else {
312-
buildOptions.unshift("assembleDebug");
313-
}
314-
315-
const handler = (data: any) => {
316-
this.emit(constants.BUILD_OUTPUT_EVENT_NAME, data);
317-
};
318-
319-
await attachAwaitDetach(constants.BUILD_OUTPUT_EVENT_NAME,
320-
this.$childProcess,
321-
handler,
322-
this.executeGradleCommand(this.getPlatformData(projectData).projectRoot,
323-
buildOptions,
324-
{ stdio: buildConfig.buildOutputStdio || "inherit" },
325-
{ emitOptions: { eventName: constants.BUILD_OUTPUT_EVENT_NAME }, throwError: true }));
325+
const buildOptions = this.getBuildOptions(buildConfig, projectData);
326+
if (this.$logger.getLevel() === "TRACE") {
327+
buildOptions.unshift("--stacktrace");
328+
buildOptions.unshift("--debug");
329+
}
330+
if (buildConfig.release) {
331+
buildOptions.unshift("assembleRelease");
326332
} else {
327-
this.$errors.failWithoutHelp("Cannot complete build because this project is ANT-based." + EOL +
328-
"Run `tns platform remove android && tns platform add android` to switch to Gradle and try again.");
333+
buildOptions.unshift("assembleDebug");
329334
}
335+
336+
const handler = (data: any) => {
337+
this.emit(constants.BUILD_OUTPUT_EVENT_NAME, data);
338+
};
339+
340+
await attachAwaitDetach(constants.BUILD_OUTPUT_EVENT_NAME,
341+
this.$childProcess,
342+
handler,
343+
this.executeGradleCommand(this.getPlatformData(projectData).projectRoot,
344+
buildOptions,
345+
{ stdio: buildConfig.buildOutputStdio || "inherit" },
346+
{ emitOptions: { eventName: constants.BUILD_OUTPUT_EVENT_NAME }, throwError: true }));
330347
}
331348

332349
private getBuildOptions(settings: IAndroidBuildOptionsSettings, projectData: IProjectData): Array<string> {
@@ -374,7 +391,15 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
374391
}
375392

376393
public ensureConfigurationFileInAppResources(projectData: IProjectData): void {
377-
const originalAndroidManifestFilePath = path.join(projectData.getAppResourcesDirectoryPath(), this.$devicePlatformsConstants.Android, this.getPlatformData(projectData).configurationFileName);
394+
const appResourcesDirectoryPath = projectData.getAppResourcesDirectoryPath();
395+
const appResourcesDirStructureHasMigrated = this.$projectV4MigrationService.hasMigrated(appResourcesDirectoryPath);
396+
let originalAndroidManifestFilePath;
397+
398+
if (appResourcesDirStructureHasMigrated) {
399+
originalAndroidManifestFilePath = path.join(appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, "src", "main", this.getPlatformData(projectData).configurationFileName);
400+
} else {
401+
originalAndroidManifestFilePath = path.join(appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, this.getPlatformData(projectData).configurationFileName);
402+
}
378403

379404
const manifestExists = this.$fs.exists(originalAndroidManifestFilePath);
380405

@@ -383,16 +408,13 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
383408
return;
384409
}
385410
// Overwrite the AndroidManifest from runtime.
386-
this.$fs.copyFile(originalAndroidManifestFilePath, this.getPlatformData(projectData).configurationFilePath);
411+
if (!appResourcesDirStructureHasMigrated) {
412+
this.$fs.copyFile(originalAndroidManifestFilePath, this.getPlatformData(projectData).configurationFilePath);
413+
}
387414
}
388415

389416
public prepareAppResources(appResourcesDirectoryPath: string, projectData: IProjectData): void {
390-
const resourcesDirPath = path.join(appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName);
391-
const valuesDirRegExp = /^values/;
392-
const resourcesDirs = this.$fs.readDirectory(resourcesDirPath).filter(resDir => !resDir.match(valuesDirRegExp));
393-
_.each(resourcesDirs, resourceDir => {
394-
this.$fs.deleteDirectory(path.join(this.getAppResourcesDestinationDirectoryPath(projectData), resourceDir));
395-
});
417+
// Intentionally left empty
396418
}
397419

398420
public async preparePluginNativeCode(pluginData: IPluginData, projectData: IProjectData): Promise<void> {
@@ -542,20 +564,6 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
542564
// Nothing android specific to check yet.
543565
}
544566

545-
private _canUseGradle: boolean;
546-
private canUseGradle(projectData: IProjectData, frameworkVersion?: string): boolean {
547-
if (!this._canUseGradle) {
548-
if (!frameworkVersion) {
549-
const frameworkInfoInProjectFile = this.$projectDataService.getNSValue(projectData.projectDir, this.getPlatformData(projectData).frameworkPackageName);
550-
frameworkVersion = frameworkInfoInProjectFile && frameworkInfoInProjectFile.version;
551-
}
552-
553-
this._canUseGradle = !frameworkVersion || semver.gte(frameworkVersion, AndroidProjectService.MIN_RUNTIME_VERSION_WITH_GRADLE);
554-
}
555-
556-
return this._canUseGradle;
557-
}
558-
559567
private copy(projectRoot: string, frameworkDir: string, files: string, cpArg: string): void {
560568
const paths = files.split(' ').map(p => path.join(frameworkDir, p));
561569
shell.cp(cpArg, paths, projectRoot);

lib/services/prepare-platform-native-service.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ export class PreparePlatformNativeService extends PreparePlatformService impleme
1010
$hooksService: IHooksService,
1111
private $nodeModulesBuilder: INodeModulesBuilder,
1212
private $pluginsService: IPluginsService,
13-
private $projectChangesService: IProjectChangesService) {
13+
private $projectChangesService: IProjectChangesService,
14+
private $projectV4MigrationService: IProjectV4MigrationService) {
1415
super($fs, $hooksService, $xmlValidator);
1516
}
1617

@@ -62,13 +63,26 @@ export class PreparePlatformNativeService extends PreparePlatformService impleme
6263

6364
private copyAppResources(platformData: IPlatformData, projectData: IProjectData): void {
6465
const appDestinationDirectoryPath = path.join(platformData.appDestinationDirectoryPath, constants.APP_FOLDER_NAME);
65-
const appResourcesDirectoryPath = path.join(appDestinationDirectoryPath, constants.APP_RESOURCES_FOLDER_NAME);
66-
if (this.$fs.exists(appResourcesDirectoryPath)) {
67-
platformData.platformProjectService.prepareAppResources(appResourcesDirectoryPath, projectData);
66+
const appResourcesDestinationDirectoryPath = path.join(appDestinationDirectoryPath, constants.APP_RESOURCES_FOLDER_NAME);
67+
if (this.$fs.exists(appResourcesDestinationDirectoryPath)) {
68+
platformData.platformProjectService.prepareAppResources(appResourcesDestinationDirectoryPath, projectData);
6869
const appResourcesDestination = platformData.platformProjectService.getAppResourcesDestinationDirectoryPath(projectData);
6970
this.$fs.ensureDirectoryExists(appResourcesDestination);
70-
shell.cp("-Rf", path.join(appResourcesDirectoryPath, platformData.normalizedPlatformName, "*"), appResourcesDestination);
71-
this.$fs.deleteDirectory(appResourcesDirectoryPath);
71+
72+
if (platformData.normalizedPlatformName.toLowerCase() === "android") {
73+
const appResourcesDirectoryPath = projectData.getAppResourcesDirectoryPath();
74+
const appResourcesDirStructureHasMigrated = this.$projectV4MigrationService.hasMigrated(appResourcesDirectoryPath);
75+
76+
if (appResourcesDirStructureHasMigrated) {
77+
shell.cp("-Rf", path.join(appResourcesDirectoryPath, platformData.normalizedPlatformName, "src", "main"), appResourcesDestination);
78+
79+
return;
80+
}
81+
}
82+
83+
shell.cp("-Rf", path.join(appResourcesDestinationDirectoryPath, platformData.normalizedPlatformName, "*"), appResourcesDestination);
84+
85+
this.$fs.deleteDirectory(appResourcesDestinationDirectoryPath);
7286
}
7387
}
7488

lib/services/project-v4-migration-service.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ export class ProjectV4MigrationService implements IProjectV4MigrationService {
5555

5656
this.$logger.out(`Successfully updated your project's App_Resources/Android directory structure.\nThe previous version of App_Resources/Android has been renamed to App_Resources/${ProjectV4MigrationService.ANDROID_DIR_OLD}`);
5757
}
58-
5958
}
6059

6160
$injector.register("projectV4MigrationService", ProjectV4MigrationService);

0 commit comments

Comments
 (0)