请问这个类中的get_current_activity()方法,在其他用例文件,都有那些调用方式,方法如下:
# !/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Optional
import threading
import subprocess
import openpyxl
import re
from hytest import *
import time
import random
from appium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import WebDriverException
import os
import zipfile
import tempfile
import shutil
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
import cv2
import numpy as np
from lib.common import ADBHelper, get_app_driver, get_sup_app_driver, Operate
from selenium.webdriver.common.by import By
from PIL import Image
import statistics
from openpyxl import load_workbook
from hytest import *
from appium import webdriver
import sys
import os
import re
import time
import platform
import subprocess
from appium.webdriver.common.multi_action import MultiAction
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By
from appium.webdriver.common.appiumby import AppiumBy
from multiprocessing.dummy import Process
from selenium.webdriver import ActionChains
import yaml, ruamel.yaml
import hytest
from selenium.common.exceptions import (
TimeoutException,
ElementNotInteractableException,
StaleElementReferenceException,
NoSuchElementException,
WebDriverException
)
###############################################################################
CURRENT_TIME = datetime.now().strftime('%Y%m%d%H%M%S')
GLOBAL_REPORT_FOLDER = f"./reports/task_{CURRENT_TIME}_report"
os.makedirs(GLOBAL_REPORT_FOLDER, exist_ok=True)
class AppiumAutomationUtils:
def __init__(self, device_name, platform_version, is_large_install=False):
self.is_large_install = is_large_install
# 根据是否为大文件安装场景设置超时
self.timeout = 300 if is_large_install else 30
self.desired_caps = {
"platformName": "Android",
"deviceName": device_name,
"appium:platformVersion": platform_version,
"appium:automationName": "UiAutomator2",
"newCommandTimeout": self.timeout,
"appium:adbExecTimeout": 60000
}
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', self.desired_caps)
self.last_activity_time = time.time()
self.folder_name = GLOBAL_REPORT_FOLDER
self.report_file = os.path.join(self.folder_name, "report.xlsx")
self.report_files = os.path.join(self.folder_name, "downapp_report.xlsx")
self.report_checkfile = os.path.join(self.folder_name, "checkapp_report.xlsx")
def restart_appium_server(self):
# 启动Appium服务
start_cmd = 'appium -a 127.0.0.1 -p 4723 --session-override --allow-insecure=adb_shell'
subprocess.Popen(start_cmd, shell=True)
time.sleep(10)
@property
def get_driver(self):
return self.driver
def start_app(self, package_name):
crash_count, anr_count = 0, 0
flower_count, black_count, white_count = 0, 0, 0
try:
self.driver.activate_app(package_name)
time.sleep(5)
start_time = time.time()
while time.time() - start_time < 10:
status = self.driver.query_app_state(package_name)
if status != 2:
if self.check_app_crash():
crash_count += 1
break
if self.check_app_anr():
anr_count += 1
is_flower, is_black, is_white = self.verify_screen()
if is_flower: flower_count += 1
if is_black: black_count += 1
if is_white: white_count += 1
time.sleep(3)
except Exception as e:
if self.check_app_crash():
crash_count += 1
elif self.check_app_anr():
anr_count += 1
raise RuntimeError(f"应用启动失败: {str(e)}")
return crash_count, anr_count, flower_count, black_count, white_count
def check_screen(self):
timestamp = int(time.time() * 1000)
temp_dir = "D:/problem/temp_screenshots/"
os.makedirs(temp_dir, exist_ok=True)
temp_path = os.path.join(temp_dir, f"temp_{timestamp}.png")
try:
screenshot = self.driver.get_screenshot_as_png()
with open(temp_path, 'wb') as f:
f.write(screenshot)
except Exception as e:
return False, False, False, None
img_cv = cv2.imread(temp_path)
if img_cv is None:
os.remove(temp_path)
return False, False, False, None
height, width, _ = img_cv.shape
total_pixels = height * width
aspect_ratio = width / height
if 1.5 <= aspect_ratio <= 2.0:
num_rows, num_cols = 4, 8
elif aspect_ratio > 2.0:
num_rows, num_cols = 3, 12
else:
num_rows, num_cols = 3, 6
block_h, block_w = height // num_rows, width // num_cols
block_list = []
FEATURE_THRESHOLDS = {'variance': 150, 'entropy': 2.2, 'edge_density': 0.08, 'contrast': 40}
for row in range(num_rows):
for col in range(num_cols):
y_start = max(0, row * block_h)
y_end = min(height, (row + 1) * block_h)
x_start = max(0, col * block_w)
x_end = min(width, (col + 1) * block_w)
block = img_cv[y_start:y_end, x_start:x_end]
gray = cv2.cvtColor(block, cv2.COLOR_BGR2GRAY)
h, w = gray.shape
block_area = h * w
variance = np.var(gray)
hist = cv2.calcHist([gray], [0], None, [256], [0, 256]).flatten()
prob = hist / (block_area + 1e-7)
entropy = -np.sum(prob * np.log(prob + 1e-7))
edges = cv2.Canny(gray, 50, 150)
edge_pixels = np.count_nonzero(edges)
edge_density = edge_pixels / block_area
contrast = np.max(gray) - np.min(gray)
block_list.append({
'variance': variance, 'entropy': entropy,
'edge_density': edge_density, 'contrast': contrast,
'area': block_area, 'coords': (x_start, y_start, x_end, y_end)
})
# 原花屏检测逻辑
all_variances = [b['variance'] for b in block_list]
all_entropies = [b['entropy'] for b in block_list]
global_variance_mean = statistics.mean(all_variances)
global_entropy_mean = statistics.mean(all_entropies)
dynamic_thresholds = {
'variance': global_variance_mean - 1.5 * np.std(all_variances),
'entropy': global_entropy_mean - 1.5 * np.std(all_entropies)
}
flower_blocks = [b for b in block_list if
sum([b['variance'] < dynamic_thresholds['variance'],
b['entropy'] < dynamic_thresholds['entropy'],
b['edge_density'] > FEATURE_THRESHOLDS['edge_density'],
b['contrast'] < FEATURE_THRESHOLDS['contrast']]) >= 3
and b['area'] >= (total_pixels * 0.01)]
is_flower_screen = (sum(b['area'] for b in flower_blocks) / total_pixels) > 0.1
# 黑白屏检测逻辑
img_pil = Image.open(temp_path).convert('RGBA')
color, total = (0, 0, 0), 0
for count, (r, g, b, a) in img_pil.getcolors(img_pil.size[0] * img_pil.size[1]):
if a != 0:
color = (color[0] + r * count, color[1] + g * count, color[2] + b * count)
total += count
if total > 0:
dominant_color = (int(color[0] / total), int(color[1] / total), int(color[2] / total))
mean_brightness = statistics.mean(dominant_color)
is_black_screen = mean_brightness < 10
is_white_screen = mean_brightness > 254
else:
is_black_screen, is_white_screen = True, False
return is_flower_screen, is_black_screen, is_white_screen, temp_path
def verify_screen(self):
"""
二次检测屏幕异常,减少检测屏幕异常误报率
"""
save_dir = "D:/problem/problemphoto/"
os.makedirs(save_dir, exist_ok=True)
temp_files = []
# 第一次检测
first_flower, first_black, first_white, first_temp = self.check_screen()
if first_temp:
temp_files.append(first_temp)
if not (first_flower or first_black or first_white):
self.clean_temp_files(temp_files)
return False, False, False
time.sleep(0.8)
second_flower, second_black, second_white, second_temp = self.check_screen()
if second_temp:
temp_files.append(second_temp)
# 最终判定:两次同类异常才保存
final_flower = first_flower and second_flower
final_black = first_black and second_black
final_white = first_white and second_white
# 截图保存逻辑
if final_flower or final_black or final_white:
timestamp = time.strftime("%Y%m%d_%H%M%S", time.localtime())
anomaly_types = []
if final_flower: anomaly_types.append("flower")
if final_black: anomaly_types.append("black")
if final_white: anomaly_types.append("white")
filename = f"{timestamp}_{'_'.join(anomaly_types)}.png"
# 保存二次检测的临时截图到目标目录
shutil.copy(second_temp, os.path.join(save_dir, filename))
self.log_error()
# 清理所有临时文件(无论是否保存)
self.clean_temp_files(temp_files)
return final_flower, final_black, final_white
def clean_temp_files(self, temp_files):
""" 辅助方法:安全删除临时文件 """
for path in temp_files:
if os.path.exists(path):
try:
os.remove(path)
except Exception as e:
pass
def install_app(self, apk_path):
"""使用 os.system 执行 adb 命令"""
command = f"adb install -d -r -g {apk_path}"
exit_code = os.system(command)
if exit_code == 0:
print("应用安装成功")
else:
print("安装失败")
def random_operation(self, duration,package_name,timeout=25):
crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count = 0, 0, 0, 0, 0
# 获取设备屏幕尺寸
screen = self.driver.get_window_size()
screen_width = screen['width']
screen_height = screen['height']
start_time = time.time()
last_operation_time = time.time() # 记录最后一次成功操作的时间
while time.time() - start_time < duration:
# 检测全局超时
if time.time() - last_operation_time > timeout:
print(f"操作超时({timeout}秒无响应),结束测试")
break
#驻留检测
try:
currentt_package = self.get_current_package().lower()
target_package = package_name.lower()
if currentt_package != target_package:
print(f"当前包名不匹配目标!!!")
self.driver.activate_app(package_name)
time.sleep(3)
last_operation_time = time.time()
except Exception as e:
print(f"驻留检测失败:{e}")
try:
# 随机选择操作类型(点击/滑动/输入)
operation = random.choice(['click', 'swipe', 'input'])
if operation == 'click':
# 随机坐标点击
x = random.randint(0, screen_width)
y = random.randint(0, screen_height)
self.driver.tap([(x, y)], duration=50)
time.sleep(0.3)
elif operation == 'swipe':
# 随机方向滑动(上下左右)
direction = random.choice(['up', 'down', 'left', 'right'])
if direction == 'up':
self.driver.swipe(screen_width // 2, screen_height * 3 // 4, screen_width // 2,
screen_height // 4, 500)
elif direction == 'down':
self.driver.swipe(screen_width // 2, screen_height // 4, screen_width // 2,
screen_height * 3 // 4, 500)
elif direction == 'left':
self.driver.swipe(screen_width * 3 // 4, screen_height // 2, screen_width // 4,
screen_height // 2, 500)
elif direction == 'right':
self.driver.swipe(screen_width // 4, screen_height // 2, screen_width * 3 // 4,
screen_height // 2, 500)
time.sleep(0.5)
elif operation == 'input':
input_elements = self.driver.find_elements(AppiumBy.CLASS_NAME, "android.widget.EditText")
if input_elements:
input_element = random.choice(input_elements)
input_element.click()
random_digits = ''.join(str(random.randint(0, 9)) for _ in range(random.randint(1, 10)))
input_element.send_keys(random_digits)
time.sleep(0.8)
if self.check_app_crash():
crash_count += 1
if self.check_app_anr():
anr_count += 1
is_flower, is_black, is_white = self.verify_screen()
if is_flower:
flower_screen_count += 1
if is_black:
black_screen_count += 1
if is_white:
white_screen_count += 1
last_operation_time = time.time()
except Exception as e:
pass
return (crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count)
def restart_app(self, times, package_name):
"""
带重试逻辑的应用重启方法,支持 Activity 动态获取
:param times: 重启循环次数
:param package_name: 目标应用包名
"""
crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count = 0, 0, 0, 0, 0
for _ in range(times):
try:
# 步骤1:终止应用并等待
self.driver.terminate_app(package_name)
time.sleep(5)
# 步骤2:尝试激活应用
self.driver.activate_app(package_name)
time.sleep(5)
except Exception as e:
self.last_activity_time = time.time()
retry_count = 0
while retry_count < 2:
try:
self.driver.activate_app(package_name)
time.sleep(5)
current_package = self.driver.current_package
if package_name == current_package:
break
else:
print(f"第{retry_count + 1}次启动未启动成功")
retry_count += 1
time.sleep(5)
except Exception as retry_e:
continue
if self.check_app_crash():
crash_count += 1
if self.check_app_anr():
anr_count += 1
is_flower, is_black, is_white = self.verify_screen()
if is_flower:
flower_screen_count += 1
if is_black:
black_screen_count += 1
if is_white:
white_screen_count += 1
return crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count
def uninstall_app(self, package_name):
try:
self.driver.terminate_app(package_name)
os.system(f"adb uninstall {package_name}")
return True
except:
return False
pass
def generate_report(self, app_name, package_name, crash_count, anr_count,
flower_screen_count, black_screen_count, white_screen_count,
app_version, install_result, start_result,uninstall_result):
if not os.path.exists(self.report_file):
wb = openpyxl.Workbook()
sheet = wb.active
sheet.append(["序号", "应用名称", "包名", "应用版本号", "安装应用", "启动应用",
"闪退次数", "ANR次数", "花屏次数", "黑屏次数", "白屏次数", "卸载结果","统计"])
row_number = 1
else:
wb = openpyxl.load_workbook(self.report_file)
sheet = wb.active
row_number = len(sheet['A'])
install_result_str = "成功" if install_result else "失败"
start_result_str = "成功" if start_result else "失败"
uninstall_result_str = "成功" if uninstall_result else "失败"
has_failure = (not install_result) or (not start_result) or \
(crash_count > 0 or anr_count > 0 or flower_screen_count > 0 or
black_screen_count > 0 or white_screen_count > 0)
status = "fail" if has_failure else "pass"
sheet.append([
row_number, app_name, package_name, app_version,
install_result_str, start_result_str,
crash_count, anr_count, flower_screen_count,
black_screen_count, white_screen_count,uninstall_result_str,
status
])
# 保存文件
wb.save(self.report_file)
def generate_report_even_failed(self, app_name, package_name, crash_count, anr_count,
flower_screen_count, black_screen_count, white_screen_count,
app_version, install_result, start_result,uninstall_result):
try:
self.generate_report(app_name, package_name, crash_count, anr_count,
flower_screen_count, black_screen_count, white_screen_count,
app_version, install_result, start_result,uninstall_result)
except Exception as e:
print(f"生成报告时出错:{str(e)}")
def log_error(self):
current_timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
log_folder = f"D:/problem/logs/{current_timestamp}"
os.makedirs(log_folder, exist_ok=True)
adb_pull_command = f"pull /data/log/hilogs {log_folder}"
ADBHelper().adb(adb_pull_command)
time.sleep(10)
adb_pull_command = f"pull /data/log/dropbox {log_folder}"
ADBHelper().adb(adb_pull_command)
time.sleep(10)
def quit_driver(self):
self.driver.quit()
def click_element_by_texts(self, texts):
"""循环匹配文本点击页面文本元素"""
screenshot_dir = "D:/problem/clickscreenshot"
if not os.path.exists(screenshot_dir):
os.makedirs(screenshot_dir)
print(f"已创建截图文件夹:{screenshot_dir}")
for text in texts:
try:
element = self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, f'new UiSelector().text("{text}")')
if element.is_enabled() and element.is_displayed():
element.click()
return True
except:
continue
else:
screenshot_name = f"{int(time.time())}.png"
screenshot_path = os.path.join(screenshot_dir, screenshot_name)
self.driver.save_screenshot(screenshot_path)
return False
def get_app_version(self, package_name):
"""获取当前应用版本"""
try:
result = os.popen(f"adb shell dumpsys package {package_name} | findstr versionName").read().strip()
if result:
parts = result.split('=')
if len(parts) > 1:
return parts[1]
return "未知版本"
except:
return "未知版本"
def check_app_crash(self):
"""检测应用是否闪退"""
try:
current_activity = self.get_current_activity()
home_activity = "com.huawei.android.launcher.unihome.UniHomeLauncher"
if current_activity == home_activity:
print(f"应用发生闪退!!!")
self.scrennphoto_problem(problem_type="crash")
self.log_error()
return True
else:
return False
except Exception as e:
print(f"检测闪退时出错: {e}")
return None
def scrennphoto_problem(self, problem_type: str):
"""封装:截图并记录日志(根据问题类型生成不同目录)"""
base_dir = "D:/problem/"
screenshot_dir = os.path.join(base_dir, f"{problem_type}photo/")
os.makedirs(screenshot_dir, exist_ok=True)
timestamp = time.strftime('%Y%m%d_%H%M%S')
screenshot_path = os.path.join(screenshot_dir, f"{problem_type}_{timestamp}.png")
if self.driver.save_screenshot(screenshot_path):
print(f"截图保存成功:{screenshot_path}")
else:
print(f"截图保存失败:{screenshot_path}")
# def check_app_anr(self):
# """判断当前页面是否存在ANR问题"""
# try:
# # 执行ANR检测命令
# result = subprocess.check_output(
# "adb shell logcat -d | grep -i ANR",
# shell=True,
# text=True,
# stderr=subprocess.STDOUT
# )
# # 判断是否存在ANR
# if "ANR" in result:
# self.scrennphoto_problem(problem_type="anr")
# self.log_error()
# return True
# return True
# except Exception as e:
# return False
def check_app_anr(self):
"""判断当前页面是否存在ANR问题"""
anr_keywords = ["无响应", "关闭应用", "是否将其关闭", "等待"]
try:
has_anr_screen = False
for keyword in anr_keywords:
elements = self.driver.find_elements(
by=AppiumBy.XPATH,
value=f"//*[contains(@text, '{keyword}')]"
)
if elements:
has_anr_screen = True
break
if has_anr_screen:
print(f"检测到ANR:日志存在ANR记录且屏幕显示无响应提示")
self.scrennphoto_problem(problem_type="anr")
self.log_error()
return True
else:
return False
except Exception as e:
print(f"ANR检测异常:{str(e)}")
return False
def is_target_activity(self, package_name, activity):
"""判断当前 Activity 是否属于目标应用"""
return activity and activity.startswith(package_name)
def get_current_activity(self):
"""获取当前Android设备的Activity名称"""
try:
# 执行ADB命令获取窗口信息
command = "adb shell dumpsys window | findstr mCurrentFocus"
result = subprocess.check_output(command, shell=True, text=True, timeout=5)
except subprocess.CalledProcessError:
return "错误:ADB命令执行失败,请检查设备连接"
except subprocess.TimeoutExpired:
return "错误:命令执行超时,请确认ADB服务正常"
except Exception as e:
return f"错误:{str(e)}"
if not result.strip():
return "提示:未获取到窗口信息,请先打开一个应用"
# 用正则表达式匹配/后面的内容
match = re.search(r'/([^ }]+)', result)
if match:
return match.group(1)
else:
return "提示:未找到Activity名称,输出格式可能不一致"
def get_current_package(self):
"""验证应用是否下载成功"""
current_package = self.driver.current_package # 获取当前包名
return current_package
def pull_download_apk(self):
"""
从Android设备提取指定包名的APK文件
"""
# 固定参数设置
adb_path = 'adb'
output_dir = 'D:\\apk'
# 获取当前应用包名
try:
package_name = self.get_current_package()
if not package_name:
raise ValueError("无法获取当前应用包名")
except Exception as e:
raise RuntimeError(f"获取包名失败: {str(e)}")
# 确保输出目录存在
# os.makedirs(output_dir, exist_ok=True)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 获取包安装路径
cmd_get_path = f"{adb_path} shell pm path {package_name}"
try:
result = subprocess.run(cmd_get_path, capture_output=True, text=True, shell=True, timeout=30)
if result.returncode != 0:
raise RuntimeError(f"获取包路径失败: {result.stderr.strip()}")
# 解析输出结果
output = result.stdout.strip()
if not output:
raise ValueError(f"未找到包名为 '{package_name}' 的应用")
# 提取APK路径 (取第一个路径)
apk_paths = re.findall(r'package:(.+)', output)
if not apk_paths:
raise ValueError(f"无法解析包路径: {output}")
device_path = apk_paths[0].strip()
print(f"设备路径: {device_path}")
except subprocess.TimeoutExpired:
raise RuntimeError("获取包路径超时,请检查设备连接")
# 创建本地文件名和路径
local_filename = f"{package_name}.apk"
local_path = os.path.join(output_dir, local_filename)
# 执行pull命令
cmd_pull = f"{adb_path} pull {device_path} \"{local_path}\""
try:
result = subprocess.run(cmd_pull, capture_output=True, text=True, shell=True, timeout=60)
if result.returncode != 0:
raise RuntimeError(f"提取APK失败: {result.stderr.strip()}")
except subprocess.TimeoutExpired:
raise RuntimeError("提取APK超时,文件可能过大")
# 验证文件是否成功提取
if not os.path.exists(local_path):
raise FileNotFoundError(f"文件提取失败: {local_path}")
print(f"成功提取APK到: {local_path}")
return local_path
def check_downapp_verify(self, package_name, app_name):
"""检测应用是否下载正确(返回字典)"""
try:
current_package = self.get_current_package().lower()
expected_package = package_name.lower()
# 构造返回结果(包含状态、应用名、包名、原因)
result = {
"status": None,
"app_name": app_name,
"package_name": package_name,
"reason": ""
}
if current_package == expected_package:
return True
else:
result["status"] = False
result["reason"] = f"下载应用包名不符"
return result
except Exception as e:
return {
"status": None,
"app_name": app_name,
"package_name": package_name,
"reason": f"检测应用时出错: {e}"
}
def downapp_report(self, app_name, package_name, download_result, pullapk_result, remark=None):
if not os.path.exists(self.report_files):
wb = openpyxl.Workbook()
sheet = wb.active
sheet.append(["应用名称", "包名", "下载结果", "上传结果", "统计", "备注"])
row_number = 1
else:
wb = openpyxl.load_workbook(self.report_files)
sheet = wb.active
row_number = len(sheet['A'])
download_result_str = "成功" if download_result else "失败"
pullapk_result_str = "成功" if pullapk_result else "失败"
has_failure = (not download_result) or (not pullapk_result)
status = "fail" if has_failure else "pass"
sheet.append([
app_name,
package_name,
download_result_str,
pullapk_result_str,
status,
remark
])
wb.save(self.report_files)
def click_element_with_swipe(self,driver, target_id, target_text, timeout=10, max_swipe=0):
"""
定位并点击同时满足ID和文本条件的元素(未找到时下滑重试),返回操作结果
"""
uiautomator_selector = f'new UiSelector().resourceId("{target_id}").textContains("{target_text}")'
located = False
for attempt in range(max_swipe + 1):
try:
element = WebDriverWait(driver, timeout).until(
EC.element_to_be_clickable(("-android uiautomator", uiautomator_selector))
)
element.click()
print(f"成功点击元素(ID={target_id}, 文本={target_text})")
located = True
break
except TimeoutException:
if attempt < max_swipe:
print(f"第{attempt + 1}次定位超时,尝试下滑...")
self.swipe_down(driver)
else:
print(f"已尝试{max_swipe + 1}次,未找到符合条件的元素")
except Exception as e:
print(f"操作失败,原因:{str(e)}")
located = False
break
return located
def swipe_down(self, driver, duration=500, swipe_times=1):
"""
动态计算坐标实现下滑(页面向下滚动)
"""
# 获取屏幕尺寸
window_size = driver.get_window_size()
x = window_size["width"]
y = window_size["height"]
# x, y = ADBHelper().get_phone_size()
x1 = x * 0.5
y1 = y * 0.9
x2 = x * 0.5
y2 = y * 0.2
for i in range(swipe_times):
driver.swipe(x1, y1, x2, y2, duration)
print(f"第{i + 1}/{swipe_times}次下滑操作完成,等待页面加载...")
driver.implicitly_wait(3)
print(f"全部{swipe_times}次下滑操作执行完毕")
def swipe_up(self, driver, duration=500, swipe_times=1):
"""
动态计算坐标实现上滑(页面向上滚动)
"""
# 获取屏幕尺寸
# window_size = driver.get_window_size()
# x = window_size["width"]
# y = window_size["height"]
x, y = ADBHelper().get_phone_size()
x1 = x * 0.5
y1 = y * 0.2
x2 = x * 0.5
y2 = y * 0.9
for i in range(swipe_times):
driver.swipe(x1, y1, x2, y2, duration)
print(f"第{i + 1}/{swipe_times}次上滑操作完成,等待页面加载...")
driver.implicitly_wait(3)
print(f"全部{swipe_times}次上滑操作执行完毕")
def go_back(self, driver, times=1, interval=3):
"""
:param times: 要点击返回键的次数(需≥0,默认1次)
:param interval: 每次点击的间隔时间(秒,默认3秒)
"""
# 执行返回键点击
try:
for i in range(times):
driver.press_keycode(4)
print(f"已点击返回键(第{i + 1}/{times}次)")
time.sleep(interval)
return True
except WebDriverException as e:
print(f"返回键操作失败,原因:{str(e)}")
pass
return False
def wait_element_click(self,driver, locator, timeout=600):
"""
等待元素可点击后尝试点击,返回点击是否成功
"""
try:
element = WebDriverWait(driver, timeout).until(
EC.element_to_be_clickable(locator)
)
except Exception as e:
return False
try:
element.click()
return True
except (ElementNotInteractableException, StaleElementReferenceException, WebDriverException):
return False
def download_AG_app(self, driver, app_name, package_name):
market_package = "com.huawei.appmarket"
try:
for i in range(2):
driver.press_keycode(187)
try:
driver.find_element(By.ID, 'com.huawei.android.launcher:id/clear_all_recents_image_button').click()
except:
pass
driver.press_keycode(3)
except:
pass
time.sleep(10)
driver.activate_app(market_package)
time.sleep(10)
self.click_element_with_swipe(driver, target_id='com.huawei.appmarket:id/enter_button', target_text='暂不安装')
self.click_element_with_swipe(driver, target_id='android:id/button2', target_text='以后再说')
self.swipe_up(driver, swipe_times=3)
driver.find_element(By.ID, 'com.huawei.appmarket:id/fixed_search_view').click()
time.sleep(3)
src_text = driver.find_element(By.ID, "com.huawei.appmarket:id/search_src_text")
src_text.set_text(app_name)
time.sleep(3)
driver.find_element(By.ID, 'com.huawei.appmarket:id/hwsearchview_search_text_button').click()
time.sleep(3)
result1 = self.click_element_with_swipe(driver, target_id='com.huawei.appmarket:id/ItemTitle',target_text=f'{app_name}', max_swipe=3)
# 可以在应用市场搜索到该应用
if result1 == True:
time.sleep(5)
# 场景1:应用未安装
result2= self.click_element_with_swipe(driver, target_id='com.huawei.appmarket:id/hwprogressbutton_percentage_text_view',target_text='安装')
if result2 == True:
open_text = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("打开")')
result3=self.wait_element_click(driver, open_text)
# 应用规定时间内安装完成
if result3 == True:
time.sleep(5)
self.click_element_with_swipe(driver,target_id='com.android.permissioncontroller:id/permission_allow_button',target_text='允许')
else: # 下载超时&开发者原因暂不支持下载
self.click_element_with_swipe(driver,target_id='com.huawei.appmarket:id/hwprogressbutton_percentage_text_view',target_text='%')
self.go_back(driver, times=3)
return {
"status": "notime",
"app_name": app_name,
"package_name": package_name,
"reason": f"{app_name}下载超时&开发者原因暂不支持下载 "
}
# 场景2:应用已存在
else:
time.sleep(30)
result4 = self.click_element_with_swipe(driver,target_id='com.huawei.appmarket:id/hwprogressbutton_percentage_text_view', target_text='打开')
if result4 == True:
time.sleep(5)
self.click_element_with_swipe(driver, target_id='com.android.permissioncontroller:id/permission_allow_button',target_text='允许')
else:
pass
else:
failure_info = {
"status": "fail1",
"app_name": app_name,
"package_name": package_name,
"reason": f"应用市场未找到应用:{app_name}"
}
self.go_back(driver, times=3)
return failure_info
def check_apk_architecture(self,apk_path: str, app_name: str, package_name: str) -> dict:
"""
检测APK架构并返回指定格式的结果字典
:param apk_path: APK文件路径
:param app_name: 应用名称(需外部传入)
:param package_name: 应用包名(需外部传入)
:return: 包含检测状态的字典(check_info)
"""
# 初始化默认结果(检测失败状态)
check_info = {
"status": "fail",
"app_name": app_name,
"package_name": package_name,
"remark": "检测失败"
}
x64_archs = {'arm64-v8a', 'x86_64', 'mips64'}
x32_archs = {'armeabi', 'armeabi-v7a', 'x86', 'mips'}
detected_64 = set()
detected_32 = set()
try:
if not os.path.isfile(apk_path):
check_info["remark"] = "检测失败:APK文件不存在"
return check_info
with zipfile.ZipFile(apk_path, 'r') as zip_ref:
all_members = zip_ref.namelist()
for member in all_members:
member = member.replace('\\', '/')
if member.startswith("lib/"):
lib_subpath = member.split("lib/")[1].split('/')
if len(lib_subpath) < 1:
continue
arch_dir = lib_subpath[0].lower()
if not arch_dir:
continue
if arch_dir in x32_archs:
detected_32.add(arch_dir)
elif arch_dir in x64_archs:
detected_64.add(arch_dir)
# 判断检测结果
has_64bit = len(detected_64) > 0
if has_64bit:
# 64位检测成功
check_info.update({
"status": "success",
"remark": "应用64位,已保留"
})
else:
# 32位检测成功
os.remove(apk_path)
check_info.update({
"status": "success",
"remark": "应用32位,已删除"
})
except Exception as e:
check_info["remark"] = f"检测失败:{e}"
return check_info
def checkapp_report(self, app_name, package_name, check_result):
if not os.path.exists(self.report_checkfile):
wb = openpyxl.Workbook()
sheet = wb.active
sheet.append(["应用名称", "包名", "检测结果"])
row_number = 1
else:
wb = openpyxl.load_workbook(self.report_checkfile)
sheet = wb.active
row_number = len(sheet['A'])
sheet.append([
app_name,
package_name,
check_result
])
wb.save(self.report_checkfile)
最新发布