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:
1 parent
8ad62be068
commit
506f9ac725
43 files changed
+16704
-23
No files matched your search
@@ -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",
|
||||
]
|
||||
Reference in new issue
Block a user