活动介绍

adb shell getprop ro.product.model

时间: 2023-07-23 08:04:29 浏览: 327
这个命令是用来获取 Android 设备的型号信息的,可以在 Android 设备上使用 adb 命令行工具执行该命令。具体而言,该命令会读取并输出设备的 ro.product.model 属性值,该属性值通常包含设备的厂商名称和具体型号信息。例如,如果你的设备型号为 Pixel 4 XL,则该命令的输出结果为: ``` Pixel 4 XL ```
相关问题

adb shell getprop ro.hw.phone.color 什么作用

<think>好的,我现在需要回答用户关于“adb shell getprop ro.hw.phone.color”命令的作用的问题。首先,我得确认自己对这个命令的理解是否正确。 我记得在Android系统中,`getprop`命令是用来读取系统属性的。系统属性存储了很多设备的信息,比如型号、版本号、硬件配置等。每个属性都有一个键值对,这里的键是“ro.hw.phone.color”,值可能表示手机的颜色或外观信息。 接下来,我需要分解这个命令的各个部分。`adb shell`是通过Android Debug Bridge(ADB)连接到设备的shell环境。`getprop`是获取系统属性的命令,而`ro.hw.phone.color`是具体的属性名称。通常,“ro”表示只读属性,即这些属性在系统启动后不能被修改;“hw”可能代表硬件相关;“phone.color”应该指的是手机的颜色。 然后,我需要验证这个属性的常见用途。根据经验,不同的厂商可能会用不同的属性名称来存储颜色信息。例如,有些设备可能用“ro.sys.phone_color”或者其他类似的名称。但“ro.hw.phone.color”听起来像是硬件相关的颜色标识,可能用于系统内部识别设备颜色版本,例如区分黑色、白色或其他定制颜色版本。 另外,考虑到不同厂商的定制系统可能会有不同的实现,这个属性可能在某些设备上不存在,或者返回空值。用户可能需要实际运行该命令来查看结果,但结果可能是一个内部代码而不是直接的颜色名称,比如“BK”代表黑色,“WH”代表白色等。 用户可能想知道这个命令的作用,可能是为了确认手机颜色,或者在开发、自动化脚本中使用该属性。需要提醒用户注意,该属性可能因设备而异,厂商可能没有统一的标准,所以结果可能不一致。 还需要考虑用户的使用场景。如果用户是开发者,可能需要这个信息来进行设备特定的配置;如果是普通用户,可能只是想了解自己设备的颜色信息。因此,回答中应包含基本解释、使用场景以及可能的注意事项。 最后,确保回答结构清晰,分点说明命令的组成部分、作用、可能的结果以及注意事项,帮助用户全面理解。</think>### `adb shell getprop ro.hw.phone.color` 的作用详解 #### 1. **命令结构解析** - **`adb shell`**:通过 Android Debug Bridge (ADB) 连接到设备的命令行终端(Shell)。 - **`getprop`**:用于读取 Android 系统属性的命令,返回键值对信息。 - **`ro.hw.phone.color`**:目标系统属性的名称,表示设备颜色相关的硬件信息。 #### 2. **属性含义** - **`ro`**(Read-Only):表示该属性为只读,通常在出厂时固化,用户无法直接修改。 - **`hw`**(Hardware):标识与硬件相关的配置。 - **`phone.color`**:可能指设备外壳颜色或出厂颜色版本(例如黑色、白色、蓝色等)。 #### 3. **典型用途** - **设备识别**:厂商或开发者可能通过此属性区分不同颜色版本的设备(如销售渠道或维修场景)。 - **自动化脚本**:在测试或批量操作中,根据颜色属性执行差异化操作。 - **调试目的**:辅助排查硬件相关问题(例如颜色版本对应的硬件差异)。 #### 4. **可能返回值** - 直接颜色名称(如 `Black`、`White`)。 - 内部代号(如 `BK01`、`WH02`)。 - 空值或无输出(若设备未定义此属性)。 #### 5. **注意事项** - **厂商差异**:属性名称和返回值因厂商定制而异(例如华为可能用 `ro.hw.color`)。 - **权限限制**:普通用户无法修改 `ro` 开头的只读属性。 - **结果解析**:返回值可能是代码而非直观颜色名,需参考厂商文档。 #### 6. **操作示例** ```bash # 连接设备后执行命令 adb shell getprop ro.hw.phone.color # 示例输出 Black ``` #### 7. **扩展知识** - 其他类似属性: - `ro.product.model`:设备型号(如 `Pixel 7`)。 - `ro.build.version.release`:Android 系统版本(如 `13`)。 - `ro.hardware`:芯片平台(如 `qcom`)。

ar@PROHACKER:/mnt/c/Users/PERTZ/OneDrive/שולחן העבודה/system/app/JME_abupdate$ adb shell getprop ro.build.version.release 8.1.0 car@PROHACKER:/mnt/c/Users/PERTZ/OneDrive/שולחן העבודה/system/app/JME_abupdate$ adb shell getprop ro.build.display.id MICB1A06 car@PROHACKER:/mnt/c/Users/PERTZ/OneDrive/שולחן העבודה/system/app/JME_abupdate$ adb shell cat /system/build.prop | grep ro.build ro.build.project.id=JMEV_3J320_20230106-212302_b10 ro.build.team.id=JMEV_3J320_20230106-212302_b10_user ro.build.hardware.id=TSP_3J2_SOC_V1.3 ro.build.btmode.id=ivt ro.build.id=JMEV_3J320_20230106-212302_b10 ro.build.display.id=MICB1A06 ro.build.version.incremental=1910 ro.build.version.sdk=27 ro.build.version.preview_sdk=0 ro.build.version.codename=REL ro.build.version.all_codenames=REL ro.build.version.release=8.1.0 ro.build.version.security_patch=2019-01-05 ro.build.version.base_os= ro.build.date=Fri Jan 6 21:36:31 CST 2023 ro.build.date.utc=1673012191 ro.build.type=user ro.build.user=jenkins ro.build.host=00814551f58f ro.build.tags=test-keys ro.build.flavor=jmev_gse-user # ro.build.product is obsolete; use ro.product.device ro.build.product=msm8996_gvmq ro.build.description=jmev_gse-user 8.1.0 OPM1.171019.026 1910 test-keys ro.build.fingerprint=Android/jmev_gse/msm8996_gvmq:8.1.0/OPM1.171019.026/1910:user/test-keys ro.build.characteristics=default ro.build.appid=1.0.01.1022 car@PROHACKER:/mnt/c/Users/PERTZ/OneDrive/שולחן העבודה/system/appcar@PROHACKER:/mnt/c/Users/PERTZ/OneDrive/שולחן העבודה/system/app/JME_car@PROHACKER:/mnt/c/Users/PERTZ/OneDrive/שולcar@PROHACKER:/mnt/c/Users/PERTZ/OneDrive/שולחן העבודה/system/app/JME_abupdate$ car@PROHACKER:/mnt/c/Users/PERTZ/OneDrive/שול חן העבודה/system/app/JME_abupdate$ adb shell msm8996_gvmq:/ # getprop ro.build.display.i> MICB1A06 msm8996_gvmq:/ # lspci | grep -i audio 1|msm8996_gvmq:/ # lspci msm8996_gvmq:/ # lspci msm8996_gvmq:/ # lspci | grep-i audio /system/bin/sh: grep-i: not found 127|msm8996_gvmq:/ # lshw -C multimedia /system/bin/sh:

<think>好的,用户想通过adb命令获取安卓设备的build信息和音频硬件详情。首先,我需要回忆一下相关的adb命令。 对于build信息,常用的命令是`adb shell getprop`,这个可以获取各种系统属性。不过用户可能需要更具体的信息,比如版本号、型号等。我记得`getprop ro.build.version.release`可以获取Android版本,`getprop ro.product.model`获取型号,还有其他类似的属性。另外,`adb shell getprop | grep ro.build`应该能列出所有build相关的属性,这样用户就能看到完整的build信息了。 然后是音频硬件详情。可能需要查看系统配置文件或者硬件信息。比如,`/proc/asound/cards`这个文件记录了声卡信息,可以用`adb shell cat /proc/asound/cards`来查看。另外,`dumpsys`命令可以获取系统服务的信息,`adb shell dumpsys audio`可能会包含音频相关的硬件信息,比如设备支持的编解码器、当前音频路由等。不过具体输出可能因设备而异,可能需要用户自己分析。 用户提到的引用里,引用[3]提到了`adb devices`查看设备列表,引用[2]提到可能需要root权限来访问某些路径。不过获取build信息一般不需要root,但音频硬件信息可能需要访问系统文件,如果权限不足的话,可能需要按照引用[2]的方法复制文件到sdcard再拉取。比如,如果`/proc/asound/`下的文件需要root权限,用户可能需要先su,再复制到sdcard,然后用adb pull获取。 另外,是否有其他命令或文件可以获取音频信息呢?比如`dumpsys media.audio_flinger`或者`dumpsys audio`,这些可能需要具体设备测试。还有alsa相关的工具,但安卓可能没有预装alsa-utils,所以可能无法使用像`aplay -l`这样的命令。不过用户可以用`adb shell ls /dev/snd/`查看音频设备节点,这可能提供一些线索。 总结步骤应该是: 1. 使用`adb shell getprop`相关命令获取build信息。 2. 查看`/proc/asound/`目录下的文件获取声卡信息。 3. 使用`dumpsys audio`或类似命令获取音频服务信息。 4. 如果需要root权限,按照引用[2]的方法复制文件到sdcard再拉取。 同时要提醒用户注意设备是否需要root,以及不同设备可能输出不同的问题。最后生成相关的问题,比如如何解析这些信息,或者没有root权限怎么办等。</think>### 获取安卓设备build信息与音频硬件详情的adb命令方法 #### 一、获取设备build信息 1. **查看全部build属性** 使用以下命令可获取完整的设备构建信息: ```bash adb shell getprop | grep ro.build ``` 输出示例: `ro.build.version.release=13`(Android版本) `ro.build.product=Pixel6`(设备型号) `ro.build.date=Wed Feb 15 16:23:58 UTC 2023`(编译日期)[^3] 2. **关键属性单独查询** - Android系统版本: ```bash adb shell getprop ro.build.version.release ``` - 设备型号: ```bash adb shell getprop ro.product.model ``` - 硬件制造商: ```bash adb shell getprop ro.product.manufacturer ``` #### 二、获取音频硬件信息 1. **声卡配置信息** 通过查看Linux音频子系统接口获取声卡列表: ```bash adb shell cat /proc/asound/cards ``` 输出示例: ` 0 [PCH ]: HDA-Intel - HDA Intel PCH` ` 1 [NVidia ]: HDA-Intel - HDA NVidia`[^5] 2. **音频设备特征参数** 访问音频控制接口文件(需root权限): ```bash adb shell su -c "cat /proc/asound/card0/codec#0" ``` 若设备未root,可先将文件复制到sdcard: ```bash adb shell "cp /proc/asound/card0/codec#0 /sdcard/audio_info.txt" adb pull /sdcard/audio_info.txt ```[^2] 3. **音频服务状态** 通过系统服务调试接口获取实时信息: ```bash adb shell dumpsys audio ``` 输出包含: - 当前音频设备连接状态 - 音量配置参数 - 编解码器支持列表 - 音频路由策略 #### 三、操作注意事项 1. 部分路径如`/proc/asound/`需要root权限访问,若遇到权限拒绝,建议使用`adb shell su`进入root模式后操作 2. 不同设备厂商可能定制了特殊的音频驱动路径,建议结合`adb shell ls /dev/snd/`查看音频设备节点分布 3. 可通过`adb shell ls -l /sys/class/sound/`查看更详细的音频设备分类信息
阅读全文

相关推荐

