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();
    }
相关推荐
openinstall全渠道统计3 小时前
免填邀请码工具:赋能六大核心场景,重构App增长新模型
android·ios·harmonyos
双鱼大猫3 小时前
一句话说透Android里面的ServiceManager的注册服务
android
双鱼大猫3 小时前
一句话说透Android里面的查找服务
android
双鱼大猫3 小时前
一句话说透Android里面的SystemServer进程的作用
android
双鱼大猫3 小时前
一句话说透Android里面的View的绘制流程和实现原理
android
双鱼大猫4 小时前
一句话说透Android里面的Window的内部机制
android
双鱼大猫4 小时前
一句话说透Android里面的为什么要设计Window?
android
双鱼大猫5 小时前
一句话说透Android里面的主线程创建时机,frameworks层面分析
android
苏金标5 小时前
android 快速定位当前页面
android
雾里看山8 小时前
【MySQL】内置函数
android·数据库·mysql