Java调用百度API出现{status:211,message:APP SN校验失败}

本文介绍如何解决在调用百度API时遇到的APPSN校验失败问题,详细解析了Java环境下SN签名的正确计算方法,包括参数顺序的重要性、特殊字符处理及MD5加密过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java调用百度API出现{"status":211,"message":"APP SN校验失败"}

{“status”:211,“message”:“APP SN校验失败”}

1、百度官方提供了C#、Java、python、php等版本的sn签名计算算法:
sn计算算法

2、本人在接入API接口过程中发现官方demo不太完善。以下是本人的Java代码:

package cn.maps.baidu.util;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;

public class SnCalUtil {

    public SnCalUtil() {
    }

    /**
     * 计算sn跟参数对出现顺序有关(参数对放入顺序必须跟请求中对应参数的出现顺序保持一致):
     * get请求请使用LinkedHashMap保存<key,value>,该方法根据key的插入顺序排序;
     * post请使用TreeMap保存<key,value>,该方法会自动将key按照字母a-z顺序排序。
     * 所以get请求可自定义参数顺序(sn参数必须在最后)发送请求,
     * 但是post请求必须按照字母a-z顺序填充body(sn参数必须在最后)。
     *
     * @param url       请求路径url
     * @param paramsMap 请求参数对
     * @param sk        ak对应sk秘钥
     * @return sn签名
     * @throws UnsupportedEncodingException
     */
    public String getSn(String url, Map<?, ?> paramsMap, String sk) throws UnsupportedEncodingException {
        String paramsStr = toQueryString(paramsMap);
        url = url.replaceFirst("http://api.map.baidu.com", "").trim();
        url = url.replaceFirst("http://yingyan.baidu.com", "").trim();
        System.out.println("************************Calculate Sn >>>>>url:" + url);
        //url在计算sn签名的时候,不管是get请求还是post请求,必须带?
        String wholeStr = url + paramsStr + sk;
        System.out.println("************************Calculate Sn >>>>>wholeStr:" + wholeStr);
        //对上面wholeStr再作utf8编码
        String tempStr = URLEncoder.encode(wholeStr, "UTF-8");
        System.out.println("************************Calculate Sn >>>>>tempStr:" + tempStr);
        //调用下面的MD5方法得到最后的sn签名
        String sn = MD5(tempStr);
        System.out.println("************************Calculate Sn >>>>>Sn:" + sn);
        return sn;
    }

    /**
     * 对请求参数Map内所有value作utf8编码,拼接返回结果
     *
     * @param data 请求参数对
     * @return str 字符串
     * @throws UnsupportedEncodingException 异常
     */
    public String toQueryString(Map<?, ?> data) throws UnsupportedEncodingException {
        StringBuffer queryString = new StringBuffer();
        for (Entry<?, ?> pair : data.entrySet()) {
            queryString.append(pair.getKey()).append("=");
            String ss[] = String.valueOf(pair.getValue()).split(",");
            if (ss.length>1){
                for(String s:ss){
                    queryString.append(URLEncoder.encode(s, "UTF-8")).append(",");
                }
                queryString.deleteCharAt(queryString.length()-1);
                queryString.append("&");
            }else {
                queryString.append(URLEncoder.encode(String.valueOf(pair.getValue()), "UTF-8"));
                queryString.append("&");
            }
        }
        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }
        return queryString.toString();
    }

    /**
     * 来自stackoverflow的MD5计算方法,调用了MessageDigest库函数,并把byte数组结果转换成16进制
     *
     * @param str 要计算的字符串
     * @return sn
     */
    public String MD5(String str) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] array = md.digest(str.getBytes());
            StringBuffer sb = new StringBuffer();
            for (byte b : array) {
                sb.append(Integer.toHexString((b & 0xFF) | 0x100), 1, 3);
            }
            return sb.toString();
        } catch (java.security.NoSuchAlgorithmException ignored) {
        }
        return null;
    }
}

注意:
(1)因为我是从配置文件中读取百度API接口的url,计算sn签名时候是从.com以后开始,所以我的代码有如下转换:

url = url.replaceFirst("http://api.map.baidu.com", "").trim();
url = url.replaceFirst("http://yingyan.baidu.com", "").trim();
##百度Web服务API-逆地理编码接口地址(GET请求)
maps.baidu.position.url=http://api.map.baidu.com/reverse_geocoding/v3/?

##百度鹰眼轨迹服务——终端管理类——entity的创建接口(POST请求)
maps.baidu.yingyan.terminals.entity.add.url=http://yingyan.baidu.com/api/v3/entity/add?

url在计算sn签名的时候,不管是get请求还是post请求,必须带?,否则会出现如题所示的{“status”:211,“message”:“APP SN校验失败”}

(2)官方提供的toQueryString(Map<?, ?> data)方法中做了修改,对“,”转义处理。

for (Entry<?, ?> pair : data.entrySet()) {
    queryString.append(pair.getKey()).append("=");
    String ss[] = String.valueOf(pair.getValue()).split(",");
    if (ss.length>1){
        for(String s:ss){
            queryString.append(URLEncoder.encode(s, "UTF-8")).append(",");
        }
        queryString.deleteCharAt(queryString.length()-1);
        queryString.append("&");
    }else {
        queryString.append(URLEncoder.encode(String.valueOf(pair.getValue()), "UTF-8"));
        queryString.append("&");
    }
}

或者在HttpClient发送get请求时候替换参数里的逗号为“%2C”也可以。

