编程开发 --- 安卓全自动接单

发布时间 2023-11-26 19:54:02作者: GKLBB

需求:

客户需要做一个纯手机接单的app,电脑接单也可以实现只是政策要求手机接单。因为晚上时常会遗忘订单,导致客户绩效考核。

解决思路:

既然是手机接单就有两种方法。root法和免root的无障碍法,root法有工具task app,免root有工具 一触即发app和自动精灵等等,我个人认为一触即发简单上手快推荐。

一触即发的条件判断有,截图法和控件查找法,开始我用控件法,但是app是uniapp开发的混合app,不能存在安卓控件的说法。因此只能使用截图法。

难点:

如果只是判断后点击那还简单,但是除了正常接单流程外还有一些异常要处理,下面一一列举

接单app和客户app需要持久化保活,在我之前的文章有处理办法。

网络不稳定导致的白色屏幕,这算是一种异常。可以通过铃声提醒的方式解决。

token会6小时后过期,过期后要么重新登录,要么自动续期。如果自动续期,需要重新编写app太复杂。这里采用重新登陆的方法,但是重新登陆需要短信验证码,因此引入新的问题,一触即发如何读取短信验证码。我的处理思路是,在检测到登陆超时,自动点击发送验证码,在接收验证码的手机上安装监听指定短信的app并转发给中间服务器,中间服务器临时保存验证码并提供获取验证码接口, 一触即发app发送请求获取验证码并填入app登陆。

细节:

我们先说一触即发脚本,在使用前需要在app里开启权限,开启无障碍、忽略电池优化,悬浮窗,所有的权限管理,在设置里显示 识图显示矩形,上键停止脚本

//在一触即发导入脚本即可使用,这里在一个脚本处理了两个app,思路就是截图判断是否在某一页或者是订单,是的话点击即可,包含异常处理
//打开 铁塔aiot app并处理接单
//定义两个变量
变量 永真变量 = 真;
变量 验证码 = "";
//开始循环接单
判断循环首 永真变量 = true
        打开应用("com.chinatower.powerservice");
        随机延时(5000,5000);
        弹出提示("开始查找aiot订单");
        //这里判断是否是接单的页面,依据是特征图片
        如果 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_ADBA2F4708FDE61B5248F2B5A19A239E.dddbbb,精确度:80 ,null) 则 
                弹出提示("找到工单模块,管理工单");
//点击接单模块
                点击(222,855,1);
                点击(222,855,1);
                随机延时(10000,10000);
                //检查有没有订单;
                如果 屏幕中是否包含文字("暂无内容" ,'node' ,null) 则 
                        弹出提示("暂无内容");
                        返回键();
                        //登录异常判断;
                        如果 屏幕中是否包含文字("登录超时" ,'node' ,null) 或 屏幕中是否包含文字("账号验证" ,'node' ,null) 则 
                                弹出提示("登录异常处理");
                                判断循环首 永真变量 = true
                                        震动(长)();
                                        铃声提示();
                                        弹出提示("请重新登录");
                                        关闭应用("com.chinatower.powerservice");
//因为关闭方法不起作用只能三个返回表示关闭app
                                        返回键();
                                        返回键();
                                        返回键();
//                                        任务键();
                                        打开应用("com.chinatower.powerservice");
                                        弹出提示("正在输入密码");
                                        //删除登录;
                                        点击(960,726,1);
                                        输入文字(280,754,"guokai1");
                                        //删除密码;
                                        点击(889,873,1);
                                        输入文字(304,879,"82212991@Lbb520");
                                        //同意协议;
                                        点击(89,2307,1);
                                        //点击登录;
                                        点击(549,1393,1);
                                        随机延时(3000,3000);
                                        //发送验证码;
                                        点击(882,916,1);
                                        随机延时(5000,5000);
                                        验证码 = 网页访问("http://125.75.111.54:9002/api/sms/latest" ,'GET' ,header:{} ,data:{});
                                        验证码 = 取文本中间("{验证码}","验证码","");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        输入文字(361,926,"{验证码}");
                                        //登录;
                                        点击(515,1413,1);
                                        如果 屏幕中是否包含文字("设备汇总" ,'node' ,null) 或 屏幕中是否包含文字("常用功能" ,'node' ,null) 或 屏幕中是否包含文字("修改密码" ,'node' ,null) 或 屏幕中是否包含文字("待办工单" ,'node' ,null) 则 
                                                弹出提示("登录成功进入接单");
                                                退出循环;
                                        否则
//                                                //;
                                                弹出提示("登录失败重新登录");


                                        结束 如果
                                判断循环尾
                        否则
                                弹出提示("未检测到登录异常,尝试接单");


                        结束 如果                否则
                        弹出提示("发现工单");
                        //登录异常判断;
                        如果 屏幕中是否包含文字("登录超时" ,'node' ,null) 或 屏幕中是否包含文字("账号验证" ,'node' ,null) 则 
                                弹出提示("登录异常处理");
                                判断循环首 永真变量 = true
                                        震动(长)();
                                        铃声提示();
                                        弹出提示("请重新登录");
                                        关闭应用("com.chinatower.powerservice");
                                        返回键();
                                        返回键();
                                        返回键();
//                                        任务键();
                                        打开应用("com.chinatower.powerservice");
                                        弹出提示("正在输入密码");
                                        //删除登录;
                                        点击(960,726,1);
                                        输入文字(280,754,"guokai1");
                                        //删除密码;
                                        点击(889,873,1);
                                        输入文字(304,879,"82212991@Lbb520");
                                        //同意协议;
                                        点击(89,2307,1);
                                        //点击登录;
                                        点击(549,1393,1);
                                        随机延时(3000,3000);
                                        //发送验证码;
                                        点击(882,916,1);
                                        随机延时(5000,5000);
                                        验证码 = 网页访问("http://125.75.111.54:9002/api/sms/latest" ,'GET' ,header:{} ,data:{});
                                        验证码 = 取文本中间("{验证码}","验证码","");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        输入文字(361,926,"{验证码}");
                                        //登录;
                                        点击(515,1413,1);
                                        如果 屏幕中是否包含文字("设备汇总" ,'node' ,null) 或 屏幕中是否包含文字("常用功能" ,'node' ,null) 或 屏幕中是否包含文字("修改密码" ,'node' ,null) 或 屏幕中是否包含文字("待办工单" ,'node' ,null) 则 
                                                弹出提示("登录成功进入接单");
                                                退出循环;
                                        否则
//                                                //;
                                                弹出提示("登录失败重新登录");


                                        结束 如果
                                判断循环尾
                        否则
                                弹出提示("未检测到登录异常,尝试接单");


                        结束 如果                        
                        随机延时(5000,5000);
                        //进入订单;
                        点击图片("/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_5561A0D3E52614D9F9D6371B196D921B_copy_copy_copy.dddbbb",精确度: 80,null,false);
                        点击(508,530,1);
                        点击(467,512,1);
//                        点击(375,256,1);
                        随机延时(3000,3000);
                        //接单;
                        点击图片("/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_D354F18F6107B973B80B39984C35A4E0.dddbbb",精确度: 55,null,false);
                        点击(547,2307,1);
                        //接单;
//                        点击(368,1244,1);
                        //确定;
                        点击图片("/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_1B6BF0D4DD8304905281333C863850C3.dddbbb",精确度: 80,null,false);
                        点击(684,1424,1);
                        //确定;
//                        点击(455,754,1);
                        返回键();
//                        点击图片("/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_E22206D6CB4ECE772D26A7CE5E21A5FF.dddbbb",精确度: 80,null,false);
                        点击(255,840,1);
                        点击(502,560,1);


                结束 如果        否则
                弹出提示("未找到");
                点击(138,2268,1);
                返回键();
                //登录异常判断;
                如果 屏幕中是否包含文字("登录超时" ,'node' ,null) 或 屏幕中是否包含文字("账号验证" ,'node' ,null) 则 
                        弹出提示("登录异常处理");
                        判断循环首 永真变量 = true
                                震动(长)();
                                铃声提示();
                                弹出提示("请重新登录");
                                关闭应用("com.chinatower.powerservice");
                                返回键();
                                返回键();
                                返回键();
//                                任务键();
                                打开应用("com.chinatower.powerservice");
                                弹出提示("正在输入密码");
                                //删除登录;
                                点击(960,726,1);
                                输入文字(280,754,"guokai1");
                                //删除密码;
                                点击(889,873,1);
                                输入文字(304,879,"82212991@Lbb520");
                                //同意协议;
                                点击(89,2307,1);
                                //点击登录;
                                点击(549,1393,1);
                                随机延时(3000,3000);
                                //发送验证码;
                                点击(882,916,1);
                                随机延时(5000,5000);
                                验证码 = 网页访问("http://125.75.111.54:9002/api/sms/latest" ,'GET' ,header:{} ,data:{});
                                验证码 = 取文本中间("{验证码}","验证码","");
                                弹出提示("成功获取验证码{验证码}");
                                弹出提示("成功获取验证码{验证码}");
                                弹出提示("成功获取验证码{验证码}");
                                弹出提示("成功获取验证码{验证码}");
                                输入文字(361,926,"{验证码}");
                                //登录;
                                点击(515,1413,1);
                                如果 屏幕中是否包含文字("设备汇总" ,'node' ,null) 或 屏幕中是否包含文字("常用功能" ,'node' ,null) 或 屏幕中是否包含文字("修改密码" ,'node' ,null) 或 屏幕中是否包含文字("待办工单" ,'node' ,null) 则 
                                        弹出提示("登录成功进入接单");
                                        退出循环;
                                否则
//                                        //;
                                        弹出提示("登录失败重新登录");


                                结束 如果
                        判断循环尾
                否则
                        弹出提示("未检测到登录异常,尝试接单");


                结束 如果

        结束 如果        随机延时(5000,5000);
//处理铁塔新网管app
        打开应用("com.chinatower.energymonitor");
        随机延时(5000,5000);
        弹出提示("开始查找网管订单");
        如果 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_2C97C45A842E917408B9666466501638.dddbbb,精确度:91 ,null) 则 
                弹出提示("找到工单模块,管理工单");
                弹出提示("找到工单模块,管理工单");
                随机延时(6000,6000);
//                点击图片("/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_86BA010D78C5584204EDB769C5C22F38.dddbbb",精确度: 80,null,false);
                点击(279,827,1);
//                点击图片("/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_9D13BC164F494F7A9CF33E51C67877B7.dddbbb",精确度: 50,null,false);
                //检查有没有订单;
                如果 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_E597066365DD74373F2834FCF8BD242D.dddbbb,精确度:100 ,null) 或 屏幕中是否包含文字("暂无内容" ,'node' ,null) 则 
                        弹出提示("暂无内容");
                        //暂无;
                        返回键();
                        //登录异常判断;
                        如果 屏幕中是否包含文字("登录超时" ,'node' ,null) 或 屏幕中是否包含文字("记住密码" ,'node' ,null) 或 屏幕中是否包含文字("您的登录状态已过期" ,'node' ,null) 或 屏幕中是否包含文字("获取验证码" ,'node' ,null) 则 
                                弹出提示("登录异常处理");
                                判断循环首 永真变量 = true
                                        震动(长)();
                                        铃声提示();
                                        弹出提示("请重新登录");
                                        关闭应用("com.chinatower.energymonitor");
                                        返回键();
                                        返回键();
                                        返回键();
//                                        任务键();
                                        打开应用("com.chinatower.energymonitor");
                                        弹出提示("正在输入密码");
                                        //进入账号;
                                        点击(230,714,1);
                                        //删除账号;
                                        点击(937,703,1);
                                        输入文字(237,727,"guokai1");
                                        //进入密码;
                                        点击(318,929,1);
                                        //删除密码;
                                        点击(877,898,1);
                                        输入文字(328,928,"82212991@Lbb520");
                                        //同意协议;
                                        点击(86,2307,1);
                                        //点击登录;
                                        点击(556,1379,1);
                                        点击(792,903,1);
                                        点击文字("获取验证码",'node',null,false);
                                        随机延时(5000,5000);
                                        验证码 = 网页访问("http://125.75.111.54:9002/api/sms/latest" ,'GET' ,header:{} ,data:{});
                                        验证码 = 取文本中间("{验证码}","验证码:","");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        输入文字(303,921,"{验证码}");
                                        //正式登录;
                                        点击(507,1248,1);
                                        如果 屏幕中是否包含文字("设备汇总" ,'node' ,null) 或 屏幕中是否包含文字("常用功能" ,'node' ,null) 或 屏幕中是否包含文字("修改密码" ,'node' ,null) 或 屏幕中是否包含文字("待办工单" ,'node' ,null) 则 
                                                弹出提示("登录成功进入接单");
                                                退出循环;
                                        否则
//                                                //;
                                                弹出提示("登录失败重新登录");


                                        结束 如果
                                判断循环尾
                        否则
                                弹出提示("未检测到登录异常,尝试接单");


                        结束 如果                否则
                        随机延时(5000,5000);
                        //判断是否有单;
                        如果 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_695B9FA0C04A43180E293D54E4C6B9F7.dddbbb,精确度:80 ,null) 则 
                                //如果没有代办,则进行语音提示,用户重新登录;
                                随机延时(5000,5000);
//                                如果 屏幕中是否包含文字("登录超时" ,'node' ,null) 或 屏幕中是否包含文字("您的登录状态已过期" ,'node' ,null) 或 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_E59F283A11FDE68C8F860D293DA1464B.dddbbb,精确度:80 ,null) 则 
                                        弹出提示("异常处理");
                                        判断循环首 永真变量 = true
                                                震动(长)();
                                                铃声提示();
                                                弹出提示("请重新登录");
                                                如果 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_7D02EA11322C5FFF2151EB4269873D33.dddbbb,精确度:80 ,null) 且 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_92139E94017B0A1680B46CDAA6B52671.dddbbb,精确度:80 ,null) 且 屏幕中是否包含文字("设备汇总" ,'node' ,null) 则 
                                                        退出循环;
                                                否则


                                                结束 如果
                                        判断循环尾
                                否则


                                结束 如果                                //登录异常判断;
                                如果 屏幕中是否包含文字("登录超时" ,'node' ,null) 或 屏幕中是否包含文字("记住密码" ,'node' ,null) 或 屏幕中是否包含文字("您的登录状态已过期" ,'node' ,null) 或 屏幕中是否包含文字("获取验证码" ,'node' ,null) 则 
                                        弹出提示("登录异常处理");
                                        判断循环首 永真变量 = true
                                                震动(长)();
                                                铃声提示();
                                                弹出提示("请重新登录");
                                                关闭应用("com.chinatower.energymonitor");
                                                返回键();
                                                返回键();
                                                返回键();
//                                                任务键();
                                                打开应用("com.chinatower.energymonitor");
                                                弹出提示("正在输入密码");
                                                //进入账号;
                                                点击(230,714,1);
                                                //删除账号;
                                                点击(937,703,1);
                                                输入文字(237,727,"guokai1");
                                                //进入密码;
                                                点击(318,929,1);
                                                //删除密码;
                                                点击(877,898,1);
                                                输入文字(328,928,"82212991@Lbb520");
                                                //同意协议;
                                                点击(86,2307,1);
                                                //点击登录;
                                                点击(556,1379,1);
                                                点击(792,903,1);
                                                点击文字("获取验证码",'node',null,false);
                                                随机延时(5000,5000);
                                                验证码 = 网页访问("http://125.75.111.54:9002/api/sms/latest" ,'GET' ,header:{} ,data:{});
                                                验证码 = 取文本中间("{验证码}","验证码:","");
                                                弹出提示("成功获取验证码{验证码}");
                                                弹出提示("成功获取验证码{验证码}");
                                                弹出提示("成功获取验证码{验证码}");
                                                弹出提示("成功获取验证码{验证码}");
                                                输入文字(303,921,"{验证码}");
                                                //正式登录;
                                                点击(507,1248,1);
                                                如果 屏幕中是否包含文字("设备汇总" ,'node' ,null) 或 屏幕中是否包含文字("常用功能" ,'node' ,null) 或 屏幕中是否包含文字("修改密码" ,'node' ,null) 或 屏幕中是否包含文字("待办工单" ,'node' ,null) 则 
                                                        弹出提示("登录成功进入接单");
                                                        退出循环;
                                                否则
