Created
November 4, 2025 14:47
-
-
Save Forgo7ten/11aed162e75234509fd9b42a7d73f4ff to your computer and use it in GitHub Desktop.
download_ndk.py - 输入版本下载指定ndk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| """ | |
| Android NDK 历史版本下载助手(极简元数据版) | |
| 用法示例: | |
| python ndk_downloader.py -v r28 | |
| python ndk_downloader.py -v r26 -s mac | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import os | |
| import platform | |
| import sys | |
| from pathlib import Path | |
| from typing import Dict | |
| import requests | |
| from tqdm import tqdm | |
| # 仅保留“大版本号 -> 最新小版本号” | |
| LATEST_MINOR: Dict[str, str] = { | |
| "r29": "r29", | |
| "r28": "r28c", | |
| "r27": "r27d", | |
| "r26": "r26d", | |
| "r25": "r25c", | |
| "r24": "r24", | |
| "r23": "r23c", | |
| "r22": "r22b", | |
| "r21": "r21e", | |
| "r20": "r20b", | |
| "r19": "r19c", | |
| "r18": "r18b", | |
| "r17": "r17c", | |
| "r16": "r16b", | |
| "r15": "r15c", | |
| } | |
| BASE_URL = "https://dl.google.com/android/repository/" | |
| def detect_system() -> str: | |
| """检测当前操作系统并返回规范名称。""" | |
| m = {"Windows": "windows", "Darwin": "macos", "Linux": "linux"} | |
| return m.get(platform.system(), "linux") | |
| def normalize_system(sys_str: str | None) -> str: | |
| """将用户输入统一成小写,并映射到规范名称;若为空则自动检测。""" | |
| if not sys_str: | |
| return detect_system() | |
| mapping = { | |
| "win": "windows", | |
| "windows": "windows", | |
| "mac": "macos", | |
| "macos": "macos", | |
| "darwin": "macos", | |
| "linux": "linux", | |
| } | |
| normalized = mapping.get(sys_str.lower()) | |
| if not normalized: | |
| raise ValueError(f"不支持的系统:{sys_str}") | |
| return normalized | |
| def find_version(version: str) -> str: | |
| """根据大版本号查找完整 key(支持前缀匹配)。""" | |
| version = version.lower() | |
| for k in LATEST_MINOR: | |
| if k.startswith(version): | |
| return k | |
| raise ValueError(f"不支持的 NDK 版本:{version}") | |
| def build_filename(version: str, system: str) -> str: | |
| """根据规则生成文件名。""" | |
| system = normalize_system(system) | |
| full_ver = LATEST_MINOR[find_version(version)] | |
| major = int(full_ver[1:3]) # r28 -> 28 | |
| if major >= 23: | |
| # r23 及以上 | |
| return f"android-ndk-{full_ver}-{system}.zip" | |
| else: | |
| # r22 及以下 | |
| return f"android-ndk-{full_ver}-{system}-x86_64.zip" | |
| def build_url(version: str, system: str) -> str: | |
| """根据版本和系统拼接最终下载链接。""" | |
| return BASE_URL + build_filename(version, system) | |
| def download_file(url: str, dest: str = ".") -> Path: | |
| """使用 requests + tqdm 下载文件并返回本地路径。""" | |
| dest = Path(dest) | |
| dest.mkdir(parents=True, exist_ok=True) | |
| filename = url.split("/")[-1] | |
| filepath = dest / filename | |
| resp = requests.get(url, stream=True, timeout=30) | |
| resp.raise_for_status() | |
| total = int(resp.headers.get("content-length", 0)) | |
| with tqdm( | |
| total=total, | |
| unit="B", | |
| unit_scale=True, | |
| desc=filename, | |
| ) as bar, filepath.open("wb") as fd: | |
| for chunk in resp.iter_content(chunk_size=1024 * 64): | |
| if chunk: | |
| fd.write(chunk) | |
| bar.update(len(chunk)) | |
| return filepath | |
| def main(): | |
| parser = argparse.ArgumentParser(description="Android NDK 历史版本下载助手") | |
| parser.add_argument( | |
| "--version", "-v", required=True, help="NDK 大版本号,例如 r28 / r26 / r25" | |
| ) | |
| parser.add_argument( | |
| "--system", | |
| "-s", | |
| help="目标系统:windows / macos / linux;省略则自动检测", | |
| ) | |
| parser.add_argument( | |
| "--dest", "-d", default=".", help="保存目录,默认当前目录" | |
| ) | |
| args = parser.parse_args() | |
| try: | |
| url = build_url(args.version, args.system) | |
| print(f"即将下载:{url}") | |
| saved = download_file(url, args.dest) | |
| print(f"下载完成:{saved}") | |
| except Exception as e: | |
| print(f"错误:{e}", file=sys.stderr) | |
| sys.exit(1) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment