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

需求:

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

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

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

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

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

  1. package com.android.internal.telephony;
  2. interface ITelephony{
  3. boolean endCall();
  4. void answerRingingCall();
  5. }

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

  1. import java.lang.reflect.Method;
  2. import java.util.ArrayList;
  3. import com.android.internal.telephony.ITelephony;
  4. import android.app.Service;
  5. import android.content.BroadcastReceiver;
  6. import android.content.ContentResolver;
  7. import android.content.Context;
  8. import android.content.Intent;
  9. import android.content.SharedPreferences;
  10. import android.content.SharedPreferences.Editor;
  11. import android.database.Cursor;
  12. import android.provider.ContactsContract;
  13. import android.telephony.TelephonyManager;
  14. import android.util.Log;
  15. public class PhoneStatReceiver extends BroadcastReceiver{
  16. String TAG = "tag";
  17. TelephonyManager telMgr;
  18. @Override
  19. public void onReceive(Context context, Intent intent) {
  20. telMgr = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
  21. switch (telMgr.getCallState()) {
  22. case TelephonyManager.CALL_STATE_RINGING:
  23. String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
  24. Log.v(TAG,"number:"+number);
  25. if (!getPhoneNum(context).contains(number)) {
  26. SharedPreferences phonenumSP = context.getSharedPreferences("in_phone_num", Context.MODE_PRIVATE);
  27. Editor editor = phonenumSP.edit();
  28. editor.putString(number,number);
  29. editor.commit();
  30. endCall();
  31. }
  32. break;
  33. case TelephonyManager.CALL_STATE_OFFHOOK:
  34. break;
  35. case TelephonyManager.CALL_STATE_IDLE:
  36. break;
  37. }
  38. }
  39. /**
  40. * 挂断电话
  41. */
  42. private void endCall()
  43. {
  44. Class<TelephonyManager> c = TelephonyManager.class;
  45. try
  46. {
  47. Method getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[]) null);
  48. getITelephonyMethod.setAccessible(true);
  49. ITelephony iTelephony = null;
  50. Log.e(TAG, "End call.");
  51. iTelephony = (ITelephony) getITelephonyMethod.invoke(telMgr, (Object[]) null);
  52. iTelephony.endCall();
  53. }
  54. catch (Exception e)
  55. {
  56. Log.e(TAG, "Fail to answer ring call.", e);
  57. }
  58. }
  59. private ArrayList<String>  getPhoneNum(Context context) {
  60. ArrayList<String> numList = new ArrayList<String>();
  61. //得到ContentResolver对象
  62. ContentResolver cr = context.getContentResolver();
  63. //取得电话本中开始一项的光标
  64. Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
  65. while (cursor.moveToNext())
  66. {
  67. // 取得联系人ID
  68. String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
  69. Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
  70. ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
  71. // 取得电话号码(可能存在多个号码)
  72. while (phone.moveToNext())
  73. {
  74. String strPhoneNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
  75. numList.add(strPhoneNumber);
  76. Log.v("tag","strPhoneNumber:"+strPhoneNumber);
  77. }
  78. phone.close();
  79. }
  80. cursor.close();
  81. return numList;
  82. }
  83. }

这里我们要注意以下几点:

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

2.一定要添加权限

AndroidManifest文件如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.xxxx.xxxx"
  4. android:versionCode="1"
  5. android:versionName="1.0" >
  6. <uses-sdk android:minSdkVersion="8" />
  7. <!-- 挂断手机的权限 -->
  8. <uses-permission android:name="android.permission.CALL_PHONE"/>
  9. <!-- 读取手机状态的权限 -->
  10. <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  11. <!-- 读content的权限 -->
  12. <uses-permission android:name="android.permission.READ_CONTACTS" />
  13. <application
  14. android:icon="@drawable/ic_launcher"
  15. android:label="@string/app_name" >
  16. <activity
  17. android:name=".MainActivity"
  18. android:label="@string/app_name" >
  19. <intent-filter>
  20. <action android:name="android.intent.action.MAIN" />
  21. <category android:name="android.intent.category.LAUNCHER" />
  22. </intent-filter>
  23. </activity>
  24. <!-- 注册监听手机状态 -->
  25. <receiver android:name=".PhoneStatReceiver">
  26. <intent-filter android:priority="1000" >
  27. <action android:name="android.intent.action.PHONE_STATE" />
  28. </intent-filter>
  29. </receiver>
  30. </application>
  31. </manifest>

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

  1. import java.util.Map;
  2. import android.app.ListActivity;
  3. import android.content.Context;
  4. import android.content.SharedPreferences;
  5. import android.os.Bundle;
  6. import android.util.Log;
  7. import android.widget.ArrayAdapter;
  8. public class MainActivity extends ListActivity {
  9. @Override
  10. public void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. SharedPreferences phonenumSP = getSharedPreferences("in_phone_num", Context.MODE_PRIVATE);
  13. Map map = phonenumSP.getAll();
  14. Object[] array = map.keySet().toArray();
  15. Log.v("tag",map.toString()+map.size());
  16. ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,array);
  17. setListAdapter(adapter);
  18. }
  19. }

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

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

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

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

