Android-讀取操作系統通話記錄並/撥打電話/發送短信/復制號碼到撥號盤


apps目錄的contacts應用(有讀取通話記錄功能),是訪問provider目錄的provider.contacts應用(有暴露通話記錄),所以要閱讀Android操作系統源碼-->packages/providers/ContactsProvider通話記錄的(內容提供者)

 


 

閱讀 com.android.providers.contacts 數據庫與表

Android操作系統的文件系統目錄/data/data/com.android.contacts,是訪問/data/data/com.android.providers.contacts(內容提供者應用)

所以需要閱讀/data/data/com.android.providers.contacts(內容提供者應用)的數據庫:

 

首選要有一條通話記錄 

 

打開 contacts2.db

 打開后:表非常多,視圖非常多,等等,但只需關心,calls(通話記錄表)

 

 


 

閱讀 com.android.providers.contacts AndroidManifest.xml

android:name="CallLogProvider"  通話記錄的內容提供者

android:authorities="call_log"  授權唯一標識

android:exported="true"   允許對外輸出

android:readPermission="android.permission.READ_CALL_LOG" 訪問者必須要配置的權限
android:writePermission="android.permission.WRITE_CALL_LOG" 訪問者必須要配置的權限

    <provider android:name="CallLogProvider"
            android:authorities="call_log"
            android:syncable="false" android:multiprocess="false"
            android:exported="true"
            android:readPermission="android.permission.READ_CALL_LOG"
            android:writePermission="android.permission.WRITE_CALL_LOG">
        </provider>

 

閱讀 com.android.providers.contacts CallLogProvider.java

首先要找到的就是Uri,所以搜索UriMatcher的matcher.addURI

有規律,通常情況下,matcher.addURI(授權, path, code),第二個參數 path 和數據庫表名對應的 calls

private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static {
        sURIMatcher.addURI(CallLog.AUTHORITY, "calls", CALLS);
        sURIMatcher.addURI(CallLog.AUTHORITY, "calls/#", CALLS_ID);
        sURIMatcher.addURI(CallLog.AUTHORITY, "calls/filter/*", CALLS_FILTER);
}

 


 

 

C應用 AndroidManifest.xml 權限的配置:

  <!--
        訪問操作系統短信通話記錄提供者應用,需要加入的權限
        android:readPermission="android.permission.READ_CALL_LOG"
        android:writePermission="android.permission.WRITE_CALL_LOG"
    -->
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
  <!-- C應用配置撥打電話的權限 撥打電話的權限 -->
    <uses-permission android:name="android.permission.CALL_PHONE" />

 

C應用 讀取操作系統通話記錄並/撥打電話/發送短信/復制號碼到撥號盤 Java代碼:

