Android学习能力之统计日志上传设计
来源:互联网 发布:惊天大逆转知乎 编辑:程序博客网 时间:2024/05/03 18:09
一款软件就像一个孩子,不断的在学习,在探索,当孩子犯下错误的时候,我们可以去包容,当孩子犯不改的时候,获取他就不再让人喜欢,甚至是去抛弃他。人之常情的问题,也是做软件的我们需要去考虑的问题。同样孩子的成长速度和懂事程度也是我们非常关注的。
本章讲述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<Long, JSONArray> 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<Long, JSONArray> getCrashLog(Context context) { return DBManager.getInstance(context).getLog(); } public Pair<Long, JSONArray> 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<Long, JSONArray> 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<Long, JSONArray>(maxid, array); } } } @Override public Pair<Long, JSONArray> 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 1
- Android学习能力之统计日志上传设计
- Android学习能力之开篇
- android 日志记录能力
- Android学习能力之移动应用分析
- Android学习能力之移动应用分析
- Android学习能力之移动应用分析
- android学习之-图片上传
- android-ftp-上传日志
- Android开发之app崩溃日志收集以及上传
- 设计模式学习日志
- 网页设计学习日志
- 软件设计能力提升之设计匠艺
- 软件设计能力提升之设计匠艺
- 整理:统计学习-1(续)泛化能力
- 《统计学习方法》学习笔记(2)--模型选择、泛化能力
- hadoop学习笔记之mapreduce 基于hbase日志数据的最频繁访问ip统计
- 学习篇之英文文档翻译能力
- 日志统计
- C++临时性对象的生命周期详细解析
- 【转载】C# 使用 NPOI 库读写 Excel 文件
- WPF 4.5和C#(4.1)——依赖属性
- 第40课作业第一题
- PCATTCP使用笔记——TCP UDP速度测试工具
- Android学习能力之统计日志上传设计
- 修改dll文件实例,亲试可用(斗哥帮了大忙!)
- Happy Number LeetCode
- ufldl tutorial excise - Supervised Learning and Optimization
- 多表链接 Left join
- 如何解决秒杀的性能问题和超卖的讨论
- [水+bfs] poj 3669 Meteor Shower
- tesseract-ocr语言库训练的一种出错情况
- js jq手机验证码发送