Android 代码实现来电拦截的更多相关文章

  1. Android实战_来电拦截专家

    1 项目演示: 2 代码演示: 1)MainActivity类代码: MainActivity类代码: package com.example.phoneinteceptor_one;import j ...

  2. 实现android手机来电拦截系统页面弹出自定义页面特效

    如何实现android手机来电拦截系统页面弹出自定义页面特效, 首先:    我们需要注册一个监听来电的广播PhoneStateReceiver 类:其次:    在onReceive里面我们获取an ...

  3. Android监听来电和去电

    要监听android打电话和接电话,只需下面2步骤1.第一步,写一个Receiver继承自BroadcastReceiver import android.app.Service; import an ...

  4. 下载最新Android代码的方法

    之前我是去Android官方网站下载最新Android代码,但是这种方法需要FQ,而且有时候FQ又不太方便,今天我发现一个不错的网站,是清华大学搞的,跟Android官方的代码基本保持同步,而且下载方 ...

  5. Android代码混淆官方实现方法

    首先查看一下 “project.properties” 这个文件: # This file is automatically generated by Android Tools.# Do not m ...

  6. 编写高效的Android代码

    编写高效的Android代码 毫无疑问,基于Android平台的设备一定是嵌入式设备.现代的手持设备不仅仅是一部电话那么简单,它还是一个小型的手持电脑,但是,即使是最快的最高端的手持设备也远远比不上一 ...

  7. Android代码内存优化建议-OnTrimMemory优化

    原文  http://androidperformance.com/2015/07/20/Android代码内存优化建议-OnTrimMemory优化/ OnTrimMemory 回调是 Androi ...

  8. Android代码混淆和项目宣布步骤记录器

    原本放在一起Android项目与发布的文件相混淆.我突然想到,为什么不写博客,分享.有这篇文章的情况下,. Android代码混淆及项目公布步骤记录 一.清理代码中的调试信息,如Log.System. ...

  9. Android 代码混淆 混淆方案

    本篇文章:自己在混淆的时候整理出比较全面的混淆方法,比较实用,自己走过的坑,淌出来的路.请大家不要再走回头路,可能只要我们代码加混淆,一点不对就会导致项目运行崩溃等后果,有许多人发现没有打包运行好好地 ...

随机推荐

  1. FastReport.Net使用:[18]形状(Shape)控件用法

    FastReport中,如果要画一张漂亮的报表,经常会画些形状控件来美化?那么如何用好形状(Shape)控件呢? 形状的5种类型 在工具栏的图形控件下拉菜单中有5种类型(矩形.圆角矩形.椭圆形.三角形 ...

  2. 【BZOJ 2436】 2436: [Noi2011]Noi嘉年华 (区间DP)

    2436: [Noi2011]Noi嘉年华 Description NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不 ...

  3. Palindromic Tree 回文自动机-回文树 例题+讲解

    回文树,也叫回文自动机,是2014年被西伯利亚民族发明的,其功能如下: 1.求前缀字符串中的本质不同的回文串种类 2.求每个本质不同回文串的个数 3.以下标i为结尾的回文串个数/种类 4.每个本质不同 ...

  4. BZOJ 2434 [Noi2011]阿狸的打字机(AC自动机)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2434 [题目大意] 给出一个打印的过程,'a'-'z'表示输入字母,P表示打印该字符串 ...

  5. 【刷水-贪心】BZOJ1629-[Usaco2007 Demo]Cow Acrobats

    [题目大意] 有n个头牛,给出体重和力量.每个牛的危险值等于它上面的牛的体重总和减去它的力量值,求所有方案中危险值最大值的最小值. [思路] 贪心.一开始脑补的贪心是体重大的先放下面,体重相同的根据力 ...

  6. ZOJ 3256 Tour in the Castle 插头DP 矩阵乘法

    题解 这题是一道非常好的插头题,与一般的按格转移的题目不同,由于m很大,要矩阵乘法,这题需要你做一个按列转移的插头DP. 按列转移多少与按格转移不同,但大体上还是基于连通性进行转移.每一列只有右插头是 ...

  7. 五、python的练习题

    1.输入一行字符,分别统计出其中英文字母.空格.数字和其他字符的个数. #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/6/5 ...

  8. java - 内存泄漏

    内存泄漏问题产生原因 长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场 ...

  9. java类中属性的加载顺序,以及内存分配情况介绍

    看下面例子及说明: /** 假如有外部类调用了该类,代码为:new StaticTest(); 那么下面是类属性的加载顺序 */ public class StaticTest{ public int ...

  10. [置顶] linux常用命令大全

    SSH 密令控制台 user/pwd 一:停止tomcat 1,cd .. 进入根目录 2,cd home/ 3,ll 4,cd bin/ 进入tomcat bin目录 5,ll 6,ps -ef | ...