Android 封装Log工具并上传Log文件到服务器(带类名、方法名、行数、Crash的捕捉)
然后我们根据需求来划分Log等级,一般都为 debug<info<warning<error<crash
并提供对外的打印方法。
注:这里的等级划分、和打印方法所要的信息都是跟着需求来。但是都是大同小异。我这里多写什么信息,打印方法也只留最基本的
/**
Log的分级为 Crash、Error、Warning、Info、Debug*/
public static final String CRASH_LEVEL = “CRASH”;
public static final String ERROR_LEVEL = “ERROR”;
public static final String WARNING_LEVEL = “WARNING”;
public static final String INFO_LEVEL = “INFO”;
public static final String DEBUG_LEVEL = “DEBUG”;
public void c(String logData) {
writeToFile(CRASH_LEVEL, logData);
}
public void e(String logData) {
writeToFile(ERROR_LEVEL, logData);
}
public void w(String logData) {
writeToFile(WARNING_LEVEL, logData);
}
public void i(String logData) {
writeToFile(INFO_LEVEL, type, logData);
}
public void d(String logData) {
writeToFile(DEBUG_LEVEL, logData);
}
witeTofile就是写入到文件的方法:
private static StackTraceElement getCallerStackTraceElement() {
return Thread.currentThread().getStackTrace()[5];
}
/**
将Log信息写入文件
isDouble为是否连续两次写入,防止连续两次上传服务器。
@param level
@param type
@param logData
*/
public static void writeToFile(String level, String logData) {
if (null == logPath) {
LogUtil.e(TAG, “logPath == null ,未初始化LogToFile”);
return;
}
String fileName = logPath + “/AppLogs_Android.log”;
StackTraceElement caller = getCallerStackTraceElement();
// 获取到类名
String callerClazzName = caller.getClassName();
callerClazzName = callerClazzName.substring(callerClazzName
.lastIndexOf(“.”) + 1);
//要写入的LOG内容
String log = type + " - " + callerClazzName + " - " + caller.getMethodName() + " - line " + caller.getLineNumber() + " - " + logData + “\n”;
LogUtil.d(TAG, log);
//如果父路径不存在
File file = new File(logPath);
if (!file.exists()) {
}
FileOutputStream fos = null;
BufferedWriter bw = null;
try {
fos = new FileOutputStream(fileName, true);
bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write(log);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bw != null) {
bw.close();//关闭缓冲流
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (getLogsFileSize(fileName) >= 1f) {
sendToServer(fileName);
} else if (level == CRASH_LEVEL || level == ERROR_LEVEL || level == WARNING_LEVEL) {
sendToServer(fileName);
}
}
上面有一个巨顶的方法:
Thread.currentThread().getStackTrace()[5]
这行函数能够得离当前执行代码的指令。(注:不一定是5)
因为在执行命令时,指令栈保存当前线程最近执行的代码。
它的原理是这样的:
1、MainActivity : LogTool.d(xxx,xxx)
跳转-》
2、LogTool: d(xxx,xx){wirteToFile(xxx,xxx)}
跳转-》
3、LogTool:writeToFile(xxx){}
假如上面是一个指令栈,那么我就去获取这个栈的栈底元素 [1] MainActivity… 这一行,得到的是个StackTraceElement 对象。
得到该对象之后,我们可以将该指令反射,通过getClassName()获取类名,通过getMethodName()获取方法名、通过getLineNumber()获取当前行数,就省的我们一步一步去找具体哪行了。
所以上面代码中的第5行只是我这边的情况,别的代码就要自己去推理具体在哪一行咯。
接下来就是上传到服务器,这里使用Okhttp,上传的格式是包括文件+一些附带String信息,所以使用mutIPart来提交表单,并且开启一个线程来提交。
/**
@return
*/
public static void sendToServer(final String pathName) {
new Thread(new Runnable() {
@Override
public void run() {
final File file = new File(pathName);
MediaType MEDIA_TYPE_TXT = MediaType.parse(“text/plain”);
RequestBody fileBody = MultIPartBody.create(MEDIA_TYPE_TXT, file);
MultIPartBody multiBuilder = new MultIPartBody.Builder()
.setType(MultIPartBody.FORM)
.addFormDataPart(“log_file”, file.getName(), fileBody)
.addFormDataPart(“system”, “Android”)
.addFormDataPart(“phone_number”, “110”).build();
Request request = new Request.Builder().url(APIUrl).post(multiBuilder).build();
OkHttpClient okHttpClient = new OkHttpClient();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败的处理
LogUtil.e(TAG, "上传Log文件失败 : " + e.toString());
if (getLogsFileSize(pathName) > 1f) {
file.delete();
}
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功的处理
LogUtil.d(TAG, "上传Log文件成功 : " + response.body().string());
//清空文件
file.delete();
}
});
}
}).start();
}
到这里就上传完啦。
但是我们还没有关注Crash的捕捉,因为我们自己无法判断Crash是出现在什么地方的,所以我们要写一个全局的Crash捕捉器,而Android提供了这个类,叫:Thread.UncaughtExceptionHandler,我们通过实现该接口,重写uncaughtException()方法,来处理遇到异常的情况。
该类如下(也需要在App初始化时init):
public class CrashHandlerManager implements Thread.UncaughtExceptionHandler {
private static final String TAG = “CrashHandlerManager”;
private static CrashHandlerManager instance;
private Context context;
private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
//收集信息集合
private Map<String, String> infoMap = new HashMap<>();
public synchronized static CrashHandlerManager getInstance() {
if (instance == null) {
instance = new CrashHandlerManager();
}
return instance;
}
private CrashHandlerManager() {
}
/**
初始化程序异常处理器
@param context
*/
public void initCrash(Context context) {
this.context = context;
//获取系统默认的UncaughtException处理器
uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
当UncaughtException发生会进入此方法
@param t
@param e
*/
@Override
public void uncaughtException(Thread t, Throwable e) {
if (!handleException(e) && uncaughtExceptionHandler != null) {
//如果自定义没有处理就交给系统去处理
uncaughtExceptionHandler.uncaughtException(t, e);
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
结语
现在随着短视频,抖音,快手的流行NDK模块开发也显得越发重要,需要这块人才的企业也越来越多,随之学习这块的人也变多了,音视频的开发,往往是比较难的,而这个比较难的技术就是NDK里面的技术。音视频/高清大图片/人工智能/直播/抖音等等这年与用户最紧密,与我们生活最相关的技术一直都在寻找最终的技术落地平台,以前是windows系统,而现在则是移动系统了,移动系统中又是以Android占比绝大部分为前提,所以AndroidNDK技术已经是我们必备技能了。要学习好NDK,其中的关于C/C++,jni,linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
密,与我们生活最相关的技术一直都在寻找最终的技术落地平台,以前是windows系统,而现在则是移动系统了,移动系统中又是以Android占比绝大部分为前提,所以AndroidNDK技术已经是我们必备技能了。
要学习好NDK,其中的关于C/C++,jni,linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。[外链图片转存中…(img-xhllqCgS-1712681454732)]
[外链图片转存中…(img-hPdbzlfB-1712681454732)]
Ongwu博客 版权声明:以上内容未经允许不得转载!授权事宜或对内容有异议或投诉,请联系站长,将尽快回复您,谢谢合作!