Python + adb 实现打电话功能

前言

其实很多年前写过一篇python打电话的功能,链接如下:

Python + twilio 实现打电话和发短信功能_自动发短信代码-CSDN博客

今天由于工作需要,又用python写了个关于打电话的小工具,主要是通过ADB方式实现的

实现过程

1.先利用adb指令封装几个常用的方法

具体的含义可以看注释,注释写的很清楚

python 复制代码
	def make_a_call(self, phoneNumber):
		# 拨打电话,只需传入目标电话号码即可
		phoneNumber = int(phoneNumber)

		# 执行adb指令去拨打电话
		proc = Utils.execute_adb_command('adb shell am start -a android.intent.action.CALL -d tel:{:d}'.format(int(phoneNumber)))

		resp = proc.stdout.read()

		logging.info('Calling {:d} ...'.format(phoneNumber))

	def answer_a_call(self):
		# 接听电话的函数

		# 先获取一下当前通话状态
		state = self.get_call_state()

		# 如果状态时振铃,那么接听
		if state == CallState.RING:
			Utils.execute_adb_command('adb shell am start -a android.intent.action.ANSWER')
			logging.info('Have answered a call')
		else:
			logging.info('No call incoming')

	def get_call_state(self):
		# adb shell 后的命令用双引号,否则执行出错!!!!
		proc = Utils.execute_adb_command('adb shell "dumpsys telephony.registry|grep \"mCallState\""')
		resp = proc.stdout.read()  # 读取命令执行的结果

		state = str(resp).splitlines()[-1].split('=')[-1]  # 从返回内容中取出状态字符串

		# 返回通话状态
		return Utils.to_enum(int(state), CallState)

	def hang_up_a_call(self):
		# 执行adb 指令去挂掉电话

		# 先查询一下当前的状态
		state = self.get_call_state()

		# 如果状态时振铃,正在通话中,那么执行挂断,否则log提示
		if state in [CallState.RING, CallState.CALLING]:
			proc = Utils.execute_adb_command('adb shell input keyevent 6')
			logging.info('Have hang up a call')
		else:
			logging.info('No call to be hang up')

2.再使用pysimpleGUI库写一个简单的工具界面即可

python 复制代码
# 这是绘制界面的函数
def make_window():
	"""
	Build a GUI page
	:return: window
	"""
	NetworkType = ['2G', '4G', '5G']

	def name(name, NAME_SIZE=11):
		dots = NAME_SIZE - len(name) - 2
		return sg.Text(name + ' ' + ' ' * dots, size=(NAME_SIZE, 1), justification='r', pad=(0, 0), font='Courier 11')

	# 绘制设置选项
	layout_basic = [
		[name('  网络类型:'), sg.Combo(default_value=NetworkType[2], values=NetworkType, size=(12, 2), key='-NETWORK-'), sg.Button('设置', key='-SET-', enable_events=True)],
		[name('  呼叫号码:'), sg.Input(default_text=10086, size=(12, 2), key='-NUMBER1-'), sg.Input(default_text='', size=(12, 2), key='-NUMBER2-'), sg.Input(default_text='', size=(12, 2), key='-NUMBER3-'), sg.Input(default_text='', size=(12, 2), key='-NUMBER4-'), sg.Input(default_text='', size=(12, 2), key='-NUMBER5-')],
		[name('  呼叫时间:'), sg.Input(default_text=30, size=(8, 2), key='-CALL_TIME-'), sg.Text('秒')],  # input代表输入框,default_text代表默认值, key代表给这输入框的起个别名
		[name('  循环次数:'), sg.Input(default_text=1, size=(8, 2), key='-COUNT-'), sg.Text('次')],

	]

	# 绘制操作选项
	layout_action = [
		[sg.Button('呼叫', size=(10, 2), key='-RUN-'), sg.Push(), sg.Button('挂断', size=(10, 2), key='-STOP-'), sg.Push(), sg.Button('退出', size=(10, 2), key='-EXIT-')]
	]

	col1 = sg.Column([[sg.Frame('设置:', layout_basic, size=(900, 140))],  [sg.Frame('操作:', layout_action, size=(900, 80))]])

	# 绘制版权所有信息,xxx内容可以自定义修改
	layout = [[sg.vtop(col1)], [sg.Push(), sg.Text('@Copyright xxxx.', font='楷体 12'), sg.Push()]]

	# 绘制工具的标题栏
	window = sg.Window('Make call V1.0.0', layout, auto_size_text=True, size=(1000, 300), finalize=True, enable_close_attempted_event=True)

	return window

3.呈现的结果如下

1.可以根据需要设置网络类型,比如2G,3G,4G,5G等等

2.可以自定义呼叫的号码,且支持多个号码

3.支持呼叫时间的自定义

4.支持循环次数的自定义

遇到的问题

一开始通过adb命令去切换网络时,无论如何都切换不成功;即使切换后开关飞行模式也无法生效,最后发现需要重启设备方可生效。这里贴一下ADB切换网络类型的命令,供参考:

设置网络类型:settings put global preferred_network_mode + 网络类型枚举值

获取网络类型:settings get global preferred_network_mode

各个制式的网络类型枚举值如下:

cpp 复制代码
/* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */
int NETWORK_MODE_GSM_ONLY   = 1; /* GSM only */
int NETWORK_MODE_WCDMA_ONLY  = 2; /* WCDMA only */
int NETWORK_MODE_GSM_UMTS   = 3; /* GSM/WCDMA (auto mode, according to PRL)
int NETWORK_MODE_CDMA       = 4; /* CDMA and EvDo (auto mode, according to PRL)
int NETWORK_MODE_CDMA_NO_EVDO   = 5; /* CDMA only */
int NETWORK_MODE_EVDO_NO_CDMA   = 6; /* EvDo only */
int NETWORK_MODE_GLOBAL   = 7; /* GSM/WCDMA, CDMA, and EvDo*/                                            
int NETWORK_MODE_LTE_CDMA_EVDO  = 8; /* LTE, CDMA and EvDo */
int NETWORK_MODE_LTE_GSM_WCDMA  = 9; /* LTE, GSM/WCDMA */
int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = 10;
/* LTE, CDMA, EvDo, GSM/WCDMA */
int NETWORK_MODE_LTE_ONLY     = 11; /* LTE Only mode. */
int NETWORK_MODE_LTE_WCDMA  = 12; /* LTE/WCDMA */

总结

总结下来就是ADB命令可以做很多事情,前提是需要找到相应的ADB指令,这就需要对Android有一定的了解!

有问题的伙伴可以直接加我WX:xgh321324 进行技术讨论!

相关推荐
Gu Gu Study14 小时前
ScoutLoop开放域深度研究引擎(agent的初步设计想法)
人工智能·python
神龙天舞200114 小时前
MySQL 备库为什么会延迟好几个小时
android·数据库·mysql
卷无止境14 小时前
写代码这件事,到底该讲究点什么?
后端·python
卷无止境15 小时前
循环复杂度到底在算什么,Python 代码怎么才能写得让人一看就懂
后端·python
lpfasd12315 小时前
MediaCrawler 项目深度分析
chrome·python·chrome devtools
丙氨酸長鏈15 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
Dxy123931021615 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
bamb0016 小时前
一个项目带你入门AI应用开发01
python
独行侠影a16 小时前
APScheduler+Redis 分布式定时任务:解决多实例任务重复执行
数据库·redis·分布式
05664616 小时前
Python康复训练——常用标准库
开发语言·python·学习