package liudeli.cp.client;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CallLog;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class CallLogActivity extends Activity {

    /**
     * 找尋到了Android操作系統的通話記錄內容提供者的授權和Uri
     * android:authorities="call_log"
     * sURIMatcher.addURI(CallLog.AUTHORITY, "calls", CALLS);
     */
    private final String AUTHORITY = "call_log";
    private Uri callLogUri = Uri.parse("content://" + AUTHORITY + "/calls");

    /**
     * 系統也提供了常量的方式來獲取Uir,為了學習,還是直接看源碼復制出來的比較理解些
     */
    /*private final String AUTHORITY = CallLog.AUTHORITY;
    private Uri callLogUri =  Uri.parse(CallLog.CONTENT_URI + "/calls");*/

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_call_log);

        ListView listView = findViewById(R.id.listview);

        String[] porjecting = new String[]{"_id" ,"number", "date", "type"};
        final Cursor cursor = getContentResolver().query(callLogUri,
                 porjecting,
                null, // 不要查詢條件
                null, // 不要查詢條件值
                null); // 不排序

        while (cursor.moveToNext()) {
            Log.d("cccc", "" + cursor.getString(0) + "  "+ cursor.getString(1) + " " + cursor.getString(2) + "   "+ cursor.getString(3));
        }

        final SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, // 上下文
                          R.layout.layou_calllog_item, // Item顯示的布局
                          cursor, // 游標數據
                          porjecting, // 數據從哪里來(從Cursor中獲取對應的字段)
                          new int[]{R.id.tv_id, R.id.tv_number, R.id.tv_date, R.id.tv_type} // 數據到哪里去,到Item布局里面的控件顯示
        );
        listView.setAdapter(cursorAdapter);

        // 千萬不能關閉 cursor.close();,否則數據展示不出來

        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                // 獲取Item的值 (轉換規則,傳入什么類型,就轉換成什么類型)
                final Cursor itemCursor = (Cursor) cursorAdapter.getItem(position);

                /**
                 * 把Cursor移動到指定的行數,然后在取值 itemCursor.getString(0~9)
                 */
                itemCursor.moveToPosition(position);

                new AlertDialog.Builder(CallLogActivity.this)
                        .setTitle("請選擇")
                        /*.setMessage("請選擇,下面列表的功能")*/ //列表對話框不能設置這個,否則顯示不出來
                        .setItems(new String[]{"撥打電話", "復制號碼到撥號盤", "復制號碼到短信編輯界面"}, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {

                                // 把Cursor移動到指定的行數,然后在取值 itemCursor.getString(0~9)
                                String number = itemCursor.getString(itemCursor.getColumnIndex("number"));

                                /**
                                 * 下面這三個功能,都需要隱式意圖的方式去激活系統暴露的組件
                                 * 匹配規則:只要匹配一組,就可以來
                                 */
                                switch (which) {
                                    case 0: // 撥打電話
                                        Intent intentCall =  new Intent();
                                        intentCall.setAction(Intent.ACTION_CALL);
                                        intentCall.setData(Uri.parse("tel:" + number));
                                        startActivity(intentCall);
                                        break;
                                    case 1: // 復制號碼到撥號盤
                                        Intent intentCopyCall = new Intent();
                                        intentCopyCall.setAction(Intent.ACTION_DIAL);
                                        intentCopyCall.setData(Uri.parse("tel:" + number));
                                        startActivity(intentCopyCall);
                                        break;
                                    case 2: // 復制號碼到短信編輯界面
                                        Intent intentSmsEdit = new Intent();
                                        intentSmsEdit.setAction(Intent.ACTION_VIEW);
                                        intentSmsEdit.setData(Uri.parse("sms:" + number));
                                        startActivity(intentSmsEdit);
                                        break;
                                    default:
                                        break;
                                }
                            }
                        })
                        .show();
                return false;
            }
        });
    }
}

 

C應用顯示的Layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" 
    android:layout_height="match_parent">
    
    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

 

C應用顯示的Layout --> ListVIew-->Item布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp">

    <!-- 默認比重為0 我先填充 -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="id"
            android:textColor="@android:color/black"
            />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="number"
            android:textColor="@android:color/black"
            />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="date"
            android:textColor="@android:color/black"
            android:layout_marginTop="5dp"
            />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="type"
            android:textColor="@android:color/black"
            android:layout_marginTop="5dp"
            />

    </LinearLayout>

    <!-- 哥們,你已經填充完來吧,剩下的空間我全部使用 -->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_weight="1"
        android:layout_marginLeft="20dp"
        >

        <TextView
            android:id="@+id/tv_id"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="id"
            android:textColor="@android:color/black"
            />

        <TextView
            android:id="@+id/tv_number"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="number"
            android:textColor="@android:color/black"
            />

        <TextView
            android:id="@+id/tv_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="date"
            android:textColor="@android:color/black"
            android:layout_marginTop="5dp"
            />

        <TextView
            android:id="@+id/tv_type"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="type"
            android:textColor="@android:color/black"
            android:layout_marginTop="5dp"
            />

    </LinearLayout>


</LinearLayout>

 

C應用效果圖:

 


 

真實開發中,必須要用常量,才靠譜,萬一字段變來怎么辦,是吧

    /**
         * 通話記錄通常是有常量的
         */
        Calls.Date;
        CallLog.Calls._ID
        ....
        CallLog.AUTHORITY
        CallLog.Calls.NUMBER;
        CallLog.CONTENT_URI
        ....      

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM