@@ -4,9 +4,7 @@ import * as constants from "../constants";
44import * as semver from "semver" ;
55import * as projectServiceBaseLib from "./platform-project-service-base" ;
66import { DeviceAndroidDebugBridge } from "../common/mobile/android/device-android-debug-bridge" ;
7- import { attachAwaitDetach } from "../common/helpers" ;
87import { Configurations , LiveSyncPaths } from "../common/constants" ;
9- import { SpawnOptions } from "child_process" ;
108import { performanceLog } from ".././common/decorators" ;
119
1210export class AndroidProjectService extends projectServiceBaseLib . PlatformProjectServiceBase implements IPlatformProjectService {
@@ -15,23 +13,20 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
1513 private static ANDROID_PLATFORM_NAME = "android" ;
1614 private static MIN_RUNTIME_VERSION_WITH_GRADLE = "1.5.0" ;
1715
18- private isAndroidStudioTemplate : boolean ;
19-
2016 constructor ( private $androidToolsInfo : IAndroidToolsInfo ,
21- private $childProcess : IChildProcess ,
2217 private $errors : IErrors ,
2318 $fs : IFileSystem ,
24- private $hostInfo : IHostInfo ,
2519 private $logger : ILogger ,
2620 $projectDataService : IProjectDataService ,
2721 private $injector : IInjector ,
2822 private $devicePlatformsConstants : Mobile . IDevicePlatformsConstants ,
2923 private $androidPluginBuildService : IAndroidPluginBuildService ,
3024 private $platformEnvironmentRequirements : IPlatformEnvironmentRequirements ,
3125 private $androidResourcesMigrationService : IAndroidResourcesMigrationService ,
32- private $filesHashService : IFilesHashService ) {
26+ private $filesHashService : IFilesHashService ,
27+ private $gradleCommandService : IGradleCommandService ,
28+ private $gradleBuildService : IGradleBuildService ) {
3329 super ( $fs , $projectDataService ) ;
34- this . isAndroidStudioTemplate = false ;
3530 }
3631
3732 private _platformData : IPlatformData = null ;
@@ -41,27 +36,10 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
4136 }
4237 if ( projectData && projectData . platformsDir ) {
4338 const projectRoot = path . join ( projectData . platformsDir , AndroidProjectService . ANDROID_PLATFORM_NAME ) ;
44- if ( this . isAndroidStudioCompatibleTemplate ( projectData ) ) {
45- this . isAndroidStudioTemplate = true ;
46- }
47-
48- const appDestinationDirectoryArr = [ projectRoot ] ;
49- if ( this . isAndroidStudioTemplate ) {
50- appDestinationDirectoryArr . push ( constants . APP_FOLDER_NAME ) ;
51- }
52- appDestinationDirectoryArr . push ( constants . SRC_DIR , constants . MAIN_DIR , constants . ASSETS_DIR ) ;
5339
54- const configurationsDirectoryArr = [ projectRoot ] ;
55- if ( this . isAndroidStudioTemplate ) {
56- configurationsDirectoryArr . push ( constants . APP_FOLDER_NAME ) ;
57- }
58- configurationsDirectoryArr . push ( constants . SRC_DIR , constants . MAIN_DIR , constants . MANIFEST_FILE_NAME ) ;
59-
60- const deviceBuildOutputArr = [ projectRoot ] ;
61- if ( this . isAndroidStudioTemplate ) {
62- deviceBuildOutputArr . push ( constants . APP_FOLDER_NAME ) ;
63- }
64- deviceBuildOutputArr . push ( constants . BUILD_DIR , constants . OUTPUTS_DIR , constants . APK_DIR ) ;
40+ const appDestinationDirectoryArr = [ projectRoot , constants . APP_FOLDER_NAME , constants . SRC_DIR , constants . MAIN_DIR , constants . ASSETS_DIR ] ;
41+ const configurationsDirectoryArr = [ projectRoot , constants . APP_FOLDER_NAME , constants . SRC_DIR , constants . MAIN_DIR , constants . MANIFEST_FILE_NAME ] ;
42+ const deviceBuildOutputArr = [ projectRoot , constants . APP_FOLDER_NAME , constants . BUILD_DIR , constants . OUTPUTS_DIR , constants . APK_DIR ] ;
6543
6644 const packageName = this . getProjectNameFromId ( projectData ) ;
6745
@@ -155,30 +133,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
155133 const targetSdkVersion = androidToolsInfo && androidToolsInfo . targetSdkVersion ;
156134 this . $logger . trace ( `Using Android SDK '${ targetSdkVersion } '.` ) ;
157135
158- this . isAndroidStudioTemplate = this . isAndroidStudioCompatibleTemplate ( projectData , frameworkVersion ) ;
159- if ( this . isAndroidStudioTemplate ) {
160- this . copy ( this . getPlatformData ( projectData ) . projectRoot , frameworkDir , "*" , "-R" ) ;
161- } else {
162- this . copy ( this . getPlatformData ( projectData ) . projectRoot , frameworkDir , "libs" , "-R" ) ;
163-
164- if ( config . pathToTemplate ) {
165- const mainPath = path . join ( this . getPlatformData ( projectData ) . projectRoot , constants . SRC_DIR , constants . MAIN_DIR ) ;
166- this . $fs . createDirectory ( mainPath ) ;
167- shell . cp ( "-R" , path . join ( path . resolve ( config . pathToTemplate ) , "*" ) , mainPath ) ;
168- } else {
169- this . copy ( this . getPlatformData ( projectData ) . projectRoot , frameworkDir , constants . SRC_DIR , "-R" ) ;
170- }
171- this . copy ( this . getPlatformData ( projectData ) . projectRoot , frameworkDir , "build.gradle settings.gradle build-tools" , "-Rf" ) ;
172-
173- try {
174- this . copy ( this . getPlatformData ( projectData ) . projectRoot , frameworkDir , "gradle.properties" , "-Rf" ) ;
175- } catch ( e ) {
176- this . $logger . warn ( `\n${ e } \nIt's possible, the final .apk file will contain all architectures instead of the ones described in the abiFilters!\nYou can fix this by using the latest android platform.` ) ;
177- }
178-
179- this . copy ( this . getPlatformData ( projectData ) . projectRoot , frameworkDir , "gradle" , "-R" ) ;
180- this . copy ( this . getPlatformData ( projectData ) . projectRoot , frameworkDir , "gradlew gradlew.bat" , "-f" ) ;
181- }
136+ this . copy ( this . getPlatformData ( projectData ) . projectRoot , frameworkDir , "*" , "-R" ) ;
182137
183138 this . cleanResValues ( targetSdkVersion , projectData ) ;
184139 }
@@ -277,76 +232,13 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
277232
278233 @performanceLog ( )
279234 public async buildProject ( projectRoot : string , projectData : IProjectData , buildConfig : IBuildConfig ) : Promise < void > {
280- let task ;
281- const gradleArgs = this . getGradleBuildOptions ( buildConfig , projectData ) ;
282- const baseTask = buildConfig . androidBundle ? "bundle" : "assemble" ;
283235 const platformData = this . getPlatformData ( projectData ) ;
284- const outputPath = buildConfig . androidBundle ? platformData . bundleBuildOutputPath : platformData . getBuildOutputPath ( buildConfig ) ;
285- if ( this . $logger . getLevel ( ) === "TRACE" ) {
286- gradleArgs . unshift ( "--stacktrace" ) ;
287- gradleArgs . unshift ( "--debug" ) ;
288- }
289- if ( buildConfig . release ) {
290- task = `${ baseTask } Release` ;
291- } else {
292- task = `${ baseTask } Debug` ;
293- }
294-
295- gradleArgs . unshift ( task ) ;
296-
297- const handler = ( data : any ) => {
298- this . emit ( constants . BUILD_OUTPUT_EVENT_NAME , data ) ;
299- } ;
300-
301- await attachAwaitDetach ( constants . BUILD_OUTPUT_EVENT_NAME ,
302- this . $childProcess ,
303- handler ,
304- this . executeCommand ( {
305- projectRoot : this . getPlatformData ( projectData ) . projectRoot ,
306- gradleArgs,
307- childProcessOpts : { stdio : buildConfig . buildOutputStdio || "inherit" } ,
308- spawnFromEventOptions : { emitOptions : { eventName : constants . BUILD_OUTPUT_EVENT_NAME } , throwError : true } ,
309- message : "Gradle build..."
310- } )
311- ) ;
236+ await this . $gradleBuildService . buildProject ( platformData . projectRoot , buildConfig ) ;
312237
238+ const outputPath = buildConfig . androidBundle ? platformData . bundleBuildOutputPath : platformData . getBuildOutputPath ( buildConfig ) ;
313239 await this . $filesHashService . saveHashesForProject ( this . _platformData , outputPath ) ;
314240 }
315241
316- private getGradleBuildOptions ( settings : IAndroidBuildOptionsSettings , projectData : IProjectData ) : Array < string > {
317- const configurationFilePath = this . getPlatformData ( projectData ) . configurationFilePath ;
318-
319- const buildOptions : Array < string > = this . getBuildOptions ( configurationFilePath ) ;
320-
321- if ( settings . release ) {
322- buildOptions . push ( "-Prelease" ) ;
323- buildOptions . push ( `-PksPath=${ path . resolve ( settings . keyStorePath ) } ` ) ;
324- buildOptions . push ( `-Palias=${ settings . keyStoreAlias } ` ) ;
325- buildOptions . push ( `-Ppassword=${ settings . keyStoreAliasPassword } ` ) ;
326- buildOptions . push ( `-PksPassword=${ settings . keyStorePassword } ` ) ;
327- }
328-
329- return buildOptions ;
330- }
331-
332- private getBuildOptions ( configurationFilePath ?: string ) : Array < string > {
333- this . $androidToolsInfo . validateInfo ( { showWarningsAsErrors : true , validateTargetSdk : true } ) ;
334-
335- const androidToolsInfo = this . $androidToolsInfo . getToolsInfo ( ) ;
336- const compileSdk = androidToolsInfo . compileSdkVersion ;
337- const targetSdk = this . getTargetFromAndroidManifest ( configurationFilePath ) || compileSdk ;
338- const buildToolsVersion = androidToolsInfo . buildToolsVersion ;
339- const generateTypings = androidToolsInfo . generateTypings ;
340- const buildOptions = [
341- `-PcompileSdk=android-${ compileSdk } ` ,
342- `-PtargetSdk=${ targetSdk } ` ,
343- `-PbuildToolsVersion=${ buildToolsVersion } ` ,
344- `-PgenerateTypings=${ generateTypings } `
345- ] ;
346-
347- return buildOptions ;
348- }
349-
350242 public async buildForDeploy ( projectRoot : string , projectData : IProjectData , buildConfig ?: IBuildConfig ) : Promise < void > {
351243 return this . buildProject ( projectRoot , projectData , buildConfig ) ;
352244 }
@@ -456,25 +348,18 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
456348 return nativescript && ( nativescript . android || ( nativescript . platforms && nativescript . platforms . android ) ) ;
457349 }
458350
459- public stopServices ( projectRoot : string ) : Promise < ISpawnResult > {
460- return this . executeCommand ( {
461- projectRoot,
462- gradleArgs : [ "--stop" , "--quiet" ] ,
463- childProcessOpts : { stdio : "pipe" } ,
464- message : "Gradle stop services..."
351+ public async stopServices ( platformData : IPlatformData ) : Promise < ISpawnResult > {
352+ const result = await this . $gradleCommandService . executeCommand ( [ "--stop" , "--quiet" ] , {
353+ cwd : platformData . projectRoot ,
354+ message : "Gradle stop services..." ,
355+ stdio : "pipe"
465356 } ) ;
357+
358+ return result ;
466359 }
467360
468361 public async cleanProject ( projectRoot : string , projectData : IProjectData ) : Promise < void > {
469- if ( this . $androidToolsInfo . getToolsInfo ( ) . androidHomeEnvVar ) {
470- const gradleArgs = this . getGradleBuildOptions ( { release : false } , projectData ) ;
471- gradleArgs . unshift ( "clean" ) ;
472- await this . executeCommand ( {
473- projectRoot,
474- gradleArgs,
475- message : "Gradle clean..."
476- } ) ;
477- }
362+ await this . $gradleBuildService . cleanProject ( projectRoot , { release : false } ) ;
478363 }
479364
480365 public async cleanDeviceTempFolder ( deviceIdentifier : string , projectData : IProjectData ) : Promise < void > {
@@ -494,10 +379,6 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
494379 shell . cp ( cpArg , paths , projectRoot ) ;
495380 }
496381
497- private async spawn ( command : string , args : string [ ] , opts ?: any , spawnOpts ?: ISpawnFromEventOptions ) : Promise < ISpawnResult > {
498- return this . $childProcess . spawnFromEvent ( command , args , "close" , opts || { stdio : "inherit" } , spawnOpts ) ;
499- }
500-
501382 private validatePackageName ( packageName : string ) : void {
502383 //Make the package conform to Java package types
503384 //Enforce underscore limitation
@@ -522,81 +403,14 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
522403 }
523404 }
524405
525- private getTargetFromAndroidManifest ( configurationFilePath : string ) : string {
526- let versionInManifest : string ;
527- if ( this . $fs . exists ( configurationFilePath ) ) {
528- const targetFromAndroidManifest : string = this . $fs . readText ( configurationFilePath ) ;
529- if ( targetFromAndroidManifest ) {
530- const match = targetFromAndroidManifest . match ( / .* ?a n d r o i d : t a r g e t S d k V e r s i o n = \" ( .* ?) \" / ) ;
531- if ( match && match [ 1 ] ) {
532- versionInManifest = match [ 1 ] ;
533- }
534- }
535- }
536-
537- return versionInManifest ;
538- }
539-
540- private async executeCommand ( opts : { projectRoot : string , gradleArgs : any , childProcessOpts ?: SpawnOptions , spawnFromEventOptions ?: ISpawnFromEventOptions , message : string } ) : Promise < ISpawnResult > {
541- if ( this . $androidToolsInfo . getToolsInfo ( ) . androidHomeEnvVar ) {
542- const { projectRoot, gradleArgs, message, spawnFromEventOptions } = opts ;
543- const gradlew = this . $hostInfo . isWindows ? "gradlew.bat" : "./gradlew" ;
544-
545- if ( this . $logger . getLevel ( ) === "INFO" ) {
546- gradleArgs . push ( "--quiet" ) ;
547- }
548-
549- this . $logger . info ( message ) ;
550-
551- const childProcessOpts = opts . childProcessOpts || { } ;
552- childProcessOpts . cwd = childProcessOpts . cwd || projectRoot ;
553- childProcessOpts . stdio = childProcessOpts . stdio || "inherit" ;
554- let commandResult ;
555- try {
556- commandResult = await this . spawn ( gradlew ,
557- gradleArgs ,
558- childProcessOpts ,
559- spawnFromEventOptions ) ;
560- } catch ( err ) {
561- this . $errors . failWithoutHelp ( err . message ) ;
562- }
563-
564- return commandResult ;
565- }
566- }
567-
568- private isAndroidStudioCompatibleTemplate ( projectData : IProjectData , frameworkVersion ?: string ) : boolean {
569- const currentPlatformData : IDictionary < any > = this . $projectDataService . getNSValue ( projectData . projectDir , constants . TNS_ANDROID_RUNTIME_NAME ) ;
570- const platformVersion = ( currentPlatformData && currentPlatformData [ constants . VERSION_STRING ] ) || frameworkVersion ;
571-
572- if ( ! platformVersion ) {
573- return true ;
574- }
575-
576- if ( platformVersion === constants . PackageVersion . NEXT || platformVersion === constants . PackageVersion . LATEST || platformVersion === constants . PackageVersion . RC ) {
577- return true ;
578- }
579-
580- const androidStudioCompatibleTemplate = "3.4.0" ;
581- const normalizedPlatformVersion = `${ semver . major ( platformVersion ) } .${ semver . minor ( platformVersion ) } .0` ;
582-
583- return semver . gte ( normalizedPlatformVersion , androidStudioCompatibleTemplate ) ;
584- }
585-
586406 private getLegacyAppResourcesDestinationDirPath ( projectData : IProjectData ) : string {
587- const resourcePath : string [ ] = [ constants . SRC_DIR , constants . MAIN_DIR , constants . RESOURCES_DIR ] ;
588- if ( this . isAndroidStudioTemplate ) {
589- resourcePath . unshift ( constants . APP_FOLDER_NAME ) ;
590- }
407+ const resourcePath : string [ ] = [ constants . APP_FOLDER_NAME , constants . SRC_DIR , constants . MAIN_DIR , constants . RESOURCES_DIR ] ;
591408
592409 return path . join ( this . getPlatformData ( projectData ) . projectRoot , ...resourcePath ) ;
593410 }
594411
595412 private getUpdatedAppResourcesDestinationDirPath ( projectData : IProjectData ) : string {
596- const resourcePath : string [ ] = [ constants . SRC_DIR ] ;
597- if ( this . isAndroidStudioTemplate ) {
598- resourcePath . unshift ( constants . APP_FOLDER_NAME ) ;
599- }
413+ const resourcePath : string [ ] = [ constants . APP_FOLDER_NAME , constants . SRC_DIR ] ;
600414
601415 return path . join ( this . getPlatformData ( projectData ) . projectRoot , ...resourcePath ) ;
602416 }
0 commit comments