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();
    }
相关推荐
DogDaoDao5 小时前
Android 硬件编码器参数完全指南:MediaCodec 深度解析
android·音视频·视频编解码·h264·硬编码·视频直播·mediacodec
JohnnyDeng946 小时前
Android 自定义 View:Canvas 绘图与事件分发深度解析
android
Android小码家9 小时前
Framework之Launcher小窗开发
android·framework·虚拟屏·小窗
赏金术士9 小时前
第七章:状态管理实战与架构总结
android·ui·kotlin·compose
颂love10 小时前
MySQL的执行流程
android·数据库·mysql
云起SAAS15 小时前
抖音小游戏源码 - 消消乐 | 含激励广告+成就系统 | 开箱即用商业级消除游戏模板
android·游戏·广告联盟·看激励广告联盟流量主·抖音小游戏源码 - 消消乐
大貔貅喝啤酒16 小时前
基于Windows下载安装Android Studio 3.3.2版本教程(2026详细图文版)
android·java·windows·android studio
程序员码歌16 小时前
OpenSpec 到 Superpowers:AI 编码从说清到做对
android·前端·人工智能
2501_9151063216 小时前
深入解析无源码iOS加固原理与方案,保护应用安全
android·安全·ios·小程序·uni-app·cocoa·iphone
黄林晴20 小时前
重磅官宣:Android UI 开发正式进入 Compose-first 时代
android·google io