标签:
使用的工具:Android studio
首先,需要了解的是:
ACRA有3种方式将错误信息提交到后台:
1.邮件形式,但经过测试,发现会调用系统的邮箱进行发送到指定的邮箱,如果没有邮箱,则会报错,如果没有登陆,则要登陆才去发送,很显然,中国很少会登录邮箱的,也懒得登录去发送。第一种方式,不推荐使用。
2.以GoogleDoc形式发送到一个我也不知道怎么搭建的后台。有兴趣的可以去尝试:http://www.jianshu.com/p/fd4d6a7c6175
3.自定义发送器进行发送
这里用的是第3种方式进行提交:
第一步:
配置Gradle:
compile ‘ch.acra:acra:4.9.0‘ // 应用崩溃信息
第二步:
自定义两个类:CrashSenderFactory和CrashSender类,其中发送的内容是在CrashSender中..
package com.lanhetech.testdemo; import android.content.Context; import android.support.annotation.NonNull; import com.orhanobut.logger.Logger; import com.zhy.http.okhttp.OkHttpUtils; import com.zhy.http.okhttp.callback.Callback; import org.acra.ReportField; import org.acra.collector.CrashReportData; import org.acra.sender.ReportSender; import org.acra.sender.ReportSenderException; import okhttp3.Call; import okhttp3.Response; public class CrashSender implements ReportSender { @Override public void send(@NonNull Context context, @NonNull CrashReportData errorContent) throws ReportSenderException { // 自定义需要发送的内容到后台 OkHttpUtils.get() .url("http://h-bolin.imwork.net:14572/TestServlet/servlet/UploadServlet") .addParams("APP_VERSION_CODE", errorContent.getProperty(ReportField.APP_VERSION_CODE)) .addParams("APP_VERSION_NAME", errorContent.getProperty(ReportField.APP_VERSION_NAME)) .addParams("PACKAGE_NAME", errorContent.getProperty(ReportField.PACKAGE_NAME)) .addParams("FILE_PATH", errorContent.getProperty(ReportField.FILE_PATH)) .addParams("PHONE_MODEL", errorContent.getProperty(ReportField.PHONE_MODEL)) .addParams("ANDROID_VERSION", errorContent.getProperty(ReportField.ANDROID_VERSION)) .addParams("BUILD", errorContent.getProperty(ReportField.BUILD)) .addParams("BRAND", errorContent.getProperty(ReportField.BRAND)) .addParams("STACK_TRACE", errorContent.getProperty(ReportField.STACK_TRACE)) .addParams("STACK_TRACE_HASH", errorContent.getProperty(ReportField.STACK_TRACE_HASH)) .addParams("USER_CRASH_DATE", errorContent.getProperty(ReportField.USER_CRASH_DATE)) .addParams("DUMPSYS_MEMINFO", errorContent.getProperty(ReportField.DUMPSYS_MEMINFO)) .addParams("DEVICE_ID", errorContent.getProperty(ReportField.DEVICE_ID)) .build() .execute(new Callback() { @Override public Object parseNetworkResponse(Response response, int id) throws Exception { Logger.d("response=" + response.toString()); return null; } @Override public void onError(Call call, Exception e, int id) { } @Override public void onResponse(Object response, int id) { } }); } }
package com.lanhetech.testdemo; import android.content.Context; import android.support.annotation.NonNull; import org.acra.config.ACRAConfiguration; import org.acra.sender.ReportSender; import org.acra.sender.ReportSenderFactory; public class CrashSenderFactory implements ReportSenderFactory { @NonNull @Override public ReportSender create(@NonNull Context context, @NonNull ACRAConfiguration config) { return new CrashSender(); } }
第三步:
自定义MyApplication
package com.lanhetech.testdemo; import android.app.Application; import android.content.Context; import org.acra.ACRA; import org.acra.ReportingInteractionMode; import org.acra.annotation.ReportsCrashes; @ReportsCrashes( mode = ReportingInteractionMode.TOAST, resToastText = R.string.app_error, // 更换默认的发送器 reportSenderFactoryClasses = {com.lanhetech.testdemo.CrashSenderFactory.class} ) public class MyApplication extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); ACRA.init(this); } @Override public void onCreate() { super.onCreate(); } }
第四步:
修改AndroidManifest.xml内容,获取权限
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lanhetech.testdemo"> <!--获取权限--> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> <!--修改这里application name--> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".Main2Activity"></activity> </application> </manifest>
到这里,ARCA就配置好了,但需要后台的配合。
以下是web的Servlet的代码:
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub // super.doGet(req, resp); System.out.println("参数内容:" + req.getParameter("APP_VERSION_CODE")); System.out.println("参数内容:" + req.getParameter("APP_VERSION_NAME")); System.out.println("参数内容:" + req.getParameter("PACKAGE_NAME")); System.out.println("参数内容:" + req.getParameter("FILE_PATH")); System.out.println("参数内容:" + req.getParameter("PHONE_MODEL")); System.out.println("参数内容:" + req.getParameter("ANDROID_VERSION")); System.out.println("参数内容:" + req.getParameter("BUILD")); System.out.println("参数内容:" + req.getParameter("BRAND")); System.out.println("参数内容:" + req.getParameter("STACK_TRACE")); System.out.println("参数内容:" + req.getParameter("STACK_TRACE_HASH")); System.out.println("参数内容:" + req.getParameter("USER_CRASH_DATE")); System.out.println("参数内容:" + req.getParameter("DUMPSYS_MEMINFO")); System.out.println("参数内容:" + req.getParameter("DEVICE_ID")); PrintWriter out = resp.getWriter(); out.println("0"); out.flush(); out.close(); }
测试:
public class MainActivity extends AppCompatActivity { private ImageView main_show_img; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); "1".substring(5); } }
测试结果:
参数内容:1.0 参数内容:com.lanhetech.testdemo 参数内容:/data/data/com.lanhetech.testdemo/files 参数内容:Coolpad 8705 参数内容:4.3 参数内容:BOARD=unknown BOOTLOADER=unknown BRAND=Coolpad CPU_ABI=armeabi-v7a CPU_ABI2=armeabi DEVICE=Coolpad8705 DISPLAY=4.3.018.P1.140225.8705 FINGERPRINT=Coolpad/Coolpad8705/Coolpad8705:4.3/JSS15Q/4.3.045.P1.160407.8705:user/release-keys HARDWARE=pxa1l88 HOST=ubuntu ID=JSS15Q IS_DEBUGGABLE=false MANUFACTURER=Coolpad MODEL=Coolpad 8705 PRODUCT=Coolpad8705 RADIO=unknown SERIAL=870520131010 TAGS=release-keys TIME=1460020349000 TYPE=user UNKNOWN=unknown USER=system1 VERSION.CODENAME=REL VERSION.INCREMENTAL=unknown VERSION.RELEASE=4.3 VERSION.RESOURCES_SDK_INT=18 VERSION.SDK=18 VERSION.SDK_INT=18 参数内容:Coolpad 参数内容:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.lanhetech.testdemo/com.lanhetech.testdemo.MainActivity}: java.lang.StringIndexOutOfBoundsException: length=1; index=5 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2224) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2279) at android.app.ActivityThread.access$600(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5215) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:760) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.StringIndexOutOfBoundsException: length=1; index=5 at java.lang.String.indexAndLength(String.java:579) at java.lang.String.substring(String.java:1438) at com.lanhetech.testdemo.MainActivity.onCreate(MainActivity.java:32) at android.app.Activity.performCreate(Activity.java:5146) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1090) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2188) ... 11 more java.lang.StringIndexOutOfBoundsException: length=1; index=5 at java.lang.String.indexAndLength(String.java:579) at java.lang.String.substring(String.java:1438) at com.lanhetech.testdemo.MainActivity.onCreate(MainActivity.java:32) at android.app.Activity.performCreate(Activity.java:5146) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1090) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2188) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2279) at android.app.ActivityThread.access$600(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1269) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5215) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:760) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576) at dalvik.system.NativeStart.main(Native Method) 参数内容:null 参数内容:2016-09-29T16:33:34.236+08:00 参数内容:Permission Denial: can‘t dump meminfo from from pid=20656, uid=10084 without permission android.permission.DUMP 参数内容:null
注意点:
首先需要注意一点,Acra使用独立进程:acra
,进行采集数据的发送,保证当app崩溃时,采集仍然能发送出去。
由于使用独立的进程,所以会导致application被实例化多次,这样就需要注意app自身的某些业务逻辑,不要在application类中执行多次,从而导致app产生bug。
对Acra的相关配置一般在application中进行初始化。
参考资料:
http://www.jianshu.com/p/fd4d6a7c6175
http://blog.sina.com.cn/s/blog_8a86f4dd0101g6d4.html
http://blog.csdn.net/fhlkm/article/details/8603133
ACRA 框架的使用 -- 发送到后台解析(后台的代码也在)
标签:
原文地址:http://www.cnblogs.com/H-BolinBlog/p/5920401.html