diff --git a/README.md b/README.md index 89485969..9c549508 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # SmsForwarder (短信转发器) -Android手机监听短信并根据指定规则转发到其他手机、钉钉机器人、企业微信群机器人、邮箱、bark、webhook等 +Android手机监听短信并根据指定规则转发到其他手机:钉钉机器人、企业微信群机器人、企业微信应用消息、邮箱、bark、webhook等 > ⚠ 此项目在 [xiaoyuanhost/TranspondSms](https://github.com/xiaoyuanhost/TranspondSms) 的基础上优化改造而来,感谢原作者! @@ -41,7 +41,8 @@ Android手机监听短信并根据指定规则转发到其他手机、钉钉机 - [x] 转发到邮箱(支持:SMTP) - [x] 转发到Bark(支持:验证码/动态密码自动复制) - [x] 转发到webhook(支持:单个web页面([向设置的url发送POST请求](doc/POST_WEB.md))) -- [x] 转发到企业微信群机器人(待验证) +- [x] 转发到企业微信群机器人 +- [x] 转发到企业微信应用消息 - [x] 在线检测新版本、升级 - [x] 清理缓存 - [x] 兼容6.xx、7.xx、8.xx、9.xx、10.xx @@ -50,7 +51,7 @@ Android手机监听短信并根据指定规则转发到其他手机、钉钉机 ### 使用流程: 1. 在Android手机上安装SmsForwarder 本APP后点击应用图标打开 -2. 在设置发送方页面,添加或点击已添加的发送方来设置转发短信使用的方式,现在支持钉钉机器人、企业微信群机器人、邮箱、网页、Bark: +2. 在设置发送方页面,添加或点击已添加的发送方来设置转发短信使用的方式,现在支持钉钉机器人、企业微信群机器人、企业微信应用消息、邮箱、网页、Bark: + 设置钉钉机器人请先在钉钉群中添加自定义机器人,复制机器人的token和secret,填入弹出框。点击测试会使用该机器人向群内发送一条消息;点击确认即可添加配置。 + 配置邮箱请先在你邮箱的后台管理页面配置smtp选项,并设置密码(授权码),并参照说明配置SmsForwarder弹出框的smtp信息。点击测试会使用该邮箱向配置的邮箱发送一条测试邮件;点击确认即可添加配置。 + 配置网页通知请先在 msg.allmything.com 注册登陆并添加一个消息通道,复制消息通道token填入配置弹框。点击测试会向该消息通道推送一条测试消息,可在 msg.allmything.com 的消息页面查看(页面会自动刷新);点击确认即可添加配置。 @@ -75,7 +76,7 @@ Android手机监听短信并根据指定规则转发到其他手机、钉钉机 | ![添加编辑发送方网页通知](pic/sendersetwebnotify.png "添加编辑发送方网页通知") | ![添加编辑发送方企业微信群机器人](pic/sendersetqywechat.png "添加编辑发送方企业微信群机器人") | | ![状态栏运行状态](pic/taskbar.png "状态栏运行状态") | ![应用设置](pic/setting.png "应用设置") | | ![在线升级](pic/update.png "在线升级") | ![增加卡槽标识](pic/siminfo.png "增加卡槽标识") | -| ![多重匹配规则](pic/multimatch.png "多重匹配规则") | | +| ![多重匹配规则](pic/multimatch.png "多重匹配规则")| ![转发到企业微信应用消息](pic/sendersetqywxapp.png "转发到企业微信应用消息") | -------- @@ -93,6 +94,7 @@ Android手机监听短信并根据指定规则转发到其他手机、钉钉机 + [v1.3.0](app/release/SmsForwarder_release_20210303_1.3.0.apk) 支持双卡手机,增加卡槽标识/运营商/手机号(如果能获取的话) + [v1.4.0](app/release/SmsForwarder_release_20210304_1.4.0.apk) 支持多重匹配规则 + [v1.4.1](app/release/SmsForwarder_release_20210304_1.4.1.apk) 设置中允许关闭页面帮助/表单填写提示 ++ [v1.5.0](app/release/SmsForwarder_release_20210305_1.5.0.apk) 新增转发到企业微信应用消息 ## LICENSE diff --git a/app/build.gradle b/app/build.gradle index 54711e0f..389ce829 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,8 +14,8 @@ android { applicationId "com.idormy.sms.forwarder" minSdkVersion 23 targetSdkVersion 28 - versionCode 12 - versionName "1.4.1" + versionCode 13 + versionName "1.5.0" testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' } signingConfigs { diff --git a/app/release/SmsForwarder_release_20210305_1.5.0.apk b/app/release/SmsForwarder_release_20210305_1.5.0.apk new file mode 100644 index 00000000..b70d853a Binary files /dev/null and b/app/release/SmsForwarder_release_20210305_1.5.0.apk differ diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index ad820ec1..32e33910 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -10,9 +10,9 @@ { "type": "SINGLE", "filters": [], - "versionCode": 12, - "versionName": "1.4.1", - "outputFile": "SmsForwarder_release_20210304_1.4.1.apk" + "versionCode": 13, + "versionName": "1.5.0", + "outputFile": "SmsForwarder_release_20210305_1.5.0.apk" } ] } \ No newline at end of file diff --git a/app/src/main/java/com/idormy/sms/forwarder/MyApplication.java b/app/src/main/java/com/idormy/sms/forwarder/MyApplication.java index e2aebe60..08d14386 100644 --- a/app/src/main/java/com/idormy/sms/forwarder/MyApplication.java +++ b/app/src/main/java/com/idormy/sms/forwarder/MyApplication.java @@ -26,6 +26,9 @@ public class MyApplication extends Application { public static Map SimInfo = new HashMap(); //是否关闭页面提示 public static boolean showHelpTip = true; + //企业微信 + public static String QyWxAccessToken; + public static long QyWxAccessTokenExpiresIn = 0; /** * MyApplication.QyWxAccessTokenExpiresIn) { + String gettokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?"; + gettokenUrl += "corpid=" + corpID; + gettokenUrl += "&corpsecret=" + secret; + Log.d(TAG, "gettokenUrl:" + gettokenUrl); + + OkHttpClient client = new OkHttpClient(); + final Request request = new Request.Builder().url(gettokenUrl).get().build(); + Call call = client.newCall(request); + call.enqueue(new Callback() { + @Override + public void onFailure(Call call, final IOException e) { + Log.d(TAG, "onFailure:" + e.getMessage()); + if (handError != null) { + Message msg = new Message(); + msg.what = NOTIFY; + Bundle bundle = new Bundle(); + bundle.putString("DATA", "获取access_token失败:" + e.getMessage()); + msg.setData(bundle); + handError.sendMessage(msg); + } + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + final String json = response.body().string(); + Log.d(TAG, "Code:" + response.code() + " Response: " + json); + JSONObject jsonObject = JSON.parseObject(json); + int errcode = jsonObject.getInteger("errcode"); + if (errcode == 0) { + MyApplication.QyWxAccessToken = jsonObject.getString("access_token"); + MyApplication.QyWxAccessTokenExpiresIn = System.currentTimeMillis() + (jsonObject.getInteger("expires_in") - 120) * 1000; //提前2分钟过期 + Log.d(TAG, "access_token:" + MyApplication.QyWxAccessToken); + Log.d(TAG, "expires_in:" + MyApplication.QyWxAccessTokenExpiresIn); + + sendTextMsg(handError, agentID, toUser, content); + } else { + String errmsg = jsonObject.getString("errmsg"); + Log.d(TAG, "onFailure:" + errmsg); + if (handError != null) { + Message msg = new Message(); + msg.what = NOTIFY; + Bundle bundle = new Bundle(); + bundle.putString("DATA", "获取access_token失败:" + errmsg); + msg.setData(bundle); + handError.sendMessage(msg); + } + } + } + + }); + } else { + sendTextMsg(handError, agentID, toUser, content); + } + + } + + //发送文本消息 + public static void sendTextMsg(final Handler handError, String agentID, String toUser, String content) { + String sendUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + MyApplication.QyWxAccessToken; + Log.d(TAG, "sendUrl:" + sendUrl); + + Map textMsgMap = new HashMap(); + textMsgMap.put("touser", toUser); + textMsgMap.put("msgtype", "text"); + textMsgMap.put("agentid", agentID); + + Map textText = new HashMap(); + textText.put("content", content); + textMsgMap.put("text", textText); + + String textMsg = JSON.toJSONString(textMsgMap); + Log.d(TAG, "textMsg:" + textMsg); + + OkHttpClient client = new OkHttpClient(); + RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), textMsg); + + final Request request = new Request.Builder() + .url(sendUrl) + .addHeader("Content-Type", "application/json; charset=utf-8") + .post(requestBody) + .build(); + Call call = client.newCall(request); + call.enqueue(new Callback() { + @Override + public void onFailure(Call call, final IOException e) { + Log.d(TAG, "onFailure:" + e.getMessage()); + if (handError != null) { + android.os.Message msg = new android.os.Message(); + msg.what = NOTIFY; + Bundle bundle = new Bundle(); + bundle.putString("DATA", "发送失败:" + e.getMessage()); + msg.setData(bundle); + handError.sendMessage(msg); + } + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + final String responseStr = response.body().string(); + Log.d(TAG, "Code:" + String.valueOf(response.code()) + " Response: " + responseStr); + + if (handError != null) { + android.os.Message msg = new android.os.Message(); + msg.what = NOTIFY; + Bundle bundle = new Bundle(); + bundle.putString("DATA", "发送状态:" + responseStr); + msg.setData(bundle); + handError.sendMessage(msg); + Log.d(TAG, "Code:" + String.valueOf(response.code()) + " Response: " + responseStr); + } + + } + }); + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_alter_dialog_setview_qywxapp.xml b/app/src/main/res/layout/activity_alter_dialog_setview_qywxapp.xml new file mode 100644 index 00000000..e392acfc --- /dev/null +++ b/app/src/main/res/layout/activity_alter_dialog_setview_qywxapp.xml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +