首页 > 代码库 > ACRA 框架的使用 -- 发送到后台解析(后台的代码也在)

ACRA 框架的使用 -- 发送到后台解析(后台的代码也在)

使用的工具: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 one rror(Call call, Exception e, int id) {                    }                    @Override                    public void onResponse(Object response, int id) {                    }                });    }}
View Code
技术分享
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();    }}
View Code

第三步:

自定义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();    }}
View Code

第四步:

修改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>
View Code

到这里,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();    }
View Code

测试:

技术分享
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);    }}
View Code

测试结果:

技术分享
参数内容:1.0参数内容:com.lanhetech.testdemo参数内容:/data/data/com.lanhetech.testdemo/files参数内容:Coolpad 8705参数内容:4.3参数内容:BOARD=unknownBOOTLOADER=unknownBRAND=CoolpadCPU_ABI=armeabi-v7aCPU_ABI2=armeabiDEVICE=Coolpad8705DISPLAY=4.3.018.P1.140225.8705FINGERPRINT=Coolpad/Coolpad8705/Coolpad8705:4.3/JSS15Q/4.3.045.P1.160407.8705:user/release-keysHARDWARE=pxa1l88HOST=ubuntuID=JSS15QIS_DEBUGGABLE=falseMANUFACTURER=CoolpadMODEL=Coolpad 8705PRODUCT=Coolpad8705RADIO=unknownSERIAL=870520131010TAGS=release-keysTIME=1460020349000TYPE=userUNKNOWN=unknownUSER=system1VERSION.CODENAME=RELVERSION.INCREMENTAL=unknownVERSION.RELEASE=4.3VERSION.RESOURCES_SDK_INT=18VERSION.SDK=18VERSION.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 morejava.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
View Code

注意点:

首先需要注意一点,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 框架的使用 -- 发送到后台解析(后台的代码也在)