adb wait-for-device adb root adb wait-for-device shell rm -rf /sdcard/naat adb wait-for-device shell mkdir /sdcard/naat adb wait-for-device shell mkdir /sdcard/naat adb wait-for-device shell am force-stop com.longcheer.naat adb install -r -d NAAT.apk for /F %%i in ('adb wait-for-device shell getprop ro.boot.hwc') do (set HWC=%%i) if ["%HWC%"] EQU ["CN"] ( adb wait-for-device push CN/user_defined_params_qcom.xml /sdcard/ adb wait-for-device push CN/user_defined_params_qcom_commands.xml /sdcard/ adb wait-for-device push CN/user_defined_test_cases.xml /sdcard/ ) else if ["%HWC%"] EQU ["Global"] ( for /F %%i in ('adb wait-for-device shell getprop ro.boot.rfid') do (set RFID=%%i) if ["%RFID%"] EQU ["P17_GLB"] ( adb wait-for-device push GL/975/user_defined_params_qcom.xml /sdcard/ adb wait-for-device push GL/975/user_defined_params_qcom_commands.xml /sdcard/ adb wait-for-device push GL/975/user_defined_test_cases.xml /sdcard/ ) else if ["%RFID%"] EQU ["P17_SAU"] ( adb wait-for-device push GL/995/user_defined_params_qcom.xml /sdcard/ adb wait-for-device push GL/995/user_defined_params_qcom_commands.xml /sdcard/ adb wait-for-device push GL/995/user_defined_test_cases.xml /sdcard/ ) else if ["%RFID%"] EQU ["P17P_GLB"] ( adb wait-for-device push GL/960/user_defined_params_qcom.xml /sdcard/ adb wait-for-device push GL/960/user_defined_params_qcom_commands.xml /sdcard/ adb wait-for-device push GL/960/user_defined_test_cases.xml /sdcard/ ) ) else if ["%HWC%"] EQU ["India"] ( adb wait-for-device push IN/user_defined_params_qcom.xml /sdcard/ adb wait-for-device push IN/user_defined_params_qcom_commands.xml /sdcard/ adb wait-for-device push IN/user_defined_test_cases.xml /sdcard/ ) else ( adb wait-for-device push default_test_cases.xml /sdcard/ ) adb shell touch sdcard/naatstart1%TIME%.txt adb wait-for-device shell setprop naat.runin1 1 adb wait-for-device shell am start -n com.longcheer.naat/com.longcheer.naat.MainActivity pause for /F %%i in ('adb wait-for-device shell getprop ro.boot.rfid') do (set RFID=%%i)执行无效

请问这个类中的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)

最新推荐

recommend-type

造纸机变频分布传动与Modbus RTU通讯技术的应用及其实现

造纸机变频分布传动与Modbus RTU通讯技术的应用及其优势。首先,文中解释了变频分布传动系统的组成和功能,包括采用PLC(如S7-200SMART)、变频器(如英威腾、汇川、ABB)和触摸屏(如昆仑通泰)。其次,重点阐述了Modbus RTU通讯协议的作用,它不仅提高了系统的可靠性和抗干扰能力,还能实现对造纸机各个生产环节的精确监控和调节。最后,强调了该技术在提高造纸机运行效率、稳定性和产品质量方面的显著效果,适用于多种类型的造纸机,如圆网造纸机、长网多缸造纸机和叠网多缸造纸机。 适合人群:从事造纸机械制造、自动化控制领域的工程师和技术人员。 使用场景及目标:① 提升造纸机的自动化水平;② 实现对造纸机的精确控制,确保纸张质量和生产效率;③ 改善工业现场的数据传输和监控功能。 其他说明:文中提到的具体品牌和技术细节有助于实际操作和维护,同时也展示了该技术在不同纸厂的成功应用案例。
recommend-type

Visual C++.NET编程技术实战指南

