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();
    }
相关推荐
dalancon4 分钟前
VSYNC 信号流程分析 (Android 14)
android
dalancon14 分钟前
VSYNC 信号完整流程2
android
dalancon16 分钟前
SurfaceFlinger 上帧后 releaseBuffer 完整流程分析
android
用户69371750013841 小时前
不卷AI速度,我卷自己的从容——北京程序员手记
android·前端·人工智能
程序员Android2 小时前
Android 刷新一帧流程trace拆解
android
墨狂之逸才2 小时前
解决 Android/Gradle 编译报错:Comparison method violates its general contract!
android
阿明的小蝴蝶3 小时前
记一次Gradle环境的编译问题与解决
android·前端·gradle
汪海游龙3 小时前
开源项目 Trending AI 招募 Google Play 内测人员(12 名)
android·github
qq_283720054 小时前
MySQL技巧(四): EXPLAIN 关键参数详细解释
android·adb
没有了遇见5 小时前
Android 架构之网络框架多域名配置<三>
android