android调试stetho的那点事

在调试安卓程序的过程中,受不了每次看日志查看网络的响应和导出db的动作(甚至有时候都无法导出db),这里安利一个facebook出品的神器 stetho,不过这个有些限制,在使用的时候一定的通过usb与调试的手机相连通的,也要使用chrome浏览器

1. stetho支持的功能

支持的功能主要是针对网络和db的,看github项目上的趋势,应该是在准备一些后续的功能(按照需求集成咯,我觉得网络和db的最重要了),把官网的介绍抠了下来官网stetho介绍

1. 支持应用的网络请求返回报文的查看

在chrome浏览器中输入chrome://inspect来进入。(第一次使用这个功能的时候要,,,重要的事情要说三遍,不然你点击了inpect永远是空白的,如果没法,请查看这篇文章)
android调试stetho的那点事_第1张图片

android调试stetho的那点事_第2张图片

2. 支持的db查看功能 和 支持的sql语句直接进行交互功能(增删改查都是可以的)

android调试stetho的那点事_第3张图片

2. 集成stetho

  • 导入依赖
    implementation ‘com.facebook.stetho:stetho:1.5.0’

  • 根据网络请求框架导入不同的依赖包
    implementation ‘com.facebook.stetho:stetho-okhttp3:1.5.0’
    or:
    implementation ‘com.facebook.stetho:stetho-urlconnection:1.5.0’

  • 在application中进行集成

public class MyApplication extends Application {
  public void onCreate() {
    super.onCreate();
    Stetho.initializeWithDefaults(this);
  }
}
  • 如果是有网络请求的,以okhttp举例,创建okhttpClient的时候需要加入一个拦截器
    new OkHttpClient.Builder()
      .addNetworkInterceptor(new StethoInterceptor())
      .build()
    

3. 集成stetho的建议(干货)

  1. 建立一个单独的productFlavor来集成功能,不要在正式的环境中集成这个东西。会使得应用变得更加庞大,也给应用留下漏洞
    比如在build.gradle建立一个productflavor

     productFlavors {
         {
           
        }
    }
    

    在应用的的main目录中建立一个productFlavor innerteset的目录,然后把,通过清单合并操作中的替换application类的方式重新指定application.
    android调试stetho的那点事_第4张图片

    android调试stetho的那点事_第5张图片

  2. 关于网络的请求中,有的应用的报文是有加解密的。这里需要做一些额外的动作
    修改默认的网络请求拦截类 StethoInterceptor.class,新建的一个类把原来的类文件中东西拷贝出来进行调整
    解密请求的报文,主要是修改内部类OkHttpInspectorRequestbody(),拿到原始报文的,请求体,完成解密动作后重新包装生成一个请求体,给原来的代码使用。下面有一个我在自己应用中使用的实例

      @Nullable
        public byte[] body() throws IOException {
    	//我的测试应用的请求报文都是data:{}的格式,所以这里这么写,各个应用要按照自己应用的需求改写
            FormBody copyedBody = (FormBody) (this.mRequest.body());
            List<String> nameList = new ArrayList<>();
            List<String> valusList = new ArrayList<>();
            for (int i=0; i< copyedBody.size(); i++) {
                nameList.add(copyedBody.encodedName(i));
                if ("data".equals(copyedBody.encodedName(i))) {
                    valusList.add(new JsonFormatUtil().formart(这里解密请求的报文));
                }
            }
    
            FormBody copyedBody2 = new FormBody.Builder().add(nameList.get(0), valusList.get(0)).build();
            FormBody body = copyedBody2;
    		//下面这块代码不动,保持原样,上面重新生成了requestBody而已
            if (body == null) {
                return null;
            } else {
                OutputStream out = this.mRequestBodyHelper.createBodySink(this.firstHeaderValue("Content-Encoding"));
                BufferedSink bufferedSink = Okio.buffer(Okio.sink(out));
    
                try {
                    body.writeTo(bufferedSink);
                } finally {
                    bufferedSink.close();
                }
    
                return this.mRequestBodyHelper.getDisplayBody();
            }
    
        }
    

    解密返回报文,返回的报文,stetho是保存在文件中的然后进行的发送,需要修改默认的ResponseHandler
    抄袭原来的ReponseHanlder,主要修改的onEOF方式

       //调整原来的类,增加一个readFile的方法
        public void onEOF() {
        this.reportDataReceived();
        try {
            readFile(this.mRequestId);
        } catch (IOException e) {
            Log.e(TAG, "readFile Exception onEOF:  " + e);
        }
        this.mEventReporter.responseReadFinished(this.mRequestId);
    }
    
    //读取默认的文件
    public ResponseBodyData readFile(String requestId) throws IOException {
        ResponseBodyFileManager responseBodyFileManager = new ResponseBodyFileManager(CeshiApplication.getApplication());
        ResponseBodyData responseBodyData = responseBodyFileManager.readFile(requestId);
        OutputStream outputStream = null;
    	//这个对象是数据的对象,用于json转换使用
        SfReponseBodyData sfReponseBodyData = new Gson().fromJson(responseBodyData.data, SfReponseBodyData.class);
        sfReponseBodyData.data = 这里就可以进行解密的动作,得到解密的字符串;
        try {
            outputStream = responseBodyFileManager.openResponseBodyFile(requestId, responseBodyData.base64Encoded);
            String data = new Gson().toJson(sfReponseBodyData);
            data = data.replace("\\", "");
            data = new JsonFormatUtil().formart(data);
            outputStream.write(data.getBytes());
        } catch (Exception e) {
            Log.e(TAG, "readFile Exception: " + e);
        } finally {
            if (null != outputStream) {
                outputStream.close();
            }
        }
        LogUtils.getInstance().showLogD(TAG, "readFile" ,"new record");
        return null;
    }
    
    

    为了在浏览器上好看,报文最后都需要进行格式化,比如我这里是默认的json报文,就进行格式化后传给浏览器

//网络上随便抠的一段格式代码
public class JsonFormatUtil {

    public String formart(String s) {
        int level = 0;
        //存放格式化的json字符串
        StringBuilder jsonForMatStr = new StringBuilder();
        for (int index = 0; index < s.length(); index++)//将字符串中的字符逐个按行输出
        {
            //获取s中的每个字符
            char c = s.charAt(index);

            //level大于0并且jsonForMatStr中的最后一个字符为\n,jsonForMatStr加入\t
            if (level > 0 && '\n' == jsonForMatStr.charAt(jsonForMatStr.length() - 1)) {
                jsonForMatStr.append(getLevelStr(level));
            }
            //遇到"{"和"["要增加空格和换行,遇到"}"和"]"要减少空格,以对应,遇到","要换行
            switch (c) {
                case '{':
                case '[':
                    jsonForMatStr.append(c + "\n");
                    level++;
                    break;
                case ',':
                    jsonForMatStr.append(c + "\n");
                    break;
                case '}':
                case ']':
                    jsonForMatStr.append("\n");
                    level--;
                    jsonForMatStr.append(getLevelStr(level));
                    jsonForMatStr.append(c);
                    break;
                default:
                    jsonForMatStr.append(c);
                    break;
            }
        }
        return jsonForMatStr.toString();
    }

    private static String getLevelStr(int level) {
        StringBuilder levelStr = new StringBuilder();
        for (int levelI = 0; levelI < level; levelI++) {
            levelStr.append("\t");
        }
        return levelStr.toString();
    }
}

你可能感兴趣的:(Android,stetho,调试,神器,查看db)