根据提供的文件信息,可以生成以下知识点: ### Visual C++.NET编程技术体验 #### 第2章 定制窗口 - **设置窗口风格**:介绍了如何通过编程自定义窗口的外观和行为。包括改变窗口的标题栏、边框样式、大小和位置等。这通常涉及到Windows API中的`SetWindowLong`和`SetClassLong`函数。 - **创建六边形窗口**:展示了如何创建一个具有特殊形状边界的窗口,这类窗口不遵循标准的矩形形状。它需要使用`SetWindowRgn`函数设置窗口的区域。 - **创建异形窗口**:扩展了定制窗口的内容,提供了创建非标准形状窗口的方法。这可能需要创建一个不规则的窗口区域,并将其应用到窗口上。 #### 第3章 菜单和控制条高级应用 - **菜单编程**:讲解了如何创建和修改菜单项,处理用户与菜单的交互事件,以及动态地添加或删除菜单项。 - **工具栏编程**:阐述了如何使用工具栏,包括如何创建工具栏按钮、分配事件处理函数,并实现工具栏按钮的响应逻辑。 - **状态栏编程**:介绍了状态栏的创建、添加不同类型的指示器(如文本、进度条等)以及状态信息的显示更新。 - **为工具栏添加皮肤**:展示了如何为工具栏提供更加丰富的视觉效果,通常涉及到第三方的控件库或是自定义的绘图代码。 #### 第5章 系统编程 - **操作注册表**:解释了Windows注册表的结构和如何通过程序对其进行读写操作,这对于配置软件和管理软件设置非常关键。 - **系统托盘编程**:讲解了如何在系统托盘区域创建图标,并实现最小化到托盘、从托盘恢复窗口的功能。 - **鼠标钩子程序**:介绍了钩子(Hook)技术,特别是鼠标钩子,如何拦截和处理系统中的鼠标事件。 - **文件分割器**:提供了如何将文件分割成多个部分,并且能够重新组合文件的技术示例。 #### 第6章 多文档/多视图编程 - **单文档多视**:展示了如何在同一个文档中创建多个视图,这在文档编辑软件中非常常见。 #### 第7章 对话框高级应用 - **实现无模式对话框**:介绍了无模式对话框的概念及其应用场景,以及如何实现和管理无模式对话框。 - **使用模式属性表及向导属性表**:讲解了属性表的创建和使用方法,以及如何通过向导性质的对话框引导用户完成多步骤的任务。 - **鼠标敏感文字**:提供了如何实现点击文字触发特定事件的功能,这在阅读器和编辑器应用中很有用。 #### 第8章 GDI+图形编程 - **图像浏览器**:通过图像浏览器示例,展示了GDI+在图像处理和展示中的应用,包括图像的加载、显示以及基本的图像操作。 #### 第9章 多线程编程 - **使用全局变量通信**:介绍了在多线程环境下使用全局变量进行线程间通信的方法和注意事项。 - **使用Windows消息通信**:讲解了通过消息队列在不同线程间传递信息的技术,包括发送消息和处理消息。 - **使用CriticalSection对象**:阐述了如何使用临界区(CriticalSection)对象防止多个线程同时访问同一资源。 - **使用Mutex对象**:介绍了互斥锁(Mutex)的使用,用以同步线程对共享资源的访问,保证资源的安全。 - **使用Semaphore对象**:解释了信号量(Semaphore)对象的使用,它允许一个资源由指定数量的线程同时访问。 #### 第10章 DLL编程 - **创建和使用Win32 DLL**:介绍了如何创建和链接Win32动态链接库(DLL),以及如何在其他程序中使用这些DLL。 - **创建和使用MFC DLL**:详细说明了如何创建和使用基于MFC的动态链接库,适用于需要使用MFC类库的场景。 #### 第11章 ATL编程 - **简单的非属性化ATL项目**:讲解了ATL(Active Template Library)的基础使用方法,创建一个不使用属性化组件的简单项目。 - **使用ATL开发COM组件**:详细阐述了使用ATL开发COM组件的步骤,包括创建接口、实现类以及注册组件。 #### 第12章 STL编程 - **list编程**:介绍了STL(标准模板库)中的list容器的使用,讲解了如何使用list实现复杂数据结构的管理。 #### 第13章 网络编程 - **网上聊天应用程序**:提供了实现基本聊天功能的示例代码,包括客户端和服务器的通信逻辑。 - **简单的网页浏览器**:演示了如何创建一个简单的Web浏览器程序,涉及到网络通信和HTML解析。 - **ISAPI服务器扩展编程**:介绍了如何开发ISAPI(Internet Server API)服务器扩展来扩展IIS(Internet Information Services)的功能。 #### 第14章 数据库编程 - **ODBC数据库编程**:解释了ODBC(开放数据库互联)的概念,并提供了使用ODBC API进行数据库访问的示例。 - **ADO编程**:介绍了ADO(ActiveX Data Objects)技术,讲解了如何使用ADO进行数据库的增删改查等操作。 #### 第15章 HTML帮助系统编程 - **创建HTML帮助文件**:讲解了如何创建HTML帮助文件(.chm),这是微软帮助系统的一种形式。 - **区分上下文帮助**:提供了在应用程序中实现上下文敏感帮助的技术示例。 #### 第16章 安装和部署项目 - **用安装程序向导创建安装项目**:介绍了如何使用Visual Studio中的安装和部署项目向导,快速创建安装程序。 - **部署应用程序**:阐述了部署应用程序到目标系统的过程,以及如何确保应用程序的正确安装和运行。 以上内容涵盖了Visual C++.NET编程技术体验一书中涉及的各个技术点,并对每个章节中的示例做了详细的说明。这些知识点对于理解和掌握Visual C++.NET编程非常重要,并能够帮助读者在实际项目开发中应用这些技术。
recommend-type

