@@ -18,11 +18,11 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
18
18
private static MIN_RUNTIME_VERSION_WITH_GRADLE = "1.3.0" ;
19
19
private static MIN_REQUIRED_NODEJS_VERSION_FOR_STATIC_BINDINGS = "4.2.1" ;
20
20
private static REQUIRED_DEV_DEPENDENCIES = [
21
- { name : "babel-traverse" , version : "^6.4.5" } ,
22
- { name : "babel-types" , version : "^6.4.5" } ,
23
- { name : "babylon" , version : "^6.4.5" } ,
24
- { name : "filewalker" , version : "^0.1.2" } ,
25
- { name : "lazy" , version : "^1.0.11" }
21
+ { name : "babel-traverse" , version : "^6.4.5" } ,
22
+ { name : "babel-types" , version : "^6.4.5" } ,
23
+ { name : "babylon" , version : "^6.4.5" } ,
24
+ { name : "filewalker" , version : "^0.1.2" } ,
25
+ { name : "lazy" , version : "^1.0.11" }
26
26
] ;
27
27
28
28
private get sysInfoData ( ) : ISysInfoData {
@@ -50,8 +50,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
50
50
private $projectTemplatesService : IProjectTemplatesService ,
51
51
private $xmlValidator : IXmlValidator ,
52
52
private $npm : INodePackageManager ) {
53
- super ( $fs , $projectData , $projectDataService ) ;
54
- this . _androidProjectPropertiesManagers = Object . create ( null ) ;
53
+ super ( $fs , $projectData , $projectDataService ) ;
54
+ this . _androidProjectPropertiesManagers = Object . create ( null ) ;
55
55
}
56
56
57
57
private _platformData : IPlatformData = null ;
@@ -86,7 +86,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
86
86
87
87
public getAppResourcesDestinationDirectoryPath ( frameworkVersion ?: string ) : IFuture < string > {
88
88
return ( ( ) => {
89
- if ( this . canUseGradle ( frameworkVersion ) . wait ( ) ) {
89
+ if ( this . canUseGradle ( frameworkVersion ) . wait ( ) ) {
90
90
return path . join ( this . platformData . projectRoot , "src" , "main" , "res" ) ;
91
91
}
92
92
@@ -100,30 +100,30 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
100
100
this . validateProjectName ( this . $projectData . projectName ) ;
101
101
102
102
// this call will fail in case `android` is not set correctly.
103
- this . $androidToolsInfo . getPathToAndroidExecutable ( { showWarningsAsErrors : true } ) . wait ( ) ;
104
- this . $androidToolsInfo . validateJavacVersion ( this . sysInfoData . javacVersion , { showWarningsAsErrors : true } ) . wait ( ) ;
103
+ this . $androidToolsInfo . getPathToAndroidExecutable ( { showWarningsAsErrors : true } ) . wait ( ) ;
104
+ this . $androidToolsInfo . validateJavacVersion ( this . sysInfoData . javacVersion , { showWarningsAsErrors : true } ) . wait ( ) ;
105
105
} ) . future < void > ( ) ( ) ;
106
106
}
107
107
108
108
public createProject ( frameworkDir : string , frameworkVersion : string , pathToTemplate ?: string ) : IFuture < void > {
109
109
return ( ( ) => {
110
- if ( semver . lt ( frameworkVersion , AndroidProjectService . MIN_RUNTIME_VERSION_WITH_GRADLE ) ) {
110
+ if ( semver . lt ( frameworkVersion , AndroidProjectService . MIN_RUNTIME_VERSION_WITH_GRADLE ) ) {
111
111
this . $errors . failWithoutHelp ( `The NativeScript CLI requires Android runtime ${ AndroidProjectService . MIN_RUNTIME_VERSION_WITH_GRADLE } or later to work properly.` ) ;
112
112
}
113
113
114
114
this . $fs . ensureDirectoryExists ( this . platformData . projectRoot ) . wait ( ) ;
115
- this . $androidToolsInfo . validateInfo ( { showWarningsAsErrors : true , validateTargetSdk : true } ) . wait ( ) ;
115
+ this . $androidToolsInfo . validateInfo ( { showWarningsAsErrors : true , validateTargetSdk : true } ) . wait ( ) ;
116
116
let androidToolsInfo = this . $androidToolsInfo . getToolsInfo ( ) . wait ( ) ;
117
117
let targetSdkVersion = androidToolsInfo . targetSdkVersion ;
118
118
this . $logger . trace ( `Using Android SDK '${ targetSdkVersion } '.` ) ;
119
- if ( this . $options . symlink ) {
119
+ if ( this . $options . symlink ) {
120
120
this . symlinkDirectory ( "libs" , this . platformData . projectRoot , frameworkDir ) . wait ( ) ;
121
121
} else {
122
122
this . copy ( this . platformData . projectRoot , frameworkDir , "libs" , "-R" ) ;
123
123
}
124
124
125
125
// These files and directories should not be symlinked as CLI is modifying them and we'll change the original values as well.
126
- if ( pathToTemplate ) {
126
+ if ( pathToTemplate ) {
127
127
let mainPath = path . join ( this . platformData . projectRoot , "src" , "main" ) ;
128
128
this . $fs . createDirectory ( mainPath ) . wait ( ) ;
129
129
shell . cp ( "-R" , path . join ( path . resolve ( pathToTemplate ) , "*" ) , mainPath ) ;
@@ -138,17 +138,25 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
138
138
}
139
139
140
140
this . cleanResValues ( targetSdkVersion , frameworkVersion ) . wait ( ) ;
141
- if ( this . canUseStaticBindingGenerator ( ) ) {
141
+ if ( this . canUseStaticBindingGenerator ( ) ) {
142
142
let npmConfig = {
143
143
"save" : true ,
144
144
"save-dev" : true ,
145
145
"save-exact" : true ,
146
146
"silent" : true
147
147
} ;
148
148
149
- _ . each ( AndroidProjectService . REQUIRED_DEV_DEPENDENCIES , ( dependency : any ) =>
150
- this . $npm . install ( `${ dependency . name } @${ dependency . version } ` , this . $projectData . projectDir , npmConfig ) . wait ( )
151
- ) ;
149
+ let projectPackageJson : any = this . $fs . readJson ( this . $projectData . projectFilePath ) . wait ( ) ;
150
+
151
+ _ . each ( AndroidProjectService . REQUIRED_DEV_DEPENDENCIES , ( dependency : any ) => {
152
+ let dependencyVersionInProject = projectPackageJson . dependencies [ dependency . name ] || projectPackageJson . devDependencies [ dependency . name ] ;
153
+
154
+ if ( ! dependencyVersionInProject ) {
155
+ this . $npm . install ( `${ dependency . name } @${ dependency . version } ` , this . $projectData . projectDir , npmConfig ) . wait ( ) ;
156
+ } else if ( ! semver . satisfies ( dependencyVersionInProject , dependency . version ) ) {
157
+ this . $errors . failWithoutHelp ( `Your project have installed ${ dependency . name } version ${ dependencyVersionInProject } but Android platform requires version ${ dependency . version } .` ) ;
158
+ }
159
+ } ) ;
152
160
} else {
153
161
this . $logger . printMarkdown ( ` As you are using Node.js \`${ this . sysInfoData . nodeVer } \` Static Binding Generator will be turned off.` +
154
162
`Upgrade your Node.js to ${ AndroidProjectService . MIN_REQUIRED_NODEJS_VERSION_FOR_STATIC_BINDINGS } or later, so you can use this feature.` ) ;
@@ -170,14 +178,15 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
170
178
let resDestinationDir = this . getAppResourcesDestinationDirectoryPath ( frameworkVersion ) . wait ( ) ;
171
179
let directoriesInResFolder = this . $fs . readDirectory ( resDestinationDir ) . wait ( ) ;
172
180
let directoriesToClean = directoriesInResFolder
173
- . map ( dir => { return {
181
+ . map ( dir => {
182
+ return {
174
183
dirName : dir ,
175
184
sdkNum : parseInt ( dir . substr ( AndroidProjectService . VALUES_VERSION_DIRNAME_PREFIX . length ) )
176
185
} ;
177
186
} )
178
187
. filter ( dir => dir . dirName . match ( AndroidProjectService . VALUES_VERSION_DIRNAME_PREFIX )
179
- && dir . sdkNum
180
- && ( ! targetSdkVersion || ( targetSdkVersion < dir . sdkNum ) ) )
188
+ && dir . sdkNum
189
+ && ( ! targetSdkVersion || ( targetSdkVersion < dir . sdkNum ) ) )
181
190
. map ( dir => path . join ( resDestinationDir , dir . dirName ) ) ;
182
191
this . $logger . trace ( "Directories to clean:" ) ;
183
192
this . $logger . trace ( directoriesToClean ) ;
@@ -209,7 +218,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
209
218
210
219
private getProjectNameFromId ( ) : string {
211
220
let id : string ;
212
- if ( this . $projectData && this . $projectData . projectId ) {
221
+ if ( this . $projectData && this . $projectData . projectId ) {
213
222
id = this . $projectData . projectId . split ( "." ) [ 2 ] ;
214
223
}
215
224
@@ -226,7 +235,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
226
235
227
236
public updatePlatform ( currentVersion : string , newVersion : string , canUpdate : boolean , addPlatform ?: Function , removePlatforms ?: ( platforms : string [ ] ) => IFuture < void > ) : IFuture < boolean > {
228
237
return ( ( ) => {
229
- if ( semver . eq ( newVersion , AndroidProjectService . MIN_RUNTIME_VERSION_WITH_GRADLE ) ) {
238
+ if ( semver . eq ( newVersion , AndroidProjectService . MIN_RUNTIME_VERSION_WITH_GRADLE ) ) {
230
239
let platformLowercase = this . platformData . normalizedPlatformName . toLowerCase ( ) ;
231
240
removePlatforms ( [ platformLowercase . split ( "@" ) [ 0 ] ] ) . wait ( ) ;
232
241
addPlatform ( platformLowercase ) . wait ( ) ;
@@ -239,8 +248,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
239
248
240
249
public buildProject ( projectRoot : string , buildConfig ?: IBuildConfig ) : IFuture < void > {
241
250
return ( ( ) => {
242
- if ( this . canUseGradle ( ) . wait ( ) ) {
243
- this . $androidToolsInfo . validateInfo ( { showWarningsAsErrors : true , validateTargetSdk : true } ) . wait ( ) ;
251
+ if ( this . canUseGradle ( ) . wait ( ) ) {
252
+ this . $androidToolsInfo . validateInfo ( { showWarningsAsErrors : true , validateTargetSdk : true } ) . wait ( ) ;
244
253
let androidToolsInfo = this . $androidToolsInfo . getToolsInfo ( ) . wait ( ) ;
245
254
let compileSdk = androidToolsInfo . compileSdkVersion ;
246
255
let targetSdk = this . getTargetFromAndroidManifest ( ) . wait ( ) || compileSdk ;
@@ -253,15 +262,15 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
253
262
`-PsupportVersion=${ appCompatVersion } ` ,
254
263
] ;
255
264
256
- if ( this . $options . release ) {
265
+ if ( this . $options . release ) {
257
266
buildOptions . push ( "-Prelease" ) ;
258
267
buildOptions . push ( `-PksPath=${ path . resolve ( this . $options . keyStorePath ) } ` ) ;
259
268
buildOptions . push ( `-Palias=${ this . $options . keyStoreAlias } ` ) ;
260
269
buildOptions . push ( `-Ppassword=${ this . $options . keyStoreAliasPassword } ` ) ;
261
270
buildOptions . push ( `-PksPassword=${ this . $options . keyStorePassword } ` ) ;
262
271
}
263
272
264
- if ( ! this . canUseStaticBindingGenerator ( ) ) {
273
+ if ( ! this . canUseStaticBindingGenerator ( ) ) {
265
274
buildOptions . push ( "-PdontRunSbg" ) ;
266
275
}
267
276
@@ -296,7 +305,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
296
305
297
306
// In case the file is not correct, looks like we are still using the default AndroidManifest.xml from runtime and the current file (in res dir)
298
307
// should be merged with it.
299
- if ( this . isAndroidManifestFileCorrect ( androidManifestPath ) . wait ( ) ) {
308
+ if ( this . isAndroidManifestFileCorrect ( androidManifestPath ) . wait ( ) ) {
300
309
// Delete the AndroidManifest.xml file from res directory as the runtime will consider it as addition to the one in src/main and will try to merge them.
301
310
// However now they are the same file.
302
311
this . $fs . deleteFile ( androidManifestPath ) . wait ( ) ;
@@ -312,7 +321,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
312
321
313
322
// In case we should extract the manifest from default template, but for some reason we cannot, break the execution,
314
323
// so the original file from Android runtime will be used.
315
- if ( shouldExtractDefaultManifest && ! this . extractAndroidManifestFromDefaultTemplate ( originalAndroidManifestFilePath ) . wait ( ) ) {
324
+ if ( shouldExtractDefaultManifest && ! this . extractAndroidManifestFromDefaultTemplate ( originalAndroidManifestFilePath ) . wait ( ) ) {
316
325
return ;
317
326
}
318
327
@@ -366,7 +375,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
366
375
367
376
// Copy include.gradle file
368
377
let includeGradleFilePath = path . join ( pluginPlatformsFolderPath , "include.gradle" ) ;
369
- if ( this . $fs . exists ( includeGradleFilePath ) . wait ( ) ) {
378
+ if ( this . $fs . exists ( includeGradleFilePath ) . wait ( ) ) {
370
379
shell . cp ( "-f" , includeGradleFilePath , pluginConfigurationDirectoryPath ) ;
371
380
}
372
381
} ) . future < void > ( ) ( ) ;
@@ -377,7 +386,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
377
386
try {
378
387
this . $fs . deleteDirectory ( path . join ( this . platformData . projectRoot , "configurations" , pluginData . name ) ) . wait ( ) ;
379
388
this . $fs . deleteDirectory ( path . join ( this . platformData . projectRoot , "src" , pluginData . name ) ) . wait ( ) ;
380
- } catch ( e ) {
389
+ } catch ( e ) {
381
390
if ( e . code === "ENOENT" ) {
382
391
this . $logger . debug ( "No native code jars found: " + e . message ) ;
383
392
} else {
@@ -412,8 +421,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
412
421
private _canUseGradle : boolean ;
413
422
private canUseGradle ( frameworkVersion ?: string ) : IFuture < boolean > {
414
423
return ( ( ) => {
415
- if ( ! this . _canUseGradle ) {
416
- if ( ! frameworkVersion ) {
424
+ if ( ! this . _canUseGradle ) {
425
+ if ( ! frameworkVersion ) {
417
426
this . $projectDataService . initialize ( this . $projectData . projectDir ) ;
418
427
frameworkVersion = this . $projectDataService . getValue ( this . platformData . frameworkPackageName ) . wait ( ) . version ;
419
428
}
@@ -431,7 +440,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
431
440
}
432
441
433
442
private spawn ( command : string , args : string [ ] , opts ?: any ) : IFuture < void > {
434
- return this . $childProcess . spawnFromEvent ( command , args , "close" , opts || { stdio : "inherit" } ) ;
443
+ return this . $childProcess . spawnFromEvent ( command , args , "close" , opts || { stdio : "inherit" } ) ;
435
444
}
436
445
437
446
private validatePackageName ( packageName : string ) : void {
@@ -442,7 +451,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
442
451
}
443
452
444
453
//Class is a reserved word
445
- if ( / \b [ C c ] l a s s \b / . test ( packageName ) ) {
454
+ if ( / \b [ C c ] l a s s \b / . test ( packageName ) ) {
446
455
this . $errors . fail ( "class is a reserved word" ) ;
447
456
}
448
457
}
@@ -463,9 +472,9 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
463
472
let versionInManifest : string ;
464
473
if ( this . $fs . exists ( this . platformData . configurationFilePath ) . wait ( ) ) {
465
474
let targetFromAndroidManifest : string = this . $fs . readText ( this . platformData . configurationFilePath ) . wait ( ) ;
466
- if ( targetFromAndroidManifest ) {
475
+ if ( targetFromAndroidManifest ) {
467
476
let 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 = \" ( .* ?) \" / ) ;
468
- if ( match && match [ 1 ] ) {
477
+ if ( match && match [ 1 ] ) {
469
478
versionInManifest = match [ 1 ] ;
470
479
}
471
480
}
@@ -483,7 +492,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
483
492
_ . each ( directoryContent , ( file : string ) => {
484
493
let sourceFilePath = path . join ( frameworkDir , directoryName , file ) ;
485
494
let destinationFilePath = path . join ( projectRoot , directoryName , file ) ;
486
- if ( this . $fs . getFsStats ( sourceFilePath ) . wait ( ) . isFile ( ) ) {
495
+ if ( this . $fs . getFsStats ( sourceFilePath ) . wait ( ) . isFile ( ) ) {
487
496
this . $fs . symlink ( sourceFilePath , destinationFilePath ) . wait ( ) ;
488
497
} else {
489
498
this . $fs . symlink ( sourceFilePath , destinationFilePath , "dir" ) . wait ( ) ;
@@ -500,15 +509,15 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
500
509
// Use a real magic to detect if this is the correct file, by checking some mandatory strings.
501
510
let fileContent = this . $fs . readText ( pathToAndroidManifest ) . wait ( ) ,
502
511
isFileCorrect = ! ! ( ~ fileContent . indexOf ( "android:minSdkVersion" ) && ~ fileContent . indexOf ( "android:targetSdkVersion" )
503
- && ~ fileContent . indexOf ( "uses-permission" ) && ~ fileContent . indexOf ( "<application" )
504
- && ~ fileContent . indexOf ( "<activity" ) && ~ fileContent . indexOf ( "<intent-filter>" )
505
- && ~ fileContent . indexOf ( "android.intent.action.MAIN" ) && ~ fileContent . indexOf ( "com.tns.ErrorReportActivity" )
506
- && ~ fileContent . indexOf ( "android:versionCode" )
507
- && ! this . $xmlValidator . getXmlFileErrors ( pathToAndroidManifest ) . wait ( ) ) ;
512
+ && ~ fileContent . indexOf ( "uses-permission" ) && ~ fileContent . indexOf ( "<application" )
513
+ && ~ fileContent . indexOf ( "<activity" ) && ~ fileContent . indexOf ( "<intent-filter>" )
514
+ && ~ fileContent . indexOf ( "android.intent.action.MAIN" ) && ~ fileContent . indexOf ( "com.tns.ErrorReportActivity" )
515
+ && ~ fileContent . indexOf ( "android:versionCode" )
516
+ && ! this . $xmlValidator . getXmlFileErrors ( pathToAndroidManifest ) . wait ( ) ) ;
508
517
509
518
this . $logger . trace ( `Existing ${ this . platformData . configurationFileName } is ${ isFileCorrect ? "" : "NOT " } correct.` ) ;
510
519
return isFileCorrect ;
511
- } catch ( err ) {
520
+ } catch ( err ) {
512
521
this . $logger . trace ( `Error while checking ${ pathToAndroidManifest } : ` , err ) ;
513
522
return false ;
514
523
}
@@ -519,9 +528,9 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
519
528
520
529
private getConfigurationFileBackupName ( originalAndroidManifestFilePath : string ) : IFuture < string > {
521
530
return ( ( ) => {
522
- if ( ! this . _configurationFileBackupName ) {
531
+ if ( ! this . _configurationFileBackupName ) {
523
532
let defaultBackupName = this . platformData . configurationFileName + ".backup" ;
524
- if ( this . $fs . exists ( path . join ( path . dirname ( originalAndroidManifestFilePath ) , defaultBackupName ) ) . wait ( ) ) {
533
+ if ( this . $fs . exists ( path . join ( path . dirname ( originalAndroidManifestFilePath ) , defaultBackupName ) ) . wait ( ) ) {
525
534
defaultBackupName += `_${ createGUID ( false ) } ` ;
526
535
}
527
536
this . _configurationFileBackupName = defaultBackupName ;
@@ -541,7 +550,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
541
550
private revertBackupOfOriginalAndroidManifest ( originalAndroidManifestFilePath : string ) : IFuture < void > {
542
551
return ( ( ) => {
543
552
let pathToBackupFile = path . join ( path . dirname ( originalAndroidManifestFilePath ) , this . getConfigurationFileBackupName ( originalAndroidManifestFilePath ) . wait ( ) ) ;
544
- if ( this . $fs . exists ( pathToBackupFile ) . wait ( ) ) {
553
+ if ( this . $fs . exists ( pathToBackupFile ) . wait ( ) ) {
545
554
this . $logger . trace ( `Could not extract ${ this . platformData . configurationFileName } from default template. Reverting the change of your app/App_Resources/${ this . platformData . configurationFileName } .` ) ;
546
555
shell . mv ( pathToBackupFile , originalAndroidManifestFilePath ) ;
547
556
}
@@ -556,11 +565,11 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
556
565
if ( this . $fs . exists ( templateAndroidManifest ) . wait ( ) ) {
557
566
this . $logger . trace ( `${ originalAndroidManifestFilePath } is missing. Upgrading the source of the project with one from the new project template. Copy ${ templateAndroidManifest } to ${ originalAndroidManifestFilePath } ` ) ;
558
567
try {
559
- if ( alreadyHasAndroidManifest ) {
568
+ if ( alreadyHasAndroidManifest ) {
560
569
this . backupOriginalAndroidManifest ( originalAndroidManifestFilePath ) . wait ( ) ;
561
570
}
562
571
this . $fs . copyFile ( templateAndroidManifest , originalAndroidManifestFilePath ) . wait ( ) ;
563
- } catch ( e ) {
572
+ } catch ( e ) {
564
573
this . $logger . trace ( `Copying template's ${ this . platformData . configurationFileName } failed. ` , e ) ;
565
574
this . revertBackupOfOriginalAndroidManifest ( originalAndroidManifestFilePath ) . wait ( ) ;
566
575
return false ;
@@ -570,7 +579,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
570
579
return false ;
571
580
}
572
581
573
- if ( alreadyHasAndroidManifest ) {
582
+ if ( alreadyHasAndroidManifest ) {
574
583
this . $logger . warn ( `Your ${ this . platformData . configurationFileName } in app/App_Resources/Android will be replaced by the default one from hello-world template.` ) ;
575
584
this . $logger . printMarkdown ( `The original file will be moved to \`${ this . getConfigurationFileBackupName ( originalAndroidManifestFilePath ) . wait ( ) } \`. Merge it **manually** with the new \`${ this . platformData . configurationFileName } \` in your app/App_Resources/Android.` ) ;
576
585
}
0 commit comments