android調試stetho的那點事

在調試安卓程序的過程中,受不了每次看日誌查看網絡的響應和導出db的動作(甚至有時候都無法導出db),這裏安利一個facebook出品的神器 stetho,不過這個有些限制,在使用的時候一定的通過usb與調試的手機相連通的,也要使用chrome瀏覽器

1. stetho支持的功能

支持的功能主要是針對網絡和db的,看github項目上的趨勢,應該是在準備一些後續的功能(按照需求集成咯,我覺得網絡和db的最重要了),把官網的介紹摳了下來官網stetho介紹

1. 支持應用的網絡請求返回報文的查看

在chrome瀏覽器中輸入chrome://inspect來進入。(第一次使用這個功能的時候要翻牆,翻牆,翻牆,重要的事情要說三遍,不然你點擊了inpect永遠是空白的)
進行查看頁面

進行網絡請求查看頁面

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

進行db查看頁面

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.
    爲flavor創建單獨的application和清單文件

    重新指定application

  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();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章