前言
开发过程中,碰到异常崩溃什么的都是无可避免的,这里介绍一种记录方法:将异常捕获并以钉钉消息的形式发送到钉钉聊天群;
自定义机器人
一、获取自定义机器人webhook
在机器人管理页面选择“自定义”机器人,输入机器人名字并选择要发送消息的群。
1、进入群聊天设置
2、找到群机器人入口
3、找到自定义机器人,并添加
4、命名机器人、选择要消息接收群
5、获得这个机器人对应的Webhook地址
格式如下所示
https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxxxxxx
二、使用机器人
获取到Webhook地址后,就可以使用任何方式向这个地址发起HTTP POST 请求,实现给我们想要告知的群组发送消息。当前自定义机器人支持文本(text)、连接(link)、markdown(markdown)三种消息类型,大家可以根据自己的需求选择合适的消息类型
下面是官网定义的消息格式
{
"msgtype": "text",
"text": {
"content": "我就是我, @1825718XXXX 是不一样的烟火" //被@人的手机号
},
"at": {
"atMobiles": [
"1825718XXXX"
],
"isAtAll": false //@所有人时:true,否则为:false
}
}
自定义机器人发送消息时,可以通过手机号码指定“被@人列表”。在“被@人列表”里面的人员,在收到该消息时,会有@消息提醒(免打扰会话仍然通知提醒,首屏出现“有人@你”)
异常捕获工具类
public class CrashUtils implements UncaughtExceptionHandler {
private UncaughtExceptionHandler exceptionHandler;
public CrashUtils() {
exceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
writeToFile(
writer.toString() + "\n" + thread.getName() + "\n"
+ thread.toString(), FileUtils.getCrashSavePath());
exceptionHandler.uncaughtException(thread, ex);
}
private void writeToFile(String stacktrace, String filename) {
ErrorInfoBean infoBean = new ErrorInfoBean(UsersCache.getInstance().getPhone(),
SystemUtils.getDeviceModel(), AppUtils.getVersion(MyApplication.getInstance()),
TimeUtils.getCurData(), "APP Crash Info:\n" + stacktrace, SPUtil.newInstance(MyApplication.getInstance()).getString(AppConstants.REQUEST_INFO));
try {
File targetFile = new File(filename);
if (!targetFile.exists()) {
targetFile.createNewFile();
}
if (targetFile.exists()) {
try {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_UNMOUNTED)) {
return;
}
FileWriter fileWriter = new FileWriter(targetFile);
BufferedWriter bos = new BufferedWriter(fileWriter);
bos.write(infoBean.toString());
// bos.write(android.os.Build.VERSION.SDK_INT + "\n");
// bos.write(android.os.Build.MODEL + "\n");
// bos.write("APP :" + SystemUtils.getVersionName() + "\n");
// bos.write("time :"
// + DateFormat.format("yyyy-MM-dd kk:mm:ss",
// new Date(System.currentTimeMillis())) + "\n");
// bos.write(stacktrace);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* {
* "msgtype": "text",
* "text": {
* "content": "我就是我, @1825718XXXX 是不一样的烟火"
* }
* }
*
* @param stacktrace
*/
public static void sendDingDing(String stacktrace) {
JSONObject reqBody = new JSONObject();
reqBody.put("accessToken", "429670b34acbe67723ea19be29ea2801f23b9eaf2900033bcf5874e400b18cf3");
reqBody.put("content", stacktrace);
ApiClient.requestService.sendDing(NetworkUtils.getRequestBody(reqBody.toString()))
.compose(RxSchedulerUtils.normalSchedulersTransformer())
.subscribe(new BaseSubscriber<SimpleResult>() {
@Override
public void onSuccess(SimpleResult entity) {
LogUtils.logd(entity.getData());
}
@Override
public void onFailure(SimpleResult entity, int errCode, String errMsg) {
}
});
}
}
在Subscriber抛出错误的地方调用发送的方法
public abstract class BaseSubscriber<T> extends Subscriber<T> {
@Override
public void onStart() {
super.onStart();
if (!NetworkUtils.isNetworkConnected(MyApplication.getInstance())) {
if (!isUnsubscribed()) {
unsubscribe();
}
onFailure(null, 0, MyApplication.getInstance().getString(R.string.no_network));
}
}
@Override
public void onCompleted() {
}
@Override
public void onNext(T t) {
if (t == null) {
onFailure(null, 0, MyApplication.getInstance().getString(R.string.no_network));
return;
}
onSuccess(t);
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
FileUtils.saveLog(e.toString());
ErrorInfoBean infoBean = new ErrorInfoBean(UsersCache.getInstance().getPhone(),
SystemUtils.getDeviceModel(), AppUtils.getVersion(MyApplication.getInstance()),
TimeUtils.getCurData(), e.toString(), SPUtil.newInstance(MyApplication.getInstance()).getString(AppConstants.REQUEST_INFO));
CrashUtils.sendDingDing(infoBean.toString()); //发送给钉钉
}
public abstract void onSuccess(T result);
public abstract void onFailure(T result, int errCode, String errMsg);
}
这样就算接入成功了,可以在群消息里接收你的错误日志了