@@ -6,10 +6,11 @@ import { Helpers } from './helpers';
66import { EOL } from "os" ;
77import * as semver from "semver" ;
88import * as path from "path" ;
9+ import * as _ from "lodash" ;
910
1011export class AndroidToolsInfo implements NativeScriptDoctor . IAndroidToolsInfo {
11- private static ANDROID_TARGET_PREFIX = "android" ;
12- private static SUPPORTED_TARGETS = [
12+ public readonly ANDROID_TARGET_PREFIX = "android" ;
13+ public readonly SUPPORTED_TARGETS = [
1314 "android-17" ,
1415 "android-18" ,
1516 "android-19" ,
@@ -22,13 +23,15 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
2223 "android-27" ,
2324 "android-28" ,
2425 ] ;
25- private static MIN_REQUIRED_COMPILE_TARGET = 28 ;
26- private static REQUIRED_BUILD_TOOLS_RANGE_PREFIX = ">=23" ;
27- private static VERSION_REGEX = / ( ( \d + \. ) { 2 } \d + ) / ;
26+ public readonly MIN_REQUIRED_COMPILE_TARGET = 28 ;
27+ public readonly REQUIRED_BUILD_TOOLS_RANGE_PREFIX = ">=23" ;
28+ public readonly VERSION_REGEX = / ( ( \d + \. ) { 2 } \d + ) / ;
2829 private static MIN_JAVA_VERSION = "1.8.0" ;
2930
3031 private toolsInfo : NativeScriptDoctor . IAndroidToolsInfoData ;
31- private androidHome = process . env [ "ANDROID_HOME" ] ;
32+ public get androidHome ( ) : string {
33+ return process . env [ "ANDROID_HOME" ] ;
34+ }
3235 private pathToEmulatorExecutable : string ;
3336
3437 constructor ( private childProcess : ChildProcess ,
@@ -40,8 +43,11 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
4043 if ( ! this . toolsInfo ) {
4144 const infoData : NativeScriptDoctor . IAndroidToolsInfoData = Object . create ( null ) ;
4245 infoData . androidHomeEnvVar = this . androidHome ;
43- infoData . compileSdkVersion = this . getCompileSdk ( ) ;
46+ infoData . installedTargets = this . getInstalledTargets ( ) ;
47+ infoData . latestValidAndroidTarget = this . getLatestValidAndroidTarget ( infoData . installedTargets ) ;
48+ infoData . compileSdkVersion = this . getCompileSdk ( infoData . latestValidAndroidTarget ) ;
4449 infoData . buildToolsVersion = this . getBuildToolsVersion ( ) ;
50+ infoData . maxSupportedSdkVersion = this . getMaxSupportedVersion ( ) ;
4551
4652 this . toolsInfo = infoData ;
4753 }
@@ -55,7 +61,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
5561 const isAndroidHomeValid = this . isAndroidHomeValid ( ) ;
5662 if ( ! toolsInfoData . compileSdkVersion ) {
5763 errors . push ( {
58- warning : `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.` ,
64+ warning : `Cannot find a compatible Android SDK for compilation. To be able to build for Android, install Android SDK ${ this . MIN_REQUIRED_COMPILE_TARGET } or later.` ,
5965 additionalInformation : `Run \`\$ ${ this . getPathToSdkManagementTool ( ) } \` to manage your Android SDK versions.` ,
6066 platforms : [ Constants . ANDROID_PLATFORM_NAME ]
6167 } ) ;
@@ -93,7 +99,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
9399 + "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 +
94100 " described in " + this . getSystemRequirementsLink ( ) ;
95101
96- const matchingVersion = this . helpers . appendZeroesToVersion ( installedJavaCompilerVersion || "" , 3 ) . match ( AndroidToolsInfo . VERSION_REGEX ) ;
102+ const matchingVersion = this . helpers . appendZeroesToVersion ( installedJavaCompilerVersion || "" , 3 ) . match ( this . VERSION_REGEX ) ;
97103 const installedJavaCompilerSemverVersion = matchingVersion && matchingVersion [ 1 ] ;
98104 if ( installedJavaCompilerSemverVersion ) {
99105 let warning : string = null ;
@@ -145,7 +151,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
145151
146152 public async getPathToAdbFromAndroidHome ( ) : Promise < string > {
147153 if ( this . androidHome ) {
148- let pathToAdb = path . join ( this . androidHome , "platform-tools" , "adb" ) ;
154+ const pathToAdb = path . join ( this . androidHome , "platform-tools" , "adb" ) ;
149155 try {
150156 await this . childProcess . execFile ( pathToAdb , [ "help" ] ) ;
151157 return pathToAdb ;
@@ -179,6 +185,43 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
179185 return errors ;
180186 }
181187
188+ public validateMinSupportedTargetSdk ( targetSdk : number ) : NativeScriptDoctor . IWarning [ ] {
189+ const errors : NativeScriptDoctor . IWarning [ ] = [ ] ;
190+ const newTarget = `${ this . ANDROID_TARGET_PREFIX } -${ targetSdk } ` ;
191+ const targetSupported = _ . includes ( this . SUPPORTED_TARGETS , newTarget ) ;
192+
193+ if ( ! _ . includes ( this . SUPPORTED_TARGETS , newTarget ) ) {
194+ const supportedVersions = this . SUPPORTED_TARGETS . sort ( ) ;
195+ const minSupportedVersion = this . parseAndroidSdkString ( _ . first ( supportedVersions ) ) ;
196+
197+ if ( ! targetSupported && targetSdk && ( targetSdk < minSupportedVersion ) ) {
198+ errors . push ( {
199+ warning :`The selected Android target SDK ${ newTarget } is not supported. You must target ${ minSupportedVersion } or later.` ,
200+ additionalInformation : "" ,
201+ platforms : [ Constants . ANDROID_PLATFORM_NAME ]
202+ } ) ;
203+ }
204+ }
205+
206+ return [ ] ;
207+ }
208+
209+ public validataMaxSupportedTargetSdk ( targetSdk : number ) : NativeScriptDoctor . IWarning [ ] {
210+ const errors : NativeScriptDoctor . IWarning [ ] = [ ] ;
211+ const newTarget = `${ this . ANDROID_TARGET_PREFIX } -${ targetSdk } ` ;
212+ const targetSupported = _ . includes ( this . SUPPORTED_TARGETS , newTarget ) ;
213+
214+ if ( ! targetSupported && ! targetSdk || targetSdk > this . getMaxSupportedVersion ( ) ) {
215+ errors . push ( {
216+ warning :`Support for the selected Android target SDK ${ newTarget } is not verified. Your Android app might not work as expected.` ,
217+ additionalInformation : "" ,
218+ platforms : [ Constants . ANDROID_PLATFORM_NAME ]
219+ } ) ;
220+ }
221+
222+ return errors ;
223+ }
224+
182225 public getPathToEmulatorExecutable ( ) : string {
183226 if ( ! this . pathToEmulatorExecutable ) {
184227 const emulatorExecutableName = "emulator" ;
@@ -222,12 +265,11 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
222265 return sdkManagementToolPath ;
223266 }
224267
225- private getCompileSdk ( ) : number {
226- let latestValidAndroidTarget = this . getLatestValidAndroidTarget ( ) ;
268+ private getCompileSdk ( latestValidAndroidTarget : string ) : number {
227269 if ( latestValidAndroidTarget ) {
228- let integerVersion = this . parseAndroidSdkString ( latestValidAndroidTarget ) ;
270+ const integerVersion = this . parseAndroidSdkString ( latestValidAndroidTarget ) ;
229271
230- if ( integerVersion && integerVersion >= AndroidToolsInfo . MIN_REQUIRED_COMPILE_TARGET ) {
272+ if ( integerVersion && integerVersion >= this . MIN_REQUIRED_COMPILE_TARGET ) {
231273 return integerVersion ;
232274 }
233275 }
@@ -236,11 +278,11 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
236278 private getMatchingDir ( pathToDir : string , versionRange : string ) : string {
237279 let selectedVersion : string ;
238280 if ( this . fs . exists ( pathToDir ) ) {
239- let subDirs = this . fs . readDirectory ( pathToDir ) ;
281+ const subDirs = this . fs . readDirectory ( pathToDir ) ;
240282
241- let subDirsVersions = subDirs
283+ const subDirsVersions = subDirs
242284 . map ( dirName => {
243- let dirNameGroups = dirName . match ( AndroidToolsInfo . VERSION_REGEX ) ;
285+ const dirNameGroups = dirName . match ( this . VERSION_REGEX ) ;
244286 if ( dirNameGroups ) {
245287 return dirNameGroups [ 1 ] ;
246288 }
@@ -249,7 +291,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
249291 } )
250292 . filter ( dirName => ! ! dirName ) ;
251293
252- let version = semver . maxSatisfying ( subDirsVersions , versionRange ) ;
294+ const version = semver . maxSatisfying ( subDirsVersions , versionRange ) ;
253295 if ( version ) {
254296 selectedVersion = subDirs . find ( dir => dir . indexOf ( version ) !== - 1 ) ;
255297 }
@@ -259,36 +301,26 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
259301 }
260302
261303 private getBuildToolsRange ( ) : string {
262- return `${ AndroidToolsInfo . REQUIRED_BUILD_TOOLS_RANGE_PREFIX } <=${ this . getMaxSupportedVersion ( ) } ` ;
304+ return `${ this . REQUIRED_BUILD_TOOLS_RANGE_PREFIX } <=${ this . getMaxSupportedVersion ( ) } ` ;
263305 }
264306
265307 private getBuildToolsVersion ( ) : string {
266308 let buildToolsVersion : string ;
267309 if ( this . androidHome ) {
268- let pathToBuildTools = path . join ( this . androidHome , "build-tools" ) ;
269- let buildToolsRange = this . getBuildToolsRange ( ) ;
310+ const pathToBuildTools = path . join ( this . androidHome , "build-tools" ) ;
311+ const buildToolsRange = this . getBuildToolsRange ( ) ;
270312 buildToolsVersion = this . getMatchingDir ( pathToBuildTools , buildToolsRange ) ;
271313 }
272314
273315 return buildToolsVersion ;
274316 }
275317
276- private getLatestValidAndroidTarget ( ) : string {
277- const installedTargets = this . getInstalledTargets ( ) ;
278- let latestValidAndroidTarget : string ;
279- const sortedAndroidToolsInfo = AndroidToolsInfo . SUPPORTED_TARGETS . sort ( ) ;
280-
281- sortedAndroidToolsInfo . forEach ( s => {
282- if ( installedTargets . indexOf ( s ) >= 0 ) {
283- latestValidAndroidTarget = s ;
284- }
285- } ) ;
286-
287- return latestValidAndroidTarget ;
318+ private getLatestValidAndroidTarget ( installedTargets : string [ ] ) : string {
319+ return _ . findLast ( this . SUPPORTED_TARGETS . sort ( ) , supportedTarget => _ . includes ( installedTargets , supportedTarget ) ) ;
288320 }
289321
290322 private parseAndroidSdkString ( androidSdkString : string ) : number {
291- return parseInt ( androidSdkString . replace ( `${ AndroidToolsInfo . ANDROID_TARGET_PREFIX } -` , "" ) ) ;
323+ return parseInt ( androidSdkString . replace ( `${ this . ANDROID_TARGET_PREFIX } -` , "" ) ) ;
292324 }
293325
294326 private getInstalledTargets ( ) : string [ ] {
@@ -305,7 +337,7 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
305337 }
306338
307339 private getMaxSupportedVersion ( ) : number {
308- return this . parseAndroidSdkString ( AndroidToolsInfo . SUPPORTED_TARGETS . sort ( ) [ AndroidToolsInfo . SUPPORTED_TARGETS . length - 1 ] ) ;
340+ return this . parseAndroidSdkString ( this . SUPPORTED_TARGETS . sort ( ) [ this . SUPPORTED_TARGETS . length - 1 ] ) ;
309341 }
310342
311343 private getSystemRequirementsLink ( ) : string {
0 commit comments