| // Copyright 2022 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package sdkpath provides functions for locating the Android SDK. |
| // These functions respect the ANDROID_HOME environment variable, and |
| // otherwise use the default SDK location. |
| package sdkpath |
| |
| import ( |
| "fmt" |
| "os" |
| "path/filepath" |
| "runtime" |
| "strconv" |
| "strings" |
| ) |
| |
| // AndroidHome returns the absolute path of the selected Android SDK, |
| // if one can be found. |
| func AndroidHome() (string, error) { |
| androidHome := os.Getenv("ANDROID_HOME") |
| if androidHome == "" { |
| home, err := os.UserHomeDir() |
| if err != nil { |
| return "", err |
| } |
| switch runtime.GOOS { |
| case "windows": |
| // See https://android.googlesource.com/platform/tools/adt/idea/+/85b4bfb7a10ad858a30ffa4003085b54f9424087/native/installer/win/setup_android_studio.nsi#100 |
| androidHome = filepath.Join(home, "AppData", "Local", "Android", "sdk") |
| case "darwin": |
| // See https://android.googlesource.com/platform/tools/asuite/+/67e0cd9604379e9663df57f16a318d76423c0aa8/aidegen/lib/ide_util.py#88 |
| androidHome = filepath.Join(home, "Library", "Android", "sdk") |
| default: // Linux, BSDs, etc. |
| // See LINUX_ANDROID_SDK_PATH in ide_util.py above. |
| androidHome = filepath.Join(home, "Android", "Sdk") |
| } |
| } |
| if info, err := os.Stat(androidHome); err != nil { |
| return "", fmt.Errorf("%w; Android SDK was not found at %s", err, androidHome) |
| } else if !info.IsDir() { |
| return "", fmt.Errorf("%s is not a directory", androidHome) |
| } |
| return androidHome, nil |
| } |
| |
| // AndroidAPIPath returns an android SDK platform directory within the configured SDK. |
| // If there are multiple platforms that satisfy the minimum version requirement, |
| // AndroidAPIPath returns the latest one among them. |
| func AndroidAPIPath(api int) (string, error) { |
| sdk, err := AndroidHome() |
| if err != nil { |
| return "", err |
| } |
| sdkDir, err := os.Open(filepath.Join(sdk, "platforms")) |
| if err != nil { |
| return "", fmt.Errorf("failed to find android SDK platform: %w", err) |
| } |
| defer sdkDir.Close() |
| fis, err := sdkDir.Readdir(-1) |
| if err != nil { |
| return "", fmt.Errorf("failed to find android SDK platform (API level: %d): %w", api, err) |
| } |
| |
| var apiPath string |
| var apiVer int |
| for _, fi := range fis { |
| name := fi.Name() |
| if !strings.HasPrefix(name, "android-") { |
| continue |
| } |
| n, err := strconv.Atoi(name[len("android-"):]) |
| if err != nil || n < api { |
| continue |
| } |
| p := filepath.Join(sdkDir.Name(), name) |
| _, err = os.Stat(filepath.Join(p, "android.jar")) |
| if err == nil && apiVer < n { |
| apiPath = p |
| apiVer = n |
| } |
| } |
| if apiVer == 0 { |
| return "", fmt.Errorf("failed to find android SDK platform (API level: %d) in %s", |
| api, sdkDir.Name()) |
| } |
| return apiPath, nil |
| } |