@@ -72,8 +72,8 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
7272 const errors : NativeScriptDoctor . IWarning [ ] = [ ] ;
7373 const toolsInfoData = this . getToolsInfo ( config ) ;
7474 const isAndroidHomeValid = this . isAndroidHomeValid ( ) ;
75- const runtimeVersion = this . getRuntimeVersion ( config ) ;
76- const supportsOnlyMinRequiredCompileTarget = this . getMaxSupportedCompileVersion ( runtimeVersion ) === AndroidToolsInfo . MIN_REQUIRED_COMPILE_TARGET ;
75+ const supportsOnlyMinRequiredCompileTarget = this . getMaxSupportedCompileVersion ( config ) === AndroidToolsInfo . MIN_REQUIRED_COMPILE_TARGET ;
76+
7777 if ( ! toolsInfoData . compileSdkVersion ) {
7878 errors . push ( {
7979 warning : `Cannot find a compatible Android SDK for compilation. To be able to build for Android, install Android SDK ${ AndroidToolsInfo . MIN_REQUIRED_COMPILE_TARGET } ${ supportsOnlyMinRequiredCompileTarget ? "" : " or later" } .` ,
@@ -367,68 +367,97 @@ export class AndroidToolsInfo implements NativeScriptDoctor.IAndroidToolsInfo {
367367 return ! errors && ! errors . length ;
368368 }
369369
370- private getAndroidRuntimeVersionFromProjectDir ( projectDir : string ) : string {
371- let runtimePackage : string = null ;
372- let runtimeVersion : string = null ;
373- if ( projectDir && this . fs . exists ( projectDir ) ) {
374- const pathToPackageJson = path . join ( projectDir , Constants . PACKAGE_JSON ) ;
375-
376- if ( this . fs . exists ( pathToPackageJson ) ) {
377- const content = this . fs . readJson < INativeScriptProjectPackageJson > ( pathToPackageJson ) ;
378- const scopedRuntime = "@nativescript/android" ;
379- const oldRuntime = "tns-android" ;
380- if ( content ) {
381- if ( content . devDependencies && content . devDependencies [ scopedRuntime ] ) {
382- runtimePackage = scopedRuntime ;
383- runtimeVersion = content . devDependencies [ scopedRuntime ] ;
384- } else if ( content . nativescript && content . nativescript [ oldRuntime ] && content . nativescript [ oldRuntime ] . version ) {
385- runtimePackage = oldRuntime ;
386- runtimeVersion = content && content . nativescript && content . nativescript [ oldRuntime ] && content . nativescript [ oldRuntime ] . version ;
387- }
388- }
389-
390- }
391- }
392-
393- if ( runtimeVersion && runtimeVersion . includes ( 'tgz' ) ) {
394- try {
395- runtimeVersion = require ( `${ runtimePackage } /package.json` ) . version ;
396- } catch ( err ) {
397- runtimeVersion = null ;
398- }
399- }
400-
401- return runtimeVersion ;
370+ private getAndroidRuntimePackageFromProjectDir ( projectDir : string ) : { name : string , version : string } {
371+ if ( ! projectDir || ! this . fs . exists ( projectDir ) ) {
372+ return null
373+ }
374+ const pathToPackageJson = path . join ( projectDir , Constants . PACKAGE_JSON ) ;
375+
376+ if ( ! this . fs . exists ( pathToPackageJson ) ) {
377+ return null
378+ }
379+
380+ const content = this . fs . readJson < INativeScriptProjectPackageJson > ( pathToPackageJson ) ;
381+
382+ if ( ! content ) {
383+ return null
384+ }
385+
386+ // in case we have a nativescript key and a runtime with a version
387+ // we are dealing with a legacy project and should respect the values
388+ // in the nativescript key
389+ if ( content && content . nativescript && content . nativescript [ 'tns-android' ] && content . nativescript [ 'tns-android' ] . version ) {
390+ return {
391+ name : Constants . ANDROID_OLD_RUNTIME ,
392+ version : content . nativescript && content . nativescript [ 'tns-android' ] && content . nativescript [ 'tns-android' ] . version
393+ } ;
394+ }
395+
396+ if ( content && content . devDependencies ) {
397+ const foundRuntime = Object . keys ( content . devDependencies ) . find ( depName => {
398+ return depName === Constants . ANDROID_SCOPED_RUNTIME || depName === Constants . ANDROID_OLD_RUNTIME
399+ } )
400+
401+ if ( foundRuntime ) {
402+ let version = content . devDependencies [ foundRuntime ]
403+
404+ if ( version . includes ( 'tgz' ) ) {
405+ try {
406+ const packagePath = require . resolve ( `${ foundRuntime } /package.json` , {
407+ paths : [ projectDir ]
408+ } )
409+ version = require ( packagePath ) . version ;
410+ } catch ( err ) {
411+ version = '*' ;
412+ }
413+ }
414+
415+ return {
416+ name : foundRuntime ,
417+ version
418+ }
419+ }
420+ }
421+
422+ return null
402423 }
403424
404425 private getRuntimeVersion ( { runtimeVersion, projectDir } : { runtimeVersion ?: string , projectDir ?: string } ) : string {
405- runtimeVersion = runtimeVersion || this . getAndroidRuntimeVersionFromProjectDir ( projectDir ) ;
426+ let runtimePackage = {
427+ name : Constants . ANDROID_SCOPED_RUNTIME ,
428+ version : runtimeVersion
429+ }
430+ if ( ! runtimeVersion ) {
431+ runtimePackage = this . getAndroidRuntimePackageFromProjectDir ( projectDir )
432+ runtimeVersion = runtimePackage ?. version ;
433+ }
434+
406435 if ( runtimeVersion ) {
407436 // Check if the version is not "next" or "rc", i.e. tag from npm
408- if ( ! semver . valid ( runtimeVersion ) ) {
437+ if ( ! semver . validRange ( runtimeVersion ) ) {
409438 try {
410- const npmViewOutput = this . childProcess . execSync ( `npm view ${ Constants . ANDROID_RUNTIME } dist-tags --json` ) ;
439+ const npmViewOutput = this . childProcess . execSync ( `npm view ${ runtimePackage . name } dist-tags --json` ) ;
411440 const jsonNpmViewOutput = JSON . parse ( npmViewOutput ) ;
441+
412442 runtimeVersion = jsonNpmViewOutput [ runtimeVersion ] || runtimeVersion ;
413443 } catch ( err ) {
414444 // Maybe there's no npm here
415445 }
416446 }
417447 }
418448
419- if ( runtimeVersion && ! semver . valid ( runtimeVersion ) ) {
449+ if ( runtimeVersion && ! semver . validRange ( runtimeVersion ) ) {
420450 // If we got here, something terribly wrong happened.
421451 throw new Error ( `The determined Android runtime version ${ runtimeVersion } is not valid. Unable to verify if the current system is setup for Android development.` ) ;
422452 }
423453
424454 return runtimeVersion ;
425455 }
426456
427- private getMaxSupportedCompileVersion ( runtimeVersion : string ) : number {
428- if ( runtimeVersion && semver . lt ( semver . coerce ( runtimeVersion ) , "6.1.0" ) ) {
457+ private getMaxSupportedCompileVersion ( config : Partial < NativeScriptDoctor . IProjectDir > & { runtimeVersion ? : string } ) : number {
458+ if ( config . runtimeVersion && semver . lt ( semver . coerce ( config . runtimeVersion ) , "6.1.0" ) ) {
429459 return 28 ;
430460 }
431-
432- return this . parseAndroidSdkString ( _ . last ( this . getSupportedTargets ( runtimeVersion ) . sort ( ) ) ) ;
461+ return this . parseAndroidSdkString ( _ . last ( this . getSupportedTargets ( config . projectDir ) . sort ( ) ) ) ;
433462 }
434463}
0 commit comments