<think>我们注意到在获取存储大小时出现了错误,原因是命令输出包含多行信息,并且我们只取了最后一行,但实际输出格式可能不是预期的那样。
另外IMEI的获取命令也可能需要调整,因为输出结果不是预期的数字。
我们需要调整两个部分:
1. IMEI获取:使用更可靠的命令
2. 存储大小:调整命令和解析方式
以下是修改后的脚本:
```python
import subprocess
import re
def get_android_info():
"""获取Android手机基本信息"""
info = {}
# 1. 检查ADB设备连接
try:
devices_output = subprocess.check_output(["adb", "devices"]).decode()
if "device" not in devices_output:
raise Exception("未检测到已连接的Android设备,请确保已开启USB调试")
except FileNotFoundError:
raise Exception("ADB工具未安装或未加入系统PATH")
# 2. 获取设备基本信息
commands = {
"平台": "adb shell getprop ro.board.platform",
"基线版本": "adb shell getprop ro.build.version.incremental",
"项目代号": "adb shell getprop ro.build.product",
"芯片ID": "adb shell getprop ro.boot.chipid || adb shell getprop ro.boot.serialno",
"内核版本": "adb shell cat /proc/version",
"型号": "adb shell getprop ro.product.model",
"厂家": "adb shell getprop ro.product.manufacturer",
# 修改IMEI获取方式:使用dumpsys iphonesubinfo
"IMEI": "adb shell dumpsys iphonesubinfo | grep 'Device ID' | awk -F '=' '{print $2}' | tr -d '[:space:]'",
"内存大小": "adb shell cat /proc/meminfo | grep MemTotal",
# 修改存储大小获取:使用df命令并指定/data分区,并确保只取数字
"存储大小": "adb shell df /data | grep -v Filesystem | awk '{print $2}'"
}
# 3. 执行命令并解析结果
for key, cmd in commands.items():
try:
# 提取命令主体(去除管道部分)
base_cmd = cmd.split("|")[0].strip().split()
# 注意:这里我们使用完整的命令字符串,因为有些命令包含管道,所以使用shell=True
# 但为了安全,我们使用列表形式传递命令,并设置shell=False(默认),所以需要拆分管道命令
# 但是有些命令包含管道,我们改为使用shell=True,但要注意安全风险(因为用户输入不可控)
# 这里我们改为使用shell=True,因为管道需要shell解析
output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT).decode().strip()
# 特殊处理IMEI和存储大小
if key == "IMEI":
if not output or "null" in output:
# 尝试第二种方法
try:
output = subprocess.check_output("adb shell service call iphonesubinfo 1 | awk -F \"'\" '{print $2}' | grep -Eo '[0-9]+' | tr -d '\\n'", shell=True).decode().strip()
except:
output = "需要READ_PHONE_STATE权限"
if len(output) < 10: # IMEI通常15位
output = "获取失败(可能需要权限)"
elif key == "存储大小":
# 尝试转换为整数,可能有多行,取第一行
lines = output.splitlines()
if lines:
# 取第一行(因为/data分区可能只出现一次)
for line in lines:
if line.strip():
size_str = line.strip().split()[0]
break
try:
size_kb = int(size_str)
size_gb = round(size_kb / 1024 / 1024, 1) # 转换为GB
output = f"{size_gb} GB"
except:
output = f"解析失败: {output}"
else:
output = "无数据"
elif key == "内存大小":
mem_kb = int(re.search(r'\d+', output).group())
mem_mb = mem_kb // 1024
output = f"{mem_mb} MB"
info[key] = output
except subprocess.CalledProcessError as e:
info[key] = f"命令执行错误: {e.output.decode().strip()}"
except Exception as e:
info[key] = f"获取失败: {str(e)}"
return info
if __name__ == "__main__":
print("正在获取Android设备信息...")
device_info = get_android_info()
print("\n=== Android设备基本信息 ===")
for key, value in device_info.items():
print(f"{key}: {value}")
```
### 主要修改点:
1. **IMEI获取**:
- 使用 `dumpsys iphonesubinfo` 命令替代 `service call`,并提取设备ID
- 增加了备选方案(如果第一种方式失败则尝试第二种)
2. **存储大小获取**:
- 修改命令为 `adb shell df /data | grep -v Filesystem | awk '{print $2}'`,避免表头
- 增加多行处理逻辑,确保获取到数据行
3. **错误处理**:
- 捕获子进程错误并显示具体错误信息
- 对存储大小解析增加了异常处理
### 使用注意:
- 由于不同Android版本和厂商定制,命令输出可能不同
- IMEI获取在部分设备上需要root权限
§§相关问题§§
1. 如何在不使用root权限的情况下获取Android设备的唯一标识?
2. 针对不同Android版本,如何适配存储空间获取方法?
3. 怎样通过ADB命令获取Android设备的电池信息?
4. 如何检测Android设备是否已root?
5. 在获取设备信息时,如何处理不同厂商的定制系统差异?
</think>
根据您提供的报错信息,主要存在两个问题:IMEI获取格式错误和存储大小解析失败。下面是修复后的完整脚本:
```python
import subprocess
import re
def get_android_info():
"""获取Android手机基本信息(修复版本)"""
info = {}
# 1. 检查ADB设备连接
try:
devices_output = subprocess.check_output(["adb", "devices"], timeout=5).decode()
if "device" not in devices_output.replace("\r", "").split("\n")[1]:
raise Exception("未检测到已连接的Android设备")
except (FileNotFoundError, subprocess.TimeoutExpired):
raise Exception("ADB未安装或设备未连接")
# 2. 获取设备基本信息
commands = {
"平台": ["adb", "shell", "getprop", "ro.board.platform"],
"基线版本": ["adb", "shell", "getprop", "ro.build.version.incremental"],
"项目代号": ["adb", "shell", "getprop", "ro.build.product"],
"芯片ID": ["adb", "shell", "getprop", "ro.boot.chipid"],
"内核版本": ["adb", "shell", "cat", "/proc/version"],
"型号": ["adb", "shell", "getprop", "ro.product.model"],
"厂家": ["adb", "shell", "getprop", "ro.product.manufacturer"],
"内存大小": ["adb", "shell", "cat", "/proc/meminfo"],
"存储大小": ["adb", "shell", "df", "/data"],
}
# 3. 执行命令并解析结果
for key, cmd in commands.items():
try:
output = subprocess.check_output(cmd, timeout=5).decode().strip()
# 特殊字段处理
if key == "芯片ID" and not output:
output = subprocess.check_output(
["adb", "shell", "getprop", "ro.boot.serialno"],
timeout=5
).decode().strip()
elif key == "内存大小":
match = re.search(r"MemTotal:\s*(\d+)\s*kB", output)
if match:
mem_mb = int(match.group(1)) // 1024
output = f"{mem_mb} MB"
elif key == "存储大小":
lines = output.splitlines()
if len(lines) > 1:
parts = lines[1].split()
if len(parts) > 2:
size_kb = int(parts[1])
size_gb = round(size_kb / 1024 / 1024, 1)
output = f"{size_gb} GB"
info[key] = output if output else "未获取到数据"
except Exception as e:
info[key] = f"获取失败: {str(e)}"
# 4. 单独获取IMEI(需要特殊处理)
try:
imei_output = subprocess.check_output(
"adb shell service call iphonesubinfo 1 | grep -o \"[0-9a-fA-F]\{14\}\"",
shell=True,
timeout=5
).decode().strip()
if imei_output:
info["IMEI"] = imei_output
else:
info["IMEI"] = "需要READ_PHONE_STATE权限"
except:
info["IMEI"] = "获取失败"
return info
if __name__ == "__main__":
print("正在获取Android设备信息...")
try:
device_info = get_android_info()
print("\n=== Android设备基本信息 ===")
for key, value in device_info.items():
print(f"{key}: {value}")
except Exception as e:
print(f"\n错误: {str(e)}")
print("请确保:")
print("1. 已安装ADB并添加到PATH")
print("2. 手机开启USB调试模式")
print("3. 使用USB连接手机并授权调试")
```
### 修复的问题:
1. **IMEI获取问题**:
- 使用 `grep -o "[0-9a-fA-F]\{14\}"` 直接提取15位IMEI(最后一位校验位不提取)
- 添加了权限提示,当无法获取时显示"需要READ_PHONE_STATE权限"
2. **存储大小解析失败**:
- 使用更健壮的解析逻辑:`df /data` 命令取第二行数据
- 先按空格分割再取值,避免不同格式导致的问题
- 添加多重检查确保数据有效性
3. **其他改进**:
- 所有命令添加5秒超时防止卡死
- 更清晰的错误提示(包括ADB安装和设备连接检查)
- 芯片ID获取添加备用方案(使用serialno)
- 内存大小解析使用正则表达式确保准确性
- 主函数添加全局异常捕获
### 使用说明:
1. 保存为`.py`文件运行
2. **确保手机已开启USB调试模式**(设置 → 开发者选项)
3. 首次连接需要在手机上授权调试权限
4. 如果IMEI获取失败,请检查手机是否授予了电话权限