diff --git a/lib/constants.ts b/lib/constants.ts index c8f5e556b6..1ff3ad5f49 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -24,7 +24,10 @@ export const SRC_DIR = "src"; export const MAIN_DIR = "main"; export const ASSETS_DIR = "assets"; export const MANIFEST_FILE_NAME = "AndroidManifest.xml"; +export const APP_GRADLE_FILE_NAME = "app.gradle"; +export const INFO_PLIST_FILE_NAME = "Info.plist"; export const INCLUDE_GRADLE_NAME = "include.gradle"; +export const BUILD_XCCONFIG_FILE_NAME = "build.xcconfig"; export const BUILD_DIR = "build"; export const OUTPUTS_DIR = "outputs"; export const APK_DIR = "apk"; diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index 8c8710fa94..224f4122bf 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -69,6 +69,12 @@ interface IProjectData extends IProjectDir { appResourcesDirectoryPath: string; projectType: string; nsConfig: INsConfig; + androidManifestPath: string; + appGradlePath: string; + gradleFilesDirectoryPath: string; + infoPlistPath: string; + buildXcconfigPath: string; + /** * Initializes project data with the given project directory. If none supplied defaults to --path option or cwd. * @param {string} projectDir Project root directory. diff --git a/lib/project-data.ts b/lib/project-data.ts index f5bc33b325..90cda0cdac 100644 --- a/lib/project-data.ts +++ b/lib/project-data.ts @@ -43,13 +43,20 @@ export class ProjectData implements IProjectData { public dependencies: any; public devDependencies: IStringDictionary; public projectType: string; + public androidManifestPath: string; + public infoPlistPath: string; + public appGradlePath: string; + public gradleFilesDirectoryPath: string; + public buildXcconfigPath: string; constructor(private $fs: IFileSystem, private $errors: IErrors, private $projectHelper: IProjectHelper, private $staticConfig: IStaticConfig, private $options: IOptions, - private $logger: ILogger) { } + private $logger: ILogger, + private $androidResourcesMigrationService: IAndroidResourcesMigrationService, + private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants) { } public initializeProjectData(projectDir?: string): void { projectDir = projectDir || this.$projectHelper.projectDir; @@ -108,6 +115,11 @@ export class ProjectData implements IProjectData { this.nsConfig = nsConfig; this.appDirectoryPath = this.getAppDirectoryPath(); this.appResourcesDirectoryPath = this.getAppResourcesDirectoryPath(); + this.androidManifestPath = this.getPathToAndroidManifest(this.appResourcesDirectoryPath); + this.gradleFilesDirectoryPath = path.join(this.appResourcesDirectoryPath, this.$devicePlatformsConstants.Android); + this.appGradlePath = path.join(this.gradleFilesDirectoryPath, constants.APP_GRADLE_FILE_NAME); + this.infoPlistPath = path.join(this.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS, constants.INFO_PLIST_FILE_NAME); + this.buildXcconfigPath = path.join(this.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS, constants.BUILD_XCCONFIG_FILE_NAME); return; } @@ -115,6 +127,15 @@ export class ProjectData implements IProjectData { this.errorInvalidProject(projectDir); } + private getPathToAndroidManifest(appResourcesDir: string): string { + const androidDirPath = path.join(appResourcesDir, this.$devicePlatformsConstants.Android); + const androidManifestDir = this.$androidResourcesMigrationService.hasMigrated(appResourcesDir) ? + path.join(androidDirPath, constants.SRC_DIR, constants.MAIN_DIR) : + androidDirPath; + + return path.join(androidManifestDir, constants.MANIFEST_FILE_NAME); + } + private errorInvalidProject(projectDir: string): void { const currentDir = path.resolve("."); this.$logger.trace(`Unable to find project. projectDir: ${projectDir}, options.path: ${this.$options.path}, ${currentDir}`); diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index 2558a2d8bb..50505a5daf 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -256,11 +256,9 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject const gradleSettingsFilePath = path.join(this.getPlatformData(projectData).projectRoot, "settings.gradle"); shell.sed('-i', /__PROJECT_NAME__/, this.getProjectNameFromId(projectData), gradleSettingsFilePath); - // will replace applicationId in app/App_Resources/Android/app.gradle if it has not been edited by the user - const userAppGradleFilePath = path.join(projectData.appResourcesDirectoryPath, this.$devicePlatformsConstants.Android, "app.gradle"); - try { - shell.sed('-i', /__PACKAGE__/, projectData.projectId, userAppGradleFilePath); + // will replace applicationId in app/App_Resources/Android/app.gradle if it has not been edited by the user + shell.sed('-i', /__PACKAGE__/, projectData.projectId, projectData.appGradlePath); } catch (e) { this.$logger.warn(`\n${e}.\nCheck if you're using an outdated template and update it.`); } @@ -520,7 +518,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject } // Copy include.gradle file - const includeGradleFilePath = path.join(pluginPlatformsFolderPath, "include.gradle"); + const includeGradleFilePath = path.join(pluginPlatformsFolderPath, constants.INCLUDE_GRADLE_NAME); if (this.$fs.exists(includeGradleFilePath)) { shell.cp("-f", includeGradleFilePath, pluginConfigurationDirectoryPath); } diff --git a/lib/services/android-resources-migration-service.ts b/lib/services/android-resources-migration-service.ts index 75e6959673..612fe07558 100644 --- a/lib/services/android-resources-migration-service.ts +++ b/lib/services/android-resources-migration-service.ts @@ -37,7 +37,7 @@ export class AndroidResourcesMigrationService implements IAndroidResourcesMigrat const getDirectories = (files: string[]) => files.filter(isDirectory); const getFiles = (files: string[]) => files.filter((file: string) => !isDirectory(file)); - this.$fs.copyFile(path.join(originalAppResources, "app.gradle"), path.join(appResourcesDestination, "app.gradle")); + this.$fs.copyFile(path.join(originalAppResources, constants.APP_GRADLE_FILE_NAME), path.join(appResourcesDestination, constants.APP_GRADLE_FILE_NAME)); const appResourcesFiles = getAllFiles(originalAppResources); const resourceDirectories = getDirectories(appResourcesFiles); diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index ee5d65a1de..365aa08448 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -16,6 +16,7 @@ import { XCConfigService } from "./xcconfig-service"; import * as simplePlist from "simple-plist"; import * as mobileprovision from "ios-mobileprovision-finder"; import { SpawnOptions } from "child_process"; +import { BUILD_XCCONFIG_FILE_NAME } from "../constants"; export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServiceBase implements IPlatformProjectService { private static XCODE_PROJECT_EXT_NAME = ".xcodeproj"; @@ -89,8 +90,8 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ frameworkDirectoriesExtensions: [".framework"], frameworkDirectoriesNames: ["Metadata", "metadataGenerator", "NativeScript", "internal"], targetedOS: ['darwin'], - configurationFileName: "Info.plist", - configurationFilePath: path.join(projectRoot, projectData.projectName, projectData.projectName + "-Info.plist"), + configurationFileName: constants.INFO_PLIST_FILE_NAME, + configurationFilePath: path.join(projectRoot, projectData.projectName, projectData.projectName + `-${constants.INFO_PLIST_FILE_NAME}`), relativeToFrameworkConfigurationFilePath: path.join("__PROJECT_NAME__", "__PROJECT_NAME__-Info.plist"), fastLivesyncFileExtensions: [".tiff", ".tif", ".jpg", "jpeg", "gif", ".png", ".bmp", ".BMPf", ".ico", ".cur", ".xbm"] // https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImage_Class/ }; @@ -338,7 +339,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ // Starting from tns-ios 1.4 the xcconfig file is referenced in the project template const frameworkVersion = this.getFrameworkVersion(this.getPlatformData(projectData).frameworkPackageName, projectData.projectDir); if (semver.lt(frameworkVersion, "1.4.0")) { - basicArgs.push("-xcconfig", path.join(projectRoot, projectData.projectName, "build.xcconfig")); + basicArgs.push("-xcconfig", path.join(projectRoot, projectData.projectName, BUILD_XCCONFIG_FILE_NAME)); } // if (this.$logger.getLevel() === "INFO") { @@ -1039,7 +1040,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f } private validateFramework(libraryPath: string): void { - const infoPlistPath = path.join(libraryPath, "Info.plist"); + const infoPlistPath = path.join(libraryPath, constants.INFO_PLIST_FILE_NAME); if (!this.$fs.exists(infoPlistPath)) { this.$errors.failWithoutHelp("The bundle at %s does not contain an Info.plist file.", libraryPath); } @@ -1227,13 +1228,13 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f const allPlugins: IPluginData[] = await (this.$injector.resolve("pluginsService")).getAllInstalledPlugins(projectData); for (const plugin of allPlugins) { const pluginPlatformsFolderPath = plugin.pluginPlatformsFolderPath(IOSProjectService.IOS_PLATFORM_NAME); - const pluginXcconfigFilePath = path.join(pluginPlatformsFolderPath, "build.xcconfig"); + const pluginXcconfigFilePath = path.join(pluginPlatformsFolderPath, BUILD_XCCONFIG_FILE_NAME); if (this.$fs.exists(pluginXcconfigFilePath)) { await this.mergeXcconfigFiles(pluginXcconfigFilePath, pluginsXcconfigFilePath); } } - const appResourcesXcconfigPath = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); + const appResourcesXcconfigPath = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, BUILD_XCCONFIG_FILE_NAME); if (this.$fs.exists(appResourcesXcconfigPath)) { await this.mergeXcconfigFiles(appResourcesXcconfigPath, pluginsXcconfigFilePath); } @@ -1289,7 +1290,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f private getBuildXCConfigFilePath(projectData: IProjectData): string { const buildXCConfig = path.join(projectData.appResourcesDirectoryPath, - this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); + this.getPlatformData(projectData).normalizedPlatformName, BUILD_XCCONFIG_FILE_NAME); return buildXCConfig; } @@ -1350,7 +1351,7 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f const choicePersist = await this.$prompter.promptForChoice("Do you want to make teamId: " + teamId + " a persistent choice for your app?", choicesPersist); switch (choicesPersist.indexOf(choicePersist)) { case 0: - const xcconfigFile = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, "build.xcconfig"); + const xcconfigFile = path.join(projectData.appResourcesDirectoryPath, this.getPlatformData(projectData).normalizedPlatformName, BUILD_XCCONFIG_FILE_NAME); this.$fs.appendFile(xcconfigFile, "\nDEVELOPMENT_TEAM = " + teamId + "\n"); break; case 1: diff --git a/lib/services/itmstransporter-service.ts b/lib/services/itmstransporter-service.ts index 83dbbf3698..e60b23da2c 100644 --- a/lib/services/itmstransporter-service.ts +++ b/lib/services/itmstransporter-service.ts @@ -1,7 +1,7 @@ import * as path from "path"; import * as temp from "temp"; import { EOL } from "os"; -import { ITMSConstants } from "../constants"; +import { ITMSConstants, INFO_PLIST_FILE_NAME } from "../constants"; import { ItunesConnectApplicationTypes } from "../constants"; import { quoteString, versionCompare } from "../common/helpers"; @@ -135,7 +135,7 @@ export class ITMSTransporterService implements IITMSTransporterService { } const appFile = path.join(payloadDir, allApps[0]); - const plistObject = await this.$bplistParser.parseFile(path.join(appFile, "Info.plist")); + const plistObject = await this.$bplistParser.parseFile(path.join(appFile, INFO_PLIST_FILE_NAME)); const bundleId = plistObject && plistObject[0] && plistObject[0].CFBundleIdentifier; if (!bundleId) { this.$errors.failWithoutHelp(`Unable to determine bundle identifier from ${ipaFileFullPath}.`); diff --git a/lib/services/project-changes-service.ts b/lib/services/project-changes-service.ts index 334ba8cad8..6af8e7e5c0 100644 --- a/lib/services/project-changes-service.ts +++ b/lib/services/project-changes-service.ts @@ -1,5 +1,5 @@ import * as path from "path"; -import { NODE_MODULES_FOLDER_NAME, NativePlatformStatus, PACKAGE_JSON_FILE_NAME } from "../constants"; +import { NODE_MODULES_FOLDER_NAME, NativePlatformStatus, PACKAGE_JSON_FILE_NAME, APP_GRADLE_FILE_NAME, BUILD_XCCONFIG_FILE_NAME } from "../constants"; import { getHash } from "../common/helpers"; const prepareInfoFileName = ".nsprepareinfo"; @@ -77,12 +77,12 @@ export class ProjectChangesService implements IProjectChangesService { if (platform === this.$devicePlatformsConstants.iOS.toLowerCase()) { this._changesInfo.configChanged = this.filesChanged([path.join(platformResourcesDir, platformData.configurationFileName), path.join(platformResourcesDir, "LaunchScreen.storyboard"), - path.join(platformResourcesDir, "build.xcconfig") + path.join(platformResourcesDir, BUILD_XCCONFIG_FILE_NAME) ]); } else { this._changesInfo.configChanged = this.filesChanged([ path.join(platformResourcesDir, platformData.configurationFileName), - path.join(platformResourcesDir, "app.gradle") + path.join(platformResourcesDir, APP_GRADLE_FILE_NAME) ]); } } diff --git a/test/ios-project-service.ts b/test/ios-project-service.ts index 3e383a35fb..8e9a09626c 100644 --- a/test/ios-project-service.ts +++ b/test/ios-project-service.ts @@ -33,6 +33,7 @@ import { NodePackageManager } from "../lib/node-package-manager"; import { assert } from "chai"; import { IOSProvisionService } from "../lib/services/ios-provision-service"; import { SettingsService } from "../lib/common/test/unit-tests/stubs"; +import { BUILD_XCCONFIG_FILE_NAME } from "../lib/constants"; import { ProjectDataStub } from "./stubs"; import temp = require("temp"); @@ -800,7 +801,7 @@ describe("Merge Project XCConfig files", () => { iOSEntitlementsService = testInjector.resolve("iOSEntitlementsService"); - appResourcesXcconfigPath = path.join(projectData.appResourcesDirectoryPath, "iOS", "build.xcconfig"); + appResourcesXcconfigPath = path.join(projectData.appResourcesDirectoryPath, "iOS", BUILD_XCCONFIG_FILE_NAME); appResourceXCConfigContent = `CODE_SIGN_IDENTITY = iPhone Distribution // To build for device with XCode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html // DEVELOPMENT_TEAM = YOUR_TEAM_ID; diff --git a/test/platform-service.ts b/test/platform-service.ts index 8faa479779..f765d84d69 100644 --- a/test/platform-service.ts +++ b/test/platform-service.ts @@ -22,6 +22,7 @@ import * as ChildProcessLib from "../lib/common/child-process"; import ProjectChangesLib = require("../lib/services/project-changes-service"); import { Messages } from "../lib/common/messages/messages"; import { SettingsService } from "../lib/common/test/unit-tests/stubs"; +import { INFO_PLIST_FILE_NAME, MANIFEST_FILE_NAME } from "../lib/constants"; require("should"); const temp = require("temp"); @@ -425,7 +426,7 @@ describe('Platform Service Tests', () => { appDestinationDirectoryPath: testDirData.appDestFolderPath, appResourcesDestinationDirectoryPath: testDirData.appResourcesFolderPath, normalizedPlatformName: platformToTest, - configurationFileName: platformToTest === "ios" ? "Info.plist" : "AndroidManifest.xml", + configurationFileName: platformToTest === "ios" ? INFO_PLIST_FILE_NAME : MANIFEST_FILE_NAME, projectRoot: testDirData.tempFolder, platformProjectService: { prepareProject: (): any => null, diff --git a/test/plugin-variables-service.ts b/test/plugin-variables-service.ts index 6e51f32899..c99f24cb11 100644 --- a/test/plugin-variables-service.ts +++ b/test/plugin-variables-service.ts @@ -12,6 +12,7 @@ import { StaticConfig } from "../lib/config"; import { MessagesService } from "../lib/common/services/messages-service"; import { Yok } from '../lib/common/yok'; import { SettingsService } from "../lib/common/test/unit-tests/stubs"; +import { DevicePlatformsConstants } from "../lib/common/mobile/device-platforms-constants"; import * as stubs from './stubs'; import * as path from "path"; import * as temp from "temp"; @@ -39,6 +40,10 @@ function createTestInjector(): IInjector { }); testInjector.register("staticConfig", StaticConfig); testInjector.register("settingsService", SettingsService); + testInjector.register("devicePlatformsConstants", DevicePlatformsConstants); + testInjector.register("androidResourcesMigrationService", { + hasMigrated: () => true + }); return testInjector; } diff --git a/test/project-data.ts b/test/project-data.ts index 67f1a2775b..5a465b6611 100644 --- a/test/project-data.ts +++ b/test/project-data.ts @@ -1,5 +1,6 @@ import { ProjectData } from "../lib/project-data"; import { Yok } from "../lib/common/yok"; +import { DevicePlatformsConstants } from "../lib/common/mobile/device-platforms-constants"; import { assert } from "chai"; import * as stubs from "./stubs"; import * as path from "path"; @@ -30,6 +31,12 @@ describe("projectData", () => { testInjector.register("options", {}); + testInjector.register("devicePlatformsConstants", DevicePlatformsConstants); + + testInjector.register("androidResourcesMigrationService", { + hasMigrated: () => true + }); + testInjector.register("projectData", ProjectData); return testInjector; diff --git a/test/services/android-plugin-build-service.ts b/test/services/android-plugin-build-service.ts index 51b58372a6..da3c77049f 100644 --- a/test/services/android-plugin-build-service.ts +++ b/test/services/android-plugin-build-service.ts @@ -7,6 +7,7 @@ import { HostInfo } from "../../lib/common/host-info"; import { Logger } from "../../lib/common/logger"; import * as ErrorsLib from "../../lib/common/errors"; import temp = require("temp"); +import { INCLUDE_GRADLE_NAME } from "../../lib/constants"; temp.track(); describe('androiPluginBuildService', () => { @@ -65,7 +66,7 @@ dependencies { compile "com.android.support:design:$supportVersion" }`; - fs.writeFile(path.join(pluginFolder, "include.gradle"), validIncludeGradleContent); + fs.writeFile(path.join(pluginFolder, INCLUDE_GRADLE_NAME), validIncludeGradleContent); } function setUpPluginNativeFolder(manifestFile: boolean, resFolder: boolean, assetsFolder: boolean) { @@ -196,7 +197,7 @@ dependencies { tempPluginDirPath: pluginFolder }; - const includeGradleName = "include.gradle"; + const includeGradleName = INCLUDE_GRADLE_NAME; await androidBuildPluginService.migrateIncludeGradle(config); const includeGradleContent = fs.readText(path.join(pluginFolder, includeGradleName).toString()); const productFlavorsAreRemoved = includeGradleContent.indexOf("productFlavors") === -1; diff --git a/test/stubs.ts b/test/stubs.ts index c355a92939..8fb02569e6 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -258,6 +258,12 @@ export class ProjectDataStub implements IProjectData { devDependencies: IStringDictionary; projectType: string; appResourcesDirectoryPath: string; + public androidManifestPath: string; + public infoPlistPath: string; + public appGradlePath: string; + public gradleFilesDirectoryPath: string; + public buildXcconfigPath: string; + public initializeProjectData(projectDir?: string): void { this.projectDir = this.projectDir || projectDir; }