diff --git a/android_pyapi.egg-info/PKG-INFO b/android_pyapi.egg-info/PKG-INFO new file mode 100644 index 0000000..603666b --- /dev/null +++ b/android_pyapi.egg-info/PKG-INFO @@ -0,0 +1,264 @@ +Metadata-Version: 2.4 +Name: android-pyapi +Version: 1.0.0 +Summary: Android API for Python — 在桌面/Linux 上原生运行 Android API +Home-page: https://gitee.com/shuiyu1123/Android-pyApi +Author: shuiyu1123 +License: MIT +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: MacOS +Classifier: Operating System :: Microsoft :: Windows +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Hardware +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +License-File: LICENSE +Provides-Extra: linux +Requires-Dist: psutil; extra == "linux" +Requires-Dist: requests; extra == "linux" +Requires-Dist: Pillow; extra == "linux" +Requires-Dist: opencv-python; extra == "linux" +Requires-Dist: numpy; extra == "linux" +Provides-Extra: windows +Requires-Dist: psutil; extra == "windows" +Requires-Dist: requests; extra == "windows" +Requires-Dist: Pillow; extra == "windows" +Requires-Dist: opencv-python; extra == "windows" +Requires-Dist: numpy; extra == "windows" +Requires-Dist: pyautogui; extra == "windows" +Requires-Dist: pyperclip; extra == "windows" +Requires-Dist: screeninfo; extra == "windows" +Requires-Dist: pywin32; extra == "windows" +Requires-Dist: wmi; extra == "windows" +Requires-Dist: pycaw; extra == "windows" +Requires-Dist: comtypes; extra == "windows" +Requires-Dist: win10toast; extra == "windows" +Provides-Extra: dev +Requires-Dist: pytest; extra == "dev" +Requires-Dist: pytest-cov; extra == "dev" +Dynamic: author +Dynamic: classifier +Dynamic: description +Dynamic: description-content-type +Dynamic: home-page +Dynamic: license +Dynamic: license-file +Dynamic: provides-extra +Dynamic: requires-python +Dynamic: summary + +# Android-pyApi + +> **Android API for Python** — 在桌面/Linux 上原生运行 Android API 的 Python 库 + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/) +[![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Windows-green.svg)](#) + +## 这是什么 + +Android-pyApi 将完整的 Android SDK API 翻译为纯 Python 实现,让你在桌面环境直接调用 Android API——不需要模拟器、不需要真机、不需要 Android Studio。 + +**213 个模块,178,000+ 行代码,覆盖 android/java/javax/org/dalvik 全包。** + +在 Linux 上,系统级 API(网络、传感器、蓝牙、音频、位置等)使用真实系统调用,返回真实数据。 + +## 核心特性 + +### API 覆盖 + +| 包 | 模块数 | 内容 | +|---|---|---| +| `android.*` | 167 | app, content, os, view, widget, graphics, media, hardware, net, telephony, provider 等 | +| `java.*` | 35 | lang, io, util, net, nio, security, crypto, sql, math, time 等 | +| `javax.*` | 4 | net, crypto, security, sql | +| `org.*` | 5 | json, w3c_dom, xml_sax, xml_pull, apache_http | +| `dalvik.*` | 1 | system | + +### Linux 真实实现 + +在 Linux 环境下,以下 API 使用真实系统调用而非存根: + +| API | 实现方式 | 真实行为 | +|-----|---------|---------| +| ConnectivityManager | `ip` 命令 + `/proc/net` | 真实 IP、接口、DNS、网关 | +| LocationManager | IP 地理定位 | 真实经纬度、城市、ISP | +| SensorManager | `/sys/class/hwmon` | 真实温度、CPU 频率、风扇 | +| AudioManager | `amixer` (ALSA) | 真实音量控制 | +| BluetoothAdapter | `bluetoothctl` (BlueZ) | 真实扫描、配对、连接 | +| ClipboardManager | `xclip` | 真实剪贴板读写 | +| PowerManager / BatteryManager | `psutil` + `/sys/class/power_supply` | 真实 CPU、内存、电池 | +| TelephonyManager | MAC 地址 + 内核版本 | 真实设备 ID | +| NotificationManager | `notify-send` | 真实桌面通知 | +| Activity / Display | `xdotool` + X11 | 真实屏幕尺寸、截屏 | +| ActivityManager | `psutil` + `/proc` | 真实进程列表 | +| Shell | `subprocess` | 真实命令执行 | +| Camera | OpenCV / V4L2 | 真实拍照 | +| UI 自动化 | `xdotool` | 真实点击、输入、按键 | + +### Windows 真实实现 + +在 Windows 环境下,以下 API 使用真实系统调用而非存根: + +| API | 实现方式 | 真实行为 | +|-----|---------|---------| +| ConnectivityManager | `ipconfig` + `netsh` + `socket` | 真实 IP、接口、DNS、网关、WiFi 信息 | +| LocationManager | IP 地理定位 | 真实经纬度、城市、ISP | +| SensorManager | `wmi` + `psutil` | 真实温度、CPU 频率、风扇转速 | +| AudioManager | `pycaw` / PowerShell | 真实音量控制、静音 | +| BluetoothAdapter | PowerShell Bluetooth cmdlets | 真实设备列表、配对状态 | +| ClipboardManager | `pyperclip` | 真实剪贴板读写 | +| PowerManager / BatteryManager | `psutil` | 真实 CPU、内存、电池状态 | +| NotificationManager | `win10toast` / PowerShell | 真实桌面通知 (Toast) | +| Activity / Display | `pyautogui` + `screeninfo` + `win32api` | 真实屏幕尺寸、截屏 | +| ActivityManager | `psutil` + `tasklist` | 真实进程列表 | +| Shell | `subprocess` + PowerShell | 真实命令执行 | +| Camera | OpenCV | 真实拍照 | +| UI 自动化 | `pyautogui` + `win32gui` | 真实点击、输入、按键、窗口操作 | + +### 跨平台 + +- **Linux** — 系统级 API 使用真实实现 (`_linux_impl.py`) +- **Windows** — 系统级 API 使用真实实现 (`_windows_impl.py`) +- **macOS** — 系统级 API 使用存根(后续支持) +- **API 形状** — 所有平台一致,方法签名完全对齐 Android SDK + +## 安装 + +```bash +# 从源码安装 +git clone https://gitee.com/shuiyu1123/Android-pyApi.git +cd Android-pyApi +pip install -e . + +# 或直接使用 +export PYTHONPATH=/path/to/Android-pyApi:$PYTHONPATH +``` + +### 可选依赖 + +```bash +# Python 库 (所有平台通用) +pip install psutil requests Pillow opencv-python numpy + +# Linux 系统工具 +sudo apt install xclip xdotool libnotify-bin alsa-utils bluez lm-sensors + +# Windows 专用库 (推荐安装以启用完整功能) +pip install pyautogui pyperclip screeninfo pywin32 wmi pycaw comtypes win10toast +``` + +## 快速开始 + +```python +from android_pyapi import Intent, Uri, Bundle, File, JSONObject, ArrayList, HashMap + +# Intent — Android 最核心的 API +intent = Intent("android.intent.action.VIEW") +intent.setData(Uri.parse("https://example.com")) +intent.putExtra("key", "value") +print(intent.getAction()) # android.intent.action.VIEW +print(intent.getData()) # https://example.com +print(intent.getStringExtra("key")) # value + +# java.util 集合 +lst = ArrayList() +lst.add("hello") +lst.add("world") +print(lst.size()) # 2 +print(lst.get(0)) # hello + +# JSONObject +json = JSONObject() +json.put("name", "test") +json.put("version", 42) +print(json.toString()) # {"name":"test","version":42} + +# Linux 真实实现 +from android_pyapi import Build, LocationManager, ConnectivityManager +print(Build.MODEL) # 真实主机名 +print(Build.MANUFACTURER) # Linux + +loc = LocationManager().getLastKnownLocation("network") +print(loc) # 真实经纬度 +``` + +## 项目结构 + +``` +android_pyapi/ +├── _core.py # Stub 基类、全局上下文 +├── _linux_impl.py # Linux 真实实现层 (14个实现类) +├── _windows_impl.py # Windows 真实实现层 (14个实现类) +├── __init__.py # 统一导出 +├── android/ # 167 个 Android 模块 +│ ├── app.py # Activity, Service, Fragment, Notification +│ ├── content.py # Context, Intent, ContentResolver, ClipboardManager +│ ├── os.py # Handler, Looper, Bundle, Build, PowerManager +│ ├── view.py # View, ViewGroup, MotionEvent, KeyEvent +│ ├── widget.py # TextView, Button, ListView, RecyclerView, Toast +│ ├── graphics.py # Bitmap, Canvas, Paint, Color, Path, Matrix +│ ├── hardware.py # SensorManager, Camera, BiometricPrompt +│ ├── net.py # ConnectivityManager, NetworkInfo +│ ├── telephony.py # TelephonyManager, SmsManager +│ ├── location.py # LocationManager, Location, Geocoder +│ ├── media.py # AudioManager, MediaPlayer, MediaRecorder +│ └── ... +├── java/ # 35 个 Java 标准库模块 +│ ├── lang.py # String, Math, System, Thread, Exception 体系 +│ ├── io.py # File, InputStream, OutputStream, Reader, Writer +│ ├── util.py # ArrayList, HashMap, Calendar, Collections, UUID +│ ├── net.py # URL, HttpURLConnection, Socket +│ └── ... +├── javax/ # 4 个 javax 模块 +├── org/ # 5 个 org 模块 +└── dalvik/ # 1 个 dalvik 模块 +``` + +## 设计理念 + +### 不是模拟器 + +Android-pyApi 不是 Android 模拟器。它不包含 ART 虚拟机、SurfaceFlinger、binder 等底层基础设施。 + +它是 **API 兼容层**: +- **API 形状** — 类名、方法签名、常量值完全对齐 Android SDK +- **系统级行为** — 在 Linux 上用真实系统调用实现 +- **框架级行为** — Activity 生命周期、View 渲染等保持存根(桌面无对应框架) + +### 渐进式真实化 + +``` +存根 (所有平台) → Linux 真实实现 → macOS 真实实现 → Windows 真实实现 +``` + +每个 API 从"返回硬编码值"逐步演进为"调用真实系统功能"。 + +## 使用场景 + +- **Android 脚本开发** — 在桌面编写和调试依赖 Android API 的 Python 脚本 +- **跨平台工具** — 用 Android API 风格编写跨平台系统工具 +- **学习 Android API** — 不需要 Android Studio 就能探索 API +- **自动化测试** — 在 CI/CD 中测试 Android API 调用逻辑 +- **IoT / 嵌入式** — 在 Linux 设备上用 Android API 风格操作硬件 + +## 贡献 + +欢迎贡献!特别需要: + +- macOS 真实实现层 (`_macos_impl.py`) +- 更多 API 的真实行为实现 +- 测试用例 + +## License + +[MIT](LICENSE) diff --git a/android_pyapi.egg-info/SOURCES.txt b/android_pyapi.egg-info/SOURCES.txt new file mode 100644 index 0000000..e585b57 --- /dev/null +++ b/android_pyapi.egg-info/SOURCES.txt @@ -0,0 +1,230 @@ +LICENSE +README.md +setup.py +android_pyapi/__init__.py +android_pyapi/_core.py +android_pyapi/_linux_impl.py +android_pyapi/_windows_impl.py +android_pyapi.egg-info/PKG-INFO +android_pyapi.egg-info/SOURCES.txt +android_pyapi.egg-info/dependency_links.txt +android_pyapi.egg-info/requires.txt +android_pyapi.egg-info/top_level.txt +android_pyapi/android/__init__.py +android_pyapi/android/accessibilityservice.py +android_pyapi/android/accounts.py +android_pyapi/android/animation.py +android_pyapi/android/app.py +android_pyapi/android/app_actionbar.py +android_pyapi/android/app_admin.py +android_pyapi/android/app_assist.py +android_pyapi/android/app_backup.py +android_pyapi/android/app_dialog.py +android_pyapi/android/app_fragment.py +android_pyapi/android/app_job.py +android_pyapi/android/app_notification.py +android_pyapi/android/app_people.py +android_pyapi/android/app_role.py +android_pyapi/android/app_search.py +android_pyapi/android/app_slice.py +android_pyapi/android/app_tasks.py +android_pyapi/android/app_time.py +android_pyapi/android/app_usage.py +android_pyapi/android/app_voiceinteractor.py +android_pyapi/android/app_wallpaper.py +android_pyapi/android/appwidget.py +android_pyapi/android/bluetooth.py +android_pyapi/android/bluetooth_le.py +android_pyapi/android/companion.py +android_pyapi/android/companion_ext.py +android_pyapi/android/content.py +android_pyapi/android/content_intent.py +android_pyapi/android/content_om.py +android_pyapi/android/content_pm.py +android_pyapi/android/content_res.py +android_pyapi/android/content_sync.py +android_pyapi/android/credentials.py +android_pyapi/android/database.py +android_pyapi/android/database_ext.py +android_pyapi/android/database_sqlite.py +android_pyapi/android/drm.py +android_pyapi/android/gesture.py +android_pyapi/android/gesture_ext.py +android_pyapi/android/graphics.py +android_pyapi/android/graphics_drawable.py +android_pyapi/android/graphics_drawable_ext.py +android_pyapi/android/graphics_drawable_shapes.py +android_pyapi/android/graphics_fonts.py +android_pyapi/android/graphics_pdf.py +android_pyapi/android/graphics_surface.py +android_pyapi/android/graphics_text.py +android_pyapi/android/hardware.py +android_pyapi/android/hardware_biometrics.py +android_pyapi/android/hardware_camera2.py +android_pyapi/android/hardware_camera2_params.py +android_pyapi/android/hardware_consumerir.py +android_pyapi/android/hardware_display.py +android_pyapi/android/hardware_fingerprint.py +android_pyapi/android/hardware_hdmi.py +android_pyapi/android/hardware_input.py +android_pyapi/android/hardware_light.py +android_pyapi/android/hardware_location.py +android_pyapi/android/hardware_radio.py +android_pyapi/android/hardware_sensor_ext.py +android_pyapi/android/hardware_serial.py +android_pyapi/android/hardware_thermal.py +android_pyapi/android/hardware_usb.py +android_pyapi/android/inputmethod.py +android_pyapi/android/inputmethodservice.py +android_pyapi/android/location.py +android_pyapi/android/location_ext.py +android_pyapi/android/location_geofence.py +android_pyapi/android/managers.py +android_pyapi/android/media.py +android_pyapi/android/media_async.py +android_pyapi/android/media_audio.py +android_pyapi/android/media_audiofx.py +android_pyapi/android/media_browse.py +android_pyapi/android/media_capture.py +android_pyapi/android/media_effect.py +android_pyapi/android/media_face.py +android_pyapi/android/media_image.py +android_pyapi/android/media_midi.py +android_pyapi/android/media_projection.py +android_pyapi/android/media_remoteblob.py +android_pyapi/android/media_session.py +android_pyapi/android/media_tv.py +android_pyapi/android/media_tv_ext.py +android_pyapi/android/mtp.py +android_pyapi/android/net.py +android_pyapi/android/net_ethernet.py +android_pyapi/android/net_ext.py +android_pyapi/android/net_hotspot2.py +android_pyapi/android/net_http.py +android_pyapi/android/net_nsd.py +android_pyapi/android/net_rtp.py +android_pyapi/android/net_sip.py +android_pyapi/android/net_ssl.py +android_pyapi/android/net_vpn.py +android_pyapi/android/net_wifi.py +android_pyapi/android/net_wifi_aware.py +android_pyapi/android/net_wifi_rtt.py +android_pyapi/android/nfc.py +android_pyapi/android/nfc_ext.py +android_pyapi/android/opengl.py +android_pyapi/android/os.py +android_pyapi/android/os_health.py +android_pyapi/android/os_power.py +android_pyapi/android/os_storage.py +android_pyapi/android/os_user.py +android_pyapi/android/permission.py +android_pyapi/android/preference.py +android_pyapi/android/print.py +android_pyapi/android/printservice.py +android_pyapi/android/provider.py +android_pyapi/android/provider_calendar.py +android_pyapi/android/provider_contacts.py +android_pyapi/android/provider_settings.py +android_pyapi/android/renderscript.py +android_pyapi/android/se.py +android_pyapi/android/security.py +android_pyapi/android/service_autofill.py +android_pyapi/android/service_controls.py +android_pyapi/android/service_dreams.py +android_pyapi/android/service_media.py +android_pyapi/android/service_notification.py +android_pyapi/android/service_quicksettings.py +android_pyapi/android/service_voice.py +android_pyapi/android/service_vr.py +android_pyapi/android/service_wallpaper.py +android_pyapi/android/sip.py +android_pyapi/android/speech.py +android_pyapi/android/speech_tts.py +android_pyapi/android/system.py +android_pyapi/android/telecom.py +android_pyapi/android/telephony.py +android_pyapi/android/telephony_cdma.py +android_pyapi/android/telephony_data.py +android_pyapi/android/telephony_euicc.py +android_pyapi/android/telephony_gsm.py +android_pyapi/android/telephony_ims.py +android_pyapi/android/telephony_mbms.py +android_pyapi/android/test.py +android_pyapi/android/text.py +android_pyapi/android/text_format.py +android_pyapi/android/text_method.py +android_pyapi/android/text_style.py +android_pyapi/android/text_util.py +android_pyapi/android/transition.py +android_pyapi/android/util.py +android_pyapi/android/uwb.py +android_pyapi/android/view.py +android_pyapi/android/view_accessibility.py +android_pyapi/android/view_accessibility_ext.py +android_pyapi/android/view_animation.py +android_pyapi/android/view_animator.py +android_pyapi/android/view_autofill.py +android_pyapi/android/view_dragndrop.py +android_pyapi/android/view_ext.py +android_pyapi/android/view_gesture.py +android_pyapi/android/view_haptic.py +android_pyapi/android/view_inputmethod.py +android_pyapi/android/view_textclassifier.py +android_pyapi/android/view_textservice.py +android_pyapi/android/view_translation.py +android_pyapi/android/view_window.py +android_pyapi/android/webkit.py +android_pyapi/android/webkit_ext.py +android_pyapi/android/widget.py +android_pyapi/android/widget_adapter.py +android_pyapi/android/widget_ext.py +android_pyapi/dalvik/__init__.py +android_pyapi/dalvik/system.py +android_pyapi/java/__init__.py +android_pyapi/java/beans.py +android_pyapi/java/crypto.py +android_pyapi/java/io.py +android_pyapi/java/io_ext.py +android_pyapi/java/io_file.py +android_pyapi/java/lang.py +android_pyapi/java/lang_annotation.py +android_pyapi/java/lang_invoke.py +android_pyapi/java/lang_management.py +android_pyapi/java/lang_ref.py +android_pyapi/java/lang_reflect.py +android_pyapi/java/math.py +android_pyapi/java/net.py +android_pyapi/java/nio.py +android_pyapi/java/nio_byteorder.py +android_pyapi/java/nio_channels.py +android_pyapi/java/nio_charset.py +android_pyapi/java/nio_file.py +android_pyapi/java/rmi.py +android_pyapi/java/security.py +android_pyapi/java/security_cert.py +android_pyapi/java/security_spec.py +android_pyapi/java/sql.py +android_pyapi/java/text.py +android_pyapi/java/time.py +android_pyapi/java/util.py +android_pyapi/java/util_concurrent.py +android_pyapi/java/util_concurrent_atomic.py +android_pyapi/java/util_concurrent_locks.py +android_pyapi/java/util_function.py +android_pyapi/java/util_logging.py +android_pyapi/java/util_prefs.py +android_pyapi/java/util_regex.py +android_pyapi/java/util_stream.py +android_pyapi/java/util_zip.py +android_pyapi/javax/__init__.py +android_pyapi/javax/crypto.py +android_pyapi/javax/net.py +android_pyapi/javax/security.py +android_pyapi/javax/sql.py +android_pyapi/org/__init__.py +android_pyapi/org/json.py +android_pyapi/org/w3c_dom.py +android_pyapi/org/xml_pull.py +android_pyapi/org/xml_sax.py +android_pyapi/org/apache/__init__.py +android_pyapi/org/apache/http.py \ No newline at end of file diff --git a/android_pyapi.egg-info/dependency_links.txt b/android_pyapi.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/android_pyapi.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/android_pyapi.egg-info/requires.txt b/android_pyapi.egg-info/requires.txt new file mode 100644 index 0000000..e01aae4 --- /dev/null +++ b/android_pyapi.egg-info/requires.txt @@ -0,0 +1,26 @@ + +[dev] +pytest +pytest-cov + +[linux] +psutil +requests +Pillow +opencv-python +numpy + +[windows] +psutil +requests +Pillow +opencv-python +numpy +pyautogui +pyperclip +screeninfo +pywin32 +wmi +pycaw +comtypes +win10toast diff --git a/android_pyapi.egg-info/top_level.txt b/android_pyapi.egg-info/top_level.txt new file mode 100644 index 0000000..f6b9637 --- /dev/null +++ b/android_pyapi.egg-info/top_level.txt @@ -0,0 +1 @@ +android_pyapi diff --git a/android_pyapi/android/system.py b/android_pyapi/android/system.py index 255c276..8e2eae6 100644 --- a/android_pyapi/android/system.py +++ b/android_pyapi/android/system.py @@ -80,7 +80,7 @@ class OsConstants(Stub): SIGTTIN = 21 SIGTTOU = 22 - # errno 常量 + # errno 常量 (使用 getattr 处理 Windows 上不存在的常量) EPERM = errno.EPERM ENOENT = errno.ENOENT ESRCH = errno.ESRCH @@ -95,7 +95,7 @@ class OsConstants(Stub): ENOMEM = errno.ENOMEM EACCES = errno.EACCES EFAULT = errno.EFAULT - ENOTBLK = errno.ENOTBLK + ENOTBLK = getattr(errno, 'ENOTBLK', 15) # Windows 不支持 EBUSY = errno.EBUSY EEXIST = errno.EEXIST EXDEV = errno.EXDEV @@ -106,7 +106,7 @@ class OsConstants(Stub): ENFILE = errno.ENFILE EMFILE = errno.EMFILE ENOTTY = errno.ENOTTY - ETXTBSY = errno.ETXTBSY + ETXTBSY = getattr(errno, 'ETXTBSY', 139) EFBIG = errno.EFBIG ENOSPC = errno.ENOSPC ESPIPE = errno.ESPIPE @@ -123,16 +123,16 @@ class OsConstants(Stub): ELOOP = errno.ELOOP ENOMSG = errno.ENOMSG EIDRM = errno.EIDRM - ENOSTR = errno.ENOSTR - ENODATA = errno.ENODATA - ETIME = errno.ETIME - ENOSR = errno.ENOSR - EREMOTE = errno.EREMOTE - ENOLINK = errno.ENOLINK + ENOSTR = getattr(errno, 'ENOSTR', 125) + ENODATA = getattr(errno, 'ENODATA', 120) + ETIME = getattr(errno, 'ETIME', 137) + ENOSR = getattr(errno, 'ENOSR', 124) + EREMOTE = getattr(errno, 'EREMOTE', 10071) + ENOLINK = getattr(errno, 'ENOLINK', 121) EPROTO = errno.EPROTO - EMULTIHOP = errno.EMULTIHOP - EBADMSG = errno.EBADMSG - EOVERFLOW = errno.EOVERFLOW + EMULTIHOP = getattr(errno, 'EMULTIHOP', 10072) # Windows 不支持 + EBADMSG = getattr(errno, 'EBADMSG', 104) + EOVERFLOW = getattr(errno, 'EOVERFLOW', 132) EILSEQ = errno.EILSEQ ENOTSOCK = errno.ENOTSOCK EDESTADDRREQ = errno.EDESTADDRREQ @@ -140,10 +140,10 @@ class OsConstants(Stub): EPROTOTYPE = errno.EPROTOTYPE ENOPROTOOPT = errno.ENOPROTOOPT EPROTONOSUPPORT = errno.EPROTONOSUPPORT - ESOCKTNOSUPPORT = errno.ESOCKTNOSUPPORT - EOPNOTSUPP = errno.EOPNOTSUPP - EPFNOSUPPORT = errno.EPFNOSUPPORT - EAFNOSUPPORT = errno.EAFNOSUPPORT + ESOCKTNOSUPPORT = getattr(errno, 'ESOCKTNOSUPPORT', 10044) + EOPNOTSUPP = getattr(errno, 'EOPNOTSUPP', 10045) + EPFNOSUPPORT = getattr(errno, 'EPFNOSUPPORT', 10046) + EAFNOSUPPORT = getattr(errno, 'EAFNOSUPPORT', 10047) EADDRINUSE = errno.EADDRINUSE EADDRNOTAVAIL = errno.EADDRNOTAVAIL ENETDOWN = errno.ENETDOWN @@ -154,32 +154,32 @@ class OsConstants(Stub): ENOBUFS = errno.ENOBUFS EISCONN = errno.EISCONN ENOTCONN = errno.ENOTCONN - ESHUTDOWN = errno.ESHUTDOWN - ETOOMANYREFS = errno.ETOOMANYREFS + ESHUTDOWN = getattr(errno, 'ESHUTDOWN', 10058) + ETOOMANYREFS = getattr(errno, 'ETOOMANYREFS', 10059) ETIMEDOUT = errno.ETIMEDOUT ECONNREFUSED = errno.ECONNREFUSED - EHOSTDOWN = errno.EHOSTDOWN + EHOSTDOWN = getattr(errno, 'EHOSTDOWN', 10064) EHOSTUNREACH = errno.EHOSTUNREACH EALREADY = errno.EALREADY EINPROGRESS = errno.EINPROGRESS - ESTALE = errno.ESTALE - EUCLEAN = errno.EUCLEAN - ENOTNAM = errno.ENOTNAM - ENAVAIL = errno.ENAVAIL - EISNAM = errno.EISNAM - EREMOTEIO = errno.EREMOTEIO - EDQUOT = errno.EDQUOT - ENOMEDIUM = errno.ENOMEDIUM - EMEDIUMTYPE = errno.EMEDIUMTYPE - ECANCELED = errno.ECANCELED - ENOKEY = errno.ENOKEY - EKEYEXPIRED = errno.EKEYEXPIRED - EKEYREVOKED = errno.EKEYREVOKED - EKEYREJECTED = errno.EKEYREJECTED - EOWNERDEAD = errno.EOWNERDEAD - ENOTRECOVERABLE = errno.ENOTRECOVERABLE - ERFKILL = errno.ERFKILL - EHWPOISON = getattr(errno, 'EHWPOISON', 1001) + ESTALE = getattr(errno, 'ESTALE', 10070) + EUCLEAN = getattr(errno, 'EUCLEAN', 117) # Windows 不支持 + ENOTNAM = getattr(errno, 'ENOTNAM', 118) # Windows 不支持 + ENAVAIL = getattr(errno, 'ENAVAIL', 119) # Windows 不支持 + EISNAM = getattr(errno, 'EISNAM', 120) # Windows 不支持 + EREMOTEIO = getattr(errno, 'EREMOTEIO', 121) # Windows 不支持 + EDQUOT = getattr(errno, 'EDQUOT', 10069) + ENOMEDIUM = getattr(errno, 'ENOMEDIUM', 123) # Windows 不支持 + EMEDIUMTYPE = getattr(errno, 'EMEDIUMTYPE', 124) # Windows 不支持 + ECANCELED = getattr(errno, 'ECANCELED', 105) + ENOKEY = getattr(errno, 'ENOKEY', 126) # Windows 不支持 + EKEYEXPIRED = getattr(errno, 'EKEYEXPIRED', 127) # Windows 不支持 + EKEYREVOKED = getattr(errno, 'EKEYREVOKED', 128) # Windows 不支持 + EKEYREJECTED = getattr(errno, 'EKEYREJECTED', 129) # Windows 不支持 + EOWNERDEAD = getattr(errno, 'EOWNERDEAD', 133) + ENOTRECOVERABLE = getattr(errno, 'ENOTRECOVERABLE', 127) + ERFKILL = getattr(errno, 'ERFKILL', 132) # Windows 不支持 + EHWPOISON = getattr(errno, 'EHWPOISON', 1001) # Windows 不支持 def __init__(self): super().__init__() diff --git a/setup.py b/setup.py index be42b24..07c3838 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,13 @@ from setuptools import setup, find_packages +from pathlib import Path + +long_description = Path("README.md").read_text(encoding="utf-8") setup( name="android-pyapi", version="1.0.0", description="Android API for Python — 在桌面/Linux 上原生运行 Android API", - long_description=open("README.md").read(), + long_description=long_description, long_description_content_type="text/markdown", license="MIT", author="shuiyu1123", diff --git a/test_windows.py b/test_windows.py new file mode 100644 index 0000000..ae038ff --- /dev/null +++ b/test_windows.py @@ -0,0 +1,145 @@ +""" +Windows 实现层测试脚本 +""" + +import sys +import platform + +print("=" * 60) +print(f"平台: {platform.system()} {platform.release()}") +print(f"Python: {platform.python_version()}") +print("=" * 60) + +# 测试基本导入 +print("\n[1] 测试基本导入...") +try: + from android_pyapi import Intent, Uri, Bundle, JSONObject, ArrayList + print(" ✓ 基本 Android API 导入成功") +except Exception as e: + print(f" ✗ 基本导入失败: {e}") + +# 测试 Intent +print("\n[2] 测试 Intent...") +try: + intent = Intent("android.intent.action.VIEW") + intent.setData(Uri.parse("https://example.com")) + intent.putExtra("key", "value") + print(f" ✓ Action: {intent.getAction()}") + print(f" ✓ Data: {intent.getData()}") + print(f" ✓ Extra: {intent.getStringExtra('key')}") +except Exception as e: + print(f" ✗ Intent 测试失败: {e}") + +# 测试集合类 +print("\n[3] 测试集合类...") +try: + lst = ArrayList() + lst.add("hello") + lst.add("world") + print(f" ✓ ArrayList size: {lst.size()}") + print(f" ✓ ArrayList[0]: {lst.get(0)}") + + json = JSONObject() + json.put("name", "test") + json.put("version", 42) + print(f" ✓ JSONObject: {json.toString()}") +except Exception as e: + print(f" ✗ 集合类测试失败: {e}") + +# 测试 Windows 实现层 +print("\n[4] 测试 Windows 实现层...") +try: + from android_pyapi._windows_impl import ( + IS_WINDOWS, get_windows_capabilities, + WindowsNetwork, WindowsPower, WindowsDisplay, + WindowsClipboard, WindowsProcess, WindowsLocation + ) + print(f" ✓ IS_WINDOWS: {IS_WINDOWS}") + + caps = get_windows_capabilities() + print(f" ✓ 能力检测: {sum(caps.values())}/{len(caps)} 项可用") +except Exception as e: + print(f" ✗ Windows 实现层导入失败: {e}") + import traceback + traceback.print_exc() + +# 测试网络功能 +print("\n[5] 测试网络功能...") +try: + ip = WindowsNetwork.get_ip_address() + print(f" ✓ IP 地址: {ip}") + + connected = WindowsNetwork.get_connectivity() + print(f" ✓ 网络连通: {connected}") + + wifi = WindowsNetwork.get_wifi_info() + print(f" ✓ WiFi SSID: {wifi.get('ssid', 'N/A')}") +except Exception as e: + print(f" ✗ 网络测试失败: {e}") + +# 测试电源信息 +print("\n[6] 测试电源信息...") +try: + battery = WindowsPower.get_battery_info() + print(f" ✓ 电池存在: {battery['present']}") + print(f" ✓ 电池电量: {battery['level']}%") + print(f" ✓ 电池状态: {battery['status']}") + + cpu = WindowsPower.get_cpu_usage() + print(f" ✓ CPU 使用率: {cpu}%") + + mem = WindowsPower.get_memory_info() + print(f" ✓ 内存使用: {mem['percent']}%") +except Exception as e: + print(f" ✗ 电源测试失败: {e}") + +# 测试显示信息 +print("\n[7] 测试显示信息...") +try: + w, h = WindowsDisplay.get_screen_size() + print(f" ✓ 屏幕尺寸: {w}x{h}") + + x, y = WindowsDisplay.get_mouse_position() + print(f" ✓ 鼠标位置: ({x}, {y})") +except Exception as e: + print(f" ✗ 显示测试失败: {e}") + +# 测试剪贴板 +print("\n[8] 测试剪贴板...") +try: + test_text = "Android-pyApi 测试文本" + WindowsClipboard.write(test_text) + read_text = WindowsClipboard.read() + if read_text == test_text: + print(f" ✓ 剪贴板读写成功") + else: + print(f" ⚠ 剪贴板内容不匹配: '{read_text}'") +except Exception as e: + print(f" ✗ 剪贴板测试失败: {e}") + +# 测试进程管理 +print("\n[9] 测试进程管理...") +try: + procs = WindowsProcess.list_processes() + print(f" ✓ 进程数量: {len(procs)}") + + sys_info = WindowsProcess.get_system_info() + print(f" ✓ 主机名: {sys_info['hostname']}") + print(f" ✓ 系统: {sys_info['platform']} {sys_info['windows_version']}") +except Exception as e: + print(f" ✗ 进程管理测试失败: {e}") + +# 测试位置信息 +print("\n[10] 测试位置信息...") +try: + loc = WindowsLocation.get_location() + print(f" ✓ 来源: {loc['source']}") + print(f" ✓ 经纬度: {loc['latitude']}, {loc['longitude']}") + if loc.get('city'): + print(f" ✓ 城市: {loc['city']}") +except Exception as e: + print(f" ✗ 位置测试失败: {e}") + +print("\n" + "=" * 60) +print("测试完成!") +print("=" * 60)