//                                                        //;
                                                        弹出提示("登录失败重新登录");


                                                结束 如果
                                        判断循环尾
                                否则
                                        弹出提示("未检测到登录异常,尝试接单");


                                结束 如果                                弹出提示("发现工单");
                                //进入订单;
                                点击图片("/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_5561A0D3E52614D9F9D6371B196D921B_copy_copy_copy.dddbbb",精确度: 84,null,false);
                                点击(484,483,1);
                                滑动([{手势: &手势1,time: 789}],false);
                                滑动([{手势: &手势1,time: 1326}],false);
                                //接单;
                                点击图片("/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_EDF06D95AE95876317FB3C557B35399C_copy_copy_copy_copy.dddbbb",精确度: 80,null,false);
                                点击(518,2281,1);
                                //确定;
                                点击图片("/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_9920D481D731BDCF0293B1FFE2BD528F_copy_copy.dddbbb",精确度: 80,null,false);
                                返回键();
                        否则
                                //登录异常处理;
//                                打开应用("com.chinatower.energymonitor");
//                                判断循环首 永真变量 = true
                                        铃声提示();
                                        震动(长)();
                                        弹出提示("请重新登录");
                                        如果 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_BEFCAB3735BC5271347D245290F22261.dddbbb,精确度:80 ,null) 则 
                                                退出循环;

                                        结束 如果                                        如果 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_BC254EAC6CA641960C1E3D004394ED30.dddbbb,精确度:80 ,null) 则 
                                                退出循环;
                                        否则


                                        结束 如果                                        如果 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_F403337EC41FD824B66F859F342663D7.dddbbb,精确度:80 ,null) 则 
                                                退出循环;

                                        结束 如果                                        如果 屏幕中是否包含图片(/storage/emulated/0/YiChuJiFaProject/workSpaceImage/img_E0332EC3573B2E895156835F0A6AB702.dddbbb,精确度:80 ,null) 则 
                                                退出循环;

                                        结束 如果
                                判断循环尾
                                //白屏检测;
                                判断循环首 永真变量 = true
                                        震动(长)();
                                        铃声提示();
                                        弹出提示("请重新登录");
                                        关闭应用("com.chinatower.energymonitor");
                                        返回键();
                                        返回键();
                                        返回键();
//                                        任务键();
                                        打开应用("com.chinatower.energymonitor");
                                        弹出提示("正在输入密码");
                                        //进入账号;
                                        点击(230,714,1);
                                        //删除账号;
                                        点击(937,703,1);
                                        输入文字(237,727,"guokai1");
                                        //进入密码;
                                        点击(318,929,1);
                                        //删除密码;
                                        点击(877,898,1);
                                        输入文字(328,928,"82212991@Lbb520");
                                        //同意协议;
                                        点击(86,2307,1);
                                        //点击登录;
                                        点击(556,1379,1);
                                        点击(792,903,1);
                                        点击文字("获取验证码",'node',null,false);
                                        随机延时(5000,5000);
                                        验证码 = 网页访问("http://125.75.111.54:9002/api/sms/latest" ,'GET' ,header:{} ,data:{});
                                        验证码 = 取文本中间("{验证码}","验证码:","");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        弹出提示("成功获取验证码{验证码}");
                                        输入文字(303,921,"{验证码}");
                                        //正式登录;
                                        点击(507,1248,1);
                                        如果 屏幕中是否包含文字("设备汇总" ,'node' ,null) 或 屏幕中是否包含文字("常用功能" ,'node' ,null) 或 屏幕中是否包含文字("修改密码" ,'node' ,null) 或 屏幕中是否包含文字("待办工单" ,'node' ,null) 则 
                                                弹出提示("登录成功进入接单");
                                                退出循环;
                                        否则
