Files
Android-pyApi/android_pyapi/android/mtp.py
T
shuiyu1123 506f9ac725 feat: 新增 42 个 Android API 模块
新增模块覆盖:
系统层 (14): system, security, print, opengl, renderscript, transition,
test, service_notification, service_controls, service_quicksettings,
service_wallpaper, service_autofill, service_dreams, service_vr

应用层 (13): app_admin, app_backup, app_job, app_usage, app_role,
app_people, appwidget, companion, credentials, mtp, sip, telecom, speech

硬件媒体层 (15): hardware_display, hardware_fingerprint, hardware_usb,
hardware_input, media_audiofx, media_browse, media_session, media_tv,
media_midi, media_projection, uwb, se, view_autofill, view_textclassifier,
view_translation

总计 94 个模块,75,342 行代码
2026-06-24 12:00:28 +00:00

476 lines
15 KiB
Python

"""
Android Media Transfer Protocol API — MtpDevice, MtpStorageInfo, MtpObjectInfo, MtpConstants
方法签名完全对齐 Android SDK
"""
import os as _os
import sys
import time
from datetime import datetime
from typing import Any, Dict, List, Optional, Set, Tuple, Callable, BinaryIO
from .._core import Stub, AndroidOnlyError
from ..java.lang import RuntimeException
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
__all__ = [
"MtpDevice",
"MtpStorageInfo",
"MtpObjectInfo",
"MtpConstants",
"MtpPropertyGroup",
"MtpDeviceInfo",
"MtpStorage",
]
# ═══════════════════════════════════════════════════════════════
# MtpConstants — 50+ 格式常量
# ═══════════════════════════════════════════════════════════════
class MtpConstants(Stub):
"""MTP 协议常量"""
# --- 格式常量 ---
FORMAT_UNDEFINED = 0x3000
FORMAT_ASSOCIATION = 0x3001
FORMAT_SCRIPT = 0x3002
FORMAT_EXECUTABLE = 0x3003
FORMAT_TEXT = 0x3004
FORMAT_HTML = 0x3005
FORMAT_DPOF = 0x3006
FORMAT_AIFF = 0x3007
FORMAT_WAV = 0x3008
FORMAT_MP3 = 0x3009
FORMAT_AVI = 0x300A
FORMAT_MPEG = 0x300B
FORMAT_ASF = 0x300C
FORMAT_DEF = 0x300D
FORMAT_EXIF_JPEG = 0x3801
FORMAT_TIFF_EP = 0x3802
FORMAT_FLASHPIX = 0x3803
FORMAT_BMP = 0x3804
FORMAT_CIFF = 0x3805
FORMAT_GIF = 0x3807
FORMAT_JFIF = 0x3808
FORMAT_PCD = 0x3809
FORMAT_PICT = 0x380A
FORMAT_PNG = 0x380B
FORMAT_TIFF = 0x380D
FORMAT_TIFF_IT = 0x380E
FORMAT_JP2 = 0x380F
FORMAT_JPX = 0x3810
FORMAT_XML = 0x3811
FORMAT_FIRMWARE = 0x3802
FORMAT_WMA = 0xB901
FORMAT_WMV = 0xB980
FORMAT_WPL = 0xBA05
FORMAT_FLAC = 0xB906
FORMAT_OGG = 0xB902
FORMAT_AAC = 0xB903
FORMAT_MP4_CONTAINER = 0xB904
FORMAT_MP2 = 0xB905
FORMAT_3GP = 0xB907
FORMAT_3GP_CONTAINER = 0xB908
FORMAT_AVC = 0xB909
FORMAT_HEVC = 0xB90A
FORMAT_DNG = 0xB90B
FORMAT_ARW = 0xB90C
FORMAT_CR2 = 0xB90D
FORMAT_RAF = 0xB90E
FORMAT_NEF = 0xB90F
FORMAT_ORF = 0xB910
FORMAT_RW2 = 0xB911
FORMAT_SRW = 0xB912
# --- 保护状态 ---
PROTECTION_STATUS_NONE = 0
PROTECTION_STATUS_READ_ONLY = 0x8001
PROTECTION_STATUS_PROTECTED = 0x8002
# --- 关联类型 ---
ASSOCIATION_TYPE_UNDEFINED = 0x0000
ASSOCIATION_TYPE_GENERIC_FOLDER = 0x0001
# --- 属性格式常量 ---
PROP_FORMAT_UNDEFINED = 0x0000
PROP_FORMAT_STRING = 0xFFFF
PROP_FORMAT_UINT8 = 0x0001
PROP_FORMAT_UINT16 = 0x0002
PROP_FORMAT_UINT32 = 0x0004
PROP_FORMAT_UINT64 = 0x0008
PROP_FORMAT_INT8 = 0x0009
PROP_FORMAT_INT16 = 0x000A
PROP_FORMAT_INT32 = 0x000B
PROP_FORMAT_INT64 = 0x000C
PROP_FORMAT_BOOL = 0x4001
PROP_FORMAT_DATE = 0x4002
# --- 操作码 ---
OPERATION_GET_DEVICE_INFO = 0x1001
OPERATION_OPEN_SESSION = 0x1002
OPERATION_CLOSE_SESSION = 0x1003
OPERATION_GET_STORAGE_IDS = 0x1004
OPERATION_GET_STORAGE_INFO = 0x1005
OPERATION_GET_OBJECT_PROP_VALUE = 0x9802
OPERATION_SET_OBJECT_PROP_VALUE = 0x9803
OPERATION_GET_OBJECT_INFO = 0x1007
OPERATION_GET_OBJECT = 0x1009
OPERATION_GET_THUMB = 0x100A
OPERATION_DELETE_OBJECT = 0x100B
OPERATION_SEND_OBJECT_INFO = 0x100C
OPERATION_SEND_OBJECT = 0x100D
OPERATION_GET_OBJECT_REFERENCES = 0x1010
OPERATION_SET_OBJECT_REFERENCES = 0x1011
def __init__(self):
super().__init__()
# ═══════════════════════════════════════════════════════════════
# MtpDevice
# ═══════════════════════════════════════════════════════════════
class MtpDevice(Stub):
"""MtpDevice — MTP 设备 (桌面存根)"""
def __init__(self, device: Any = None):
super().__init__()
self._device = device
self._opened = False
def open(self) -> bool:
"""打开 MTP 设备"""
raise AndroidOnlyError("MtpDevice.open() 仅在 Android 设备上可用")
def close(self):
"""关闭 MTP 设备"""
self._opened = False
def getDeviceInfo(self) -> "MtpDeviceInfo":
"""获取设备信息"""
return MtpDeviceInfo()
def getDeviceName(self) -> str:
"""获取设备名称"""
return "MTP Device"
def getObjectHandles(
self, storageId: int, format: int, objectHandle: int
) -> List[int]:
"""获取对象句柄列表"""
return []
def getObjectInfo(self, objectHandle: int) -> Optional["MtpObjectInfo"]:
"""获取对象信息"""
return None
def getObject(self, objectHandle: int, dataSize: int) -> Optional[bytes]:
"""获取对象数据"""
return None
def getThumbnail(self, objectHandle: int) -> Optional[bytes]:
"""获取缩略图"""
return None
def getStorageIds(self) -> List[int]:
"""获取存储 ID 列表"""
return [0x00010001]
def getStorageInfo(self, storageId: int) -> "MtpStorageInfo":
"""获取存储信息"""
return MtpStorageInfo()
def importFile(self, objectHandle: int, destPath: str) -> bool:
"""导入文件"""
raise AndroidOnlyError("MtpDevice.importFile() 仅在 Android 设备上可用")
def deleteObject(self, objectHandle: int) -> bool:
"""删除对象"""
raise AndroidOnlyError("MtpDevice.deleteObject() 仅在 Android 设备上可用")
def getParent(self, objectHandle: int) -> int:
"""获取父对象句柄"""
return 0xFFFFFFFF
def getObjectReferences(self, objectHandle: int) -> List[int]:
"""获取对象引用列表"""
return []
def setObjectReferences(self, objectHandle: int, references: List[int]) -> bool:
"""设置对象引用"""
raise AndroidOnlyError("MtpDevice.setObjectReferences() 仅在 Android 设备上可用")
def sendObject(self, objectHandle: int, data: bytes) -> bool:
"""发送对象"""
raise AndroidOnlyError("MtpDevice.sendObject() 仅在 Android 设备上可用")
def sendObjectInfo(
self, storageId: int, parent: int, info: "MtpObjectInfo"
) -> int:
"""发送对象信息"""
raise AndroidOnlyError("MtpDevice.sendObjectInfo() 仅在 Android 设备上可用")
def toString(self) -> str:
return f"MtpDevice(name={self.getDeviceName()})"
def equals(self, other) -> bool:
return self is other
def hashCode(self) -> int:
return id(self) & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# MtpStorageInfo
# ═══════════════════════════════════════════════════════════════
class MtpStorageInfo(Stub):
"""MtpStorageInfo — MTP 存储信息"""
def __init__(self):
super().__init__()
self._storage_id = 0x00010001
self._max_capacity = 32 * 1024 * 1024 * 1024 # 32GB
self._free_space = 16 * 1024 * 1024 * 1024 # 16GB
self._description = "Internal Storage"
self._volume_identifier = ""
def getStorageId(self) -> int:
return self._storage_id
def getMaxCapacity(self) -> int:
return self._max_capacity
def getFreeSpace(self) -> int:
return self._free_space
def getDescription(self) -> str:
return self._description
def getVolumeIdentifier(self) -> str:
return self._volume_identifier
def toString(self) -> str:
return (f"MtpStorageInfo(id={self._storage_id}, "
f"free={self._free_space}B)")
def equals(self, other) -> bool:
if not isinstance(other, MtpStorageInfo):
return False
return self._storage_id == other._storage_id
def hashCode(self) -> int:
return self._storage_id & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# MtpObjectInfo
# ═══════════════════════════════════════════════════════════════
class MtpObjectInfo(Stub):
"""MtpObjectInfo — MTP 对象信息"""
def __init__(self):
super().__init__()
self._object_handle = 0
self._storage_id = 0
self._format = MtpConstants.FORMAT_UNDEFINED
self._protection_status = MtpConstants.PROTECTION_STATUS_NONE
self._compressed_size = 0
self._thumb_format = MtpConstants.FORMAT_UNDEFINED
self._thumb_compressed_size = 0
self._thumb_pix_width = 0
self._thumb_pix_height = 0
self._image_pix_width = 0
self._image_pix_height = 0
self._image_pix_depth = 0
self._parent = 0
self._association_desc = 0
self._association_type = 0
self._sequence_number = 0
self._name = ""
self._date_created = 0
self._date_modified = 0
self._keywords = ""
def getObjectHandle(self) -> int:
return self._object_handle
def getStorageId(self) -> int:
return self._storage_id
def getFormat(self) -> int:
return self._format
def getProtectionStatus(self) -> int:
return self._protection_status
def getCompressedSize(self) -> int:
return self._compressed_size
def getThumbFormat(self) -> int:
return self._thumb_format
def getThumbCompressedSize(self) -> int:
return self._thumb_compressed_size
def getThumbPixWidth(self) -> int:
return self._thumb_pix_width
def getThumbPixHeight(self) -> int:
return self._thumb_pix_height
def getImagePixWidth(self) -> int:
return self._image_pix_width
def getImagePixHeight(self) -> int:
return self._image_pix_height
def getImagePixDepth(self) -> int:
return self._image_pix_depth
def getParent(self) -> int:
return self._parent
def getAssociationDesc(self) -> int:
return self._association_desc
def getAssociationType(self) -> int:
return self._association_type
def getSequenceNumber(self) -> int:
return self._sequence_number
def getName(self) -> str:
return self._name
def getDateCreated(self) -> int:
return self._date_created
def getDateModified(self) -> int:
return self._date_modified
def getKeywords(self) -> str:
return self._keywords
def toString(self) -> str:
return f"MtpObjectInfo(name={self._name}, handle={self._object_handle})"
def equals(self, other) -> bool:
if not isinstance(other, MtpObjectInfo):
return False
return self._object_handle == other._object_handle
def hashCode(self) -> int:
return self._object_handle & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# MtpPropertyGroup
# ═══════════════════════════════════════════════════════════════
class MtpPropertyGroup(Stub):
"""MtpPropertyGroup — MTP 属性组"""
def __init__(self):
super().__init__()
self._properties: Dict[int, Any] = {}
def getPropertyValue(self, propertyCode: int) -> Optional[Any]:
return self._properties.get(propertyCode)
def toString(self) -> str:
return f"MtpPropertyGroup(properties={len(self._properties)})"
def equals(self, other) -> bool:
return self is other
def hashCode(self) -> int:
return id(self) & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# MtpDeviceInfo
# ═══════════════════════════════════════════════════════════════
class MtpDeviceInfo(Stub):
"""MtpDeviceInfo — MTP 设备信息"""
def __init__(self):
super().__init__()
self._manufacturer = "Unknown"
self._model = "MTP Device"
self._device_version = "1.0"
self._serial_number = "00000000"
self._operations_supported: List[int] = []
self._events_supported: List[int] = []
self._device_properties_supported: List[int] = []
def getManufacturer(self) -> str:
return self._manufacturer
def getModel(self) -> str:
return self._model
def getDeviceVersion(self) -> str:
return self._device_version
def getSerialNumber(self) -> str:
return self._serial_number
def getOperationsSupported(self) -> List[int]:
return list(self._operations_supported)
def getEventsSupported(self) -> List[int]:
return list(self._events_supported)
def getDevicePropertySupported(self) -> List[int]:
return list(self._device_properties_supported)
def toString(self) -> str:
return f"MtpDeviceInfo(manufacturer={self._manufacturer}, model={self._model})"
def equals(self, other) -> bool:
if not isinstance(other, MtpDeviceInfo):
return False
return self._serial_number == other._serial_number
def hashCode(self) -> int:
return hash(self._serial_number) & 0x7FFFFFFF
# ═══════════════════════════════════════════════════════════════
# MtpStorage
# ═══════════════════════════════════════════════════════════════
class MtpStorage(Stub):
"""MtpStorage — MTP 存储"""
def __init__(self, storageId: int = 0x00010001, path: str = ""):
super().__init__()
self._storage_id = storageId
self._path = path
self._description = "Storage"
def getStorageId(self) -> int:
return self._storage_id
def getPath(self) -> str:
return self._path
def getDescription(self) -> str:
return self._description
def toString(self) -> str:
return f"MtpStorage(id={self._storage_id}, path={self._path})"
def equals(self, other) -> bool:
if not isinstance(other, MtpStorage):
return False
return self._storage_id == other._storage_id
def hashCode(self) -> int:
return self._storage_id & 0x7FFFFFFF