概述
/**
- 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()) {
file.mkdirs();//创建父路径
}
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){}
假如上面是一个指令栈,那么我就去获取这个栈
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
的栈底元素 [1] MainActivity… 这一行,得到的是个StackTraceElement
对象。
得到该对象之后,我们可以将该指令反射,通过getClassName()
获取类名,通过getMethodName()
获取方法名、通过getLineNumber()
获取当前行数,就省的我们一步一步去找具体哪行了。
所以上面代码中的第5行只是我这边的情况,别的代码就要自己去推理具体在哪一行咯。
接下来就是上传到服务器,这里使用Okhttp,上传的格式是包括文件+一些附带String信息,所以使用mutipart来提交表单,并且开启一个线程来提交。
/**
-
上传Log文件至服务器
-
@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();
//设置该CrashHandler为程序得默认处理器
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);
}
}
private boolean handleException(Throwable e) {
if (e == null) {
return false;
}
collectionDeviceInfo(context, e.toString());
return true;
}
/**
-
收集错误处理信息
-
@param context
-
@param e
*/
private void collectionDeviceInfo(Context context, String e) {
//获得包管理器
try {
PackageManager pm = context.getPackageManager();
//获取该应用信息
最后
以上就是妩媚鞋子为你收集整理的Android 封装Log工具并上传Log文件到服务器(带类名、方法名的全部内容,希望文章能够帮你解决Android 封装Log工具并上传Log文件到服务器(带类名、方法名所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复