为了更好地理解这个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添加点击事件使用户可以把拦截到的电话添加到通讯录等功能。



转载于:https://blog.51cto.com/7594980/1285653