//                                                //;
                                                弹出提示("登录失败重新登录,下一次循环");


                                        结束 如果
                                判断循环尾


                        结束 如果

                结束 如果        否则
                弹出提示("未找到模块");
                铃声提示();
                点击(159,2249,1);
                点击(138,2268,1);
                //防止接单界面出现白屏,后卡住;
                返回键();
                //登录异常判断;
                如果 屏幕中是否包含文字("登录超时" ,'node' ,null) 或 屏幕中是否包含文字("记住密码" ,'node' ,null) 或 屏幕中是否包含文字("您的登录状态已过期" ,'node' ,null) 或 屏幕中是否包含文字("获取验证码" ,'node' ,null) 则 
                        弹出提示("登录异常处理");
                        判断循环首 永真变量 = true
                                震动(长)();
                                铃声提示();
                                弹出提示("请重新登录");
                                关闭应用("com.chinatower.energymonitor");
                                返回键();
                                返回键();
                                返回键();
//                                任务键();
                                打开应用("com.chinatower.energymonitor");
                                弹出提示("正在输入密码");
                                //进入账号;
                                点击(230,714,1);
                                //删除账号;
                                点击(937,703,1);
                                输入文字(237,727,"guokai1");
                                //进入密码;
                                点击(318,929,1);
                                //删除密码;
                                点击(877,898,1);
                                输入文字(328,928,"82212991@Lbb520");
                                //同意协议;
                                点击(86,2307,1);
                                //点击登录;
                                点击(556,1379,1);
                                点击(792,903,1);
                                点击文字("获取验证码",'node',null,false);
                                随机延时(5000,5000);
                                验证码 = 网页访问("http://125.75.111.54:9002/api/sms/latest" ,'GET' ,header:{} ,data:{});
                                验证码 = 取文本中间("{验证码}","验证码:","");
                                弹出提示("成功获取验证码{验证码}");
                                弹出提示("成功获取验证码{验证码}");
                                弹出提示("成功获取验证码{验证码}");
                                弹出提示("成功获取验证码{验证码}");
                                输入文字(303,921,"{验证码}");
                                //正式登录;
                                点击(507,1248,1);
                                如果 屏幕中是否包含文字("设备汇总" ,'node' ,null) 或 屏幕中是否包含文字("常用功能" ,'node' ,null) 或 屏幕中是否包含文字("修改密码" ,'node' ,null) 或 屏幕中是否包含文字("待办工单" ,'node' ,null) 则 
                                        弹出提示("登录成功进入接单");
                                        退出循环;
                                否则
//                                        //;
                                        弹出提示("登录失败重新登录");


                                结束 如果
                        判断循环尾
                否则
                        弹出提示("未检测到登录异常,尝试接单");


                结束 如果

        结束 如果        随机延时(5000,5000);

判断循环尾

 

 

服务器端使用springboot,代码如下、

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>demo</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Spring Boot Starter Web 包含了 Spring MVC 和内嵌的 Tomcat -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring Boot Starter Data JPA 提供了对 Spring Data 和 JPA 的支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.persistence/persistence-api -->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>

        <!-- H2 Database,一个内存数据库,用于快速开发和测试 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 

 

application.properties

# H2 ?????
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

# ????? H2 ???
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

server.port=9002

 

 

package com.example.demo;


import org.springframework.boot.SpringApplication;
        import org.springframework.boot.autoconfigure.SpringBootApplication;
        import org.springframework.boot.autoconfigure.domain.EntityScan;

@SpringBootApplication
@EntityScan(basePackages = "com.example.demo") // 指定实体类的扫描路径
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

 

 

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/sms")
public class SmsController {

    @Autowired
    private SmsRepository smsRepository;

    @PostMapping
    public void receiveSms( SmsRequest smsRequest) {
        SmsEntity smsEntity = new SmsEntity();
        smsEntity.setPhoneNumber(smsRequest.getPhoneNumber());
        smsEntity.setMessage(smsRequest.getMessage());
        smsRepository.save(smsEntity);
    }

    @GetMapping("/latest")
    public SmsEntity getLatestSms() {
        // 从数据库中获取最新的一条短信
        return smsRepository.findFirstByOrderByIdDesc().orElse(null);
    }

    
    @GetMapping("/all")
    public List<SmsEntity> getAllSms() {
        // 从数据库中获取所有短信
        return smsRepository.findAll();
    }
}

 

 

package com.example.demo;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class SmsEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    private String phoneNumber;
    private String message;

    // getters and setters

}

 

 

package com.example.demo;

import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;

public interface SmsRepository extends JpaRepository<SmsEntity, Long> {
    Optional<SmsEntity> findFirstByOrderByIdDesc(); // 更新这里
}

 

 

package com.example.demo;

public class SmsRequest {

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getMessage() {
    }

    public void setMessage(String message) {
        this.message = message;
    }

    private String phoneNumber;
    private String message;

    // getters and setters
}

 

安卓转发短信的实现

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- 宣告应用使用的硬件特性,这里声明了对电话功能的需求,但设置为非必需 -->
    <uses-feature
        android:name="android.hardware.telephony"
        android:required="false" />

    <!-- 宣告应用所需的权限 -->
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 注意:上面的 INTERNET 权限只需要声明一次 -->

    <application
        <!-- 定义应用的网络安全配置 -->
        android:networkSecurityConfig="@xml/network_security_config"
        <!-- 允许应用进行备份 -->
        android:allowBackup="true"
        <!-- 定义数据提取规则 -->
        android:dataExtractionRules="@xml/data_extraction_rules"
        <!-- 定义完整备份内容规则 -->
        android:fullBackupContent="@xml/backup_rules"
        <!-- 设置应用图标 -->
        android:icon="@mipmap/ic_launcher"
        <!-- 设置应用标签 -->
        android:label="@string/app_name"
        <!-- 设置圆形应用图标 -->
        android:roundIcon="@mipmap/ic_launcher_round"
        <!-- 设置应用支持从右到左的布局 -->
        android:supportsRtl="true"
        <!-- 设置应用主题 -->
        android:theme="@style/Theme.MyApplication"
        <!-- 定义目标 API 版本,这里设置为 31 -->
        tools:targetApi="31">

        <!-- 定义应用的主 Activity,会在启动时被调用 -->
        <activity
            android:name=".MainActivity"
            <!-- 定义 Activity 是否可以被其他应用组件访问 -->
            android:exported="true">
            <intent-filter>
                <!-- 定义 Activity 接收的主要动作 -->
                <action android:name="android.intent.action.MAIN" />

                <!-- 定义 Activity 接收的主要类别 -->
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- 定义短信接收器,用于接收短信 -->
        <receiver android:name=".SmsReceiver"
            <!-- 定义接收器是否可以被其他应用组件访问 -->
            android:exported="true">
            <intent-filter>
                <!-- 定义接收器接收的主要动作 -->
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>

        <!-- 定义后台服务,用于处理短信 -->
        <service android:name=".SmsService" />
    </application>

</manifest>

 

 

// 包名,这里表示该文件属于com.example.myapplication包
package com.example.myapplication;

// 导入必要的 Android 类
import android.content.Intent;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.Switch;
import androidx.appcompat.app.AppCompatActivity;

// MainActivity 类,继承自 AppCompatActivity 类
public class MainActivity extends AppCompatActivity {

    // 声明 Switch 类型的成员变量 smsSwitch
    private Switch smsSwitch;

    // 在 Activity 创建时调用的方法
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // 调用父类的 onCreate 方法
        super.onCreate(savedInstanceState);
        // 设置当前 Activity 使用的布局文件
        setContentView(R.layout.activity_main);

        // 通过布局文件中定义的 ID 获取 Switch 控件的实例
        smsSwitch = findViewById(R.id.smsSwitch);

        // 为 Switch 控件设置状态变更监听器
        smsSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            // 在 Switch 状态发生变化时调用的方法
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // 判断 Switch 的状态是否为选中
                if (isChecked) {
                    // 如果选中,启动 SmsService 服务
                    startService(new Intent(MainActivity.this, SmsService.class));
                } else {
                    // 如果未选中,停止 SmsService 服务
                    stopService(new Intent(MainActivity.this, SmsService.class));
                }
            }
        });
    }
}

 

 

package com.example.myapplication;

// SmsService.java

import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;

