HrLogUtil 低成本邮件发送日志 和 快速埋点 功能
HrLogUtilHrLogUtil 是一个 Android 平台的日志记录工具库。主要解决低成本邮件发送日志和快速埋点功能https://github.com/shaoweijie/hr-log 急需Github上的star多谢各位基础功能特性埋点功能支持自动埋点记录用户交互行为。视图级别弹窗必须采用ASM方式日志上传支持将日志通过邮件发送。日志级别支持支持 VERBOSE、INFO、DEBUG、WARNING、ERROR 等日志级别。日志输出方式支持控制台输出和文件输出。日志文件管理支持日志文件的自动写入、压缩和邮件发送。崩溃捕获自动捕获未处理的异常并记录日志。生命周期日志记录 Activity 的生命周期事件。使用方法依赖应用级别的build.gradle中添加android{//...// 排除sum mail中的META-INF文件packagingOptions{jniLibs{excludes[META-INF/*]}resources{excludes[project.properties,META-INF/*]}}}dependencies{//...implementationcom.sun.mail:android-mail:1.6.7implementationcom.sun.mail:android-activation:1.6.7implementationcom.gitee.Hancher:hrlog:1.0.2}初始化在 Application 的 onCreate 中初始化日志记录功能日志文件大小限制MAX_FILE_SIZE定义单个日志文件的最大大小。最大文件数量MAX_FILE_COUNT定义保留的日志文件最大数量。邮件配置通过SEND_MAIL,SEND_SMTP,SEND_PSW配置邮件发送参数。HrLogUtil.IS_WRITE_TO_FILEtrue;//默认写入文件HrLogUtil.MAX_FILE_COUNT10;//默认保留10个日志文件HrLogUtil.MAX_FILE_SIZE50*1024*1024;//默认单个日志文件最大50MHrLogUtil.initWriteToFile(context,your_emailexample.com,smtp.example.com,password);日志记录支持多种日志级别HrLogUtil.d();HrLogUtil.v(Verbose message);HrLogUtil.i(Info message);HrLogUtil.d(Debug message);HrLogUtil.w(Warning message);HrLogUtil.e(Error message);日志如下2026-08-06 16:38:22.749 11235-11235 HrLogUtil com.hancher.plugin D (MainActivity.java:16) onCreate(): 2026-08-06 16:38:22.749 11235-11235 HrLogUtil com.hancher.plugin V (MainActivity.java:17) onCreate(): Verbose message 2026-08-06 16:38:22.749 11235-11235 HrLogUtil com.hancher.plugin I (MainActivity.java:18) onCreate(): Info message 2026-08-06 16:38:22.749 11235-11235 HrLogUtil com.hancher.plugin D (MainActivity.java:19) onCreate(): Debug message 2026-08-06 16:38:22.749 11235-11235 HrLogUtil com.hancher.plugin W (MainActivity.java:20) onCreate(): Warning message 2026-08-06 16:38:22.749 11235-11235 HrLogUtil com.hancher.plugin E (MainActivity.java:21) onCreate(): Error message折叠后16:40:30.231 D (MainActivity.java:16) onCreate(): 16:40:30.231 V (MainActivity.java:17) onCreate(): Verbose message 16:40:30.231 I (MainActivity.java:18) onCreate(): Info message 16:40:30.231 D (MainActivity.java:19) onCreate(): Debug message 16:40:30.231 W (MainActivity.java:20) onCreate(): Warning message 16:40:30.231 E (MainActivity.java:21) onCreate(): Error message崩溃捕获无需配置自动捕获未处理的异常折叠前2026-08-06 17:07:36.296 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): Test 2026-08-06 17:07:36.306 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): com.hancher.plugins.MainActivity.lambda$onCreate$0(MainActivity.java:28) 2026-08-06 17:07:36.314 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): com.hancher.plugins.MainActivity$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0) 2026-08-06 17:07:36.323 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): android.os.Handler.handleCallback(Handler.java:942) 2026-08-06 17:07:36.328 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): android.os.Handler.dispatchMessage(Handler.java:99) 2026-08-06 17:07:36.333 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): android.os.Looper.loopOnce(Looper.java:240) 2026-08-06 17:07:36.337 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): android.os.Looper.loop(Looper.java:351) 2026-08-06 17:07:36.340 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): android.app.ActivityThread.main(ActivityThread.java:8422) 2026-08-06 17:07:36.343 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): java.lang.reflect.Method.invoke(Native Method) 2026-08-06 17:07:36.346 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584) 2026-08-06 17:07:36.349 17194-17194 HrLogUtil com.hancher.plugin E 全埋点(异常): com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1013)折叠后16:51:16.620 E 全埋点(异常): Test 16:51:16.629 E 全埋点(异常): com.hancher.plugins.MainActivity.lambda$onCreate$0(MainActivity.java:28) 16:51:16.636 E 全埋点(异常): com.hancher.plugins.MainActivity$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0) 16:51:16.645 E 全埋点(异常): android.os.Handler.handleCallback(Handler.java:942) 16:51:16.650 E 全埋点(异常): android.os.Handler.dispatchMessage(Handler.java:99) 16:51:16.655 E 全埋点(异常): android.os.Looper.loopOnce(Looper.java:240) 16:51:16.660 E 全埋点(异常): android.os.Looper.loop(Looper.java:351) 16:51:16.664 E 全埋点(异常): android.app.ActivityThread.main(ActivityThread.java:8422) 16:51:16.668 E 全埋点(异常): java.lang.reflect.Method.invoke(Native Method) 16:51:16.671 E 全埋点(异常): com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584) 16:51:16.675 E 全埋点(异常): com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1013)生命周期日志无需配置自动记录 Activity 生命周期2026-08-06 16:49:45.178 13768-13768 HrLogUtil com.hancher.plugin D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onCreate 2026-08-06 16:49:45.403 13768-13768 HrLogUtil com.hancher.plugin D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onStart 2026-08-06 16:49:45.413 13768-13768 HrLogUtil com.hancher.plugin I 全埋点(生命周期): com.hancher.plugins.MainActivity -- onResume 2026-08-06 16:49:45.478 13768-13768 HrLogUtil com.hancher.plugin D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onPause 2026-08-06 16:49:45.485 13768-13768 HrLogUtil com.hancher.plugin D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onStop 2026-08-06 16:49:45.491 13768-13768 HrLogUtil com.hancher.plugin D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onSaveInstanceState折叠后16:49:45.178 D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onCreate 16:49:45.403 D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onStart 16:49:45.413 I 全埋点(生命周期): com.hancher.plugins.MainActivity -- onResume 16:49:45.478 D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onPause 16:49:45.485 D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onStop 16:49:45.491 D 全埋点(生命周期): com.hancher.plugins.MainActivity -- onSaveInstanceState埋点功能无需配置自动记录 View 的点击事件(无法记录弹窗中的点击事件可以不用此方案直接采用ASM方案)findViewById(R.id.main).setOnClickListener(view-{HrLogUtil.d(回调);});折叠前2026-08-06 16:58:04.541 14901-14901 HrLogUtil com.hancher.plugin V 全埋点(点击):{name:LinearLayout,id:R.id.main} 2026-08-06 16:58:04.542 14901-14901 HrLogUtil com.hancher.plugin D (MainActivity.java:18) lambda$onCreate$0(): 回调折叠后16:58:04.541 V 全埋点(点击):{name:LinearLayout,id:R.id.main} 16:58:04.542 D (MainActivity.java:18) lambda$onCreate$0(): 回调日志上传上传日志文件HrLogUtil.uploadLog(activity,邮件标题,邮件正文内容);ASM埋点gradle8.9、asm9.6gradle-wrapper.propertiesdistributionUrlhttps\://services.gradle.org/distributions/gradle-8.9-bin.zipproject build.gradlebuildscript { dependencies { classpath com.gitee.Hancher:hr-asm9-log:1.0.2 } }module build.gradleplugins { alias(libs.plugins.android.application) id com.hancher.plugins.hrasm9log } android { compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } } dependencies { // 字节码 implementation org.ow2.asm:asm:9.6 implementation org.ow2.asm:asm-commons:9.6 implementation org.ow2.asm:asm-analysis:9.6 implementation org.ow2.asm:asm-tree:9.6 implementation org.ow2.asm:asm-util:9.6 implementation com.android.tools.build:gradle:8.4.2, { exclude group:org.ow2.asm } }覆写 LogUtilcom/hancher/plugins/hrasm9log/LogUtilpackagecom.hancher.plugins.hrasm9log;importandroid.content.res.Resources;importandroid.util.Log;importandroid.view.View;importandroid.widget.TextView;publicclassHrAsmLogUtil{publicstaticvoidclick(Viewv){if(vnull){Log.d(HrLogUtil,全埋点(点击):v is null);return;}StringBufferstringBuffernewStringBuffer();Stringnamev.getClass().getName();try{namename.substring(name.lastIndexOf(.)1);}catch(Exceptione){}stringBuffer.append(类名:).append(name);if(vinstanceofTextView){TextViewb(TextView)v;stringBuffer.append(, 文本框内容:).append(b.getText().toString());}intidv.getId();if(id!View.NO_ID){finalResourcesrv.getResources();if(id0/* Resources.resourceHasPackage(id)*/r!null){try{stringBuffer.append(, 视图:).append(R.r.getResourceTypeName(id).r.getResourceEntryName(id));}catch(Resources.NotFoundExceptione){}}}Log.d(HrLogUtil,全埋点(点击):stringBuffer.toString());}}效果2025-08-12 10:10:59.703 22432-22432 HrLogUtil com.hancher.hrasm9demo D 全埋点(点击):类名:FloatingActionButton, 视图:R.id.fab 2025-08-12 10:11:03.361 22432-22432 HrLogUtil com.hancher.hrasm9demo D 全埋点(点击):类名:MaterialButton, 文本框内容:Next, 视图:R.id.button_first 2025-08-12 10:11:05.968 22432-22432 HrLogUtil com.hancher.hrasm9demo D 全埋点(点击):类名:MaterialButton, 文本框内容:Previous, 视图:R.id.button_secondgradle5.6.4、asm7.0gradle-wrapper.propertiesdistributionUrlhttps\://services.gradle.org/distributions/gradle-5.6.4-all.zipproject build.gradledependencies { classpath com.android.tools.build:gradle:3.6.3 classpath com.gitee.Hancher:hr-asm-log:1.0.0 }module build.gradleapply plugin: com.hancher.plugins.hrasmlog android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } registerTransform(new com.hancher.plugins.hrasmlog.HrAsmLogPluginProject()) } dependencies { // 字节码 implementation org.ow2.asm:asm:7.0 implementation org.ow2.asm:asm-commons:7.0 implementation org.ow2.asm:asm-tree:7.0 implementation org.ow2.asm:asm-util:7.0 implementation com.gitee.Hancher:hr-asm-log:1.0.0, { exclude group:com.android.tools exclude group:com.android.tools.build } }覆写 LogUtilcom/hancher/plugins/hrasmlog/LogUtilpackagecom.hancher.plugins.hrasmlog;importandroid.content.res.Resources;importandroid.util.Log;importandroid.view.View;importandroid.widget.TextView;publicclassLogUtil{publicstaticvoidclick(Viewv){if(vnull){Log.d(LogUtil,全埋点(点击):v is null);return;}StringBufferstringBuffernewStringBuffer();Stringnamev.getClass().getName();try{namename.substring(name.lastIndexOf(.)1);}catch(Exceptione){}stringBuffer.append(类名:).append(name);if(vinstanceofTextView){TextViewb(TextView)v;stringBuffer.append(, 文本框内容:).append(b.getText().toString());}intidv.getId();if(id!View.NO_ID){finalResourcesrv.getResources();if(id0/* Resources.resourceHasPackage(id)*/r!null){try{stringBuffer.append(, 视图:).append(R.r.getResourceTypeName(id).r.getResourceEntryName(id));}catch(Resources.NotFoundExceptione){}}}Log.d(LogUtil,全埋点(点击):stringBuffer.toString());}}效果2025-08-08 15:23:32.548 4030-4030/com.hancher.asmdemo D/LogUtil: 全埋点(点击):类名:FloatingActionButton, 视图:R.id.fab 2025-08-08 15:23:43.210 4030-4030/com.hancher.asmdemo D/LogUtil: 全埋点(点击):类名:FloatingActionButton, 视图:R.id.fab2 2025-08-08 15:23:44.725 4030-4030/com.hancher.asmdemo D/LogUtil: 全埋点(点击):类名:AppCompatButton, 文本框内容:Next, 视图:R.id.button_first 2025-08-08 15:23:49.300 4030-4030/com.hancher.asmdemo D/LogUtil: 全埋点(点击):类名:AppCompatButton, 文本框内容:Previous, 视图:R.id.button_second 2025-08-08 15:23:50.486 4030-4030/com.hancher.asmdemo D/LogUtil: 全埋点(点击):类名:AppCompatButton, 文本框内容:Next, 视图:R.id.button_first许可证本项目采用 MIT 许可证。详情请查看 LICENSE 文件。
