1
1
import * as path from "path" ;
2
- import * as semver from "semver" ;
3
2
import { cache } from "./common/decorators" ;
4
3
import { androidToolsInfo } from "nativescript-doctor" ;
5
4
6
5
export class AndroidToolsInfo implements IAndroidToolsInfo {
7
- private static ANDROID_TARGET_PREFIX = "android" ;
8
- private static SUPPORTED_TARGETS = [
9
- "android-17" ,
10
- "android-18" ,
11
- "android-19" ,
12
- "android-21" ,
13
- "android-22" ,
14
- "android-23" ,
15
- "android-24" ,
16
- "android-25" ,
17
- "android-26" ,
18
- "android-27" ,
19
- "android-28" ,
20
- ] ;
21
- private static MIN_REQUIRED_COMPILE_TARGET = 28 ;
22
- private static REQUIRED_BUILD_TOOLS_RANGE_PREFIX = ">=23" ;
23
- private static VERSION_REGEX = / ( ( \d + \. ) { 2 } \d + ) / ;
24
-
25
- private showWarningsAsErrors : boolean ;
26
- private toolsInfo : IAndroidToolsInfoData ;
27
- private selectedCompileSdk : number ;
28
- private get androidHome ( ) : string {
29
- return process . env [ "ANDROID_HOME" ] ;
30
- }
31
-
32
6
constructor ( private $errors : IErrors ,
33
- private $fs : IFileSystem ,
34
7
private $logger : ILogger ,
35
8
private $options : IOptions ,
36
9
protected $staticConfig : Config . IStaticConfig ) {
37
10
}
38
11
39
12
@cache ( )
40
13
public getToolsInfo ( ) : IAndroidToolsInfoData {
41
- if ( ! this . toolsInfo ) {
42
- const infoData : IAndroidToolsInfoData = Object . create ( null ) ;
43
- infoData . androidHomeEnvVar = this . androidHome ;
44
- infoData . compileSdkVersion = this . getCompileSdkVersion ( ) ;
45
- infoData . buildToolsVersion = this . getBuildToolsVersion ( ) ;
46
- infoData . targetSdkVersion = this . getTargetSdk ( ) ;
47
- infoData . generateTypings = this . shouldGenerateTypings ( ) ;
48
-
49
- this . toolsInfo = infoData ;
50
- }
14
+ const infoData : IAndroidToolsInfoData = < IAndroidToolsInfoData > ( androidToolsInfo . getToolsInfo ( ) ) ;
15
+
16
+ infoData . androidHomeEnvVar = androidToolsInfo . androidHome ;
17
+ infoData . compileSdkVersion = this . getCompileSdkVersion ( infoData . installedTargets , infoData . compileSdkVersion ) ;
18
+ infoData . targetSdkVersion = this . getTargetSdk ( infoData . compileSdkVersion ) ;
19
+ infoData . generateTypings = this . shouldGenerateTypings ( ) ;
20
+
21
+ this . $logger . trace ( "Installed Android Targets are: " , infoData . installedTargets ) ;
22
+ this . $logger . trace ( "Selected buildToolsVersion is:" , infoData . buildToolsVersion ) ;
51
23
52
- return this . toolsInfo ;
24
+ return infoData ;
53
25
}
54
26
55
27
public validateInfo ( options ?: IAndroidToolsInfoValidateInput ) : boolean {
56
28
let detectedErrors = false ;
57
- this . showWarningsAsErrors = options && options . showWarningsAsErrors ;
58
- const isAndroidHomeValid = this . validateAndroidHomeEnvVariable ( ) ;
29
+ const showWarningsAsErrors = options && options . showWarningsAsErrors ;
30
+ const isAndroidHomeValid = this . validateAndroidHomeEnvVariable ( options ) ;
59
31
60
- detectedErrors = androidToolsInfo . validateInfo ( ) . map ( warning => this . printMessage ( warning . warning ) ) . length > 0 ;
32
+ detectedErrors = androidToolsInfo . validateInfo ( ) . map ( warning => this . printMessage ( warning . warning , showWarningsAsErrors ) ) . length > 0 ;
61
33
62
34
if ( options && options . validateTargetSdk ) {
63
- detectedErrors = this . validateTargetSdk ( ) ;
35
+ detectedErrors = this . validateTargetSdk ( options ) ;
64
36
}
65
37
66
38
return detectedErrors || ! isAndroidHomeValid ;
67
39
}
68
40
69
41
public validateTargetSdk ( options ?: IAndroidToolsInfoOptions ) : boolean {
70
- this . showWarningsAsErrors = options && options . showWarningsAsErrors ;
42
+ let detectedErrors = false ;
43
+ const showWarningsAsErrors = options && options . showWarningsAsErrors ;
71
44
72
45
const toolsInfoData = this . getToolsInfo ( ) ;
73
46
const targetSdk = toolsInfoData . targetSdkVersion ;
74
- const newTarget = `${ AndroidToolsInfo . ANDROID_TARGET_PREFIX } -${ targetSdk } ` ;
75
47
76
- if ( ! _ . includes ( AndroidToolsInfo . SUPPORTED_TARGETS , newTarget ) ) {
77
- const supportedVersions = AndroidToolsInfo . SUPPORTED_TARGETS . sort ( ) ;
78
- const minSupportedVersion = this . parseAndroidSdkString ( _ . first ( supportedVersions ) ) ;
48
+ detectedErrors = androidToolsInfo . validateMinSupportedTargetSdk ( targetSdk ) . map ( warning => this . printMessage ( warning . warning , showWarningsAsErrors ) ) . length > 0 ;
79
49
80
- if ( targetSdk && ( targetSdk < minSupportedVersion ) ) {
81
- this . printMessage ( `The selected Android target SDK ${ newTarget } is not supported. You must target ${ minSupportedVersion } or later.` ) ;
82
- return true ;
83
- } else if ( ! targetSdk || targetSdk > this . getMaxSupportedVersion ( ) ) {
84
- this . $logger . warn ( `Support for the selected Android target SDK ${ newTarget } is not verified. Your Android app might not work as expected.` ) ;
85
- }
50
+ if ( ! detectedErrors ) {
51
+ androidToolsInfo . validataMaxSupportedTargetSdk ( targetSdk ) . map ( warning => this . $logger . warn ( warning . warning ) ) ;
86
52
}
87
53
88
- return false ;
54
+ return detectedErrors ;
89
55
}
90
56
91
57
public validateJavacVersion ( installedJavacVersion : string , options ?: IAndroidToolsInfoOptions ) : boolean {
92
- if ( options ) {
93
- this . showWarningsAsErrors = options . showWarningsAsErrors ;
94
- }
58
+ const showWarningsAsErrors = options && options . showWarningsAsErrors ;
95
59
96
- return androidToolsInfo . validateJavacVersion ( installedJavacVersion ) . map ( warning => this . printMessage ( warning . warning ) ) . length > 0 ;
60
+ return androidToolsInfo . validateJavacVersion ( installedJavacVersion ) . map ( warning => this . printMessage ( warning . warning , showWarningsAsErrors ) ) . length > 0 ;
97
61
}
98
62
99
63
public async getPathToAdbFromAndroidHome ( ) : Promise < string > {
@@ -102,19 +66,17 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
102
66
} catch ( err ) {
103
67
// adb does not exist, so ANDROID_HOME is not set correctly
104
68
// try getting default adb path (included in CLI package)
105
- this . $logger . trace ( `Error while executing '${ path . join ( this . androidHome , "platform-tools" , "adb" ) } help'. Error is: ${ err . message } ` ) ;
69
+ this . $logger . trace ( `Error while executing '${ path . join ( androidToolsInfo . androidHome , "platform-tools" , "adb" ) } help'. Error is: ${ err . message } ` ) ;
106
70
}
107
71
108
72
return null ;
109
73
}
110
74
111
75
@cache ( )
112
76
public validateAndroidHomeEnvVariable ( options ?: IAndroidToolsInfoOptions ) : boolean {
113
- if ( options ) {
114
- this . showWarningsAsErrors = options . showWarningsAsErrors ;
115
- }
77
+ const showWarningsAsErrors = options && options . showWarningsAsErrors ;
116
78
117
- return androidToolsInfo . validateAndroidHomeEnvVariable ( ) . map ( warning => this . printMessage ( warning . warning ) ) . length > 0 ;
79
+ return androidToolsInfo . validateAndroidHomeEnvVariable ( ) . map ( warning => this . printMessage ( warning . warning , showWarningsAsErrors ) ) . length > 0 ;
118
80
}
119
81
120
82
private shouldGenerateTypings ( ) : boolean {
@@ -127,119 +89,36 @@ export class AndroidToolsInfo implements IAndroidToolsInfo {
127
89
* In case additional details must be shown as info message, use the second parameter.
128
90
* NOTE: The additional information will not be printed when showWarningsAsErrors flag is set.
129
91
* @param {string } msg The message that will be shown as warning or error.
130
- * @param {string } additionalMsg The additional message that will be shown as info message.
131
92
* @return {void }
132
93
*/
133
- private printMessage ( msg : string , additionalMsg ?: string ) : void {
134
- if ( this . showWarningsAsErrors ) {
94
+ private printMessage ( msg : string , showWarningsAsErrors : boolean ) : void {
95
+ if ( showWarningsAsErrors ) {
135
96
this . $errors . failWithoutHelp ( msg ) ;
136
97
} else {
137
98
this . $logger . warn ( msg ) ;
138
99
}
139
-
140
- if ( additionalMsg ) {
141
- this . $logger . printMarkdown ( additionalMsg ) ;
142
- }
143
100
}
144
101
145
- private getCompileSdkVersion ( ) : number {
146
- if ( ! this . selectedCompileSdk ) {
147
- const userSpecifiedCompileSdk = this . $options . compileSdk ;
148
- if ( userSpecifiedCompileSdk ) {
149
- const installedTargets = this . getInstalledTargets ( ) ;
150
- const androidCompileSdk = `${ AndroidToolsInfo . ANDROID_TARGET_PREFIX } -${ userSpecifiedCompileSdk } ` ;
151
- if ( ! _ . includes ( installedTargets , androidCompileSdk ) ) {
152
- this . $errors . failWithoutHelp ( `You have specified '${ userSpecifiedCompileSdk } ' for compile sdk, but it is not installed on your system.` ) ;
153
- }
154
-
155
- this . selectedCompileSdk = userSpecifiedCompileSdk ;
156
- } else {
157
- const latestValidAndroidTarget = this . getLatestValidAndroidTarget ( ) ;
158
- if ( latestValidAndroidTarget ) {
159
- const integerVersion = this . parseAndroidSdkString ( latestValidAndroidTarget ) ;
160
-
161
- if ( integerVersion && integerVersion >= AndroidToolsInfo . MIN_REQUIRED_COMPILE_TARGET ) {
162
- this . selectedCompileSdk = integerVersion ;
163
- }
164
- }
165
- }
166
- }
102
+ private getCompileSdkVersion ( installedTargets : string [ ] , latestCompileSdk : number ) : number {
103
+ const userSpecifiedCompileSdk = this . $options . compileSdk ;
167
104
168
- return this . selectedCompileSdk ;
169
- }
170
-
171
- private getTargetSdk ( ) : number {
172
- const targetSdk = this . $options . sdk ? parseInt ( this . $options . sdk ) : this . getCompileSdkVersion ( ) ;
173
- this . $logger . trace ( `Selected targetSdk is: ${ targetSdk } ` ) ;
174
- return targetSdk ;
175
- }
176
-
177
- private getMatchingDir ( pathToDir : string , versionRange : string ) : string {
178
- let selectedVersion : string ;
179
- if ( this . $fs . exists ( pathToDir ) ) {
180
- const subDirs = this . $fs . readDirectory ( pathToDir ) ;
181
- this . $logger . trace ( `Directories found in ${ pathToDir } are ${ subDirs . join ( ", " ) } ` ) ;
182
-
183
- const subDirsVersions = subDirs
184
- . map ( dirName => {
185
- const dirNameGroups = dirName . match ( AndroidToolsInfo . VERSION_REGEX ) ;
186
- if ( dirNameGroups ) {
187
- return dirNameGroups [ 1 ] ;
188
- }
189
-
190
- return null ;
191
- } )
192
- . filter ( dirName => ! ! dirName ) ;
193
- this . $logger . trace ( `Versions found in ${ pathToDir } are ${ subDirsVersions . join ( ", " ) } ` ) ;
194
- const version = semver . maxSatisfying ( subDirsVersions , versionRange ) ;
195
- if ( version ) {
196
- selectedVersion = _ . find ( subDirs , dir => dir . indexOf ( version ) !== - 1 ) ;
105
+ if ( userSpecifiedCompileSdk ) {
106
+ const androidCompileSdk = `${ androidToolsInfo . ANDROID_TARGET_PREFIX } -${ userSpecifiedCompileSdk } ` ;
107
+ if ( ! _ . includes ( installedTargets , androidCompileSdk ) ) {
108
+ this . $errors . failWithoutHelp ( `You have specified '${ userSpecifiedCompileSdk } ' for compile sdk, but it is not installed on your system.` ) ;
197
109
}
198
- }
199
- this . $logger . trace ( "Selected version is: " , selectedVersion ) ;
200
- return selectedVersion ;
201
- }
202
-
203
- private getBuildToolsRange ( ) : string {
204
- return `${ AndroidToolsInfo . REQUIRED_BUILD_TOOLS_RANGE_PREFIX } <=${ this . getMaxSupportedVersion ( ) } ` ;
205
- }
206
110
207
- private getBuildToolsVersion ( ) : string {
208
- let buildToolsVersion : string ;
209
- if ( this . androidHome ) {
210
- const pathToBuildTools = path . join ( this . androidHome , "build-tools" ) ;
211
- const buildToolsRange = this . getBuildToolsRange ( ) ;
212
- buildToolsVersion = this . getMatchingDir ( pathToBuildTools , buildToolsRange ) ;
111
+ return userSpecifiedCompileSdk ;
213
112
}
214
113
215
- return buildToolsVersion ;
216
- }
217
-
218
- private getLatestValidAndroidTarget ( ) : string {
219
- const installedTargets = this . getInstalledTargets ( ) ;
220
- return _ . findLast ( AndroidToolsInfo . SUPPORTED_TARGETS . sort ( ) , supportedTarget => _ . includes ( installedTargets , supportedTarget ) ) ;
221
- }
222
-
223
- private parseAndroidSdkString ( androidSdkString : string ) : number {
224
- return parseInt ( androidSdkString . replace ( `${ AndroidToolsInfo . ANDROID_TARGET_PREFIX } -` , "" ) ) ;
114
+ return latestCompileSdk ;
225
115
}
226
116
227
- @cache ( )
228
- private getInstalledTargets ( ) : string [ ] {
229
- let installedTargets : string [ ] = [ ] ;
230
- if ( this . androidHome ) {
231
- const pathToInstalledTargets = path . join ( this . androidHome , "platforms" ) ;
232
- if ( this . $fs . exists ( pathToInstalledTargets ) ) {
233
- installedTargets = this . $fs . readDirectory ( pathToInstalledTargets ) ;
234
- }
235
- }
236
- this . $logger . trace ( "Installed Android Targets are: " , installedTargets ) ;
237
-
238
- return installedTargets ;
239
- }
240
-
241
- private getMaxSupportedVersion ( ) : number {
242
- return this . parseAndroidSdkString ( _ . last ( AndroidToolsInfo . SUPPORTED_TARGETS . sort ( ) ) ) ;
117
+ // TODO check if still needed
118
+ private getTargetSdk ( compileSdk : number ) : number {
119
+ const targetSdk = this . $options . sdk ? parseInt ( this . $options . sdk ) : compileSdk ;
120
+ this . $logger . trace ( `Selected targetSdk is: ${ targetSdk } ` ) ;
121
+ return targetSdk ;
243
122
}
244
123
}
245
124
$injector . register ( "androidToolsInfo" , AndroidToolsInfo ) ;
0 commit comments