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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 onError(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=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
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 框架的使用 -- 发送到后台解析(后台的代码也在)的主要内容,如果未能解决你的问题,请参考以下文章

Android mina框架使用详情

[源码解析] 深度学习分布式训练框架 horovod --- 后台线程架构

php 后台接受POST值

ACRA:如何将 ACRA 报告写入文件(在 SD 卡中)?

后台用map传值list集合到下一个后台时,后台怎么用map接list的值

MUI框架-09-MUI 与后台数据交互