@@ -21,9 +21,9 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
21
21
private pathToAndroidExecutable : string ;
22
22
private _androidExecutableName : string ;
23
23
private get androidExecutableName ( ) : string {
24
- if ( ! this . _androidExecutableName ) {
24
+ if ( ! this . _androidExecutableName ) {
25
25
this . _androidExecutableName = "android" ;
26
- if ( this . $hostInfo . isWindows ) {
26
+ if ( this . $hostInfo . isWindows ) {
27
27
this . _androidExecutableName += ".bat" ;
28
28
}
29
29
}
@@ -36,17 +36,18 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
36
36
private $fs : IFileSystem ,
37
37
private $hostInfo : IHostInfo ,
38
38
private $logger : ILogger ,
39
- private $options : IOptions ) { }
39
+ private $options : IOptions ,
40
+ private $adb : Mobile . IAndroidDebugBridge ) { }
40
41
41
- public getPathToAndroidExecutable ( options ?: { showWarningsAsErrors : boolean } ) : IFuture < string > {
42
+ public getPathToAndroidExecutable ( options ?: { showWarningsAsErrors : boolean } ) : IFuture < string > {
42
43
return ( ( ) : string => {
43
- if ( options ) {
44
+ if ( options ) {
44
45
this . showWarningsAsErrors = options . showWarningsAsErrors ;
45
46
}
46
47
if ( ! this . pathToAndroidExecutable ) {
47
- if ( this . validateAndroidHomeEnvVariable ( this . androidHome ) . wait ( ) ) {
48
+ if ( this . validateAndroidHomeEnvVariable ( this . androidHome ) . wait ( ) ) {
48
49
let androidPath = path . join ( this . androidHome , "tools" , this . androidExecutableName ) ;
49
- if ( ! this . trySetAndroidPath ( androidPath ) . wait ( ) && ! this . trySetAndroidPath ( this . androidExecutableName ) . wait ( ) ) {
50
+ if ( ! this . trySetAndroidPath ( androidPath ) . wait ( ) && ! this . trySetAndroidPath ( this . androidExecutableName ) . wait ( ) ) {
50
51
this . printMessage ( `Unable to find "${ this . androidExecutableName } " executable file. Make sure you have set ANDROID_HOME environment variable correctly.` ) ;
51
52
}
52
53
} else {
@@ -62,15 +63,15 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
62
63
return ( ( ) : boolean => {
63
64
let isAndroidPathCorrect = true ;
64
65
try {
65
- let result = this . $childProcess . spawnFromEvent ( androidPath , [ "--help" ] , "close" , { } , { throwError : false } ) . wait ( ) ;
66
- if ( result && result . stdout ) {
66
+ let result = this . $adb . executeCommand ( [ "--help" ] , { returnChildProcess : true } ) . wait ( ) ;
67
+ if ( result && result . stdout ) {
67
68
this . $logger . trace ( result . stdout ) ;
68
69
this . pathToAndroidExecutable = androidPath ;
69
70
} else {
70
71
this . $logger . trace ( `Unable to find android executable from '${ androidPath } '.` ) ;
71
72
isAndroidPathCorrect = false ;
72
73
}
73
- } catch ( err ) {
74
+ } catch ( err ) {
74
75
this . $logger . trace ( `Error occurred while checking androidExecutable from '${ androidPath } '. ${ err . message } ` ) ;
75
76
isAndroidPathCorrect = false ;
76
77
}
@@ -81,7 +82,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
81
82
82
83
public getToolsInfo ( ) : IFuture < IAndroidToolsInfoData > {
83
84
return ( ( ) : IAndroidToolsInfoData => {
84
- if ( ! this . toolsInfo ) {
85
+ if ( ! this . toolsInfo ) {
85
86
let infoData : IAndroidToolsInfoData = Object . create ( null ) ;
86
87
infoData . androidHomeEnvVar = this . androidHome ;
87
88
infoData . compileSdkVersion = this . getCompileSdk ( ) . wait ( ) ;
@@ -96,57 +97,57 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
96
97
} ) . future < IAndroidToolsInfoData > ( ) ( ) ;
97
98
}
98
99
99
- public validateInfo ( options ?: { showWarningsAsErrors : boolean , validateTargetSdk : boolean } ) : IFuture < boolean > {
100
- return ( ( ) : boolean => {
100
+ public validateInfo ( options ?: { showWarningsAsErrors : boolean , validateTargetSdk : boolean } ) : IFuture < boolean > {
101
+ return ( ( ) : boolean => {
101
102
let detectedErrors = false ;
102
103
this . showWarningsAsErrors = options && options . showWarningsAsErrors ;
103
104
let toolsInfoData = this . getToolsInfo ( ) . wait ( ) ;
104
105
let isAndroidHomeValid = this . validateAndroidHomeEnvVariable ( toolsInfoData . androidHomeEnvVar ) . wait ( ) ;
105
- if ( ! toolsInfoData . compileSdkVersion ) {
106
+ if ( ! toolsInfoData . compileSdkVersion ) {
106
107
this . printMessage ( `Cannot find a compatible Android SDK for compilation. To be able to build for Android, install Android SDK ${ AndroidToolsInfo . MIN_REQUIRED_COMPILE_TARGET } or later.` ,
107
- "Run `$ android` to manage your Android SDK versions." ) ;
108
+ "Run `$ android` to manage your Android SDK versions." ) ;
108
109
detectedErrors = true ;
109
110
}
110
111
111
- if ( ! toolsInfoData . buildToolsVersion ) {
112
+ if ( ! toolsInfoData . buildToolsVersion ) {
112
113
let buildToolsRange = this . getBuildToolsRange ( ) ;
113
114
let versionRangeMatches = buildToolsRange . match ( / ^ .* ?( [ \d \. ] + ) \s + .* ?( [ \d \. ] + ) $ / ) ;
114
115
let message = `You can install any version in the following range: '${ buildToolsRange } '.` ;
115
116
116
117
// Improve message in case buildToolsRange is something like: ">=22.0.0 <=22.0.0" - same numbers on both sides
117
- if ( versionRangeMatches && versionRangeMatches [ 1 ] && versionRangeMatches [ 2 ] && versionRangeMatches [ 1 ] === versionRangeMatches [ 2 ] ) {
118
+ if ( versionRangeMatches && versionRangeMatches [ 1 ] && versionRangeMatches [ 2 ] && versionRangeMatches [ 1 ] === versionRangeMatches [ 2 ] ) {
118
119
message = `You have to install version ${ versionRangeMatches [ 1 ] } .` ;
119
120
}
120
121
121
122
let invalidBuildToolsAdditionalMsg = 'Run `android` from your command-line to install required `Android Build Tools`.' ;
122
- if ( ! isAndroidHomeValid ) {
123
+ if ( ! isAndroidHomeValid ) {
123
124
invalidBuildToolsAdditionalMsg += ' In case you already have them installed, make sure `ANDROID_HOME` environment variable is set correctly.' ;
124
125
}
125
126
126
127
this . printMessage ( "You need to have the Android SDK Build-tools installed on your system. " + message , invalidBuildToolsAdditionalMsg ) ;
127
128
detectedErrors = true ;
128
129
}
129
130
130
- if ( ! toolsInfoData . supportRepositoryVersion ) {
131
+ if ( ! toolsInfoData . supportRepositoryVersion ) {
131
132
let invalidSupportLibAdditionalMsg = 'Run `$ android` to manage the Local Maven repository for Support Libraries.' ;
132
- if ( ! isAndroidHomeValid ) {
133
+ if ( ! isAndroidHomeValid ) {
133
134
invalidSupportLibAdditionalMsg += ' In case you already have it installed, make sure `ANDROID_HOME` environment variable is set correctly.' ;
134
135
}
135
136
this . printMessage ( `You need to have Android SDK ${ AndroidToolsInfo . MIN_REQUIRED_COMPILE_TARGET } or later and the latest Local Maven repository for Support Libraries installed on your system.` , invalidSupportLibAdditionalMsg ) ;
136
137
detectedErrors = true ;
137
138
}
138
139
139
- if ( options && options . validateTargetSdk ) {
140
+ if ( options && options . validateTargetSdk ) {
140
141
let targetSdk = toolsInfoData . targetSdkVersion ;
141
142
let newTarget = `${ AndroidToolsInfo . ANDROID_TARGET_PREFIX } -${ targetSdk } ` ;
142
- if ( ! _ . contains ( AndroidToolsInfo . SUPPORTED_TARGETS , newTarget ) ) {
143
+ if ( ! _ . contains ( AndroidToolsInfo . SUPPORTED_TARGETS , newTarget ) ) {
143
144
let supportedVersions = AndroidToolsInfo . SUPPORTED_TARGETS . sort ( ) ;
144
145
let minSupportedVersion = this . parseAndroidSdkString ( _ . first ( supportedVersions ) ) ;
145
146
146
- if ( targetSdk && ( targetSdk < minSupportedVersion ) ) {
147
+ if ( targetSdk && ( targetSdk < minSupportedVersion ) ) {
147
148
this . printMessage ( `The selected Android target SDK ${ newTarget } is not supported. You must target ${ minSupportedVersion } or later.` ) ;
148
149
detectedErrors = true ;
149
- } else if ( ! targetSdk || targetSdk > this . getMaxSupportedVersion ( ) ) {
150
+ } else if ( ! targetSdk || targetSdk > this . getMaxSupportedVersion ( ) ) {
150
151
this . $logger . warn ( `Support for the selected Android target SDK ${ newTarget } is not verified. Your Android app might not work as expected.` ) ;
151
152
}
152
153
}
@@ -156,18 +157,18 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
156
157
} ) . future < boolean > ( ) ( ) ;
157
158
}
158
159
159
- public validateJavacVersion ( installedJavaVersion : string , options ?: { showWarningsAsErrors : boolean } ) : IFuture < boolean > {
160
+ public validateJavacVersion ( installedJavaVersion : string , options ?: { showWarningsAsErrors : boolean } ) : IFuture < boolean > {
160
161
return ( ( ) : boolean => {
161
162
let hasProblemWithJavaVersion = false ;
162
- if ( options ) {
163
+ if ( options ) {
163
164
this . showWarningsAsErrors = options . showWarningsAsErrors ;
164
165
}
165
166
let additionalMessage = "You will not be able to build your projects for Android." + EOL
166
167
+ "To be able to build for Android, verify that you have installed The Java Development Kit (JDK) and configured it according to system requirements as" + EOL +
167
168
" described in https://github.com/NativeScript/nativescript-cli#system-requirements." ;
168
169
let matchingVersion = ( installedJavaVersion || "" ) . match ( AndroidToolsInfo . VERSION_REGEX ) ;
169
- if ( matchingVersion && matchingVersion [ 1 ] ) {
170
- if ( semver . lt ( matchingVersion [ 1 ] , AndroidToolsInfo . MIN_JAVA_VERSION ) ) {
170
+ if ( matchingVersion && matchingVersion [ 1 ] ) {
171
+ if ( semver . lt ( matchingVersion [ 1 ] , AndroidToolsInfo . MIN_JAVA_VERSION ) ) {
171
172
hasProblemWithJavaVersion = true ;
172
173
this . printMessage ( `Javac version ${ installedJavaVersion } is not supported. You have to install at least ${ AndroidToolsInfo . MIN_JAVA_VERSION } .` , additionalMessage ) ;
173
174
}
@@ -182,7 +183,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
182
183
183
184
public getPathToAdbFromAndroidHome ( ) : IFuture < string > {
184
185
return ( ( ) => {
185
- if ( this . androidHome ) {
186
+ if ( this . androidHome ) {
186
187
let pathToAdb = path . join ( this . androidHome , "platform-tools" , "adb" ) ;
187
188
try {
188
189
this . $childProcess . execFile ( pathToAdb , [ "help" ] ) . wait ( ) ;
@@ -214,29 +215,29 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
214
215
this . $logger . warn ( msg ) ;
215
216
}
216
217
217
- if ( additionalMsg ) {
218
+ if ( additionalMsg ) {
218
219
this . $logger . printMarkdown ( additionalMsg ) ;
219
220
}
220
221
}
221
222
222
223
private getCompileSdk ( ) : IFuture < number > {
223
224
return ( ( ) : number => {
224
- if ( ! this . selectedCompileSdk ) {
225
+ if ( ! this . selectedCompileSdk ) {
225
226
let userSpecifiedCompileSdk = this . $options . compileSdk ;
226
- if ( userSpecifiedCompileSdk ) {
227
+ if ( userSpecifiedCompileSdk ) {
227
228
let installedTargets = this . getInstalledTargets ( ) . wait ( ) ;
228
229
let androidCompileSdk = `${ AndroidToolsInfo . ANDROID_TARGET_PREFIX } -${ userSpecifiedCompileSdk } ` ;
229
- if ( ! _ . contains ( installedTargets , androidCompileSdk ) ) {
230
+ if ( ! _ . contains ( installedTargets , androidCompileSdk ) ) {
230
231
this . $errors . failWithoutHelp ( `You have specified '${ userSpecifiedCompileSdk } ' for compile sdk, but it is not installed on your system.` ) ;
231
232
}
232
233
233
234
this . selectedCompileSdk = userSpecifiedCompileSdk ;
234
235
} else {
235
236
let latestValidAndroidTarget = this . getLatestValidAndroidTarget ( ) . wait ( ) ;
236
- if ( latestValidAndroidTarget ) {
237
+ if ( latestValidAndroidTarget ) {
237
238
let integerVersion = this . parseAndroidSdkString ( latestValidAndroidTarget ) ;
238
239
239
- if ( integerVersion && integerVersion >= AndroidToolsInfo . MIN_REQUIRED_COMPILE_TARGET ) {
240
+ if ( integerVersion && integerVersion >= AndroidToolsInfo . MIN_REQUIRED_COMPILE_TARGET ) {
240
241
this . selectedCompileSdk = integerVersion ;
241
242
}
242
243
}
@@ -258,14 +259,14 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
258
259
private getMatchingDir ( pathToDir : string , versionRange : string ) : IFuture < string > {
259
260
return ( ( ) : string => {
260
261
let selectedVersion : string ;
261
- if ( this . $fs . exists ( pathToDir ) . wait ( ) ) {
262
+ if ( this . $fs . exists ( pathToDir ) . wait ( ) ) {
262
263
let subDirs = this . $fs . readDirectory ( pathToDir ) . wait ( ) ;
263
264
this . $logger . trace ( `Directories found in ${ pathToDir } are ${ subDirs . join ( ", " ) } ` ) ;
264
265
265
266
let subDirsVersions = subDirs
266
267
. map ( dirName => {
267
268
let dirNameGroups = dirName . match ( AndroidToolsInfo . VERSION_REGEX ) ;
268
- if ( dirNameGroups ) {
269
+ if ( dirNameGroups ) {
269
270
return dirNameGroups [ 1 ] ;
270
271
}
271
272
@@ -274,7 +275,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
274
275
. filter ( dirName => ! ! dirName ) ;
275
276
this . $logger . trace ( `Versions found in ${ pathToDir } are ${ subDirsVersions . join ( ", " ) } ` ) ;
276
277
let version = semver . maxSatisfying ( subDirsVersions , versionRange ) ;
277
- if ( version ) {
278
+ if ( version ) {
278
279
selectedVersion = _ . find ( subDirs , dir => dir . indexOf ( version ) !== - 1 ) ;
279
280
}
280
281
}
@@ -290,7 +291,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
290
291
private getBuildToolsVersion ( ) : IFuture < string > {
291
292
return ( ( ) : string => {
292
293
let buildToolsVersion : string ;
293
- if ( this . androidHome ) {
294
+ if ( this . androidHome ) {
294
295
let pathToBuildTools = path . join ( this . androidHome , "build-tools" ) ;
295
296
let buildToolsRange = this . getBuildToolsRange ( ) ;
296
297
buildToolsVersion = this . getMatchingDir ( pathToBuildTools , buildToolsRange ) . wait ( ) ;
@@ -304,7 +305,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
304
305
return ( ( ) : string => {
305
306
let compileSdkVersion = this . getCompileSdk ( ) . wait ( ) ;
306
307
let requiredAppCompatRange : string ;
307
- if ( compileSdkVersion ) {
308
+ if ( compileSdkVersion ) {
308
309
requiredAppCompatRange = `>=${ compileSdkVersion } <${ compileSdkVersion + 1 } ` ;
309
310
}
310
311
@@ -316,7 +317,7 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
316
317
return ( ( ) : string => {
317
318
let selectedAppCompatVersion : string ;
318
319
let requiredAppCompatRange = this . getAppCompatRange ( ) . wait ( ) ;
319
- if ( this . androidHome && requiredAppCompatRange ) {
320
+ if ( this . androidHome && requiredAppCompatRange ) {
320
321
let pathToAppCompat = path . join ( this . androidHome , "extras" , "android" , "m2repository" , "com" , "android" , "support" , "appcompat-v7" ) ;
321
322
selectedAppCompatVersion = this . getMatchingDir ( pathToAppCompat , requiredAppCompatRange ) . wait ( ) ;
322
323
}
@@ -342,15 +343,15 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
342
343
if ( ! this . installedTargetsCache ) {
343
344
try {
344
345
let pathToAndroidExecutable = this . getPathToAndroidExecutable ( ) . wait ( ) ;
345
- if ( pathToAndroidExecutable ) {
346
- let result = this . $childProcess . spawnFromEvent ( pathToAndroidExecutable , [ "list" , "targets" ] , "close" , { } , { throwError : false } ) . wait ( ) ;
347
- if ( result && result . stdout ) {
346
+ if ( pathToAndroidExecutable ) {
347
+ let result = this . $childProcess . spawnFromEvent ( pathToAndroidExecutable , [ "list" , "targets" ] , "close" , { } , { throwError : false } ) . wait ( ) ;
348
+ if ( result && result . stdout ) {
348
349
this . $logger . trace ( result . stdout ) ;
349
350
this . installedTargetsCache = [ ] ;
350
- result . stdout . replace ( / i d : \d + o r " ( .+ ) " / g, ( m :string , p1 :string ) => ( this . installedTargetsCache . push ( p1 ) , m ) ) ;
351
+ result . stdout . replace ( / i d : \d + o r " ( .+ ) " / g, ( m : string , p1 : string ) => ( this . installedTargetsCache . push ( p1 ) , m ) ) ;
351
352
}
352
353
}
353
- } catch ( err ) {
354
+ } catch ( err ) {
354
355
this . $logger . trace ( "Unable to get Android targets. Error is: " + err ) ;
355
356
}
356
357
}
@@ -365,14 +366,14 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
365
366
private _cachedAndroidHomeValidationResult : boolean = null ;
366
367
private validateAndroidHomeEnvVariable ( androidHomeEnvVar : string ) : IFuture < boolean > {
367
368
return ( ( ) : boolean => {
368
- if ( this . _cachedAndroidHomeValidationResult === null ) {
369
+ if ( this . _cachedAndroidHomeValidationResult === null ) {
369
370
this . _cachedAndroidHomeValidationResult = true ;
370
371
let expectedDirectoriesInAndroidHome = [ "build-tools" , "tools" , "platform-tools" , "extras" ] ;
371
- if ( ! androidHomeEnvVar || ! this . $fs . exists ( androidHomeEnvVar ) . wait ( ) ) {
372
+ if ( ! androidHomeEnvVar || ! this . $fs . exists ( androidHomeEnvVar ) . wait ( ) ) {
372
373
this . printMessage ( "The ANDROID_HOME environment variable is not set or it points to a non-existent directory. You will not be able to perform any build-related operations for Android." ,
373
374
"To be able to perform Android build-related operations, set the `ANDROID_HOME` variable to point to the root of your Android SDK installation directory." ) ;
374
375
this . _cachedAndroidHomeValidationResult = false ;
375
- } else if ( ! _ . any ( expectedDirectoriesInAndroidHome . map ( dir => this . $fs . exists ( path . join ( androidHomeEnvVar , dir ) ) . wait ( ) ) ) ) {
376
+ } else if ( ! _ . any ( expectedDirectoriesInAndroidHome . map ( dir => this . $fs . exists ( path . join ( androidHomeEnvVar , dir ) ) . wait ( ) ) ) ) {
376
377
this . printMessage ( "The ANDROID_HOME environment variable points to incorrect directory. You will not be able to perform any build-related operations for Android." ,
377
378
"To be able to perform Android build-related operations, set the `ANDROID_HOME` variable to point to the root of your Android SDK installation directory, " +
378
379
"where you will find `tools` and `platform-tools` directories." ) ;
0 commit comments