Android 来电白名单 只允许联系人呼入电话

客户需求只允许通讯录中联系人可以呼入电话。参考自带的黑名单实现

  1. CallsManager.java类中的onSuccessfulIncomingCall方法有一些过滤器,可以仿照黑名单的方式添加自己的过滤器。

packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java

java 复制代码
+import com.android.server.telecom.callfiltering.AsyncContactCheckFilter;

 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -505,6 +507,7 @@ public class CallsManager extends Call.ListenerBase
         filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter()));
         filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,
                 mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock));
+        filters.add(new AsyncContactCheckFilter(mContext));//mh@[非联系人挂断]
         new IncomingCallFilter(mContext, this, incomingCall, mLock,
                 mTimeoutsAdapter, filters).performFiltering();
     }
  1. 实现过滤器

packages/services/Telecomm/src/com/android/server/telecom/callfiltering/AsyncContactCheckFilter.java

java 复制代码
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.server.telecom.callfiltering;

import android.content.Context;
import android.os.AsyncTask;
import android.telecom.Log;

import com.android.server.telecom.Call;
import com.android.server.telecom.LogUtils;
import android.net.Uri;
import android.database.Cursor;

/**
 * An {@link AsyncTask} that checks if a call needs to be blocked.
 * <p> An {@link AsyncTask} is used to perform the block check to avoid blocking the main thread.
 * The block check itself is performed in the {@link AsyncTask#doInBackground(Object[])}.
 */
public class AsyncContactCheckFilter extends AsyncTask<String, Void, Boolean>
        implements IncomingCallFilter.CallFilter {
    private final Context mContext;
    private Call mIncomingCall;
    private CallFilterResultCallback mCallback;

    public AsyncContactCheckFilter(Context context) {
        mContext = context;
    }

    @Override
    public void startFilterLookup(Call call, CallFilterResultCallback callback) {
        mCallback = callback;
        mIncomingCall = call;
        String number = call.getHandle() == null ?
                null : call.getHandle().getSchemeSpecificPart();
        this.execute(number);
    }

    @Override
    protected void onPreExecute() {
    }

    @Override
    protected Boolean doInBackground(String... params) {
        try {
            return isContact(mContext, params[0]);
        } finally {
        }
    }

    @Override
    protected void onPostExecute(Boolean isContact) {
        try {
            CallFilteringResult result;
            if (!isContact) {//非联系人直接挂断
                result = new CallFilteringResult(
                        false, // shouldAllowCall
                        true, //shouldReject
                        false, //shouldAddToCallLog
                        false // shouldShowNotification
                );
            } else {
                result = new CallFilteringResult(
                        true, // shouldAllowCall
                        false, // shouldReject
                        true, // shouldAddToCallLog
                        true // shouldShowNotification
                );
            }
            mCallback.onCallFilteringComplete(mIncomingCall, result);
        } finally {
        }
    }
    
    //联系人查询
    private boolean isContact(Context context, String phoneNum) {
        Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + phoneNum);
        Cursor cursor = context.getContentResolver().query(uri, new String[] {android.provider.ContactsContract.Data.DISPLAY_NAME}, null, null, null);
        boolean exists = false;
        if (cursor != null) {
            try {
                if(cursor.moveToFirst()){
                    exists = true;
                    String name = cursor.getString(0);
                    Log.i("mh.log", "incoming phone is contact:" + name);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                cursor.close();
            }
        }
        return exists;
    }
}
  1. 可以添加一个开关,这里使用Settings的方式,也可以用广播。

frameworks/base/packages/SettingsProvider/res/values/defaults.xml

xml 复制代码
+    <!--mh@ phone blocker -->
+    <bool name="xc_unknow_incall_switch">false</bool>

frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java

java 复制代码
@@ -2355,6 +2355,10 @@ class DatabaseHelper extends SQLiteOpenHelper {
                     R.bool.def_screen_brightness_automatic_mode);
 
             loadDefaultAnimationSettings(stmt);
+            
+            //mh@{
+            loadBooleanSetting(stmt, "xc_unknow_incall_blocker",
+                    R.bool.xc_unknow_incall_switch);
+ 			 //mh@}

再修改一下CallsManager.java

java 复制代码
public void onSuccessfulIncomingCall(Call incomingCall) {
        Log.d(this, "onSuccessfulIncomingCall");
        if (incomingCall.hasProperty(Connection.PROPERTY_EMERGENCY_CALLBACK_MODE)) {
            Log.i(this, "Skipping call filtering due to ECBM");
            onCallFilteringComplete(incomingCall, new CallFilteringResult(true, false, true, true));
            return;
        }

        List<IncomingCallFilter.CallFilter> filters = new ArrayList<>();
        filters.add(new DirectToVoicemailCallFilter(mCallerInfoLookupHelper));
        filters.add(new AsyncBlockCheckFilter(mContext, new BlockCheckerAdapter()));
        filters.add(new CallScreeningServiceFilter(mContext, this, mPhoneAccountRegistrar,
                mDefaultDialerCache, new ParcelableCallUtils.Converter(), mLock));
        //mh@{
        boolean blocker = Settings.System.getInt(mContext.getContentResolver(), "xc_unknow_incall_blocker", 0) == 1;
        if(blocker) {
            filters.add(new AsyncContactCheckFilter(mContext));//mh@[非联系人挂断]
        }
        //mh@}
        new IncomingCallFilter(mContext, this, incomingCall, mLock,
                mTimeoutsAdapter, filters).performFiltering();
    }
相关推荐
JMchen12314 分钟前
【Android 性能优化实战 60 讲】06 GPU 呈现模式与卡顿视觉验证:拆解柱状图分层,秒辨渲染慢与等待慢
android·性能优化·实战·源码分析·渲染优化·gpu呈现模式·卡顿优化
91刘仁德8 小时前
MYSQL 事务原理及使用
android·mysql·adb
一笑的小酒馆10 小时前
AndroidKMP之瀑布流实现
android
RainyJiang10 小时前
AI时代下,Android的边界正在消失
android·openai·ai编程
Android-Flutter10 小时前
android 内存抖动详解
android
方白羽12 小时前
为什么 Android 非要用 Intent 传值?
android·ios·harmonyos
方白羽14 小时前
Android17 重写 MessageQueue,解决 Handler 隐性卡顿
android·app
蜡台15 小时前
Kotlin 零基础完整版实战教程|从语法入门到Android工程实战
android·开发语言·kotlin
律宏阔15 小时前
Android 车载 USB 开发笔记:USB Host、USB 串口、USB-CAN、HID 与系统 API
android
律宏阔16 小时前
Android 车载串口开发笔记:UART、RS232、RS485、串口配置与数据通信
android