Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android通話記錄CallLog簡單摘要

Android通話記錄CallLog簡單摘要

編輯:關於Android編程

最近做些和通訊相關的東西,源於網上這塊知識比較匮乏,所以我就整理下自己的思路,正好梳理下流程,以備不需之用;俗話說得好“好腦子比不了爛筆頭”;

通話記錄有幾種動作,插入(insert),刪除(delete) ,查詢(query),因為通話記錄不需要更改,所以就不用update(更新了);

一、先來看看Insert插入

首先通話記錄是在電話掛斷以後,才進行的操作,這個操作是異步的操作,在後台悄悄的插入到Calls中去的,通話記錄的Uri是“content://call_log/calls”;

Step 1:電話掛斷後,即在CallNotifier.java類(管理電話通話狀態的類)的onDisconnect()方法中:

onDisconnect()是電話主動掛斷、被動掛斷後調用的方法,即和通話方已經斷開連接後觸發的方法。在這個方法中有

段代碼如下:

 if (okToLogThisCall) {
                    CallLogAsync.AddCallArgs args;
                    int simIdEx = CALL_TYPE_NONE;

                    if (!GeminiUtils.isGeminiSupport() || isSipCall) { //Single Card
                        if (isSipCall) {
                            simIdEx = CALL_TYPE_SIP;
                        } else {
                            simIdEx = CALL_TYPE_NONE;
                            if (PhoneGlobals.getInstance().phoneMgr.hasIccCard()) {
                                SimInfoRecord info = SIMInfoWrapper.getDefault().getSimInfoBySlot(0);
                                if (info != null) {
                                    simIdEx = (int)info.mSimInfoId;
                                } else {
                                    //Give an default simId, in most case, this is invalid
                                    simIdEx = 1;
                                }
                            }
                        }
                        if (FeatureOption.MTK_VT3G324M_SUPPORT) {
                            args = new CallLogAsync.AddCallArgs(
                                mApplication, ci, logNumber, presentation,
                                callLogType, date, duration, simIdEx, vtCall);
                        } else {
                            args = new CallLogAsync.AddCallArgs(
                                mApplication, ci, logNumber, presentation,
                                callLogType, date, duration, simIdEx);
                        }
                    } else { //dual SIM

CallLogAsync.AddCallArgs這個類即為管理增加通話記錄的類;

args = new CallLogAsync.AddCallArgs(
                                mApplication, ci, logNumber, presentation,
                                callLogType, date, duration, simIdEx, vtCall);

這個方法即為初始化的證據。插入的證據在這:

try {
                        mCallLog.addCall(args);
                    } catch (SQLiteDiskIOException e) {
                        // TODO Auto-generated catch block
                        Log.e(LOG_TAG, "Error!! - onDisconnect() Disk Full!");
                        e.printStackTrace();
                    }
addCall(),即為插入DB的證據;


Step 2:在addCall()方法中執行的代碼如下:

 public AsyncTask addCall(AddCallArgs args) {
        assertUiThread();
        return new AddCallTask().execute(args);
    }
這個就是後台悄悄的插入DB的罪魁禍首:
 private class AddCallTask extends AsyncTask {
        @Override
        protected Uri[] doInBackground(AddCallArgs... callList) {
            int count = callList.length;
            Uri[] result = new Uri[count];
            for (int i = 0; i < count; i++) {
                AddCallArgs c = callList[i];

                try {
                    // May block.
                    result[i] = Calls.addCall(
                            c.ci, c.context, c.number, c.presentation,
                            c.callType, c.timestamp, c.durationInSec, c.simId, c.vtCall);
                } catch (Exception e) {
                    // This must be very rare but may happen in legitimate cases.
                    // e.g. If the phone is encrypted and thus write request fails, it may
                    // cause some kind of Exception (right now it is IllegalArgumentException, but
                    // might change).
                    //
                    // We don't want to crash the whole process just because of that.
                    // Let's just ignore it and leave logs instead.
                    Log.e(TAG, "Exception raised during adding CallLog entry: " + e);
                    result[i] = null;
                }

                
                Log.d(TAG, "Calls.addCall, number=" + c.number + " vtCall=" + c.vtCall
                        + " presentation:" + c.presentation + " callType:" + c.callType
                        + " timestamp:" + c.timestamp + " durationInSec:" + c.durationInSec
                        + " simId: " + c.simId + " vtCall:" + c.vtCall);
            }
            return result;
        }

        // Perform a simple sanity check to make sure the call was
        // written in the database. Typically there is only one result
        // per call so it is easy to identify which one failed.
        @Override
        protected void onPostExecute(Uri[] result) {
            for (Uri uri : result) {
                if (uri == null) {
                    Log.e(TAG, "Failed to write call to the log.");
                }
            }
        }
    }

Step 3:Calls.addCall()這個方法調用的地方在framework層了,CallLog.java這個類中:

路徑:frameworks/base/core/java/android/provider/CallLog.java.

方法如下:

public static Uri addCall(CallerInfo ci, Context context, String number,
                int presentation, int callType, long start, int duration, int simId, int vtCall) {
            final ContentResolver resolver = context.getContentResolver();


            // If this is a private number then set the number to Private, otherwise check
            // if the number field is empty and set the number to Unavailable
            if (presentation == PhoneConstants.PRESENTATION_RESTRICTED) {
                number = CallerInfo.PRIVATE_NUMBER;
                if (ci != null) ci.name = "";
            } else if (presentation == PhoneConstants.PRESENTATION_PAYPHONE) {
                number = CallerInfo.PAYPHONE_NUMBER;
                if (ci != null) ci.name = "";
            } else if (TextUtils.isEmpty(number)
                    || presentation == PhoneConstants.PRESENTATION_UNKNOWN) {
                number = CallerInfo.UNKNOWN_NUMBER;
                if (ci != null) ci.name = "";
            }


            ContentValues values = new ContentValues(5);


            values.put(NUMBER, number);
            values.put(TYPE, Integer.valueOf(callType));
            values.put(DATE, Long.valueOf(start));
            values.put(DURATION, Long.valueOf(duration));
            values.put(NEW, Integer.valueOf(1));
            if (callType == MISSED_TYPE) {
                values.put(IS_READ, Integer.valueOf(0));
            }
            if (ci != null) {
                values.put(CACHED_NAME, ci.name);
                values.put(CACHED_NUMBER_TYPE, ci.numberType);
                values.put(CACHED_NUMBER_LABEL, ci.numberLabel);
            }
            /// M: @{
            values.put(SIM_ID, simId);
            if (vtCall >= 0) {
                values.put(VTCALL, vtCall);
            }
            /// @}
            if ((ci != null) && (ci.person_id > 0)) {
                // Update usage information for the number associated with the contact ID.
                // We need to use both the number and the ID for obtaining a data ID since other
                // contacts may have the same number.


                final Cursor cursor;


                // We should prefer normalized one (probably coming from
                // Phone.NORMALIZED_NUMBER column) first. If it isn't available try others.
                if (ci.normalizedNumber != null) {
                    final String normalizedPhoneNumber = ci.normalizedNumber;
                    cursor = resolver.query(Phone.CONTENT_URI,
                            new String[] { Phone._ID },
                            Phone.CONTACT_ID + " =? AND " + Phone.NORMALIZED_NUMBER + " =?",
                            new String[] { String.valueOf(ci.person_id), normalizedPhoneNumber},
                            null);
                } else {
                    final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
                    cursor = resolver.query(
                            Uri.withAppendedPath(Callable.CONTENT_FILTER_URI,
                                    Uri.encode(phoneNumber)),
                            new String[] { Phone._ID },
                            Phone.CONTACT_ID + " =?",
                            new String[] { String.valueOf(ci.person_id) },
                            null);
                }


                if (cursor != null) {
                    try {
                        if (cursor.getCount() > 0 && cursor.moveToFirst()) {
                            final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
                                    .appendPath(cursor.getString(0))
                                    .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
                                                DataUsageFeedback.USAGE_TYPE_CALL)
                                    .build();
                            resolver.update(feedbackUri, new ContentValues(), null, null);
                        }
                    } finally {
                        cursor.close();
                    }
                }
            }


            /// M: new feature:IP dial enhancement start @{
            String ipPrefix = null;
            if (FeatureOption.MTK_GEMINI_SUPPORT) {
                ipPrefix = Settings.System.getString(resolver, "ipprefix" + simId);
            } else {
                ipPrefix = Settings.System.getString(resolver, "ipprefix");
            }
            if (null != ipPrefix && null != number && number.startsWith(ipPrefix)
                    && !number.equals(ipPrefix) && callType == Calls.OUTGOING_TYPE) {
                values.put(IP_PREFIX, ipPrefix);
                String tmpNumber = number.substring(ipPrefix.length(), number.length());
                values.put(NUMBER, tmpNumber);
            }
            /// @}


            //這個才是Insert的地方,和我們普通的insert是一樣的
            Uri result = resolver.insert(CONTENT_URI, values);


            removeExpiredEntries(context);


            return result;
        }

這個insert就說到這裡,未完待續。。。 。。。





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