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

  需求:

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

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

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

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

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

  [java] view plaincopyprint?package com.android.internal.telephony;

  interface ITelephony{

  boolean endCall();

  void answerRingingCall();

  }

  package com.android.internal.telephony;

  interface ITelephony{

  boolean endCall();

  void answerRingingCall();

  }

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

  [java] view plaincopyprint?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 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 getPhoneNum(Context context) {

  ArrayList numList = new ArrayList();

  //得到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;

  }

  }

  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 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 getPhoneNum(Context context) {

  ArrayList numList = new ArrayList();

  //得到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文件如下:

  [html] view plaincopyprint?

  package="com.xxxx.xxxx"

  android:versionCode="1"

  android:versionName="1.0" >

  android:icon="@drawable/ic_launcher"

  android:label="@string/app_name" >

  android:name=".MainActivity"

  android:label="@string/app_name" >

  package="com.xxxx.xxxx"

  android:versionCode="1"

  android:versionName="1.0" >

  android:icon="@drawable/ic_launcher"

  android:label="@string/app_name" >

  android:name=".MainActivity"

  android:label="@string/app_name" >

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

  [java] view plaincopyprint?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);

  }

  }

  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添加点击事件使用户可以把拦截到的电话添加到通讯录等功能。