请问这个类中的get_current_activity()方法,在其他用例文件,都有那些调用方式,方法如下: # !/usr/bin/env python # -*- coding: utf-8 -*- import sqlite3 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 ############################################################################### def get_devices(): """ 获取所有安卓设备的SN: ['B7EDU17626000398', 'B7EDU17626000233'] """ devices_list = [] str_list = os.popen('adb devices').readlines() # print(str_list) count = 0 for i in str_list: if '\tdevice' in i: device_name = '' device_name = re.sub('\tdevice', '', i).replace('\n', '').strip() # print("Device_{}_name={}".format(count, device_name)) devices_list.append(device_name) count = count + 1 # print("devices={},devices_list={}".format(count,devices_list)) return devices_list ############################################################################### # def get_sn(): # sn = get_devices()[0] # return sn # # udid = get_sn() # sup_udid = "" # host_port,sup_port = 4723,4800 # 从配置文件中获取sn和分配的端口号 device_info_path = os.path.abspath('./conf/device_info.yaml') with open(device_info_path, 'r', encoding='utf-8') as f: device_info = yaml.load(f, yaml.Loader) udid = device_info['当前项目设备详情']['host'] sup_udid = device_info['当前项目设备详情']['sup'] host_port = device_info['端口分配情况'][udid] if sup_udid == '': sup_port = '' else: sup_port = device_info['端口分配情况'][sup_udid] def get_app_driver(package, activity, sn=udid, noreset=True): desired_caps = { 'platformName': 'Android', # 被测手机是安卓 'platformVersion': ADBHelper().get_android_version(), # 手机安卓版本 'deviceName': ADBHelper().get_product_model(), # 设备名,安卓手机可以随意填写 'appPackage': package, # 启动APP Package名称 'appActivity': activity, # 启动Activity名称 'unicodeKeyboard': True, # 使用自带输入法,输入中文时填True 'resetKeyboard': False, # 执行完程序恢复原来输入法 'noReset': noreset, # 不要重置App 'newCommandTimeout': 12000, 'automationName': 'UiAutomator2', 'appWaitForLaunch': False, # 是否等待活动管理器将控制权返回给调用进程。 'udid': sn # 'app': r'd:\apk\bili.apk', } port = '' if sn == udid: port = host_port elif sn == sup_udid: port = sup_port # 连接Appium Server,初始化自动化环境 driver = webdriver.Remote('http://localhost' + ':' + str(port) + '/wd/hub', desired_caps) driver.implicitly_wait(4) time.sleep(2) return driver def get_sup_app_driver(package, activity, noreset=True): desired_caps = { 'platformName': 'Android', # 被测手机是安卓 'platformVersion': '12', # 手机安卓版本 'deviceName': 'ASN-AN00', # 设备名,安卓手机可以随意填写 'appPackage': package, # 启动APP Package名称 'appActivity': activity, # 启动Activity名称 'unicodeKeyboard': True, # 使用自带输入法,输入中文时填True 'resetKeyboard': True, # 执行完程序恢复原来输入法 'noReset': noreset, # 不要重置App 'newCommandTimeout': 6000, 'automationName': 'UiAutomator2', 'udid': sup_udid # 'app': r'd:\apk\bili.apk', } # 连接Appium Server,初始化自动化环境 driver = webdriver.Remote('http://localhost' + ':' + str(sup_port) + '/wd/hub', desired_caps) driver.implicitly_wait(3) return driver def get_third_app_driver(package, activity, sn, noreset=True): desired_caps = { 'platformName': 'Android', # 被测手机是安卓 'platformVersion': ADBHelper().get_android_version(), # 手机安卓版本 'deviceName': ADBHelper().get_product_model(), # 设备名,安卓手机可以随意填写 'appPackage': package, # 启动APP Package名称 'appActivity': activity, # 启动Activity名称 'unicodeKeyboard': True, # 使用自带输入法,输入中文时填True 'resetKeyboard': True, # 执行完程序恢复原来输入法 'noReset': noreset, # 不要重置App 'newCommandTimeout': 12000, 'automationName': 'UiAutomator2', 'udid': sn # 'app': r'd:\apk\bili.apk', } port = '' if sn == udid: port = host_port elif sn == sup_udid: port = sup_port else: port = sup_port + 5 # 连接Appium Server,初始化自动化环境 driver = webdriver.Remote('http://localhost' + ':' + str(port) + '/wd/hub', desired_caps) driver.implicitly_wait(5) return driver def uninstall_appium(sn=udid): ADBHelper(sn).adb('uninstall io.appium.uiautomator2.server.test') ADBHelper(sn).adb('uninstall io.appium.uiautomator2.server') ADBHelper(sn).adb('uninstall io.appium.settings') def catch_all_logs(): desti_path = os.path.abspath('./log/device_logs') ADBHelper().pull_file('/data/log/android_logs', desti_path) ADBHelper().pull_file('/data/log/hilogs', desti_path) ADBHelper().pull_file('/data/system/dropbox', desti_path) ADBHelper().pull_file('/data/anr', desti_path) ADBHelper().pull_file('/data/log/bbox', desti_path) ADBHelper().pull_file('/data/log/charge-log', desti_path) ADBHelper().pull_file('/log/reliability/boot_fail', desti_path) ADBHelper().pull_file('/data/log/reliability/xcollie', desti_path) ADBHelper().pull_file('/data/log/faultlog', desti_path) ADBHelper().pull_file('/data/log/LogService/901/done', desti_path) ADBHelper().pull_file('/data/log/LogService/901/uploading', desti_path) ADBHelper().pull_file('/data/log/reliability/resource_leak', desti_path) ADBHelper().pull_file('/data/log/dropbox', desti_path) ADBHelper().pull_file('/log/recovery', desti_path) ADBHelper().pull_file('/data/hisi_logs', desti_path) ADBHelper().pull_file('/data/tombstones', desti_path) ADBHelper().pull_file('/data/vendor/log/mtklog', desti_path) ADBHelper().pull_file('/data/log/sleeplog', desti_path) ADBHelper().pull_file('/data/log/jank', desti_path) Global = {} ################################################################################################## # 开关相关的类 swith_sn = [''] class Switch: def __init__(self,sn=udid): self.sn = sn swith_sn[0] = self.sn class BT: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('svc bluetooth enable') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('svc bluetooth disable') class WIFI: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('svc wifi enable') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('svc wifi disable') class DATA: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('svc data enable') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('svc data disable') class NFC: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('svc nfc enable') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('svc nfc disable') class Airplane_Mode: @classmethod def open(cls): airplanemode = get_app_driver("com.android.settings", "com.android.settings.Settings$WirelessSettingsActivity",sn=swith_sn[0]) switch_button = airplanemode.find_element(By.ID, 'android:id/switch_widget') if switch_button.get_attribute('checked') == 'false': switch_button.click() time.sleep(1) else: return # ADBHelper().shell('settings put global airplane_mode_on 1') @classmethod def close(cls): airplanemode = get_app_driver("com.android.settings", "com.android.settings.Settings$WirelessSettingsActivity",sn=swith_sn[0]) switch_button = airplanemode.find_element(By.ID, 'android:id/switch_widget') if switch_button.get_attribute('checked') == 'true': switch_button.click() time.sleep(1) else: return # ADBHelper().shell('settings put global airplane_mode_on 0') class Display_auto: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('settings put system screen_brightness_mode 1') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('settings put system screen_brightness_mode 0') class GPS: @classmethod def open(cls): driver = get_app_driver('com.android.settings', 'com.android.settings.Settings$LocationSettingsActivity',sn=swith_sn[0]) GPS_switch_button = driver.find_element(By.ID, 'android:id/switch_widget') if GPS_switch_button.get_attribute('checked') == 'false': GPS_switch_button.click() try: driver.find_element(By.ID, 'android:id/button1').click() driver.find_element(By.ID, 'android:id/button1').click() except: pass else: return True @classmethod def close(cls): driver = get_app_driver('com.android.settings', 'com.android.settings.Settings$LocationSettingsActivity',sn=swith_sn[0]) GPS_switch_button = driver.find_element(By.ID, 'android:id/switch_widget') if GPS_switch_button.get_attribute('checked') == 'true': GPS_switch_button.click() else: return True ########################################################################################## # 手机操作相关的类 operate_sn = [''] class Operate: def __init__(self,sn=udid): self.sn = sn operate_sn[0] = self.sn # 锁屏 @classmethod def lock_screen(cls): ADBHelper(operate_sn[0]).shell("input keyevent 26") # 解锁 @classmethod def unlock_screen(cls): ADBHelper(operate_sn[0]).shell("input keyevent 82") ADBHelper(operate_sn[0]).shell("wm dismiss-keyguard") # 返回 @classmethod def go_back(cls): ADBHelper(operate_sn[0]).shell('input keyevent 4') # home键 @classmethod def go_home(cls): ADBHelper(operate_sn[0]).shell('input keyevent 3') # 清除后台 @classmethod def clear(cls): ADBHelper(operate_sn[0]).go_home() x_size, y_size = ADBHelper().get_phone_size() ADBHelper(operate_sn[0]).shell(f"input tap {0.7083 * x_size} {0.978125 * y_size}") time.sleep(1) ADBHelper(operate_sn[0]).shell(f"input tap {0.5 * x_size} {0.90625 * y_size}") # 双击元素 @classmethod def double_click_by_ele(cls, driver, ele): ActionChains(driver).double_click(on_element=ele) # 双击坐标 @classmethod def double_click_by_location(cls, x_ratio, y_ratio): phone_x, phone_y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input tap {phone_x * x_ratio} {phone_y * y_ratio}') ADBHelper(operate_sn[0]).shell(f'input tap {phone_x * x_ratio} {phone_y * y_ratio}') # 滑动 class Swipe: @classmethod def up(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {x / 2} {5 * y / 8} {x / 2} {y / 4}') @classmethod def down(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {x / 2} {y / 4} {x / 2} {5 * y / 8}') @classmethod def left(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {3 * x / 4} {y / 2} {x / 4} {y / 2}') @classmethod def right(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {x / 4} {y / 2} {3 * x / 4} {y / 2}') # 自定义滑动 @classmethod def customize_swipe(self,start_x_ratio,start_y_ratio,end_x_ratio,end_y_ratio,swipe_times=1): """ start_x_ratio:滑动起始位置的x坐标占手机宽度的比例 start_y_ratio:滑动起始位置的y坐标占手机长度的比例 end_x_ratio: 滑动结束位置的x坐标占手机宽度的比例 end_y_ratio:滑动结束位置的y坐标占手机长度的比例 swipe_times: 滑动次数,默认为1 """ x, y = ADBHelper(operate_sn[0]).get_phone_size() for i in range(swipe_times): ADBHelper(operate_sn[0]).shell(f'input swipe {x*start_x_ratio} {y*start_y_ratio} {x*end_x_ratio} {y*end_y_ratio}') time.sleep(0.5) # 通过坐标点击 @classmethod def click_by_location(cls, x_ratio, y_ratio): phone_x, phone_y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input tap {phone_x * x_ratio} {phone_y * y_ratio}') # 提升屏幕亮度 @classmethod def increase_brightness(cls): ADBHelper(operate_sn[0]).shell("input keyevent 221") ADBHelper(operate_sn[0]).go_back() # 降低屏幕亮度 @classmethod def decrease_brightness(cls): ADBHelper(operate_sn[0]).shell("input keyevent 220") ADBHelper(operate_sn[0]).go_back() # 媒体音量调节 @classmethod def adjust_Volume(cls, type, operation): type_code_dict = { 'call': 0, 'ring': 2, 'media': 3, 'alarm': 4, 'assistant': 11 } if type in type_code_dict: if operation == 'increase': ADBHelper().shell(f'service call audio 9 i32 {type_code_dict[type]} i32 1 i32 1') if operation == 'decrease': ADBHelper().shell(f'service call audio 9 i32 {type_code_dict[type]} i32 -1 i32 1') if operation == 'mute': ADBHelper().shell(f'service call audio 9 i32 {type_code_dict[type]} i32 -100 i32 1') if operation == 'cancel_mute': ADBHelper().shell(f'service call audio 9 i32 {type_code_dict[type]} i32 100 i32 1') else: print("声音type参数错误!") # 设置音量 @classmethod def set_Volume(cls, type, level): type_code_dict = { 'call': 0, 'ring': 1, 'media': 3, 'alarm': 4, 'assistant': 11 } if type in type_code_dict: ADBHelper().shell(f'service call audio 10 i32 {type_code_dict[type]} i32 {level} i32 1') # 对一个元素进行长按 @classmethod def long_press(cls, driver, ele, duration=1000): TouchAction(driver).long_press(ele, duration=duration).release().perform() # 将一个元素拖拽到另外一个元素位置 @classmethod def drag_ele_to_ele(cls, driver, ele1, ele2): ActionChains(driver).click_and_hold(ele1).perform() ActionChains(driver).drag_and_drop(ele1, ele2).perform() # 将一个元素缓慢拖拽到另外一个元素位置(无惯性) @classmethod def drag_element_to_another_slowly(cls,driver, source_element, target_element, long_press_duration=2, steps=10): """ 长按源元素并缓慢拖动到目标元素位置 参数: driver: Appium驱动实例 source_element: 需要拖动的源元素 target_element: 目标位置的元素 long_press_duration: 长按时间(秒),默认2秒 steps:步数越多,拖动越慢越平滑 """ # 获取源元素的中心位置 source_location = source_element.location source_size = source_element.size start_x = source_location['x'] + source_size['width'] / 2 start_y = source_location['y'] + source_size['height'] / 2 # 获取目标元素的中心位置 target_location = target_element.location target_size = target_element.size target_x = target_location['x'] + target_size['width'] / 2 target_y = target_location['y'] + target_size['height'] / 2 # 计算需要移动的总距离 delta_x = target_x - start_x delta_y = target_y - start_y # 设置分阶段移动的步数 # 创建TouchAction实例 action = TouchAction(driver) # 执行长按操作 action.long_press(x=start_x, y=start_y, duration=long_press_duration * 1000) # 分阶段缓慢移动 for i in range(steps): # 计算当前步骤需要移动的绝对坐标 current_x = int(start_x + (i + 1) * delta_x / steps) current_y = int(start_y + (i + 1) * delta_y / steps) # 移动到指定坐标 if i == 0: # 第一步使用press操作(避免某些设备上的兼容性问题) action.press(x=current_x, y=current_y) else: # 后续步骤使用move_to action.move_to(x=current_x, y=current_y) # 释放并执行整个操作链 action.release().perform() # 将一个元素拖拽到坐标位置(有惯性) @classmethod def drag_ele_by_offset(cls, driver, ele, x_ratio, y_ratio): x, y = ADBHelper(operate_sn[0]).get_phone_size() ActionChains(driver).click_and_hold(ele).perform() ActionChains(driver).drag_and_drop_by_offset(ele, x * x_ratio, y * y_ratio).perform() @classmethod # 将一个元素缓慢拖拽到坐标位置(无惯性) def drag_ele_by_offset_slowly(cls,driver, element, x_ratio, y_ratio, long_press_duration=2, steps=10): """ 长按元素并缓慢拖动到指定坐标 参数: driver: Appium驱动实例 element: 需要长按的元素 target_x: 目标位置的x坐标 target_y: 目标位置的y坐标 long_press_duration: 长按时间(秒),默认2秒 steps:步数越多,拖动越慢越平滑 """ # 获取元素当前位置 location = element.location start_x = location['x'] start_y = location['y'] x, y = ADBHelper().get_phone_size() target_x, target_y = x * x_ratio, y * y_ratio # 计算需要移动的总距离 delta_x = target_x - start_x delta_y = target_y - start_y # 设置分阶段移动的步数 # 创建TouchAction实例 action = TouchAction(driver) # 执行长按操作 action.long_press(x=start_x, y=start_y, duration=long_press_duration * 1000) # 分阶段缓慢移动(相对于起始点的偏移量) for i in range(steps): # 计算当前步骤需要移动的相对偏移量 current_x = int(start_x + (i + 1) * delta_x / steps) current_y = int(start_y + (i + 1) * delta_y / steps) # 移动到指定坐标(使用相对偏移) if i == 0: # 第一步使用press操作(避免某些设备上的兼容性问题) action.press(x=current_x, y=current_y) else: # 后续步骤使用move_to(相对于上一个位置) action.move_to(x=current_x, y=current_y) # 释放并执行整个操作链 action.release().perform() # 下拉进入控制中心 @classmethod def getdown_ControlCenter(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {3 / 4 * x} 0 {3 / 4 * x} {y / 2} ') @classmethod # 下拉通知栏 def getdown_NotificationBar(cls, driver): driver.open_notifications() @classmethod def set_Virtual_navigation(cls): driver = get_app_driver('com.android.settings', 'com.android.settings.HWSettings',sn=operate_sn[0]) for i in range(3): ADBHelper().swipe('up') try: driver.find_element(By.XPATH, '//android.widget.Button[@text="下一步"]').click() except: pass try: driver.find_element(By.XPATH, '//android.widget.Button[@text="知道了"]').click() except: pass try: driver.find_element(By.XPATH, '//android.widget.Button[@text="同意"]').click() except: pass for i in range(3): ADBHelper().swipe('up') time.sleep(1) driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, ('new UiSelector().text("系统和更新")')).click() driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, ('new UiSelector().text("系统导航方式")')).click() # 选择虚拟导航 navradios = driver.find_elements(AppiumBy.CLASS_NAME, 'android.widget.RadioButton') navradios[1].click() driver.quit() def multi_finger(driver, operation): # 设置MultiAction,可以多点触控 multiaction = MultiAction(driver) t1 = TouchAction(driver) t2 = TouchAction(driver) t3 = TouchAction(driver) if operation == 'enlarge' or operation == 'narrow': if operation == 'enlarge': # t1.press(x=330, y=745).move_to(x=260, y=667).wait(100).release() # t2.press(x=407, y=880).move_to(x=425, y=985).wait(100).release() t1.press(x=500, y=1100).move_to(x=500, y=500).wait(100).release() t2.press(x=500, y=1300).move_to(x=500, y=1900).wait(100).release() else: t1.press(x=260, y=667).move_to(x=330, y=745).wait(100).release() t2.press(x=425, y=985).move_to(x=407, y=880).wait(100).release() # 多点操作对象加上这俩操作 multiaction.add(t1) multiaction.add(t2) if operation == 'screenshot': t1.press(x=180, y=600).move_to(x=180, y=800).wait(1000).release() t2.press(x=360, y=600).move_to(x=360, y=800).wait(1000).release() t3.press(x=600, y=600).move_to(x=600, y=800).wait(1000).release() multiaction.add(t1) multiaction.add(t2) multiaction.add(t3) multiaction.perform() def build_port(port): ADBHelper().execute_command(f'appium -p {port} --session-override') def start_appium(ports): ADBHelper().adb('forward --remove-all') ADBHelper().execute_command(f'adb -s {sup_udid} forward --remove-all') # 构建desired进程组 desired_processes = [] # 加载desired进程 for port in ports: # target="调用的方法",args="传入的参数" desired = Process(target=build_port, args=(port,)) desired_processes.append(desired) # 存储到全局变量 GSTORE['process'] = desired_processes # 开启每个进程 for desired in desired_processes: desired.start() def end_appium(ports): desired_processes = GSTORE['process'] for desired in desired_processes: desired.join() for p in ports: info = ADBHelper().execute_command_with_output(f'netstat -ano | findstr "{p}"') time.sleep(10) print(info) pid = info.splitlines()[0].split(' ')[-1] if pid != 0: wait = 0 r = ADBHelper().execute_command(f'taskkill /pid {pid} /F') while True: if wait <= 60: if r is not True: time.sleep(1) wait += 1 continue else: break else: print('杀appium进程失败!') break def handle_usb_promot(sn=udid): INFO('处理usb连接弹框') ADBHelper().go_home() driver = get_app_driver('com.huawei.android.launcher', 'com.huawei.android.launcher.unihome.UniHomeLauncher',sn) time.sleep(2) ADBHelper().go_home() try: driver.find_element(By.XPATH, '//android.widget.CheckedTextView[@text="仅充电"]').click() except: pass ADBHelper().go_home() return driver def first_getdown_controller(sn=udid): driver = get_app_driver('com.huawei.android.launcher', 'com.huawei.android.launcher.unihome.UniHomeLauncher',sn) x, y = ADBHelper(sn).get_phone_size() # 处理通知栏弹框 noti_count = 0 while noti_count < 2: noti_sign = driver.find_elements(By.ID, 'com.android.systemui:id/header_clock') if noti_sign != []: break else: ADBHelper(sn).shell(f'input swipe {1 / 4 * x} 0 {1 / 4 * x} {y / 4} ') noti_count += 1 # 处理控制中心 control_count = 0 while control_count < 2: control_sign = driver.find_elements(By.ID, 'com.android.systemui:id/settings_button') if control_sign != []: break else: ADBHelper(sn).shell(f'input swipe {3 / 4 * x} 0 {3 / 4 * x} {y / 4} ') control_count += 1 # 处理左右滑动 ADBHelper(sn).shell(f'input swipe {1 / 8 * x} {y / 10} {3 / 4 * x} {y / 10} ') button = driver.find_elements(By.XPATH, '//*[@text="知道了"]') if button != []: button[0].click() ADBHelper(sn).go_home() # 手动设置时间(hm2.0手机插白卡获取时间出错,需设置成手动) def manually_set_time(sn=udid): driver = get_app_driver('com.android.settings', 'com.android.settings.Settings$HwSystemDashboardActivity',sn) swipe_find_element(driver, '日期和时间',sn).click() switch = driver.find_element(By.XPATH, '//*[@text="自动设置"]/ancestor::*[@resource-id="com.android.settings:id/card_area"]//android.widget.Switch') if switch.get_attribute('checked') == 'true': switch.click() else: switch.click() time.sleep(2) switch.click() # 判断时间 now_time = datetime.now() now_year, now_month, now_day = str(now_time.year), str(now_time.month), str(now_time.day) ui_time = driver.find_elements(By.XPATH, '//*[@text="日期"]/../..//android.widget.TextView')[1].text year = ui_time.split('年')[0] month = ui_time.split('年')[1].split('月')[0] day = ui_time.split('年')[1].split('月')[1].split('日')[0] if not (now_year == year and now_month == month and now_day == day): driver.find_element(By.XPATH, '//*[@text="日期"]/ancestor::*[@resource-id="com.android.settings:id/card_area"]//*[@resource-id="com.android.settings:id/arrow"]').click() if now_year != year: count = 1 while count <= 5: year = driver.find_element(By.ID,'com.android.settings:id/hwadvancednumberpicker_textview').get_attribute( 'content-desc').split('年')[0] if int(year) < int(now_year): driver.find_element(By.ID,'com.android.settings:id/hwadvancednumberpicker_decrement').click() elif int(year) > int(now_year): driver.find_element(By.ID, 'com.android.settings:id/hwadvancednumberpicker_increment').click() else: break count += 1 if now_month != month: count = 1 while count <= 5: month = \ driver.find_elements(By.ID, 'com.android.settings:id/hwadvancednumberpicker_textview')[1].get_attribute( 'content-desc').split('月')[0] if int(month) < int(now_month): driver.find_elements(By.ID,'com.android.settings:id/hwadvancednumberpicker_decrement')[1].click() elif int(month) > int(now_month): driver.find_elements(By.ID, 'com.android.settings:id/hwadvancednumberpicker_increment')[1].click() else: break count += 1 if now_day != day: count = 1 while count <= 5: day = \ driver.find_elements(By.ID, 'com.android.settings:id/hwadvancednumberpicker_textview')[2].get_attribute( 'content-desc').split('日')[0] if int(day) < int(now_day): driver.find_elements(By.ID,'com.android.settings:id/hwadvancednumberpicker_decrement')[2].click() elif int(day) > int(now_day): driver.find_elements(By.ID, 'com.android.settings:id/hwadvancednumberpicker_increment')[2].click() else: break count += 1 driver.find_element(By.ID, 'com.android.settings:id/hwdatepicker_dialog_positive_btn').click() else: ADBHelper(sn).go_home() def swipe_find_element(driver, name,sn=udid,circle=5): x, y = ADBHelper(sn).get_phone_size() selector = 'new UiSelector().text("%s")' % name elements = driver.find_elements(AppiumBy.ANDROID_UIAUTOMATOR, selector) swipe = 0 while len(elements) < 1 and swipe < circle: Operate(sn).Swipe.up() elements = driver.find_elements(AppiumBy.ANDROID_UIAUTOMATOR, selector) swipe += 1 swipe = 0 while len(elements) < 1 and swipe < circle: Operate(sn).Swipe.down() elements = driver.find_elements(AppiumBy.ANDROID_UIAUTOMATOR, selector) swipe += 1 if len(elements) >= 1: return elements[0] else: INFO(name + ' not found') return None def check_element(driver, list,sn=udid): for name in list: find = swipe_find_element(driver, name,sn) if find is None: return False return True def add_APN(sn=udid): driver = get_app_driver('com.android.phone', 'com.android.phone.MSimMobileNetworkSettings',sn) apn_eles = driver.find_elements(By.XPATH, '//android.widget.TextView[@text="接入点名称 (APN)"]') # 新建第一个APN apn_eles[0].click() if len(driver.find_elements(By.XPATH, '//android.widget.TextView[@text="huawei.com"]')) == 2: ADBHelper(sn).go_home() return else: driver.find_element(By.ID, 'androidhwext:id/action_menu_more_button').click() driver.find_element(By.XPATH, '//android.widget.TextView[@text="新建 APN"]').click() time.sleep(1) # 输入名称和apn for part in ['名称','APN']: driver.find_element(By.XPATH, f'//android.widget.TextView[@text="{part}"]').click() driver.find_element(By.ID, 'android:id/edit').clear().send_keys('huawei.com') driver.find_element(By.ID, 'android:id/button1').click() driver.find_element(By.ID, 'android:id/icon2').click() driver.find_element(By.ID, 'com.android.settings:id/apn_radiobutton').click() ADBHelper(sn).go_back() # 开启卡2的APN apn_eles = driver.find_elements(By.XPATH, '//android.widget.TextView[@text="接入点名称 (APN)"]') apn_eles[1].click() driver.find_element(By.ID, 'com.android.settings:id/apn_radiobutton').click() ADBHelper(sn).go_home() # =============================================================================== # 命令跳过开机导航 def skip_guide_by_command(sn=udid): # ADBHelper(sn).adb("wait-for-device") # ADBHelper(sn).execute_command(f'adb -s {sn} remount') # ADBHelper(sn).shell("cp -r /eng/system/* /system/") # ADBHelper(sn).shell("cp -r /eng/vendor/* /vendor/") ADBHelper(sn).shell("settings put secure hw_suw_frp_state 0") ADBHelper(sn).shell("pm disable com.huawei.hwstartupguide") # ADBHelper(sn).shell("pm disable com.google.android.setupwizard") # ADBHelper(sn).shell("setting put global device_provisioned 1") # ADBHelper(sn).shell("setting put secure user_setup_complete 1") return True # 操作点击跳过开机导航 def skip_guide_by_click(sn=udid): try: driver = get_app_driver('com.huawei.hwstartupguide', 'com.huawei.hwstartupguide.LanguageSelectActivity', sn) time.sleep(10) INFO('开始启用') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/next_btn').click() time.sleep(1) INFO('选择地区') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/continue_btn').click() time.sleep(1) INFO('同意协议与声明') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/continue_btn').click() time.sleep(1) INFO('数据与隐私') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/continue_btn').click() time.sleep(1) INFO('插卡提醒跳过') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/skip_btn').click() time.sleep(5) INFO('wifi') wifi_name = 'ldb24_5G_2' wifi_pwd = 'Hy@1234%' x, y = ADBHelper().get_phone_size() # ADBHelper().shell(f'input swipe {0.5 * x} {0.5 * y} {0.5 * x} {0.8 * y}') # time.sleep(3) for i in range(5): if not driver.find_elements(By.XPATH,f'//*[@text="{wifi_name}"]'): ADBHelper().shell(f'input swipe {0.5 * x} {0.625 * y} {0.5 * x} {0.416 * y}') time.sleep(0.5) continue else: driver.find_element(By.XPATH, f'//*[@text="{wifi_name}"]').click() break driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().className("android.widget.EditText")').send_keys(wifi_pwd) driver.find_element(By.ID, 'com.android.settings:id/btn_wifi_connect').click() time.sleep(5) driver.find_element(By.ID, 'com.android.settings:id/next_btn').click() time.sleep(5) INFO('设备保护') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/skip_btn').click() time.sleep(2) INFO('钱包') try: driver.find_element(By.ID, 'com.huawei.wallet:id/oobe_add_bank_card').click() except: pass time.sleep(1) INFO('增强服务') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/continue_btn').click() time.sleep(1) INFO('智慧助手') try: driver.find_element(By.ID, 'com.huawei.vassistant:id/btn_highlight').click() except: pass time.sleep(1) INFO('数据导入') driver.find_element(By.ID, 'com.huawei.hicloud:id/set_new_device_lay').click() time.sleep(2) INFO('手势导航') driver.find_element(By.ID, 'com.android.settings:id/gesture_study_finish').click() time.sleep(10) INFO('天翼云盘') try: driver.find_element(By.ID, 'com.cn21.ecloud:id/start_mm_login_skip').click() except: pass time.sleep(10) INFO('开机导航跳过完成') except: INFO("开机导航界面点击失败,命令跳过") skip_guide_by_command() pass def SetDevelopmentSettingMode(sn=udid): ap = get_app_driver("com.android.settings", "com.android.settings.HWSettings",sn=sn,noreset=False) time.sleep(3) swipe_find_element(ap, '关于手机',sn=sn).click() time.sleep(2) for i in range(8): release = ap.find_elements(By.ID, 'android:id/title')[3] # try: # release = ap.find_elements(By.ID, 'android:id/title')[3] # except: # release = ap.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("软件版本")') # else: # pass release.click() time.sleep(1) ap.quit() def device_reset(sn=udid): """ 手机初始化 手机恢复出厂并将手机环境恢复到执行完测试_st_的环境(各领域st未执行,请自行恢复) """ driver_bar = get_app_driver('com.android.settings', 'com.android.settings.Settings$HwSystemDashboardActivity', sn=sn, noreset=False) driver_bar.find_element(By.XPATH, '//*[@text="重置"]').click() driver_bar.find_element(By.XPATH, '//*[@text="恢复出厂设置"]').click() count = 0 while count < 5: if driver_bar.find_element(By.XPATH, '//*[@text="重置手机"]').get_attribute("enabled") == "false": Operate(sn).Swipe().up() count = count + 1 else: break driver_bar.find_element(By.XPATH, '//*[@text="重置手机"]').click() driver_bar.find_element(By.ID, 'com.android.settings:id/execute_master_clear_new').click() time.sleep(60) # 等待手机恢厂完成adb上线 ADBHelper(sn).wait_device_online(max_delay=600) device_setup(sn) def device_setup(sn=udid,add_apn=True): # 跳过开机导航,恢复手机测试设置 time.sleep(10) skip_guide_by_command(sn) time.sleep(10) ADBHelper(sn).unlock_screen() time.sleep(5) ADBHelper(sn).shell('settings put system screen_off_timeout 600000') ADBHelper(sn).shell('settings put system screen_brightness_mode 0') ADBHelper(sn).shell('settings put system screen_brightness 128') try: driver = handle_usb_promot(sn) except: time.sleep(5) driver = handle_usb_promot(sn) time.sleep(60) try: driver.find_element(By.XPATH, '//android.widget.Button[@text="同意"]').click() time.sleep(1) driver.find_element(By.ID, 'android:id/button1').click() time.sleep(1) driver.find_element(By.ID, 'com.huawei.hiai:id/main_switch_ohos').click() except: pass time.sleep(30) Operate(sn).set_Virtual_navigation() SetDevelopmentSettingMode(sn) Switch(sn).GPS.open() Operate(sn).clear() if add_apn: add_APN(sn) first_getdown_controller(sn) manually_set_time(sn) if platform.system() != 'Windows': QUOTATION_MARKS = "'" else: QUOTATION_MARKS = "\"" USB_TOOLS = "adb" def device_screenshot(sn=udid): """ 截图(用于定位问题) :param sn: 手机SN:return: 截图路径 """ info_date = datetime.now().strftime('%Y%m%d%H%M%S') picture_name = "%s.png" % info_date ADBHelper(sn).shell('screencap /sdcard/%s' % picture_name) picture_save_path = os.path.abspath(r'./log/screen_shots') if not picture_save_path: os.mkdir(picture_save_path) ADBHelper(sn).pull(src_path="/sdcard/%s" % picture_name, dst_path=picture_save_path) time.sleep(1) ADBHelper(sn).shell('rm /sdcard/%s' % picture_name) return fr'{picture_save_path}\{picture_name}' # 重构的检查点函数——fail项不退出,继续进行测试,并打印失败时间点 def check_point(str, condition,driver,fail_timestamp): if hytest.common.CHECK_POINT(str, condition,failStop=False,LogSreenWebDriverIfFail=driver) == 'false': timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) INFO(f'失败时间点:{timestamp}') fail_timestamp.append(timestamp) # wifi 压测需要用到的函数 def get_wifi_log(case_name): folder_path = os.path.abspath(f'./log/wifi_log/{case_name}') ADBHelper().execute_command(f'mkdir {folder_path}') ADBHelper().remount() ADBHelper().pull_file('/data/anr/',fr'{folder_path}/anr/') ADBHelper().pull_file('/data/log/hilogs', fr'{folder_path}/hilogs/') ADBHelper().pull_file('/data/vendor/log/wifi', fr'{folder_path}/wifi1/') ADBHelper().pull_file('/data/vendor/wifi', fr'{folder_path}/wifi2/') ADBHelper().execute_command(f'adb -s {udid} shell getprop > {folder_path}/system_prop.txt') time.sleep(60) def decide_capture_log(fail_timestamp,case_name): if len(fail_timestamp) != 0: # 抓日志方法的位置 get_wifi_log(case_name) INFO('失败的时间点为:') INFO(fail_timestamp) # 检查恢复出厂设置过程 def check_reset(sn=udid,time_out=120): INFO('1、Reboot to recovery') wait1 = 0 while wait1 < time_out: state = ADBHelper(sn).get_device_state() print(state) if 'device' not in state: INFO(f'2、Recovery operate') wait2 = 0 while wait2 < time_out - wait1: state2 = ADBHelper().adb_with_output('devices') print(state2) if 'recovery' in state2: INFO(f'3、Quit recovery mode') wait3 = 0 while wait3 < time_out - wait1 - wait2: if 'recovery' not in ADBHelper().adb_with_output('devices'): INFO('recovery sucess!') return True else: time.sleep(5) wait3 += 5 return False else: time.sleep(5) wait2 += 5 return False else: time.sleep(5) wait1 += 5 return False ############################################################################### ############################################################################### # adb命令相关的类 class ADBHelper(object): def __init__(self,device_sn=udid): self.device_sn = device_sn self.device_id = self.get_device_id(device_sn) # @classmethod # def get_device_id(cls, remote_ip="", remote_port="", device_sn=""): # if remote_ip == "" or remote_port == "": # if device_sn == "": # device_id = "" # else: # device_id = "-s %s" % device_sn # else: # if device_sn == "": # device_id = "-H %s -P %s" % (remote_ip, remote_port) # else: # device_id = "-H %s -P %s -s %s" % ( # remote_ip, remote_port, device_sn) # return device_id @classmethod def get_device_id(cls, device_sn): if device_sn != '': device_id = "-s %s" % device_sn return device_id ########################################################################### # 封装的命令操作 def execute_command(self, command, print_flag=True, timeout=120): try: if print_flag: print("command: " + command) if subprocess.call(command, shell=True, timeout=timeout) == 0: print("results: successed") return True except Exception as error: print("Exception: %s" % str(error)) print("Warning: %s failed" % command) return False def execute_command_with_output(self, command, print_flag=True): if print_flag: print("command: " + command) proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) try: stdout_data, stderr_data = proc.communicate() if isinstance(stdout_data, bytes): stdout_data = stdout_data.decode('utf-8', 'ignore') finally: proc.stdout.close() proc.stderr.close() return stdout_data def execute_command_with_list_output(self, command, print_flag=True): if print_flag: print("command: " + command) return os.popen(command).readlines() def execute_command_with_content_output(self, command, print_flag=True): if print_flag: print("command: " + command) return os.popen(command).read() def adb(self, command="devices"): return self.execute_command("%s %s %s" % ( USB_TOOLS, self.device_id, command)) def adb_with_output(self, command=""): return self.execute_command_with_output("%s %s %s" % ( USB_TOOLS, self.device_id, command)).strip() def shell(self, command=""): return self.execute_command("%s %s shell %s%s%s" % ( USB_TOOLS, self.device_id, QUOTATION_MARKS, command, QUOTATION_MARKS)) def shell_with_output(self, command=""): return self.execute_command_with_output("%s %s shell %s%s%s" % ( USB_TOOLS, self.device_id, QUOTATION_MARKS, command, QUOTATION_MARKS)).strip() def pull(self, src_path="", dst_path=""): return self.execute_command("%s %s pull %s%s%s %s%s%s" % ( USB_TOOLS, self.device_id, QUOTATION_MARKS, src_path, QUOTATION_MARKS, QUOTATION_MARKS, dst_path, QUOTATION_MARKS)) ########################################################################### def remount(self): self.adb("remount") def reboot(self): """ 重启设备 """ self.adb("reboot") self.adb("wait-for-device") time.sleep(20) def recovery(self): """ 重启设备并进入recovery模式 """ self.adb('reboot recovery') def fastboot(self): """ 重启设备并进入fastboot模式 """ self.adb('reboot bootloader') def root(self): """ 获取root状态 """ return 'not found' not in self.adb_with_output('su -c ls -l /data/') def push_file(self, srcpath, despath): command = "push %s %s" % (srcpath, despath) self.adb(command) def pull_file(self, srcpath, despath): command = "pull %s %s" % (srcpath, despath) self.adb(command) ########################################################################### def wait_device_online(self, max_delay=300): while (max_delay >= 0): result = self.shell_with_output("getprop sys.boot_completed") if result != "1": max_delay = max_delay - 1 time.sleep(1) print('---not found!') else: print("Info: device is online status.") time.sleep(3) return True print("Info: device is not online status.") return False def wait_device_ready(self, max_delay=0): delay_timse = 0 while (True): window_policy = self.dumpsys_window_policy('isStatusBarKeyguard') if 'isStatusBarKeyguard=true' in window_policy: print("Info: device ready.") return True if len(window_policy) == 0: window_policy = self.dumpsys_window_policy('mShowingLockscreen') if ('mShowingLockscreen=true' in window_policy): print("Info: device ready.") return True time.sleep(1) delay_timse = delay_timse + 1 if delay_timse > max_delay: break print("Info: device is not ready.") return False def dumpsys_window_policy(self, grep_condition=None): if grep_condition == None or grep_condition == "": return self.shell_with_output('dumpsys window policy') else: grep_condition = str(grep_condition).strip().replace(' ', '\ ') return self.shell_with_output('dumpsys window policy|grep ' + grep_condition) def is_file_exist(self, file_path): if file_path != "" and " " in file_path: current_file_path = "\"%s\"" % file_path else: current_file_path = file_path message = self.shell_with_output("ls %s" % current_file_path) message = message.strip() return False if message == "" else True ########################################################################### def init_device(self): self.remount() self.shell("mount -o rw,remount,rw /%s" % "system") def init_test_path(self): test_path = "/%s/%s" % ("data", "test") self.shell('rm -rf %s' % test_path) self.shell('mkdir -p %s' % test_path) self.shell('chmod 777 %s' % test_path) ########################################################################### def get_device_state(self): """ 获取设备状态: offline | bootloader | device """ return self.adb_with_output("get-state") def get_device_serialNo(self): """ 获取设备id号,return serialNo """ return self.adb_with_output("get-serialno") def get_android_version(self): """ 获取设备中的Android版本号,如4.2.2 """ return self.shell_with_output("getprop ro.build.version.release") def get_sdk_version(self): """ 获取设备SDK版本号,如:24 """ return self.shell_with_output("getprop ro.build.version.sdk") def get_product_brand(self): """ 获取设备品牌,如:HUAWEI """ return self.shell_with_output("getprop ro.product.brand") def get_product_model(self): """ 获取设备型号,如:MHA-AL00 """ return self.shell_with_output("getprop ro.product.model") def get_product_rom(self): """ 获取设备ROM名,如:MHA-AL00C00B213 """ return self.shell_with_output("getprop ro.build.display.id") def get_lcd_model(self): """ 获取设备LCD型号 """ return self.shell_with_output("cat sys/class/graphics/fb0/lcd_model") def get_phone_size(self): """ 获取手机分辨率大小 """ str = self.shell_with_output("wm size") try: size = str.split(':')[-1] phone_x = int(size.split('x')[0]) phone_y = int(size.split('x')[1]) except: phone_x,phone_y = '','' return phone_x, phone_y # 手机界面操作 ############################################################################### # 锁屏 def lock_screen(self): self.shell("input keyevent 26") # 解锁 def unlock_screen(self): self.shell("input keyevent 82") self.shell("wm dismiss-keyguard") # 返回 def go_back(self): self.shell('input keyevent 4') # home键 def go_home(self): self.shell('input keyevent 3') # 清除后台 def clear(self): self.go_home() x_size, y_size = self.get_phone_size() self.shell(f"input tap {0.7083 * x_size} {0.978125 * y_size}") time.sleep(1) self.shell(f"input tap {0.5 * x_size} {0.90625 * y_size}") # 滑动 def swipe(self, location): x, y = self.get_phone_size() if location == 'up': self.shell(f'input swipe {x / 2} {5 * y / 8} {x / 2} {y / 4}') if location == 'down': self.shell(f'input swipe {x / 2} {y / 4} {x / 2} {5 * y / 8}') if location == 'left': self.shell(f'input swipe {3 * x / 4} {y / 2} {x / 4} {y / 2}') if location == 'right': self.shell(f'input swipe {x / 4} {y / 2} {3 * x / 4} {y / 2}') # 通过坐标点击 def click_by_location(self, x_ratio, y_ratio): phone_x, phone_y = self.get_phone_size() self.shell(f'input tap {phone_x * x_ratio} {phone_y * y_ratio}') # 提升屏幕亮度 def Increase_Brightness(self): self.shell("input keyevent 221") self.go_back() # 降低屏幕亮度 def Decrease_Brightness(self): self.shell("input keyevent 220") self.go_back() # 媒体音量调节 def Adjust_Volume(self, type, operation): type_code_dict = { 'call': 0, 'ring': 2, 'media': 3, 'alarm': 4, 'assistant': 11 } if type in type_code_dict: if operation == 'increase': self.shell(f'service call audio 57 i32 {type_code_dict[type]} i32 1 i32 1') if operation == 'decrease': self.shell(f'service call audio 9 i32 {type_code_dict[type]} i32 -1 i32 1') if operation == 'mute': self.shell(f'service call audio 9 i32 {type_code_dict[type]} i32 -100 i32 1') if operation == 'cancel_mute': self.shell(f'service call audio 9 i32 {type_code_dict[type]} i32 100 i32 1') else: print("声音type参数错误!") # 设置音量 def set_Volume(self, type, level): type_code_dict = { 'call': 0, 'ring': 1, 'media': 3, 'alarm': 4, 'assistant': 11 } if type in type_code_dict: self.shell(f'service call audio 10 i32 {type_code_dict[type]} i32 {level} i32 1') ########################################################################### ########################################################################### def init_device_ex(self, cmd): try: proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, close_fds=True) while True: stdout, stderr = proc.communicate() returncode = proc.returncode print("returncode=%s" % returncode) if returncode == 0: print('执行结果:执行成功!') if returncode != 0: errors = stderr.split('\n') for erroline in errors: if 'FAILED' in erroline: print(erroline) # 写入错误行英文日志 if returncode == 127: print('执行结果:此行为空字符串!') if returncode == 17: print('执行结果:找不到表异常') if returncode == 64: print('执行结果:sql语句异常,缺失关键字') if returncode == 41: print('执行结果:sql语句异常,查询的字段不存在') if stdout == '' and proc.poll() != None: break except Exception as e: print("调用hive客户端,执行hive语句出错") print(str(e)) """ 以上代码中returncode为执行返回结果的标志 我总结的有以下几种情况 returncode=0 表示执行成功 returncode=127 表示语句为空串 returncode=17 表示找不到表 returncode=64 表示缺失关键字 returncode=41 表示查询的字段不存在 """ def input_set_passwd(self): for _ in range(6): time.sleep(1) self.adb("shell input keyevent 8") # # obj.reboot() # # obj.wait_device_ready(60) # # obj.wait_device_online(60) # # devices = obj.get_devices() # print(devices) # # devices = obj.get_android_version() # print(devices)
最新发布
07-26
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RabbitsInTheGrass

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值