@@ -12,14 +12,12 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
12
12
private static MIN_SUPPORTED_VERSION = 17 ;
13
13
private SUPPORTED_TARGETS = [ "android-17" , "android-18" , "android-19" , "android-21" , "android-22" ] ; // forbidden for now: "android-MNC"
14
14
private static ANDROID_TARGET_PREFIX = "android" ;
15
- private static RES_DIRNAME = "res" ;
16
15
private static VALUES_DIRNAME = "values" ;
17
16
private static VALUES_VERSION_DIRNAME_PREFIX = AndroidProjectService . VALUES_DIRNAME + "-v" ;
18
17
private static ANDROID_PLATFORM_NAME = "android" ;
19
18
private static LIBS_FOLDER_NAME = "libs" ;
20
19
private static MIN_JAVA_VERSION = "1.7.0" ;
21
20
22
- private targetApi : string ;
23
21
private _androidProjectPropertiesManagers : IDictionary < IAndroidProjectPropertiesManager > ;
24
22
25
23
constructor ( private $androidEmulatorServices : Mobile . IEmulatorPlatformServices ,
@@ -30,6 +28,7 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
30
28
private $logger : ILogger ,
31
29
private $options : IOptions ,
32
30
private $projectData : IProjectData ,
31
+ private $projectDataService : IProjectDataService ,
33
32
private $propertiesParser : IPropertiesParser ,
34
33
private $sysInfo : ISysInfo ,
35
34
$fs : IFileSystem ) {
@@ -45,19 +44,21 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
45
44
this . _platformData = {
46
45
frameworkPackageName : "tns-android" ,
47
46
normalizedPlatformName : "Android" ,
48
- appDestinationDirectoryPath : path . join ( projectRoot , "assets" ) ,
49
- appResourcesDestinationDirectoryPath : path . join ( projectRoot , "res" ) ,
47
+ appDestinationDirectoryPath : path . join ( projectRoot , "src" , "main" , " assets") ,
48
+ appResourcesDestinationDirectoryPath : path . join ( projectRoot , "src" , "main" , " res") ,
50
49
platformProjectService : this ,
51
50
emulatorServices : this . $androidEmulatorServices ,
52
51
projectRoot : projectRoot ,
53
- deviceBuildOutputPath : path . join ( this . $projectData . platformsDir , "android " , "bin " ) ,
52
+ deviceBuildOutputPath : path . join ( projectRoot , "build " , "outputs" , "apk ") ,
54
53
validPackageNamesForDevice : [
55
54
`${ this . $projectData . projectName } -debug.apk` ,
56
- `${ this . $projectData . projectName } -release.apk`
55
+ `${ this . $projectData . projectName } -release.apk` ,
56
+ "android-debug.apk" ,
57
+ "android-release.apk"
57
58
] ,
58
59
frameworkFilesExtensions : [ ".jar" , ".dat" , ".so" ] ,
59
60
configurationFileName : "AndroidManifest.xml" ,
60
- configurationFilePath : path . join ( this . $projectData . platformsDir , "android " , "AndroidManifest.xml" ) ,
61
+ configurationFilePath : path . join ( projectRoot , "src" , "main ", "AndroidManifest.xml" ) ,
61
62
mergeXmlConfig : [ { "nodename" : "manifest" , "attrname" : "*" } , { "nodename" : "application" , "attrname" : "*" } ]
62
63
} ;
63
64
}
@@ -80,38 +81,28 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
80
81
return ( ( ) => {
81
82
this . $fs . ensureDirectoryExists ( projectRoot ) . wait ( ) ;
82
83
83
- let newTarget = this . getAndroidTarget ( frameworkDir ) . wait ( ) ;
84
+ let newTarget = this . getAndroidTarget ( ) . wait ( ) ;
84
85
this . $logger . trace ( `Using Android SDK '${ newTarget } '.` ) ;
85
86
let versionNumber = _ . last ( newTarget . split ( "-" ) ) ;
86
87
if ( this . $options . symlink ) {
87
88
this . copyResValues ( projectRoot , frameworkDir , versionNumber ) . wait ( ) ;
88
- this . copy ( projectRoot , frameworkDir , ".project AndroidManifest.xml project.properties custom_rules.xml" , "-f" ) . wait ( ) ;
89
+ this . copy ( projectRoot , frameworkDir , "AndroidManifest.xml custom_rules.xml" , "-f" ) ;
89
90
90
- this . symlinkDirectory ( "assets " , projectRoot , frameworkDir ) . wait ( ) ;
91
+ this . symlinkDirectory ( "build-tools " , projectRoot , frameworkDir ) . wait ( ) ;
91
92
this . symlinkDirectory ( "libs" , projectRoot , frameworkDir ) . wait ( ) ;
93
+ this . symlinkDirectory ( "src" , projectRoot , frameworkDir ) . wait ( ) ;
92
94
} else {
93
95
this . copyResValues ( projectRoot , frameworkDir , versionNumber ) . wait ( ) ;
94
- this . copy ( projectRoot , frameworkDir , "assets libs" , "-R" ) . wait ( ) ;
95
- this . copy ( projectRoot , frameworkDir , ".project AndroidManifest.xml project.properties custom_rules.xml " , "-f" ) . wait ( ) ;
96
+ this . copy ( projectRoot , frameworkDir , "build-tools libs src " , "-R" ) ;
97
+ this . copy ( projectRoot , frameworkDir , "build.gradle " , "-f" ) ;
96
98
}
97
-
98
- if ( newTarget ) {
99
- this . updateTarget ( projectRoot , newTarget ) . wait ( ) ;
100
- }
101
-
102
- // Create src folder
103
- let packageName = this . $projectData . projectId ;
104
- let packageAsPath = packageName . replace ( / \. / g, path . sep ) ;
105
- let activityDir = path . join ( projectRoot , 'src' , packageAsPath ) ;
106
- this . $fs . createDirectory ( activityDir ) . wait ( ) ;
107
-
108
99
} ) . future < any > ( ) ( ) ;
109
100
}
110
101
111
102
private copyResValues ( projectRoot : string , frameworkDir : string , versionNumber : string ) : IFuture < void > {
112
103
return ( ( ) => {
113
- let resSourceDir = path . join ( frameworkDir , AndroidProjectService . RES_DIRNAME ) ;
114
- let resDestinationDir = path . join ( projectRoot , AndroidProjectService . RES_DIRNAME ) ;
104
+ let resSourceDir = path . join ( frameworkDir , "src" , "main" , "res" ) ;
105
+ let resDestinationDir = this . platformData . appResourcesDestinationDirectoryPath ;
115
106
this . $fs . createDirectory ( resDestinationDir ) . wait ( ) ;
116
107
let versionDirName = AndroidProjectService . VALUES_VERSION_DIRNAME_PREFIX + versionNumber ;
117
108
let directoriesToCopy = [ AndroidProjectService . VALUES_DIRNAME ] ;
@@ -133,43 +124,38 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
133
124
directoriesToCopy . push ( versionDir ) ;
134
125
}
135
126
136
- this . copy ( resDestinationDir , resSourceDir , directoriesToCopy . join ( " " ) , "-R" ) . wait ( ) ;
127
+ this . copy ( resDestinationDir , resSourceDir , directoriesToCopy . join ( " " ) , "-R" ) ;
137
128
} ) . future < void > ( ) ( ) ;
138
129
}
139
130
140
131
public interpolateData ( projectRoot : string ) : IFuture < void > {
141
132
return ( ( ) => {
142
133
// Interpolate the activity name and package
143
- let manifestPath = path . join ( projectRoot , "AndroidManifest.xml" ) ;
134
+ let manifestPath = this . platformData . configurationFilePath ;
144
135
shell . sed ( '-i' , / _ _ P A C K A G E _ _ / , this . $projectData . projectId , manifestPath ) ;
145
- shell . sed ( '-i' , / _ _ A P I L E V E L _ _ / , this . getTarget ( projectRoot ) . wait ( ) . split ( '-' ) [ 1 ] , manifestPath ) ;
136
+ shell . sed ( '-i' , / _ _ A P I L E V E L _ _ / , this . getApiLevel ( ) . wait ( ) , manifestPath ) ;
146
137
147
- let stringsFilePath = path . join ( projectRoot , 'res' , 'values' , 'strings.xml' ) ;
138
+ let stringsFilePath = path . join ( this . platformData . appResourcesDestinationDirectoryPath , 'values' , 'strings.xml' ) ;
148
139
shell . sed ( '-i' , / _ _ N A M E _ _ / , this . $projectData . projectName , stringsFilePath ) ;
149
140
shell . sed ( '-i' , / _ _ T I T L E _ A C T I V I T Y _ _ / , this . $projectData . projectName , stringsFilePath ) ;
150
- shell . sed ( '-i' , / _ _ N A M E _ _ / , this . $projectData . projectName , path . join ( projectRoot , '.project' ) ) ;
151
141
} ) . future < void > ( ) ( ) ;
152
142
}
153
143
154
144
public afterCreateProject ( projectRoot : string ) : IFuture < void > {
155
145
return ( ( ) => {
156
- let targetApi = this . getTarget ( projectRoot ) . wait ( ) ;
157
- this . $logger . trace ( "Android target: %s" , targetApi ) ;
158
- this . runAndroidUpdate ( projectRoot , targetApi ) . wait ( ) ;
159
- this . adjustMinSdk ( projectRoot ) ;
146
+ let targetApi = this . getAndroidTarget ( ) . wait ( ) ;
147
+ this . $logger . trace ( `Adroid target: ${ targetApi } ` ) ;
148
+ this . adjustMinSdk ( projectRoot ) . wait ( ) ;
160
149
} ) . future < void > ( ) ( ) ;
161
150
}
162
151
163
- private adjustMinSdk ( projectRoot : string ) : void {
164
- let manifestPath = path . join ( projectRoot , "AndroidManifest.xml" ) ;
165
- let apiLevel = this . getTarget ( projectRoot ) . wait ( ) . split ( '-' ) [ 1 ] ;
166
- if ( apiLevel === "MNC" ) { // MNC SDK requires that minSdkVersion is set to "MNC"
167
- shell . sed ( '-i' , / a n d r o i d : m i n S d k V e r s i o n = " .* ?" / , `android:minSdkVersion="${ apiLevel } "` , manifestPath ) ;
168
- }
169
- }
170
-
171
- public getDebugOnDeviceSetup ( ) : Mobile . IDebugOnDeviceSetup {
172
- return { } ;
152
+ private adjustMinSdk ( projectRoot : string ) : IFuture < void > {
153
+ return ( ( ) => {
154
+ let apiLevel = this . getApiLevel ( ) . wait ( ) ;
155
+ if ( apiLevel === "MNC" ) { // MNC SDK requires that minSdkVersion is set to "MNC"
156
+ shell . sed ( '-i' , / a n d r o i d : m i n S d k V e r s i o n = " .* ?" / , `android:minSdkVersion="${ apiLevel } "` , this . platformData . configurationFilePath ) ;
157
+ }
158
+ } ) . future < void > ( ) ( ) ;
173
159
}
174
160
175
161
public canUpdatePlatform ( currentVersion : string , newVersion : string ) : IFuture < boolean > {
@@ -181,13 +167,29 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
181
167
}
182
168
183
169
public buildProject ( projectRoot : string ) : IFuture < void > {
184
- let buildConfiguration = this . $options . release ? "release" : "debug" ;
185
- let args = this . getAntArgs ( buildConfiguration , projectRoot ) ;
186
- return this . spawn ( 'ant' , args ) ;
170
+ return ( ( ) => {
171
+ this . $projectDataService . initialize ( this . $projectData . projectDir ) ;
172
+ let frameworkVersion = this . $projectDataService . getValue ( this . platformData . frameworkPackageName ) . wait ( ) . version ;
173
+ if ( semver . lt ( frameworkVersion , "1.3.0" ) ) {
174
+ let args = this . getAntArgs ( this . $options . release ? "release" : "debug" , projectRoot ) ;
175
+ this . spawn ( 'ant' , args ) . wait ( ) ;
176
+ } else { // Gradle build
177
+ let buildOptions = [ "buildapk" ] ;
178
+ if ( this . $options . release ) {
179
+ buildOptions . push ( "-Prelease" ) ;
180
+ buildOptions . push ( `-PksPath=${ this . $options . keyStorePath } ` ) ;
181
+ buildOptions . push ( `-PksPassword=${ this . $options . keyStorePassword } ` ) ;
182
+ buildOptions . push ( `-Palias=${ this . $options . keyStoreAlias } ` ) ;
183
+ buildOptions . push ( `-Ppass=${ this . $options . keyStoreAliasPassword } ` ) ;
184
+ }
185
+
186
+ this . $childProcess . spawnFromEvent ( "gradle" , buildOptions , "close" , { stdio : "inherit" , cwd : this . platformData . projectRoot } ) . wait ( ) ;
187
+ }
188
+ } ) . future < void > ( ) ( ) ;
187
189
}
188
190
189
191
public isPlatformPrepared ( projectRoot : string ) : IFuture < boolean > {
190
- return this . $fs . exists ( path . join ( projectRoot , "assets" , constants . APP_FOLDER_NAME ) ) ;
192
+ return this . $fs . exists ( path . join ( this . platformData . appDestinationDirectoryPath , constants . APP_FOLDER_NAME ) ) ;
191
193
}
192
194
193
195
private getProjectPropertiesManager ( filePath : string ) : IAndroidProjectPropertiesManager {
@@ -197,32 +199,6 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
197
199
198
200
return this . _androidProjectPropertiesManagers [ filePath ] ;
199
201
}
200
-
201
- private parseProjectProperties ( projDir : string , destDir : string ) : IFuture < void > { // projDir is libraryPath, targetPath is the path to lib folder
202
- return ( ( ) => {
203
- projDir = projDir . trim ( ) ;
204
- let projProp = path . join ( projDir , "project.properties" ) ;
205
- if ( ! this . $fs . exists ( projProp ) . wait ( ) ) {
206
- this . $logger . warn ( "Warning: File %s does not exist" , projProp ) ;
207
- return ;
208
- }
209
-
210
- let projectPropertiesManager = this . getProjectPropertiesManager ( projDir ) ;
211
- let references = projectPropertiesManager . getProjectReferences ( ) . wait ( ) ;
212
- _ . each ( references , reference => {
213
- let adjustedPath = this . $fs . isRelativePath ( reference . path ) ? path . join ( projDir , reference . path ) : reference . path ;
214
- this . parseProjectProperties ( adjustedPath , destDir ) . wait ( ) ;
215
- } ) ;
216
-
217
- this . $logger . info ( "Copying %s" , projDir ) ;
218
- shell . cp ( "-Rf" , projDir , destDir ) ;
219
-
220
- let targetDir = path . join ( destDir , path . basename ( projDir ) ) ;
221
- let targetSdk = `android-${ this . $options . sdk || AndroidProjectService . MIN_SUPPORTED_VERSION } ` ;
222
- this . $logger . info ( "Generate build.xml for %s" , targetDir ) ;
223
- this . runAndroidUpdate ( targetDir , targetSdk ) . wait ( ) ;
224
- } ) . future < void > ( ) ( ) ;
225
- }
226
202
227
203
public addLibrary ( libraryPath : string ) : IFuture < void > {
228
204
return ( ( ) => {
@@ -232,20 +208,10 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
232
208
let targetPath = path . dirname ( targetLibPath ) ;
233
209
this . $fs . ensureDirectoryExists ( targetPath ) . wait ( ) ;
234
210
235
- if ( this . $fs . exists ( path . join ( libraryPath , "project.properties" ) ) . wait ( ) ) {
236
- this . parseProjectProperties ( libraryPath , targetPath ) . wait ( ) ;
237
- }
238
-
239
211
shell . cp ( "-f" , path . join ( libraryPath , "*.jar" ) , targetPath ) ;
240
212
let projectLibsDir = path . join ( this . platformData . projectRoot , "libs" ) ;
241
213
this . $fs . ensureDirectoryExists ( projectLibsDir ) . wait ( ) ;
242
214
shell . cp ( "-f" , path . join ( libraryPath , "*.jar" ) , projectLibsDir ) ;
243
-
244
- let libProjProp = path . join ( libraryPath , "project.properties" ) ;
245
- if ( this . $fs . exists ( libProjProp ) . wait ( ) ) {
246
- this . updateProjectReferences ( this . platformData . projectRoot , targetLibPath ) . wait ( ) ;
247
- this . runAndroidUpdate ( targetLibPath , this . getTarget ( this . platformData . projectRoot ) . wait ( ) ) . wait ( ) ;
248
- }
249
215
} ) . future < void > ( ) ( ) ;
250
216
}
251
217
@@ -311,25 +277,16 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
311
277
return path . join ( this . $projectData . projectDir , "lib" , this . platformData . normalizedPlatformName , libraryName ) ;
312
278
}
313
279
314
- private updateProjectReferences ( projDir : string , libraryPath : string ) : IFuture < void > {
315
- let relLibDir = this . getLibraryRelativePath ( projDir , libraryPath ) ;
316
-
317
- let projectPropertiesManager = this . getProjectPropertiesManager ( projDir ) ;
318
- return projectPropertiesManager . addProjectReference ( relLibDir ) ;
319
- }
320
-
321
280
private getAllLibrariesForPlugin ( pluginData : IPluginData ) : IFuture < string [ ] > {
322
281
return ( ( ) => {
323
282
let filterCallback = ( fileName : string , pluginPlatformsFolderPath : string ) => fileName !== AndroidProjectService . LIBS_FOLDER_NAME && this . $fs . exists ( path . join ( pluginPlatformsFolderPath , fileName , "project.properties" ) ) . wait ( ) ;
324
283
return this . getAllNativeLibrariesForPlugin ( pluginData , AndroidProjectService . ANDROID_PLATFORM_NAME , filterCallback ) . wait ( ) ;
325
284
} ) . future < string [ ] > ( ) ( ) ;
326
285
}
327
286
328
- private copy ( projectRoot : string , frameworkDir : string , files : string , cpArg : string ) : IFuture < void > {
329
- return ( ( ) => {
330
- let paths = files . split ( ' ' ) . map ( p => path . join ( frameworkDir , p ) ) ;
331
- shell . cp ( cpArg , paths , projectRoot ) ;
332
- } ) . future < void > ( ) ( ) ;
287
+ private copy ( projectRoot : string , frameworkDir : string , files : string , cpArg : string ) : void {
288
+ let paths = files . split ( ' ' ) . map ( p => path . join ( frameworkDir , p ) ) ;
289
+ shell . cp ( cpArg , paths , projectRoot ) ;
333
290
}
334
291
335
292
private spawn ( command : string , args : string [ ] ) : IFuture < void > {
@@ -367,16 +324,6 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
367
324
return args ;
368
325
}
369
326
370
- private runAndroidUpdate ( projectPath : string , targetApi : string ) : IFuture < void > {
371
- let args = [
372
- "--path" , projectPath ,
373
- "--target" , targetApi ,
374
- "--name" , this . $projectData . projectName
375
- ] ;
376
-
377
- return this . spawn ( "android" , [ 'update' , 'project' ] . concat ( args ) ) ;
378
- }
379
-
380
327
private validatePackageName ( packageName : string ) : void {
381
328
//Make the package conform to Java package types
382
329
//Enforce underscore limitation
@@ -401,9 +348,9 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
401
348
}
402
349
}
403
350
404
- private getAndroidTarget ( frameworkDir : string ) : IFuture < string > {
351
+ private getAndroidTarget ( ) : IFuture < string > {
405
352
return ( ( ) : string => {
406
- let newTarget = this . $options . sdk ? `${ AndroidProjectService . ANDROID_TARGET_PREFIX } -${ this . $options . sdk } ` : this . getLatestValidAndroidTarget ( frameworkDir ) . wait ( ) ;
353
+ let newTarget = this . $options . sdk ? `${ AndroidProjectService . ANDROID_TARGET_PREFIX } -${ this . $options . sdk } ` : this . getLatestValidAndroidTarget ( ) . wait ( ) ;
407
354
if ( ! _ . contains ( this . SUPPORTED_TARGETS , newTarget ) ) {
408
355
let versionNumber = parseInt ( _ . last ( newTarget . split ( "-" ) ) ) ;
409
356
if ( versionNumber && ( versionNumber < AndroidProjectService . MIN_SUPPORTED_VERSION ) ) {
@@ -421,7 +368,7 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
421
368
} ) . future < string > ( ) ( ) ;
422
369
}
423
370
424
- private getLatestValidAndroidTarget ( frameworkDir : string ) : IFuture < string > {
371
+ private getLatestValidAndroidTarget ( ) : IFuture < string > {
425
372
return ( ( ) => {
426
373
let installedTargets = this . getInstalledTargets ( ) . wait ( ) ;
427
374
@@ -436,23 +383,11 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
436
383
return newTarget ;
437
384
} ) . future < string > ( ) ( ) ;
438
385
}
439
-
440
- private updateTarget ( projectRoot : string , newTarget : string ) : IFuture < void > {
386
+
387
+ private getApiLevel ( ) : IFuture < string > {
441
388
return ( ( ) => {
442
- let file = path . join ( projectRoot , "project.properties" ) ;
443
- let editor = this . $propertiesParser . createEditor ( file ) . wait ( ) ;
444
- editor . set ( "target" , newTarget ) ;
445
- let future = new Future < void > ( ) ;
446
- editor . save ( ( err :any ) => {
447
- if ( err ) {
448
- future . throw ( err ) ;
449
- } else {
450
- this . targetApi = null ; // so that later we can repopulate the cache
451
- future . return ( ) ;
452
- }
453
- } ) ;
454
- future . wait ( ) ;
455
- } ) . future < void > ( ) ( ) ;
389
+ return this . getAndroidTarget ( ) . wait ( ) . split ( '-' ) [ 1 ] ;
390
+ } ) . future < string > ( ) ( ) ;
456
391
}
457
392
458
393
private installedTargetsCache : string [ ] = null ;
@@ -466,21 +401,6 @@ class AndroidProjectService extends projectServiceBaseLib.PlatformProjectService
466
401
return this . installedTargetsCache ;
467
402
} ) . future < string [ ] > ( ) ( ) ;
468
403
}
469
-
470
- private getTarget ( projectRoot : string ) : IFuture < string > {
471
- return ( ( ) => {
472
- if ( ! this . targetApi ) {
473
- let projectPropertiesFilePath = path . join ( projectRoot , "project.properties" ) ;
474
-
475
- if ( this . $fs . exists ( projectPropertiesFilePath ) . wait ( ) ) {
476
- let properties = this . $propertiesParser . createEditor ( projectPropertiesFilePath ) . wait ( ) ;
477
- this . targetApi = properties . get ( "target" ) ;
478
- }
479
- }
480
-
481
- return this . targetApi ;
482
- } ) . future < string > ( ) ( ) ;
483
- }
484
404
485
405
private checkJava ( ) : IFuture < void > {
486
406
return ( ( ) => {
0 commit comments