Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android學習能力之統計日志上傳設計

Android學習能力之統計日志上傳設計

編輯:關於Android編程

一款軟件就像一個孩子,不斷的在學習,在探索,當孩子犯下錯誤的時候,我們可以去包容,當孩子犯不改的時候,獲取他就不再讓人喜歡,甚至是去拋棄他。人之常情的問題,也是做軟件的我們需要去考慮的問題。同樣孩子的成長速度和懂事程度也是我們非常關注的。

本章講述Android日志上傳功能,更快的更准確的將孩子的錯誤通知給我們,我們幫助孩子改正它的錯誤。

日志上傳的過程

1.日志統計和日志存儲

    public static void record(Context context, String ex) {
        if (context == null) {
            return;
        }
        PrintStream printStream = null;
        ByteArrayOutputStream bos = null;

        try {
            bos = new ByteArrayOutputStream(256);
            printStream = new PrintStream(bos);
            printStream.print(ex);
            JSONObject createJson = createJson(context, new String(bos.toByteArray()));//(1)做json
            DBManager.getInstance(context).addCrashLog(createJson.toString());//(2)存儲數據信息
            Prefs.setPrefBoolean(PrefsContants.IS_NEEDED_UPLOAD, true));
        } catch (Exception e) {
            Log.e("CrashUploadUtils", "writeLog", e);
        } finally {
            closeQuietly(printStream);//(3)
            closeQuietly(bos);
        }
    }

由上面代碼可以看出我們將數據字符串傳入統計記錄後,首先做成json數據,如步驟(1);其次將數據存入數據庫,如步驟(2);最後關閉我們的數據流,如步驟三。

(1)做成json數據

    private static JSONObject createJson(Context context, String log) {
        JSONObject object = null;
        try {
            object = new JSONObject();
            object.put("type", "crash");
            JSONObject data = new JSONObject();
            data.put("log", log);
            data.put("uk", AccountManager.getUK(context));
            data.put("version", IMManager.getVersion());
            data.put("trigger_id", Utility.getTriggerId(context));
            if (!TextUtils.isEmpty(android.os.Build.VERSION.RELEASE)) {
                data.put("os", android.os.Build.VERSION.RELEASE);
            }
            if (!TextUtils.isEmpty(android.os.Build.MODEL)) {
                data.put("device_model","mode" + android.os.Build.MODEL);
            }
            if (!TextUtils.isEmpty(android.os.Build.MANUFACTURER)) {
                data.put("manufacture",android.os.Build.MANUFACTURER);
            }
            object.put("data", data);
            object.put("ts", System.currentTimeMillis());

        } catch (JSONException e) {
            Log.e("CrashUploadUtils", "createJson", e);
        }

        return object;
    }

內容這裡可以忽略,自己放入就好。

(2)添加數據庫

    public void addCrashLog(String log) {
        synchronized (mSyncLock) {
            ContentValues values = new ContentValues();
            values.put(CrashLogColumns.COLUMN_COTENT, log);
            insert(TableDefine.DB_TABLE_CRASH_LOG, values);
        }
    }

其中insert函數,讀者要自己寫了。
(3)關閉數據流

    private static void closeQuietly(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                Log.e("CrashUploadUtils", "closeQuietly", e);
            }
        }
    }

上面我們完成了,日志的統計和信息的存儲,其中日志的存儲看上面添加數據庫的過程。

2.日志上傳

日志上傳是該功能的關鍵步驟,涉及的問題有:怎麼上傳,什麼時候上傳,什麼網絡環境下上傳?
日志上傳功能

    private static void upLoad(Context context) {
        Pair log = getCrashLog(context);//1獲取數據庫中異常信息
        if (log == null || log.first < 0) {
            return;
        }
        StringBuilder builder = new StringBuilder();
        builder.append("device_id=" + Utility.getDeviceType(context));
        builder.append("&appid=" + AccountManager.getAppid(context));
        builder.append("&statistic=" + log.second.toString());
        String jsonResult = null;
        try {//2上傳異常信息
            jsonResult = HttpUtility.doUploadPost(url, builder.toString().getBytes("utf-8"));
        } catch (UnsupportedEncodingException e) {
            Log.e("CrashUploadUtils", "upLoadCrash UnsupportedEncodingException", e);
        }
        if (jsonResult == null) {
            Log.e("CrashUploadUtils", "upload crash log failed!!");
            return;
        }

        try {
            JSONObject jsonObject = new JSONObject(jsonResult);
            int errorCode = jsonObject.optInt("err_code");
            String msg = jsonObject.optString("msg");//根據網絡結果刪除已經上傳過的信息,並更新上傳記錄時間
            if (errorCode == OK) {//3刪除上傳過的信息
                int result = DBManager.getInstance(context).deleteLogBeforeId(log.first);
                if (result > 0) {//4更新上傳時間
                    updateUploadTime(context, System.currentTimeMillis());
                }
            }
        } catch (JSONException e) {
            Log.e("CrashUploadUtils", "upLoadCrash JSONException", e);
        }
    }

