github.com/coming-chat/gomobile@v0.0.0-20220601074111-56995f7d7aba/internal/sdkpath/sdkpath.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package sdkpath provides functions for locating the Android SDK. 6 // These functions respect the ANDROID_HOME environment variable, and 7 // otherwise use the default SDK location. 8 package sdkpath 9 10 import ( 11 "fmt" 12 "os" 13 "path/filepath" 14 "runtime" 15 "strconv" 16 "strings" 17 ) 18 19 // AndroidHome returns the absolute path of the selected Android SDK, 20 // if one can be found. 21 func AndroidHome() (string, error) { 22 androidHome := os.Getenv("ANDROID_HOME") 23 if androidHome == "" { 24 home, err := os.UserHomeDir() 25 if err != nil { 26 return "", err 27 } 28 switch runtime.GOOS { 29 case "windows": 30 // See https://android.googlesource.com/platform/tools/adt/idea/+/85b4bfb7a10ad858a30ffa4003085b54f9424087/native/installer/win/setup_android_studio.nsi#100 31 androidHome = filepath.Join(home, "AppData", "Local", "Android", "sdk") 32 case "darwin": 33 // See https://android.googlesource.com/platform/tools/asuite/+/67e0cd9604379e9663df57f16a318d76423c0aa8/aidegen/lib/ide_util.py#88 34 androidHome = filepath.Join(home, "Library", "Android", "sdk") 35 default: // Linux, BSDs, etc. 36 // See LINUX_ANDROID_SDK_PATH in ide_util.py above. 37 androidHome = filepath.Join(home, "Android", "Sdk") 38 } 39 } 40 if info, err := os.Stat(androidHome); err != nil { 41 return "", fmt.Errorf("%w; Android SDK was not found at %s", err, androidHome) 42 } else if !info.IsDir() { 43 return "", fmt.Errorf("%s is not a directory", androidHome) 44 } 45 return androidHome, nil 46 } 47 48 // AndroidAPIPath returns an android SDK platform directory within the configured SDK. 49 // If there are multiple platforms that satisfy the minimum version requirement, 50 // AndroidAPIPath returns the latest one among them. 51 func AndroidAPIPath(api int) (string, error) { 52 sdk, err := AndroidHome() 53 if err != nil { 54 return "", err 55 } 56 sdkDir, err := os.Open(filepath.Join(sdk, "platforms")) 57 if err != nil { 58 return "", fmt.Errorf("failed to find android SDK platform: %w", err) 59 } 60 defer sdkDir.Close() 61 fis, err := sdkDir.Readdir(-1) 62 if err != nil { 63 return "", fmt.Errorf("failed to find android SDK platform (API level: %d): %w", api, err) 64 } 65 66 var apiPath string 67 var apiVer int 68 for _, fi := range fis { 69 name := fi.Name() 70 if !strings.HasPrefix(name, "android-") { 71 continue 72 } 73 n, err := strconv.Atoi(name[len("android-"):]) 74 if err != nil || n < api { 75 continue 76 } 77 p := filepath.Join(sdkDir.Name(), name) 78 _, err = os.Stat(filepath.Join(p, "android.jar")) 79 if err == nil && apiVer < n { 80 apiPath = p 81 apiVer = n 82 } 83 } 84 if apiVer == 0 { 85 return "", fmt.Errorf("failed to find android SDK platform (API level: %d) in %s", 86 api, sdkDir.Name()) 87 } 88 return apiPath, nil 89 }