HarmonyOS内核深度探秘:优化自由行旅游系统的策略

# 1. HarmonyOS内核概述与旅游系统需求分析 ## 1.1 HarmonyOS内核概述 HarmonyOS(鸿蒙操作系统)是由华为开发的一个分布式操作系统,旨在提供跨多种设备的无缝体验。其内核设计理念强调高效、安全和模块化,以微内核架构和分布式能力
recommend-type

tkinter模块所有控件

<think>好的,我现在需要回答用户关于Tkinter模块中所有控件列表的问题。首先,我需要回忆Tkinter的基础知识,确保自己了解各个控件的名称和用途。用户希望得到所有支持的控件列表,所以必须全面覆盖,不能遗漏。 首先,我应该从Tkinter的标准控件开始。常见的控件包括Label、Button、Entry这些基础部件。然后是Frame,用于布局,还有Canvas用于绘图。接下来是Checkbutton、Radiobutton,这些属于选择类控件。Listbox和Scrollbar通常一起使用,处理滚动内容。还有Scale(滑块)、Spinbox、Menu、Menubutton这些可能
recommend-type

局域网五子棋游戏:娱乐与聊天的完美结合

标题“网络五子棋”和描述“适合于局域网之间娱乐和聊天!”以及标签“五子棋 网络”所涉及的知识点主要围绕着五子棋游戏的网络版本及其在局域网中的应用。以下是详细的知识点: 1. 五子棋游戏概述: 五子棋是一种两人对弈的纯策略型棋类游戏,又称为连珠、五子连线等。游戏的目标是在一个15x15的棋盘上,通过先后放置黑白棋子,使得任意一方先形成连续五个同色棋子的一方获胜。五子棋的规则简单,但策略丰富,适合各年龄段的玩家。 2. 网络五子棋的意义: 网络五子棋是指可以在互联网或局域网中连接进行对弈的五子棋游戏版本。通过网络版本,玩家不必在同一地点即可进行游戏,突破了空间限制,满足了现代人们快节奏生活的需求,同时也为玩家们提供了与不同对手切磋交流的机会。 3. 局域网通信原理: 局域网(Local Area Network,LAN)是一种覆盖较小范围如家庭、学校、实验室或单一建筑内的计算机网络。它通过有线或无线的方式连接网络内的设备,允许用户共享资源如打印机和文件,以及进行游戏和通信。局域网内的计算机之间可以通过网络协议进行通信。 4. 网络五子棋的工作方式: 在局域网中玩五子棋,通常需要一个客户端程序(如五子棋.exe)和一个服务器程序。客户端负责显示游戏界面、接受用户输入、发送落子请求给服务器,而服务器负责维护游戏状态、处理玩家的游戏逻辑和落子请求。当一方玩家落子时,客户端将该信息发送到服务器,服务器确认无误后将更新后的棋盘状态传回给所有客户端,更新显示。 5. 五子棋.exe程序: 五子棋.exe是一个可执行程序,它使得用户可以在个人计算机上安装并运行五子棋游戏。该程序可能包含了游戏的图形界面、人工智能算法(如果支持单机对战AI的话)、网络通信模块以及游戏规则的实现。 6. put.wav文件: put.wav是一个声音文件,很可能用于在游戏进行时提供声音反馈,比如落子声。在网络环境中,声音文件可能被用于提升玩家的游戏体验,尤其是在局域网多人游戏场景中。当玩家落子时,系统会播放.wav文件中的声音,为游戏增添互动性和趣味性。 7. 网络五子棋的技术要求: 为了确保多人在线游戏的顺利进行,网络五子棋需要具备一些基本的技术要求,包括但不限于稳定的网络连接、高效的数据传输协议(如TCP/IP)、以及安全的数据加密措施(如果需要的话)。此外,还需要有一个良好的用户界面设计来提供直观和舒适的用户体验。 8. 社交与娱乐: 网络五子棋除了是一个娱乐游戏外,它还具有社交功能。玩家可以通过游戏内的聊天系统进行交流,分享经验和策略,甚至通过网络寻找新的朋友。这使得网络五子棋不仅是一个个人娱乐工具,同时也是一种社交活动。 总结来说,网络五子棋结合了五子棋游戏的传统魅力和现代网络技术,使得不同地区的玩家能够在局域网内进行娱乐和聊天,既丰富了人们的娱乐生活,又加强了人际交流。而实现这一切的基础在于客户端程序的设计、服务器端的稳定运行、局域网的高效通信,以及音效文件增强的游戏体验。
recommend-type

