github.com/TimaSlipko/gomobile@v1.0.8/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  }