autool/DroidBot/platforms/android/android_app.py
2026-06-17 19:44:18 +08:00

114 lines
3.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Android App Module
Android-specific application model.
"""
import logging
import os
from .android_intent import AndroidIntent
from ...core.abstract_app import AbstractApp
from ...exceptions import FATAL_EXCEPTIONS
class AndroidApp(AbstractApp):
"""
Android 应用类 - 用于解析和管理 APK 文件信息
继承自 AbstractApp实现 Android 特定的应用管理功能。
"""
def __init__(self, package_name, output_dir=None):
"""
创建 AndroidApp 实例
:param package_name: 应用包名
:param output_dir: 输出目录路径
"""
super().__init__(output_dir=output_dir)
self.app_path = None
self.output_dir = output_dir
if output_dir is not None:
if not os.path.isdir(output_dir):
os.makedirs(output_dir)
self.package_name = package_name
self._main_activity = None
self._activities = []
self.dumpsys_main_activity = None
@property
def identifier(self) -> str:
"""获取应用唯一标识符package_name"""
return self.package_name
@property
def main_activity(self) -> str:
"""获取主 Activity 名称"""
if self._main_activity is not None:
return self._main_activity
else:
if self.dumpsys_main_activity:
self.logger.warning("Cannot get main activity from manifest. Using dumpsys result instead.")
return self.dumpsys_main_activity
return None
@main_activity.setter
def main_activity(self, value):
"""设置主 Activity"""
self._main_activity = value
@property
def activities(self) -> list:
"""获取入口点列表activities"""
return self._activities
@activities.setter
def activities(self, value):
"""设置 Activity 列表"""
self._activities = value
def get_start_with_profiling_intent(self, trace_file, sampling=None) -> 'AndroidIntent':
"""获取带 profiling 的启动 Intent"""
package_name = self.package_name
if self.main_activity:
package_name += "/%s" % self.main_activity
if sampling is not None:
return AndroidIntent(prefix="start --start-profiler %s --sampling %d" % (trace_file, sampling), suffix=package_name)
else:
return AndroidIntent(prefix="start --start-profiler %s" % trace_file, suffix=package_name)
def populate_activities(self, device):
"""
使用 adb dumpsys package 获取所有 Activity
"""
import re
self.logger.info(f"Populating activities for {self.package_name} via dumpsys...")
try:
cmd = f"dumpsys package {self.package_name}"
output = device.adb.shell(cmd)
# 匹配形如: [hash] package/activity
pattern = re.compile(r'([0-9a-f]+)\s+' + re.escape(self.package_name) + r'/([^ \s]+)')
matches = pattern.findall(output)
new_activities = []
for m in matches:
activity_full_name = f"{self.package_name}/{m[1]}"
if activity_full_name not in new_activities:
new_activities.append(activity_full_name)
if new_activities:
self.activities = sorted(new_activities)
self.logger.info(f"Found {len(self.activities)} activities via dumpsys.")
else:
self.logger.warning("No activities found via dumpsys.")
except FATAL_EXCEPTIONS:
raise
except Exception as e:
self.logger.error(f"Failed to populate activities via dumpsys: {e}")
# 非致命异常activities保持为空