android 黑名單中電話攔截

今天講一下最近項目中剛做的黑名單攔截,其中可以攔截短信和電話

先講一下攔截電話的操作

首先要註冊一個監聽電話廣播的廣播接收器。

在Manifest文件中

<receiver
    android:name=".Receiver.InterceptSmsReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter android:priority="2147483647">
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>
同時還要添加讀取電話記錄,寫入電話記錄,以及監聽電話的權限

<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />

現在來說一下攔截電話的邏輯

使用廣播接收器監聽電話廣播,如果發現來電號碼存在於黑名單中,那麼就endCall(),這時要注意通話記錄中是都存在需要攔截的號碼的電話記錄,如果存在的話,要通過ContentResolver將其刪除掉。


public class InterceptCallReceiver extends BroadcastReceiver {
    private static final String TAG = "interceptcall";

    public InterceptCallReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        SharedPreferences mSp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
        boolean BlackNumStatus = mSp.getBoolean("BlackNumStatus", true);
        if (!BlackNumStatus) {
            return;
        }
        BlackNumberDBOperation operation = new BlackNumberDBOperation(context);
        if (!intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
            String mIncomingNumber = "";
            /**來電**/
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            switch (telephonyManager.getCallState()) {
                case TelephonyManager.CALL_STATE_RINGING:

                    mIncomingNumber = intent.getStringExtra("incoming_number");
                    int blackContactMode = operation.getBlackContactMode(mIncomingNumber);
                    /**這裏的Opration是一個實體類的操作類,用戶與查詢黑名單是都存在,並返回攔截模式**/
                    if (blackContactMode == 1 || blackContactMode == 3) {
                        /**
                         * 觀察呼叫記錄(其他的應用程序,像是手機通訊錄程序)的變化
                         * 如果生成了呼叫記錄,就把呼叫記錄刪除掉
                         */
                        Uri uri = Uri.parse("content://call_log/calls");
                        context.getContentResolver().registerContentObserver(uri, true, new CallLogObserver(new Handler(), mIncomingNumber, context));
                        endCall(context);

                    }
                    break;
            }
        }
    }


    private class CallLogObserver extends ContentObserver {

        /**
         * Creates a content observer.
         *
         * @param handler The handler to run {@link #onChange} on, or null if none.
         */


        private String incomingNumber;
        private Context context;

        public CallLogObserver(Handler handler, String incomingNumber, Context context) {
            super(handler);
            this.incomingNumber = incomingNumber;
            this.context = context;
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            Log.d(TAG, "呼叫數據庫的內容變化了");
            context.getContentResolver().unregisterContentObserver(this);
            deleteCallLog(incomingNumber, context);

        }
    }

    /**
     * 清除呼叫記錄
     * @param incomingNumber
     * @param context
     */

    public void deleteCallLog(String incomingNumber, Context context) {
        ContentResolver resolver = context.getContentResolver();
        Uri uri = Uri.parse("content://call_log/calls");
        Cursor cursor = resolver
                .query(uri,
                        new String[]{"_id"}, "number=?",
                        new String[]{incomingNumber}, "_id desc limit 1");
        if (cursor.moveToNext()) {
            String id = cursor.getString(0);
            resolver.delete(uri, "_id", new String[]{id});
        }
    }


    /**
     * 掛斷電話需要複製兩個AIDL(利用反射)
     */

    public void endCall(Context context){
        try {
            Class clazz=context.getClassLoader().loadClass("android.os.Service Manager");
            Method method=clazz.getDeclaredMethod("getService",String.class);
            IBinder iBinder = (IBinder) method.invoke(null,Context.TELEPHONY_SERVICE);


            ITelephony itelephony = ITelephony.Stub.asInterface(iBinder);
            itelephony.endCall();
      
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

最後,需要講的是程序掛斷電話,需要通過反射得到ITelephony接口。

需要將android源碼中的兩個AIDL複製到程序目錄中。

一個是ITelephony.aidl,需要建立一個與其包名一致的包com.android.internal.telephony(在src下建立的是com/android/internal/telephony),然後將其複製到包下

還有一個則是與ITelephony關聯的AIDL文件,NeighboringCellInfo.aidl,它所在的包是android.telephony,如上方法創建

兩個AIDL文件的下載路徑:http://pan.baidu.com/s/1pLrh9VX

密碼:y4fw


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章