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 行代码
This commit is contained in:
shuiyu1123 committed 2026-06-24 12:00:28 +00:00
1 parent 8ad62be068
commit 506f9ac725
43 files changed
+16704 -23

No files matched your search

+581
View File
@@ -0,0 +1,581 @@
"""
Android Print 组件 — PrintManager, PrintJob, PrintDocumentAdapter, PdfPrint 等
方法签名完全对齐 Android SDK (android.print 包)
"""
import os
import time
from typing import Any, Callable, Dict, List, Optional, Tuple
from .._core import Stub, AndroidOnlyError
# ═══════════════════════════════════════════════════════════════
# PrintAttributes
# ═══════════════════════════════════════════════════════════════
class PrintAttributes(Stub):
"""PrintAttributes — 打印属性"""
# 颜色模式
COLOR_MODE_MONOCHROME = 1
COLOR_MODE_COLOR = 2
# 方向
ORIENTATION_PORTRAIT = 1
ORIENTATION_LANDSCAPE = 2
# 媒质尺寸 ID
MEDIA_SIZE_UNKNOWN = "unknown"
MEDIA_SIZE_A4 = "A4"
MEDIA_SIZE_A3 = "A3"
MEDIA_SIZE_LETTER = "letter"
MEDIA_SIZE_LEGAL = "legal"
MEDIA_SIZE_ISO_A4 = "iso_a4"
MEDIA_SIZE_ISO_A3 = "iso_a3"
MEDIA_SIZE_NA_LETTER = "na_letter"
def __init__(self):
super().__init__()
self._media_size: Optional["PrintAttributes.MediaSize"] = None
self._resolution: Optional["PrintAttributes.Resolution"] = None
self._min_margins: Optional["PrintAttributes.Margins"] = None
self._color_mode: int = PrintAttributes.COLOR_MODE_COLOR
self._orientation: int = PrintAttributes.ORIENTATION_PORTRAIT
def getMediaSize(self) -> Optional["MediaSize"]:
return self._media_size
def getResolution(self) -> Optional["Resolution"]:
return self._resolution
def getMinMargins(self) -> Optional["Margins"]:
return self._min_margins
def getColorMode(self) -> int:
return self._color_mode
def getOrientation(self) -> int:
return self._orientation
def isPortrait(self) -> bool:
return self._orientation == PrintAttributes.ORIENTATION_PORTRAIT
def toString(self) -> str:
return (f"PrintAttributes(colorMode={self._color_mode}, "
f"orientation={self._orientation})")
def hashCode(self) -> int:
return hash((self._color_mode, self._orientation)) & 0x7FFFFFFF
def equals(self, other) -> bool:
if not isinstance(other, PrintAttributes):
return False
return (self._color_mode == other._color_mode
and self._orientation == other._orientation)
# ── 内部嵌套类 ──
class MediaSize(Stub):
"""MediaSize — 媒质尺寸"""
def __init__(self, id: str, label: str, width_mils: int, height_mils: int):
super().__init__()
self._id = id
self._label = label
self._width_mils = width_mils
self._height_mils = height_mils
def getId(self) -> str:
return self._id
def getLabel(self, package_manager: Any = None) -> str:
return self._label
def getWidthMils(self) -> int:
return self._width_mils
def getHeightMils(self) -> int:
return self._height_mils
def asPortrait(self) -> "PrintAttributes.MediaSize":
if self._width_mils > self._height_mils:
return PrintAttributes.MediaSize(
self._id, self._label, self._height_mils, self._width_mils)
return self
def asLandscape(self) -> "PrintAttributes.MediaSize":
if self._width_mils < self._height_mils:
return PrintAttributes.MediaSize(
self._id, self._label, self._height_mils, self._width_mils)
return self
def toString(self) -> str:
return f"MediaSize({self._id}: {self._width_mils}x{self._height_mils}mils)"
def hashCode(self) -> int:
return hash(self._id) & 0x7FFFFFFF
def equals(self, other) -> bool:
if not isinstance(other, PrintAttributes.MediaSize):
return False
return self._id == other._id
class Resolution(Stub):
"""Resolution — 打印分辨率"""
def __init__(self, id: str, label: str, horizontal_dpi: int, vertical_dpi: int):
super().__init__()
self._id = id
self._label = label
self._horizontal_dpi = horizontal_dpi
self._vertical_dpi = vertical_dpi
def getId(self) -> str:
return self._id
def getLabel(self) -> str:
return self._label
def getHorizontalDpi(self) -> int:
return self._horizontal_dpi
def getVerticalDpi(self) -> int:
return self._vertical_dpi
def toString(self) -> str:
return f"Resolution({self._id}: {self._horizontal_dpi}x{self._vertical_dpi}dpi)"
class Margins(Stub):
"""Margins — 页边距"""
NO_MARGINS: "PrintAttributes.Margins" = None
def __init__(self, left_mils: int, top_mils: int,
right_mils: int, bottom_mils: int):
super().__init__()
self._left_mils = left_mils
self._top_mils = top_mils
self._right_mils = right_mils
self._bottom_mils = bottom_mils
def getLeftMils(self) -> int:
return self._left_mils
def getTopMils(self) -> int:
return self._top_mils
def getRightMils(self) -> int:
return self._right_mils
def getBottomMils(self) -> int:
return self._bottom_mils
def toString(self) -> str:
return f"Margins({self._left_mils},{self._top_mils},{self._right_mils},{self._bottom_mils})"
class Builder(Stub):
"""Builder — PrintAttributes 构建器"""
def __init__(self):
super().__init__()
self._attrs = PrintAttributes()
def setMediaSize(self, media_size: "PrintAttributes.MediaSize") -> "PrintAttributes.Builder":
self._attrs._media_size = media_size
return self
def setResolution(self, resolution: "PrintAttributes.Resolution") -> "PrintAttributes.Builder":
self._attrs._resolution = resolution
return self
def setMinMargins(self, margins: "PrintAttributes.Margins") -> "PrintAttributes.Builder":
self._attrs._min_margins = margins
return self
def setColorMode(self, color_mode: int) -> "PrintAttributes.Builder":
self._attrs._color_mode = color_mode
return self
def setOrientation(self, orientation: int) -> "PrintAttributes.Builder":
self._attrs._orientation = orientation
return self
def build(self) -> "PrintAttributes":
return self._attrs
PrintAttributes.Margins.NO_MARGINS = PrintAttributes.Margins(0, 0, 0, 0)
# ═══════════════════════════════════════════════════════════════
# PrintJobInfo
# ═══════════════════════════════════════════════════════════════
class PrintJobInfo(Stub):
"""PrintJobInfo — 打印任务信息"""
# 状态常量
STATE_CREATED = 1
STATE_QUEUED = 2
STATE_STARTED = 3
STATE_BLOCKED = 4
STATE_COMPLETED = 5
STATE_FAILED = 6
STATE_CANCELED = 7
def __init__(self):
super().__init__()
self._label: str = ""
self._id: Optional[Any] = None
self._state: int = PrintJobInfo.STATE_CREATED
self._attributes: Optional[PrintAttributes] = None
self._copies: int = 1
self._creation_time: int = int(time.time() * 1000)
self._canceling: bool = False
self._pages: Optional[List[int]] = None
self._has_advanced_options: bool = False
def getLabel(self) -> str:
return self._label
def setLabel(self, label: str):
self._label = label
def getId(self) -> Optional[Any]:
return self._id
def getState(self) -> int:
return self._state
def setState(self, state: int):
self._state = state
def getAttributes(self) -> Optional[PrintAttributes]:
return self._attributes
def setAttributes(self, attributes: PrintAttributes):
self._attributes = attributes
def getCopies(self) -> int:
return self._copies
def setCopies(self, copies: int):
self._copies = copies
def getCreationTime(self) -> int:
return self._creation_time
def isCanceling(self) -> bool:
return self._canceling
def getPages(self) -> Optional[List[int]]:
return self._pages
def setPages(self, pages: Optional[List[int]]):
self._pages = pages
def hasAdvancedOptions(self) -> bool:
return self._has_advanced_options
def toString(self) -> str:
return f"PrintJobInfo(label={self._label}, state={self._state}, copies={self._copies})"
def hashCode(self) -> int:
return hash(self._id) & 0x7FFFFFFF
def equals(self, other) -> bool:
if not isinstance(other, PrintJobInfo):
return False
return self._id == other._id
# ── Builder ──
class Builder(Stub):
"""Builder — PrintJobInfo 构建器"""
def __init__(self, info: Optional["PrintJobInfo"] = None):
super().__init__()
self._info = PrintJobInfo()
if info:
self._info._label = info._label
self._info._id = info._id
self._info._attributes = info._attributes
self._info._copies = info._copies
def setCopies(self, copies: int) -> "PrintJobInfo.Builder":
self._info._copies = copies
return self
def setAttributes(self, attributes: PrintAttributes) -> "PrintJobInfo.Builder":
self._info._attributes = attributes
return self
def setLabel(self, label: str) -> "PrintJobInfo.Builder":
self._info._label = label
return self
def setPages(self, pages: Optional[List[int]]) -> "PrintJobInfo.Builder":
self._info._pages = pages
return self
def build(self) -> "PrintJobInfo":
return self._info
# ═══════════════════════════════════════════════════════════════
# PrintJob
# ═══════════════════════════════════════════════════════════════
class PrintJob(Stub):
"""PrintJob — 打印任务"""
def __init__(self, info: PrintJobInfo):
super().__init__()
self._info = info
self._cancelled = False
self._result: Optional[Any] = None
def getId(self) -> Optional[Any]:
return self._info.getId()
def getInfo(self) -> PrintJobInfo:
return self._info
def isStarted(self) -> bool:
return self._info.getState() >= PrintJobInfo.STATE_STARTED
def isBlocked(self) -> bool:
return self._info.getState() == PrintJobInfo.STATE_BLOCKED
def isCompleted(self) -> bool:
return self._info.getState() == PrintJobInfo.STATE_COMPLETED
def isFailed(self) -> bool:
return self._info.getState() == PrintJobInfo.STATE_FAILED
def isCancelled(self) -> bool:
return self._cancelled
def cancel(self):
"""取消打印任务"""
self._cancelled = True
self._info.setState(PrintJobInfo.STATE_CANCELED)
def restart(self):
"""重新启动打印任务"""
self._cancelled = False
self._info.setState(PrintJobInfo.STATE_QUEUED)
def setResult(self, result: Any):
self._result = result
def getResult(self) -> Optional[Any]:
return self._result
def toString(self) -> str:
return f"PrintJob(id={self.getId()}, state={self._info.getState()})"
def hashCode(self) -> int:
return hash(self.getId()) & 0x7FFFFFFF
def equals(self, other) -> bool:
if not isinstance(other, PrintJob):
return False
return self.getId() == other.getId()
# ═══════════════════════════════════════════════════════════════
# PrintDocumentAdapter
# ═══════════════════════════════════════════════════════════════
class PrintDocumentAdapter(Stub):
"""PrintDocumentAdapter — 打印文档适配器"""
EXTRA_PRINT_PREVIEW = "EXTRA_PRINT_PREVIEW"
def __init__(self):
super().__init__()
def onStart(self):
"""打印开始回调"""
pass
def onFinish(self):
"""打印结束回调"""
pass
def onLayout(self, old_attributes: PrintAttributes, new_attributes: PrintAttributes,
cancellation_signal: Any, callback: "PrintDocumentAdapterLayoutCallback",
metadata: Any):
"""布局回调 - 桌面实现直接完成"""
if callback:
callback.onLayoutFinished(self, new_attributes)
def onWrite(self, pages: List[int], destination: Any,
cancellation_signal: Any,
callback: "PrintDocumentAdapterWriteCallback"):
"""写入回调 - 桌面实现直接完成"""
if callback:
callback.onWriteFinished(pages)
class PrintDocumentAdapterLayoutCallback(Stub):
"""PrintDocumentAdapterLayoutCallback — 布局回调"""
def __init__(self):
super().__init__()
def onLayoutFinished(self, adapter: PrintDocumentAdapter, attributes: PrintAttributes):
"""布局完成"""
pass
def onLayoutFailed(self, error: Optional[str] = None):
"""布局失败"""
pass
def onLayoutCancelled(self):
"""布局取消"""
pass
class PrintDocumentAdapterWriteCallback(Stub):
"""PrintDocumentAdapterWriteCallback — 写入回调"""
def __init__(self):
super().__init__()
def onWriteFinished(self, pages: List[int]):
"""写入完成"""
pass
def onWriteFailed(self, error: Optional[str] = None):
"""写入失败"""
pass
def onWriteCancelled(self):
"""写入取消"""
pass
# ═══════════════════════════════════════════════════════════════
# PdfPrint
# ═══════════════════════════════════════════════════════════════
class PdfPrint(Stub):
"""PdfPrint — PDF 打印辅助类"""
def __init__(self, attributes: Optional[PrintAttributes] = None):
super().__init__()
self._attributes = attributes or PrintAttributes()
def getAttributes(self) -> PrintAttributes:
return self._attributes
def setAttributes(self, attributes: PrintAttributes):
self._attributes = attributes
def print(self, print_adapter: PrintDocumentAdapter, output_path: str) -> bool:
"""执行 PDF 打印 (桌面实现: 写入文件)"""
try:
os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)
# 在桌面环境, PDF 打印由适配器的 onWrite 实现处理
callback = PrintDocumentAdapterWriteCallback()
print_adapter.onWrite([1], output_path, None, callback)
return True
except Exception:
return False
def toString(self) -> str:
return f"PdfPrint(attributes={self._attributes})"
def hashCode(self) -> int:
return hash(str(self._attributes)) & 0x7FFFFFFF
def equals(self, other) -> bool:
if not isinstance(other, PdfPrint):
return False
return str(self._attributes) == str(other._attributes)
# ═══════════════════════════════════════════════════════════════
# PrintManager
# ═══════════════════════════════════════════════════════════════
class PrintManager(Stub):
"""PrintManager — 打印管理器"""
# 打印任务 ID 生成
_next_job_id = 1
def __init__(self, context: Any = None):
super().__init__()
self._context = context
self._print_jobs: Dict[str, PrintJob] = {}
def getPrintJobs(self) -> List[PrintJob]:
"""获取打印任务列表"""
return list(self._print_jobs.values())
def print(self, job_name: str, document_adapter: PrintDocumentAdapter,
attributes: Optional[PrintAttributes] = None) -> PrintJob:
"""提交打印任务"""
info = PrintJobInfo()
info.setLabel(job_name)
info.setAttributes(attributes or PrintAttributes())
info.setState(PrintJobInfo.STATE_QUEUED)
job_id = f"print_job_{PrintManager._next_job_id}"
PrintManager._next_job_id += 1
job = PrintJob(info)
self._print_jobs[job_id] = job
# 自动触发布局和写入
cancellation_signal = type("CancellationSignal", (), {"isCanceled": lambda: False})()
document_adapter.onStart()
layout_cb = PrintDocumentAdapterLayoutCallback()
document_adapter.onLayout(None, info.getAttributes(),
cancellation_signal, layout_cb, None)
info.setState(PrintJobInfo.STATE_COMPLETED)
document_adapter.onFinish()
return job
def getPrintJobById(self, job_id: str) -> Optional[PrintJob]:
"""根据 ID 获取打印任务"""
return self._print_jobs.get(job_id)
def cancelPrintJob(self, job_id: str) -> bool:
"""取消打印任务"""
job = self._print_jobs.get(job_id)
if job:
job.cancel()
return True
return False
def toString(self) -> str:
return f"PrintManager(jobs={len(self._print_jobs)})"
def hashCode(self) -> int:
return id(self) & 0x7FFFFFFF
def equals(self, other) -> bool:
return self is other
# ═══════════════════════════════════════════════════════════════
# __all__
# ═══════════════════════════════════════════════════════════════
__all__ = [
"PrintManager",
"PrintJob",
"PrintJobInfo",
"PrintDocumentAdapter",
"PrintAttributes",
"PrintDocumentAdapterLayoutCallback",
"PrintDocumentAdapterWriteCallback",
"PdfPrint",
]