/** * 在sd卡下创建crash文件保存路径 * * @return null:创建不成功,String:crash文件保存路径 */ private String createCrashReportDir() { String workDir = XConfiguration.getInstance().getWorkDirectory(); if (XStringUtils.isEmptyString(workDir)) { XLog.e(CLASS_NAME, "Failed to get workDir at:" + workDir); return null; } File saveDir = new File(workDir, CRASH_REPORT_FILE_PATH); String saveDirPath = saveDir.getAbsolutePath(); if (saveDir.exists() || saveDir.mkdirs()) { return saveDirPath; } XLog.e(CLASS_NAME, "Failed to create crash log directory at:" + saveDirPath); return null; }
/** * 拨打指定号码的电话 * * @param[in] phoneNumber 要拨打的电话号码 * @return 拨打电话是否成功 */ private boolean initiateVoiceCall(String phoneNumber) { try { if (isLegalPhoneNum(phoneNumber)) { Intent intent = new Intent(Intent.ACTION_CALL); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setData(Uri.parse(WebView.SCHEME_TEL + phoneNumber)); mContext.startActivity(intent); return true; } } catch (ActivityNotFoundException e) { XLog.e(CLASS_NAME, e.toString()); } catch (SecurityException e) { XLog.e(CLASS_NAME, e.toString()); } return false; }
/** 删除电池监听器,反注册广播接收器 */ private void removeBatteryListener() { if (null != mBroadcastReceiver) { try { getContext().unregisterReceiver(mBroadcastReceiver); mBroadcastReceiver = null; } catch (Exception e) { XLog.e(CLASS_NAME, "Error unregistering battery receiver: " + e.getMessage(), e); } } }
/** * 是否传播按键事件。 在软键盘隐藏的时候记录系统时间,当点击手机按键的时候,再取一次系统时间,比较两次时间差 * 如果差值小于某一值(一个经验值,目前是100毫秒)就认为是在很短时间内响应了手机按键,此时 认为手机按键的操作是关闭软键盘,则不需要再传播事件,如果大于该值,则认为是需要执行手机 * 按键事件,则需要传播以便执行js * * <p>为什么要根据临界值去判断? 因为,在软键盘弹出后,我们点击返回键,需要经过一下流程: 软键盘关闭->软键盘将返回事件继续传播->xFace响应返回键事件 * 那么这一段事件是系统在处理,所以关闭软键盘到响应返回键这个时间很短 * * <p>如果点击屏幕空白处将软键盘关闭,再点返回键,在这一流程中,由于是人为的关闭了软键盘和人为 的点击了返回键,所以这个时间比起系统自己来处理要长得多。 * 所以才根据临界时间来判断是否是关闭软键盘的操作。 * * @return true 传播 false 不传播 */ public boolean isPropagateEvent() { long currentSystime = 0; currentSystime = System.currentTimeMillis(); XLog.d( CLASS_NAME, "The time difference is : " + (currentSystime - mCurrentSysTimeWhenSoftKeyboardHidden)); // 计算两次时间差,小于临界值就认为,本次事件是关闭软键盘,那么就不传播事件了 if (currentSystime - mCurrentSysTimeWhenSoftKeyboardHidden < CRITICAL) { return false; } return true; }
@Override /** * 监听measurement事件,根据view的高度判断软键盘是否弹出 * * @param widthMeasureSpec * @param heightMeasureSpec */ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width, height; height = MeasureSpec.getSize(heightMeasureSpec); width = MeasureSpec.getSize(widthMeasureSpec); // 初始状态 if (mOldHeight == 0 || mOldHeight == height) { XLog.d(CLASS_NAME, "Ignore this event"); } // 转屏 else if (mScreenHeight == width) { int tmp_var = mScreenHeight; mScreenHeight = mScreenWidth; mScreenWidth = tmp_var; XLog.i(CLASS_NAME, "Orientation Change"); } // 软键盘隐藏了 else if (height > mOldHeight) { XLog.i(CLASS_NAME, "Soft Keyboard Hidden"); mCurrentSysTimeWhenSoftKeyboardHidden = System.currentTimeMillis(); } // 软键盘弹出 else if (height < mOldHeight) { XLog.i(CLASS_NAME, "Soft Keyboard Shown"); } mOldHeight = height; mOldWidth = width; }
/** * 查找指定匹配的通话记录 * * @param[in] comparisonCallRecord 待匹配的通话记录 * @param[in] startIndex 要查找的开始索引 * @param[in] endIndex 要查找的结束位置的索引 * @return 返回按照匹配的通话记录查找的所有通话记录的JSON数组 */ private JSONArray findCallRecords(JSONObject comparisonCallRecord, int startIndex, int endIndex) { JSONArray result = new JSONArray(); if (null != comparisonCallRecord) { try { String callRecordId = comparisonCallRecord.getString("callRecordId"); String callRecordAddress = comparisonCallRecord.getString("callRecordAddress"); String callRecordName = comparisonCallRecord.getString("callRecordName"); String callRecordType = comparisonCallRecord.getString("callRecordType"); long startTime = comparisonCallRecord.getLong("startTime"); long durationSeconds = comparisonCallRecord.getLong("durationSeconds"); ArrayList<String> projections = new ArrayList<String>(); projections.add(CallLog.Calls._ID); projections.add(CallLog.Calls.NUMBER); projections.add(CallLog.Calls.CACHED_NAME); ArrayList<String> projectionsValue = new ArrayList<String>(); projectionsValue.add(callRecordId); projectionsValue.add(callRecordAddress); projectionsValue.add(callRecordName); StringBuilder selection = XUtils.constructSelectionStatement(projections, projectionsValue); String selectionStr = buildSelectionStr(selection, startTime, durationSeconds, callRecordType); Cursor cursor = mContentResolver.query( CallLog.Calls.CONTENT_URI, null, selectionStr, null, CallLog.Calls.DEFAULT_SORT_ORDER); if (null == cursor) { return result; } int count = endIndex - startIndex + 1; if (count > 0) { if (cursor.moveToPosition(startIndex)) { do { JSONObject callRecord = getCallRecordFromCursor(cursor); result.put(callRecord); count--; } while (cursor.moveToNext() && count > 0); } } cursor.close(); } catch (JSONException e) { XLog.e(CLASS_NAME, e.toString()); } } return result; }
/** * 根据当前的电池状态信息构建json对象 * * @param batteryIntent 可以获取当前电池状态信息的intent * @return 包含电池信息的json对象 */ private JSONObject getBatteryInfo(Intent batteryIntent) { JSONObject obj = new JSONObject(); try { obj.put("level", batteryIntent.getIntExtra(android.os.BatteryManager.EXTRA_LEVEL, 0)); obj.put( "isPlugged", batteryIntent.getIntExtra(android.os.BatteryManager.EXTRA_PLUGGED, -1) > 0 ? true : false); } catch (JSONException e) { XLog.e(CLASS_NAME, e.getMessage(), e); } return obj; }
/** * 得到指定通话记录类型和id的通话记录 * * @param[in] callRecordType 通话记录类型 * @param[in] callRecordIndex 通话记录的索引 * @return 返回通话记录的JSON对象 */ private JSONObject getCallRecord(String callRecordType, int recordIndex) { int callType = getCallRecordType(callRecordType); Cursor c = mContentResolver.query( CallLog.Calls.CONTENT_URI, new String[] { CallLog.Calls.NUMBER, CallLog.Calls._ID, CallLog.Calls.CACHED_NAME, CallLog.Calls.TYPE, CallLog.Calls.DATE, CallLog.Calls.DURATION }, CallLog.Calls.TYPE + "=" + callType, null, CallLog.Calls.DEFAULT_SORT_ORDER); String callRecordAddress = ""; String callRecordId = ""; String callRecordName = ""; long durationSeconds = 0; long startTime = 0; JSONObject callRecord = new JSONObject(); if (null != c) { if (c.moveToPosition(recordIndex)) { callRecordAddress = c.getString(0); callRecordId = c.getString(1); callRecordName = c.getString(2); startTime = c.getLong(4); durationSeconds = c.getLong(5); } c.close(); try { callRecord.put("callRecordAddress", callRecordAddress); callRecord.put("callRecordId", callRecordId); callRecord.put("callRecordName", callRecordName); callRecord.put("durationSeconds", durationSeconds); callRecord.put("startTime", startTime); callRecord.put("callRecordType", callRecordType); } catch (JSONException e) { XLog.e(CLASS_NAME, e.getMessage()); } } return callRecord; }
/** 通过Cursor得到通话记录的JSON对象 */ private JSONObject getCallRecordFromCursor(Cursor cursor) { String callRecordId = cursor.getString(cursor.getColumnIndex(CallLog.Calls._ID)); String callRecordAddress = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER)); String callRecordName = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME)); int callRecordTypeInt = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE)); long startTime = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE)); long durationSeconds = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DURATION)); JSONObject callRecord = new JSONObject(); try { callRecord.put("callRecordId", callRecordId); callRecord.put("callRecordAddress", callRecordAddress); callRecord.put("callRecordName", callRecordName); callRecord.put("callRecordType", getCallRecordTypeStr(callRecordTypeInt)); callRecord.put("startTime", startTime); callRecord.put("durationSeconds", durationSeconds); } catch (JSONException e) { XLog.e(CLASS_NAME, e.toString()); } return callRecord; }