黑名单来电管理属于手机里比较常用的功能,今天就来简单介绍下Android上对于黑名单来电比较常见的一些处理方式。首先我们知道Android挂断电话的API是不对外开放的,对于普通的三方应用,要想进行挂断电话操作,需要使用反射来获取通话相关服务TELEPHONY_SERVICE ,然后通过AIDL与telephony建立通信。建立通信之后我们需要通过为TelephonyManager添加PhoneStateListener监听器来监听通话状态。由于TelephonyManager只提供了CALL_STATE_IDLE(闲置),CALL_STATE_RINGING(响铃),CALL_STATE_OFFHOOK(已接通)这三种通话状态,因此我们只能在监听到响铃状态时去调用ITelephony对象的endCall方法,这样就会出现来电先响铃再挂断的现象,因此这种处理方式虽然简单但也会带来不好的用户体验。
对于系统通话应用,我们可以不用考虑上述问题,接下来就说说在系统通话和联系人应用里的对于黑名单来电的管理。通常在通话记录列表或者通话记录详情界面会提供添加黑名单入口。为了方便管理,我们需要创建一个数据库用于来电黑名单管理。我们建立一个数据库辅助类用于管理数据库,数据库名称为blocklist.db,创建一个blocklist表,用于管理黑名单,创建一个call_log表,用于管理黑名单通话记录。
public class BlocklistDbHelper extends SQLiteOpenHelper { private final static String TAG = "BlocklistDbHelper"; public static final String DATABASE_NAME = "blocklist.db"; public static final int DATABASE_VERSION = 1; public BlocklistDbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { createBlocklistNumberTables(db);
createBlocklistCallLogTables(db);
...... }
private void createBlocklistNumberTables(SQLiteDatabase db) { db.execSQL("CREATE TABLE IF NOT EXISTS blocklist (_id INTEGER PRIMARY KEY, number TEXT)"); }private void createBlocklistCallLogTables(SQLiteDatabase db) { db.execSQL("CREATE TABLE IF NOT EXISTS call_log (_ID INTEGER PRIMARY KEY,date INTEGER, number TEXT)"); }在成功建立了数据库之后,我们还需要一个内容提供者ContentProvider,为外界对数据库进行增删改查操作提供相关API。public class BlocklistProvider extends ContentProvider { private final static String TAG = "BlocklistProvider"; private BlocklistDbHelper mDbHelper; private final static int URI_BLOCKLIST = 1;......private final static int URI_BLOCKLIST_CALL_LOG = 2;public final static String AUTHORITY = "com.android.blocklist"; private static final UriMatcher PMATCHER = new UriMatcher(UriMatcher.NO_MATCH); static { PMATCHER.addURI(AUTHORITY, "number", URI_BLOCKLIST);PMATCHER.addURI(AUTHORITY, "call-log", URI_BLOCKLIST_CALL_LOG);...... }在AndroidManafiest里添加相关声明。<provider android:name="com.android.contacts.blocklist.data.BlocklistProvider" android:authorities="com.amigo.blocklist" android:exported="true" />提供insert方法@Override public Uri insert(Uri uri, ContentValues values) { Cursor c = null; long pid = 0; SQLiteDatabase db = mDbHelper.getWritableDatabase(); switch (PMATCHER.match(uri)) { case URI_BLOCKLIST: c = db.query("blocklist", null, number + " = ?", new String[] { String.valueOf(values.get("number")) }, null, null, null); try { if (c != null && c.getCount() == 0) { pid = db.insert(blocklist, null, values); } } catch (Exception e) { } finally { if ((null != c) && !(c.isClosed())) { c.close(); } } return ContentUris.withAppendedId(uri, pid);好了,下面我们就可以往数据库里添加黑名单了,方式也很简单Uri uri = Uri.parse("content://" + BlocklistProvider.AUTHORITY + "/number"); ContentValues insertValues = new ContentValues(1); insertValues.put("number", number); context.getContentResolver().insert(uri, insertValues);现在我们已经成功往数据库里添加了黑名单,接下来如果黑名单数据库里的号码在来电我们就要对它进行拦截。上面提到了在响铃时对通话进行拦截效果不好,那么该在什么地方拦截它呢。要知道在哪里那么就必须对Android来电流程有一定了解。Android的整个来电流程比较复杂,对于应用层来说,最早接收到framework分发的call消息的在Telecomn的CallsManager处理,在这里会对所注册的一系列通话状态进行处理,来电所对应的回调方法是onSuccessfulIncomingCall,那么在这里处理是最为及时的。@Override public void onSuccessfulIncomingCall(Call incomingCall) { Log.d(this, "onSuccessfulIncomingCall"); setCallState(incomingCall, CallState.RINGING, "successful incoming call"); final String phoneNumber = getLogNumber(incomingCall);//判断来电号码是否是黑名单 boolean isBlockNumber = mBlockListUtils.shouldBlockNumber(phoneNumber); if (isBlockNumber) {//在这里拦截它 incomingCall.reject(false, null); mCallLogManager.logCall(incomingCall, Calls.INCOMING_TYPE);//同时往黑名单数据库里新增一条包含号码和来电时间的记录 mBlockListUtils.addRejectCallLog(phoneNumber, incomingCall.getCreationTimeMillis()); }...... }
public void addRejectCallLog(String number, long date) {Uri uri = Uri.parse("content://" + AUTHORITY + "/call-log"); ContentValues insertValues = new ContentValues(2); insertValues.put(“number”, number); insertValues.put("date", date); context.getContentResolver().insert(uri, insertValues);}这样我们就成功完成了对黑名单来电的拦截,同时也把该条通话记录成功加入到了黑名单数据库的通话记录列表。接下来当用户查看通话记录时,我们需要显示那些是被成功拦截的通话记录,这里我们可以根据通话记录的时间与黑名单数据库里通话记录表里的时间去进行匹配,如果匹配成功则为拦截的通话记录。
至此对于黑名单的来电处理就介绍完毕了,实际开发中会对上面的功能进行扩展,原理大同小异,博主还要看会欧洲杯,因此就不在这里一一叙述了
。