自由行旅游新篇章:HarmonyOS技术融合与系统架构深度解析

# 1. HarmonyOS技术概述 ## 1.1 HarmonyOS的起源与发展 HarmonyOS(鸿蒙操作系统)由华为公司开发,旨在构建全场景分布式OS,以应对不同设备间的互联问题。自从2019年首次发布以来,HarmonyOS迅速成长,并迅速应用于智能手机、平板、智能穿戴、车载设备等多种平台。该系
recommend-type

足底支撑相到达73%是什么问题

<think>好的,我现在要处理用户的问题:“足底支撑相达到73%可能的原因及影响”。首先,需要理解用户提到的“足底支撑相73%”具体指什么。足底支撑相通常指步态周期中脚与地面接触的时间占比,正常范围大约在60%-62%左右。如果达到73%,明显超出正常范围,可能意味着步态异常。 接下来,需要确定可能的原因。可能的原因包括生物力学异常,比如足弓异常(扁平足或高弓足)、踝关节活动度受限,或者肌肉力量不足,特别是小腿和足部肌肉。另外,神经系统疾病如脑卒中或帕金森病可能影响步态控制。骨骼关节问题如关节炎、髋膝关节病变也可能导致支撑时间延长。还有代偿性步态,比如因疼痛或受伤而改变步态模式。 然后是
recommend-type

宾馆预约系统开发与优化建议

宾馆预约系统是一个典型的在线服务应用,它允许用户通过互联网平台预定宾馆房间。这种系统通常包含多个模块,比如用户界面、房态管理、预订处理、支付处理和客户评价等。从技术层面来看,构建一个宾馆预约系统涉及到众多的IT知识和技术细节,下面将详细说明。 ### 标题知识点 - 宾馆预约系统 #### 1. 系统架构设计 宾馆预约系统作为一个完整的应用,首先需要进行系统架构设计,决定其采用的软件架构模式,如B/S架构或C/S架构。此外,系统设计还需要考虑扩展性、可用性、安全性和维护性。一般会采用三层架构,包括表示层、业务逻辑层和数据访问层。 #### 2. 前端开发 前端开发主要负责用户界面的设计与实现,包括用户注册、登录、房间搜索、预订流程、支付确认、用户反馈等功能的页面展示和交互设计。常用的前端技术栈有HTML, CSS, JavaScript, 以及各种前端框架如React, Vue.js或Angular。 #### 3. 后端开发 后端开发主要负责处理业务逻辑,包括用户管理、房间状态管理、订单处理等。后端技术包括但不限于Java (使用Spring Boot框架), Python (使用Django或Flask框架), PHP (使用Laravel框架)等。 #### 4. 数据库设计 数据库设计对系统的性能和可扩展性至关重要。宾馆预约系统可能需要设计的数据库表包括用户信息表、房间信息表、预订记录表、支付信息表等。常用的数据库系统有MySQL, PostgreSQL, MongoDB等。 #### 5. 网络安全 网络安全是宾馆预约系统的重要考虑因素,包括数据加密、用户认证授权、防止SQL注入、XSS攻击、CSRF攻击等。系统需要实现安全的认证机制,比如OAuth或JWT。 #### 6. 云服务和服务器部署 现代的宾馆预约系统可能部署在云平台上,如AWS, Azure, 腾讯云或阿里云。在云平台上,系统可以按需分配资源,提高系统的稳定性和弹性。 #### 7. 付款接口集成 支付模块需要集成第三方支付接口,如支付宝、微信支付、PayPal等,需要处理支付请求、支付状态确认、退款等业务。 #### 8. 接口设计与微服务 系统可能采用RESTful API或GraphQL等接口设计方式,提供服务的微服务化,以支持不同设备和服务的接入。 ### 描述知识点 - 这是我个人自己做的 请大家帮忙修改哦 #### 个人项目经验与团队合作 描述中的这句话暗示了该宾馆预约系统可能是由一个个人开发者创建的。个人开发和团队合作在软件开发流程中有着显著的不同。个人开发者需要关注的方面包括项目管理、需求分析、代码质量保证、测试和部署等。而在团队合作中,每个成员会承担不同的职责,需要有效的沟通和协作。 #### 用户反馈与迭代 描述还暗示了该系统目前处于需要外部反馈和修改的阶段。这表明系统可能还处于开发或测试阶段,需要通过用户的实际使用反馈来不断迭代改进。 ### 标签知识点 - 200 #### 未提供信息 “200”这个标签可能指的是HTTP状态码中表示请求成功(OK)的200状态码。但是,由于没有提供更多的上下文信息,无法进一步分析其在本例中的具体含义。 ### 压缩包子文件的文件名称列表知识点 - 1111 #### 文件命名与管理 “1111”这个文件名称可能是一个版本号、日期标记或者是一个简单的标识符。文件命名应当遵循一定的规则,以确保文件的可追溯性和管理的便利性。在软件开发过程中,合理组织文件和版本控制(如使用Git)是必不可少的。 综上所述,宾馆预约系统的开发是一项复杂的工程,它涉及前后端的开发、数据库设计、系统安全、接口设计等多个方面。开发者在开发过程中需要不断学习和应用各类IT知识,以确保系统能够安全、高效、稳定地运行。而对于个人开发项目,如何合理利用有限资源、高效地管理和优化项目过程也是至关重要的。
recommend-type

HarmonyOS在旅游领域的创新:揭秘最前沿应用实践

# 1. HarmonyOS旅游应用的市场前景分析 随着数字化转型的不断深入,旅游行业正面临着前所未有的变革。在这样的背景下,HarmonyOS作为一种新兴的操作系统,带来了全新的市场前景和机遇。本章将深入分析HarmonyOS在旅游应用领域的市场潜力、用户需求、以及技术创新对旅游体验的改善。 ## 1.1 市场需求与用户画像分析 旅游市场的需求持续增
recommend-type

数据架构师需要具备什么能力

<think>嗯,用户现在转向询问数据架构师的能力要求了,而且特别提到要参考站内引用内容。看来ta正在规划职业方向,可能是个技术岗位的进阶者或转行者。之前对话历史显示用户对技术细节有深度需求(比如C语言底层特性),这次提问虽然跨度大,但延续了“技术职业发展”这条主线。用户引用的三段材料其实很有意思:第一篇强调综合能力,第二篇突出编程基础,第三篇提到商业洞察力——这正好构成数据架构师的三个能力象限。用户给出的引用里埋了个关键矛盾:第二篇说“速成只能做码农”,第三篇说“需要持续学习”,暗示ta可能担心速成班的局限性。回应时得强调“扎实基础+持续成长”的平衡。技术层面需要覆盖三个维度:硬技能(数据库