商家自动化任务自动分析短信重要事情源码2-东方仙盟

发布时间:2026/8/9 1:14:27
商家自动化任务自动分析短信重要事情源码2-东方仙盟 短信代码分析package com.fairyalliance.smartanswer; import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.provider.Telephony; import android.util.Log; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Locale; import CyberWinPHP.Cyber_CPU.Cyber_Public_Var; import java.util.regex.Matcher; // 规则实体【修正增加level】 class SmsRuleItem { public String data_id; //规则id public ListString numberRegexList; public ListString bodyRegexList; /** 预警紧急等级 */ public int level; //2026-06-08-08 public ListString Extractreglist; } // 短信输出记录实体 class SmsRecordItem { public String smsAddress; public String smsBody; public long smsDateTs; public int level; /** 预警紧急等级 */ public String rule_id; //规则id } /** * 独立静态短信规则短信读取工具模块 * 【注意】本类仅做纯数据处理不启动后台、不注册广播上层Activity/Service负责调用、权限申请、网络请求、后台保活 */ public final class CyberWinEnterpriseAutoSmsRuleHelper { private static final String TAG cwSmsRuleHelper; public static final Gson GSON new Gson(); // 全局静态变量内存中保存服务器下发全部规则 public static ListSmsRuleItem GLOBAL_SMS_RULES new ArrayList(); private CyberWinEnterpriseAutoSmsRuleHelper() { // 禁止实例化纯静态类 } /** * 函数1从服务器下载并加载规则到全局静态变量 GLOBAL_SMS_RULES * param localHttpApi 接口地址 */ public static void loadRuleFromServer(String localHttpApi) { new Thread(() - { try { //规整本地标准时间 SimpleDateFormat dateFormat new SimpleDateFormat(yyyy-MM-dd HH:mm:ss, Locale.getDefault()); String nowTime dateFormat.format(System.currentTimeMillis()); //替换填写你本地电脑内网固定IP你搭建好的接口路径例http://192.168.1.105:8080/callnotify //原生GET请求携带来电号码时间两个参数推送到本地服务 URL url new URL(localHttpApi client_timenowTimemer_id77store_id72eco_typephonecall); HttpURLConnection conn (HttpURLConnection) url.openConnection(); conn.setRequestMethod(GET); conn.setConnectTimeout(3000); int code conn.getResponseCode(); writelog(本地推送,下载规则,时间nowTime返回状态码code); String responseBody ; InputStream is null; try { if(code 200 code 300){ is conn.getInputStream(); }else{ is conn.getErrorStream(); // 错误状态码拿错误流 } // 流转字符串 BufferedReader br new BufferedReader(new InputStreamReader(is,UTF-8)); StringBuilder sb new StringBuilder(); String line; while ((line br.readLine()) ! null) { sb.append(line); } responseBody sb.toString(); br.close(); writelog(本地推送,下载规则,时间nowTime返回数据responseBody); loadRuleFromServerJson(responseBody); } finally { conn.disconnect(); } } catch (Exception e) { writelog(本地推送,失败下载规则,推送本地服务异常e.getMessage()); } }).start(); } /** * 函数1从服务器下载并加载规则到全局静态变量 GLOBAL_SMS_RULES * param jsonStr 服务器返回完整JSON字符串 * return true解析成功false解析失败 */ public static boolean loadRuleFromServerJson(String jsonStr) { if (jsonStr null || jsonStr.trim().isEmpty()) { Log.e(TAG, loadRuleFromServerJson: json为空); writelog(本地推送,loadRule,数据json为空jsonStr); return false; } try { Type listType new TypeTokenListSmsRuleItem() {}.getType(); ListSmsRuleItem tempList GSON.fromJson(jsonStr, listType); if(tempList null){ return false; } // 赋值给全局静态变量 GLOBAL_SMS_RULES.clear(); GLOBAL_SMS_RULES.addAll(tempList); writelog(本地推送,loadRule,共 GLOBAL_SMS_RULES.size() 条规则); // Log.i(TAG, 加载规则完成共 GLOBAL_SMS_RULES.size() 条规则); return true; } catch (Exception e) { // Log.e(TAG, 解析规则JSON异常, e); writelog(本地推送,loadRule,解析规则JSON异常 e.getMessage() ); return false; } } /** * 函数2读取短信按【时间区间最大读取条数】读取倒序最新短信优先 * * param context 上下文需要READ_SMS权限 * param maxReadCount 最多读取多少条例如300传0代表不限制条数 * param startTimeTs 开始时间戳(毫秒)传null不限制开始从现在往前读 * param endTimeTs 结束时间戳(毫秒)传null不限制结束 * return 原始读取到的短信列表未过滤原始全部短信rule_id/level字段为空 */ public static ListSmsRecordItem readSmsList(Context context, int maxReadCount, Long startTimeTs, Long endTimeTs) { ListSmsRecordItem result new ArrayList(); ContentResolver resolver context.getContentResolver(); Uri smsUri Telephony.Sms.CONTENT_URI; // 查询字段 String[] projection { Telephony.Sms.ADDRESS, Telephony.Sms.BODY, Telephony.Sms.DATE }; // where条件拼装时间过滤 StringBuilder whereSb new StringBuilder(); ListString whereArgsList new ArrayList(); if(startTimeTs ! null){ whereSb.append(Telephony.Sms.DATE).append( ? ); whereArgsList.add(String.valueOf(startTimeTs)); } if(endTimeTs ! null){ if(whereSb.length()0){ whereSb.append( AND ); } whereSb.append(Telephony.Sms.DATE).append( ? ); whereArgsList.add(String.valueOf(endTimeTs)); } String selection whereSb.length()0 ? whereSb.toString() : null; String[] selectionArgs whereArgsList.isEmpty() ? null : whereArgsList.toArray(new String[0]); // ORDER BY date DESC最新短信排在最前面 String sortOrder Telephony.Sms.DATE DESC; Cursor cursor null; try { cursor resolver.query(smsUri, projection, selection, selectionArgs, sortOrder); if(cursor null){ return result; } int idxAddr cursor.getColumnIndex(Telephony.Sms.ADDRESS); int idxBody cursor.getColumnIndex(Telephony.Sms.BODY); int idxDate cursor.getColumnIndex(Telephony.Sms.DATE); while (cursor.moveToNext()){ // 达到最大读取条数直接退出循环 if(maxReadCount 0 result.size() maxReadCount){ break; } SmsRecordItem item new SmsRecordItem(); item.smsAddress cursor.getString(idxAddr); item.smsBody cursor.getString(idxBody); item.smsDateTs cursor.getLong(idxDate); //原始读取level、rule_id为空匹配之后才填充 item.level 0; item.rule_id null; result.add(item); } } catch (Exception e) { // Log.e(TAG,读取短信数据库异常,e); writelog(本地推送,readSmsList,读取短信数据库异常 e.getMessage() ); } finally { if(cursor ! null){ cursor.close(); } } return result; } /** * 附加工具方法使用【全局GLOBAL_SMS_RULES】对短信做正则匹配过滤 * 输入原始短信列表输出命中规则的完整SmsRecordItem回填rule_id、level * 一条短信命中多条规则返回多条记录 * param rawSmsList readSmsList返回原始短信 * return 命中结果列表每条携带rule_id、level可直接Gson序列化上传服务器 */ public static ListSmsRecordItem filterSmsByGlobalRule(ListSmsRecordItem rawSmsList){ ListSmsRecordItem out new ArrayList(); if(rawSmsList null || rawSmsList.isEmpty()){ // writelog(本地推送,过滤,短信为空 ); return out; } // writelog(本地推送,过滤,短信有数据 ); for(SmsRecordItem rawSms : rawSmsList){ //writelog(本地推送,过滤,号码: rawSms.smsAddress); int ruleCount 0; //匹配成功的正则数量 for(SmsRuleItem rule : GLOBAL_SMS_RULES){ // writelog(本地推送,s规则,number: .GSON.toJson(rule.numberRegexList)); // writelog(本地推送,s规则,body: GSON.toJson(rawSms.bodyRegexList)); //规则校验两个列表同时为空直接跳过该规则 boolean numListEmpty (rule.numberRegexList null || rule.numberRegexList.isEmpty()); boolean bodyListEmpty (rule.bodyRegexList null || rule.bodyRegexList.isEmpty()); ruleCount ruleCount 1; writelog(本地推送,s2规则,判断bodyListEmpty,原始: GSON.toJson(rule.bodyRegexList)numListEmptynumListEmpty,GSON.toJson(rule.numberRegexList)); String res判断规则ruleCount条 ; if(numListEmpty bodyListEmpty){ res判断 res判断 同时为空; } if(numListEmpty bodyListEmpty){ // writelog(本地推送,s规则,无规则 ); continue; } boolean matchNumber false; if(!numListEmpty){ // matchNumber matchAnyRegexOne(rawSms.smsAddress, rule.numberRegexList); matchNumber matchAnyRegexALL(rawSms.smsAddress, rule.numberRegexList); //matchAnyRegexALL } boolean matchBody false; if(!bodyListEmpty){ matchBody matchAnyRegexALL(rawSms.smsBody, rule.bodyRegexList); } //核心逻辑(号码非空且命中) OR (正文非空且命中) boolean ruleHit false; if(!numListEmpty matchNumber){ ruleHit true; } if(!bodyListEmpty matchBody){ ruleHit true; } //2026-08-08 同时满足 if(!bodyListEmpty !numListEmpty){ res判断 res判断 同时非空ruleHitruleHit; //非空 要求全部满足 if(matchNumber matchBody){ ruleHit true; }else{ ruleHit false; } res判断 res判断 同时非空后ruleHitruleHit; } writelog(本地推送,s2规则,res判断); if(ruleHit){ //复制一份对象回填规则id与等级不要修改原始对象 SmsRecordItem hitItem new SmsRecordItem(); hitItem.smsAddress rawSms.smsAddress; hitItem.smsBody rawSms.smsBody; hitItem.smsDateTs rawSms.smsDateTs; hitItem.rule_id rule.data_id; hitItem.level rule.level; out.add(hitItem); //❗不break允许一条短信命中多条不同规则 } } } return out; } /** * 工具判断文本是否匹配列表中**任意一条正则** */ private static boolean matchAnyRegexOne(String text, ListString regexList){ if(text null || regexList null || regexList.isEmpty()){ return false; } for(String reg : regexList){ try{ // 仅当首尾都是斜杠才剥离PHP定界符干净正则原样使用 String realReg reg; if (realReg.startsWith(/) realReg.endsWith(/)) { realReg realReg.substring(1, realReg.length() - 1); } if(Pattern.compile(realReg).matcher(text).find()){ return true; } }catch (Exception e){ // Log.w(TAG,正则表达式错误reg,e); writelog(本地推送,matchAnyRegexOne,正则表达式错误 reg ); } } return false; } /** * 且逻辑所有【非空】正则项全部匹配成功才返回true * 空字符串直接跳过不计入有效数量正则异常直接返回false */ private static boolean matchAnyRegexALL(String text, ListString regexList){ if(text null || regexList null || regexList.isEmpty()){ return false; } int validCount 0; //有效、非空的正则数量 int hitCount 0; //匹配成功的正则数量 for(String reg : regexList){ //过滤空字符串直接跳过不参与运算 if(reg null || reg.trim().length() 0){ continue; } validCount ; try{ String realReg reg; //兼容PHP旧的首尾定界符/ if (realReg.startsWith(/) realReg.endsWith(/)) { realReg realReg.substring(1, realReg.length() - 1); } boolean hit Pattern.compile(realReg).matcher(text).find(); if(hit){ hitCount; }else{ //任意一条有效正则匹配失败直接整体失败 return false; } }catch (Exception e){ writelog(本地推送,matchAnyRegexALL,正则表达式错误 reg ); //正则编译异常直接判定不通过 return false; } } //必须存在有效正则并且成功数等于全部有效正则 return validCount 0 hitCount validCount; } // 日志占位你原有writelog保留 // private static void writelog(String tag1, String tag2, String msg){ // Log.d(writelog, tag1|tag2|msg); //} private static void writelog(String type, String name, String msg) { try { CyberWinLogToFile.init( Cyber_Public_Var.cyber_main_instance); // 1. 时间格式化yyyy-MM-dd HH:mm:ss // SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss, Locale.getDefault()); // String time sdf.format(new Date()); // 2. 日志内容 // String logContent time | type | name | msg \n; String logContent type | name | msg \n; CyberWinLogToFile.d_windows(type,name,logContent); } catch (Exception e) { // 不处理避免崩溃 } } }一、整体架构设计优点职责边界清晰单一职责原则该类为final 纯静态工具类构造函数私有禁止实例化只负责短信读取、规则解析、正则匹配数据处理。不做权限申请、不注册广播、不启动 Service 保活把平台相关操作全部交给上层调用方解耦做得很好模块可复用更换上层业务组件无需改动本工具代码。实体类拆分合理单独定义SmsRuleItem规则实体、SmsRecordItem短信记录实体规则实体扩展level预警等级、Extractreglist提取正则业务字段和数据模型一一对应JSON 序列化反序列化直接适配方便后续上传上报。全局内存缓存规则使用静态集合GLOBAL_SMS_RULES内存缓存服务器下发规则不需要每次匹配都走网络 / 磁盘 IO上层只需要调用一次下载接口后续大量短信匹配直接读取内存性能高。二、网络下载规则模块优点网络请求隔离子线程loadRuleFromServer内部新建 Thread 执行 GET 网络请求严格避免主线程网络异常崩溃符合 Android 网络开发规范。异常流兼容处理HTTP 状态码非 2xx 时不取getInputStream()改用getErrorStream()读取服务端错误返回不会直接抛出流关闭异常可以拿到服务端报错内容用于排查。入参校验完备loadRuleFromServerJson对空 JSON、空白字符串做前置拦截Gson 解析做异常捕获解析失败返回布尔值给上层上层可以做重试逻辑。携带业务参数请求接口附带客户端时间、商户 ID、门店 ID、业务类型方便服务端做日志排查、多租户区分。三、短信数据库读取模块优点时间区间过滤查询动态拼装 SQLite where 条件支持起止时间戳筛选短信不用全量读取全部短信库减少内存占用支持最大读取条数限制防止一次性加载上千条短信造成 OOM 内存溢出。倒序查询sortOrder date DESC优先拿到最新收到的短信符合业务预警场景。Cursor 健壮处理判空 cursorfinally 块强制关闭游标杜绝 SQLite 游标泄漏读取列优先用getColumnIndex()获取下标不硬编码索引系统字段变更也不会数组越界。原始数据隔离读取出来的SmsRecordItem只填充短信原始信息level、rule_id 初始置空匹配规则之后复制新对象回填不会污染原始短信数据。四、正则匹配核心逻辑优点两套正则匹配函数区分语义matchAnyRegexOne或逻辑列表中任意一条正则命中即成功matchAnyRegexALL且逻辑列表所有有效正则必须全部命中才返回 true 两个方法职责完全分开适配两种业务规则场景。兼容 PHP 正则定界符自动识别并剥离正则首尾/符号服务端 PHP 直接下发原生正则字符串不用服务端额外做格式转换前后端对接更方便。过滤空正则matchAnyRegexALL自动跳过集合内空字符串正则空项不参与运算避免配置脏数据导致匹配失效。异常防护正则编译失败捕获异常不会直接崩溃正则出错直接返回 false跳过这条规则。规则逻辑完备号码列表、正文列表同时为空的规则直接跳过过滤无效脏规则号码、正文列表其中一个为空只校验非空那一侧两者同时非空时强制要求号码 正文全部命中才算规则命中业务逻辑可控。支持一条短信命中多条规则命中后不 break 循环复制新对象输出多条记录不会出现只匹配第一条规则丢失预警的问题。五、日志与稳定性优点全链路埋点日志网络下载、JSON 解析、短信读取、正则匹配各个分支都写入日志便于线上排查规则有没有下载成功、多少条规则、正则报错、读取短信异常都可以追溯。日志写入做 try‑catch 保护写入文件日志全部包裹异常捕获就算日志组件初始化失败不会打断业务主流程不会造成 App 崩溃。大量异常捕获网络、数据库、Gson 解析、正则编译全部捕获 Exception工具类内部吞异常输出日志把错误交给上层日志工具本身不会导致应用闪退。六、扩展性优点规则实体预留Extractreglist提取正则字段后续可以直接扩展短信内容提取逻辑不需要大改现有代码。预警 level 等级字段已经落地上层可以根据等级做分级告警区分普通、紧急预警。返回实体直接支持 Gson 序列化拿到filterSmsByGlobalRule输出集合直接 toJson 即可上传给服务器。所有对外方法都是 public static上层 Service/Activity 都可以直接调用接入成本低。人人皆为创造者共创方能共成长每个人都是使用者也是创造者是数字世界的消费者更是价值的生产者与分享者。在智能时代的浪潮里单打独斗的发展模式早已落幕唯有开放连接、创意共创、利益共享才能让个体价值汇聚成生态合力让技术与创意双向奔赴实现平台与伙伴的快速成长、共赢致远。原创永久分成共赴星辰大海原创创意共创、永久收益分成是东方仙盟始终坚守的核心理念。我们坚信每一份原创智慧都值得被尊重与回馈以永久分成锚定共创初心让创意者长期享有价值红利携手万千伙伴向着科技星辰大海笃定前行拥抱硅基 生命与数字智能交融的未来共筑跨越时代的数字文明共同体。东方仙盟拥抱知识开源共筑数字新生态在全球化与数字化浪潮中东方仙盟始终秉持开放协作、知识共享的理念积极拥抱开源技术与开放标准。我们相信唯有打破技术壁垒、汇聚全球智慧才能真正推动行业的可持续发展。开源赋能中小商户通过将前端异常检测、跨系统数据互联等核心能力开源化东方仙盟为全球中小商户提供了低成本、高可靠的技术解决方案让更多商家能够平等享受数字转型的红利。共建行业标准我们积极参与国际技术社区与全球开发者、合作伙伴共同制定开放协议 与技术规范推动跨境零售、文旅、餐饮等多业态的系统互联互通构建更加公平、高效的数字生态。知识普惠共促发展通过开源社区 、技术文档与培训体系东方仙盟致力于将前沿技术转化为可落地的行业实践赋能全球合作伙伴共同培育创新人才推动数字经济 的普惠式增长阿雪技术观在科技发展浪潮中我们不妨积极投身技术共享。不满足于做受益者更要主动担当贡献者 。无论是分享代码、撰写技术博客还是参与开源项目 维护改进每一个微小举动都可能蕴含推动技术进步的巨大能量。东方仙盟是汇聚力量的天地我们携手在此探索硅基 生命为科技进步添砖加瓦。Hey folks, in this wild tech - driven world, why not dive headfirst into the whole tech - sharing scene? Dont just be the one reaping all the benefits; step up and be a contributor too. Whether youre tossing out your code snippets , hammering out some tech blogs, or getting your hands dirty with maintaining and sprucing up open - source projects, every little thing you do might just end up being a massive force that pushes tech forward. And guess what? The Eastern FairyAlliance is this awesome place where we all come together. Were gonna team up and explore the whole silicon - based life thing, and in the process, well be fueling the growth of technology