(1)獲取數據庫中異常信息

    public static Pair getCrashLog(Context context) {
        return DBManager.getInstance(context).getLog();
    }

    public Pair getLog() {
        synchronized (mSyncLock) {
            CrashLogParse parse = new CrashLogParse();
            query(TableDefine.DB_TABLE_CRASH_LOG, null, null, null, null, null, CrashLogColumns._ID + " asc ", " 10 ",
                    parse);
            return parse.getResult();
        }
    }

    class CrashLogParse implements CursorParse {
        Pair result = null;

        @Override
        public void parseCursor(Cursor cursor) {
            if (cursor != null) {
                long maxid = -1;
                long id = -1;
                String log = null;
                JSONArray array = null;
                try {
                    array = new JSONArray();
                    while (cursor.moveToNext()) {
                        id = cursor.getLong(cursor.getColumnIndex(CrashLogColumns._ID));
                        log = cursor.getString(cursor.getColumnIndex(CrashLogColumns.COLUMN_COTENT));
                        if (id > maxid) {
                            maxid = id;
                        }
                        array.put(new JSONObject(log));
                    }
                } catch (JSONException e) {
                    array = null;
                    e.printStackTrace();
                }
                if (array != null) {
                    result = new Pair(maxid, array);
                }
            }
        }

        @Override
        public Pair getResult() {
            return result;
        }

    }

獲取到相應的數據庫信息,獲取的是其中的所有記錄和最大id值。
(2)上傳異常信息

    public static String doUploadPost(String httpUrl, byte[] byteToUpload) {
        if (byteToUpload == null || byteToUpload.length < 0) {
            return null;
        }
        URL url;
        HttpURLConnection httpUrlConnection = null;
        try {
            url = new URL(httpUrl);
            httpUrlConnection = (HttpURLConnection) url.openConnection();
            httpUrlConnection.setRequestMethod("POST");
            httpUrlConnection.setDoInput(true);
            // Post mode
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setConnectTimeout(30 * 1000);
            httpUrlConnection.setReadTimeout(30 * 1000);
            httpUrlConnection.setUseCaches(false);
            OutputStream outputStream = httpUrlConnection.getOutputStream();
            outputStream.write(byteToUpload);
            outputStream.flush();
            outputStream.close();
            // while (offset < byteLength) {
            // bufferOutStream.write(byteToUpload);
            // offset += length;
            // }
            int response = httpUrlConnection.getResponseCode();
            if (Constants.isDebugMode()) {
                Log.e("HttpUtility", "upload response:" + response);
            }
            if (response != HttpURLConnection.HTTP_OK) {
                return null;
            }
            return dealResponseResult(httpUrlConnection.getInputStream());
        } catch (MalformedURLException e) {
            Log.e("HttpUtility", "MalformedURLException doUploadPost", e);
        } catch (IOException e) {
            Log.e("HttpUtility", "IOException doUploadPost", e);
        } catch (Exception e) {
            Log.e("HttpUtility", "Exception doUploadPost", e);
        } finally {
            if (httpUrlConnection != null) {
                httpUrlConnection.disconnect();
            }
        }

        return null;
    }

    /**
     * @param inputStream
     * @return
     */
    public static String dealResponseResult(InputStream inputStream) {
        String resultData = null; // 存儲處理結果
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] data = new byte[1024];
        int len = 0;
        int offset = 0;
        try {
            while ((len = inputStream.read(data)) != -1) {
                byteArrayOutputStream.write(data, offset, len);
                offset += len;
            }
            resultData = new String(byteArrayOutputStream.toByteArray());
            if (Constants.isDebugMode()) {
                Log.d("HttpUtility", "resultData:" + resultData);
            }
        } catch (IOException e) {
            Log.e("HttpUtility", "IOException dealResponseResult", e);
        }
        return resultData;
    }

(3)刪除上傳過的信息

    public int deleteLogBeforeId(long id) {
        synchronized (mSyncLock) {
            return delete(TableDefine.DB_TABLE_CRASH_LOG, CrashLogColumns._ID + " <=?",
                    new String[] { String.valueOf(id) });
        }
    }

(4)更新上傳時間
其中定義了上傳時間間隔,不能上傳過於頻繁,造成服務壓力,基本幾個在10分鐘左右,這裡時間自己可以設定

    private static boolean updateUploadTime(Context context, long time) {
        if (time > lastUpdateTime) {
            lastUpdateTime = time;
            return Utility.writeLongData(context, key, lastUpdateTime);
        }
        return false;

    }

    private static long getUpdateTime(Context context) {
        if (lastUpdateTime == -1) {
            lastUpdateTime = Utility.readLongData(context, key, -1);
        }
        return lastUpdateTime;
    }

    public static boolean isNeedToUpload(Context context, long time) {
        return System.currentTimeMillis() - getUpdateTime(context) > time;
    }

(5)開始上傳

    public static void statUpload(final Context context) {
        if(!Prefs.getPrefBoolean(PrefsContants.IS_NEEDED_UPLOAD, false))){
            return;
        }
        if(!isNeedToUpload){
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                upLoadCrash(context);
            }
        }).start();
    }

以後就可以通過在服務端查看日志去快速修改app所犯下的錯誤。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved