Android 代码实现来电拦截

本文介绍如何在Android平台上开发一个应用,用于拦截并记录陌生来电,避免骚扰。通过创建自定义广播接收器和使用AIDL接口,实现对来电号码的检查与拦截功能,并在用户界面上显示拦截记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了更好地理解这个Demo,我先向大家介绍一下需求与功能。

需求:

每天都会有很多无聊的电话,比如推销商品等,占用我们大量时间不说,有时候还会打乱我们的思路,扰乱我们的正常生活。所以实现一个对某些号码(比如陌生号码,指定号码/黑名单等)进行拦截以避免受到骚扰,是很有现实用途的。

为了避免程序过分复杂,造成不易学习的麻烦我在这里只实现“如果来电号码没在联系人中,则进行挂断,并存入xml文件(SharedPreferences),并在首页显示”,以期达到抛砖引玉的效果。

其实在android在1.1版本后就已经把Phone类的相关API给隐藏起来了,想要用代码实现挂断电话的功能,就必须通过AIDL才行,然后利用反射来使用其方法。

第一步:在程序中新建一个包,包名必须为:com.android.internal.telephony,因为要使用aidl。

第二步:在这个包里面新建一个名为ITelephony.aidl的文件,然后在文件里面写入代码:

package com.android.internal.telephony;
	interface ITelephony{
		boolean endCall();
		void answerRingingCall();
	}

然后是要监听电话状态,当来电时,检测来电号码是否符合拦截标准(这个拦截标准是我们自己定的,你可以拦截指定号码如实现一个黑名单的功能,我们在这里拦截所有不在联系人里的号码,并把此号码存入文件,以方便在首页显示),代码如下:

import java.lang.reflect.Method;
import java.util.ArrayList;

import com.android.internal.telephony.ITelephony;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.telephony.TelephonyManager;
import android.util.Log;

public class PhoneStatReceiver extends BroadcastReceiver{

	String TAG = "tag";
	TelephonyManager telMgr;
	@Override
	public void onReceive(Context context, Intent intent) {
        telMgr = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
        switch (telMgr.getCallState()) {
            case TelephonyManager.CALL_STATE_RINGING:
            	String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); 
            	Log.v(TAG,"number:"+number);
            	if (!getPhoneNum(context).contains(number)) {
            		SharedPreferences phonenumSP = context.getSharedPreferences("in_phone_num", Context.MODE_PRIVATE);
            		Editor editor = phonenumSP.edit();
            		editor.putString(number,number);
            		editor.commit();
            		endCall();
            	}
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:                               
                break;
            case TelephonyManager.CALL_STATE_IDLE:                               
                break;
        }
        
	}
	/**
	 * 挂断电话
	 */
    private void endCall()
    {
        Class<TelephonyManager> c = TelephonyManager.class;         
        try
        {
            Method getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[]) null);
            getITelephonyMethod.setAccessible(true);
            ITelephony iTelephony = null;
            Log.e(TAG, "End call.");
            iTelephony = (ITelephony) getITelephonyMethod.invoke(telMgr, (Object[]) null);
            iTelephony.endCall();
        }
        catch (Exception e)
        {
            Log.e(TAG, "Fail to answer ring call.", e);
        }        
    }
    private ArrayList<String>  getPhoneNum(Context context) {
    	ArrayList<String> numList = new ArrayList<String>();
		//得到ContentResolver对象   
        ContentResolver cr = context.getContentResolver();     
        //取得电话本中开始一项的光标   
        Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);   
        while (cursor.moveToNext())   
        {               
            // 取得联系人ID   
            String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));   
            Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
            		ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);   
            // 取得电话号码(可能存在多个号码)   
            while (phone.moveToNext())   
            {   
                String strPhoneNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));   
                numList.add(strPhoneNumber);  
                Log.v("tag","strPhoneNumber:"+strPhoneNumber);
            }   
            
            phone.close();   
        }   
        cursor.close();
        return numList;
	}
}
这里我们要注意以下几点:

1.PhoneStatReceiver一定要在清单文件(AndroidManifest.xml)中注册。

2.一定要添加权限

AndroidManifest文件如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxxx.xxxx"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />
    <!-- 挂断手机的权限 -->
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <!-- 读取手机状态的权限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <!-- 读content的权限 -->
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 注册监听手机状态 -->
        <receiver android:name=".PhoneStatReceiver">
            <intent-filter android:priority="1000" >
                <action android:name="android.intent.action.PHONE_STATE" />
            </intent-filter>
        </receiver>
        
    </application>

</manifest>
其实最到这里,整个拦截功能就已经实现了,但是呢,我们的首页也不能让它光秃秃的显示个Hello World!吧。所以,在MainActivity中,再给大家加点料,就是在listView中显示所有已经被拦截的电话号码,代码如下:

import java.util.Map;
import android.app.ListActivity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;

public class MainActivity extends ListActivity {
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        SharedPreferences phonenumSP = getSharedPreferences("in_phone_num", Context.MODE_PRIVATE);
		Map map = phonenumSP.getAll();
        Object[] array = map.keySet().toArray();
        Log.v("tag",map.toString()+map.size());
        ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,array);
        
        setListAdapter(adapter);
    }
}

好了,整个项目就完成了,我们可以拦截骚扰电话了,这只是一个小例子,你可以添加一些控制功能以更加人性化,比如开启和关闭拦截,可选的拦截时间段,给ListView添加点击事件使用户可以把拦截到的电话添加到通讯录等功能。

不过,这里只是完成了对来电的拦截功能,未对外拨电话进行拦截,下篇博客再写吧!

参考:http://blog.163.com/wu_zefeng/blog/static/1826291752011312114420975/

    http://www.cotrun.net/blog/1572.html


评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值