// SmsService.java
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.telephony.SmsMessage;
// SmsService.java
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.telephony.SmsMessage;

// SmsService.java
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.telephony.SmsMessage;

public class SmsService extends Service {

    private SmsReceiver smsReceiver;

    @Override
    public void onCreate() {
        super.onCreate();
        smsReceiver = new SmsReceiver();

        // 创建一个 IntentFilter 对象并添加接收的 action
        IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");

        // 注册广播接收器
        registerReceiver(smsReceiver, intentFilter);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 处理服务启动命令
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 在服务销毁时取消注册广播接收器
        unregisterReceiver(smsReceiver);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

 

 

// 包名,这里表示该文件属于com.example.myapplication包
package com.example.myapplication;

// 导入必要的 Android 类
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import android.os.AsyncTask;

// SmsReceiver 类,继承自 BroadcastReceiver 类
public class SmsReceiver extends BroadcastReceiver {

    // 重写 BroadcastReceiver 的 onReceive 方法,用于接收短信广播
    @Override
    public void onReceive(Context context, Intent intent) {
        // 获取广播中的附加数据
        Bundle bundle = intent.getExtras();

        // 检查附加数据是否为空
        if (bundle != null) {
            // 获取短信数据数组
            Object[] pdus = (Object[]) bundle.get("pdus");

            // 检查短信数据数组是否为空
            if (pdus != null) {
                // 遍历短信数据数组
                for (Object pdu : pdus) {
                    // 将每个数据转换为 SmsMessage 对象
                    SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu);
                    // 获取短信发送者的号码
                    String sender = smsMessage.getDisplayOriginatingAddress();
                    // 获取短信内容
                    String message = smsMessage.getDisplayMessageBody();

                    // 检查短信内容是否包含 "铁塔" 字符串
                    if (message.contains("铁塔")) {
                        // 如果包含,则将短信信息传递给后台服务处理
                        sendSmsToServer(context, sender, message);
                    }
                }
            }
        }
    }

    // 将短信信息传递给后台服务处理的方法
    private void sendSmsToServer(Context context, String sender, String message) {
        // 创建异步任务对象,并执行异步任务
        new SendSmsTask(context).execute(sender, message);
    }

    // 异步任务类,用于在后台处理网络请求
    private static class SendSmsTask extends AsyncTask<String, Void, Void> {
        // 上下文对象
        private Context context;

        // 构造方法,用于初始化上下文对象
        SendSmsTask(Context context) {
            this.context = context;
        }

        // 在后台执行网络请求的方法
        @Override
        protected Void doInBackground(String... params) {
            try {
                // 构建要发送的数据
                Map<String, String> postData = new HashMap<>();
                postData.put("phoneNumber", params[0]);
                postData.put("message", params[1]);

                // 构建服务器地址
                URL url = new URL("http://125.75.111.54:9002/api/sms"); // 替换为你的服务器地址

                // 打开连接
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

                // 将数据写入请求体
                OutputStream os = connection.getOutputStream();
                os.write(getPostDataString(postData).getBytes("UTF-8"));
                os.flush();
                os.close();

                // 获取服务器响应
                int responseCode = connection.getResponseCode();

                // 检查服务器响应状态
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    // 服务器成功接收数据
                    publishProgress();  // 更新 UI
                } else {
                    // 服务器返回错误
                    publishProgress();  // 更新 UI
                }

            } catch (Exception e) {
                e.printStackTrace();
                publishProgress();  // 更新 UI
            }

            return null;
        }

        // 在 UI 线程中更新 UI,例如显示 Toast 提示用户
        @Override
        protected void onProgressUpdate(Void... values) {
            Toast.makeText(context, "短信内容发送成功", Toast.LENGTH_SHORT).show();
        }

        // 将 Map 中的数据转换为 POST 请求的数据格式
        private static String getPostDataString(Map<String, String> params) {
            StringBuilder result = new StringBuilder();
            boolean first = true;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (first) {
                    first = false;
                } else {
                    result.append("&");
                }
                result.append(entry.getKey()).append("=").append(entry.getValue());
            }
            return result.toString();
        }
    }
}