前段时间在开发一款应用,里面涉及到一个来电拦截的功能,于是乎就开始了对于来电如何拦截进行了探索,最后总结出了实现来电拦截的两种方法,并且经过实际的真机验证,在对比两种可以实现的方法,我们找出了其中较优的一种实现。

对于来电如何拦截,我们想象一下要拦截来电,首先我们的必须知道,有没有电话打进来,只有确定来了电话,我们才好去拦截,就像战斗中拦截导弹一样,没有雷达去捕获来袭导弹的信息,那就没法拦截掉来袭的导弹。这就是为什么某些导弹要使用隐形技术,目的就是为了尽量避开雷达的捕捉,增加拦截的难度。同样在电话拦截里面,我们也必须要有这样的一部“雷达”来捕捉来电。那么在Android里面哪些类可以实现这种雷达的效果呢?

第一种是PhoneStateListener,手机状态监听器,该类可以监听手机的各种状态,包括服务的状态、信号强度、消息等待指示(语音信箱)、通话转移、呼叫状态、设备单元位置、数据连接状态、数据流量方向等,我们正是利用了它来实现对于来电的监听,如下代码是我们继承PhoneStateListener的一个类的定义

class MyPhoneStateListener extends PhoneStateListener{

@Override

public void onCallStateChanged(int state, String incomingNumber) {

switch (state) {

case TelephonyManager.CALL_STATE_IDLE:

result+=" 手机空闲起来了  ";

break;

case TelephonyManager.CALL_STATE_RINGING:

result+="  手机铃声响了,来电号码:"+incomingNumber;

break;

case TelephonyManager.CALL_STATE_OFFHOOK:

result+=" 电话被挂起了 ";

default:

break;

}

super.onCallStateChanged(state, incomingNumber);

}

}

在我们复写onCallStateChanged()这个方法中,我们可以获取到来电的号码,也就是上面所说的String incomingNumber。当然我们要读取手机的状态也需要在AndroidManifest.xml文件中申明以下权限:

其中来电状态即是:TelephonyManager.CALL_STATE_RINGING,我们要拦截来电即可在这个状态下实现我们的拦截操作stopCall(),该方法将在下文实现。对于MyPhoneStateListener具体的使用方法即是在我们要拦截来电的Activity里面使用以下代码:

//获取电话服务

TelephonyManager

manager = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);

// 设置PhoneStateListener中的listen_call_state状态进行监听

manager.listen(new MyPhoneStateListener(),PhoneStateListener.LISTEN_CALL_STATE);

这样监听器设置完成后,我们就可以监听来电状态,然后实施拦截。好了,第一种拦截方式实现基本完成。

但是我们思考一下,对于这种方法虽然实现了对于来电的拦截。我们退出这个Activity再试试好像不怎么有效。我想大多数人希望的是,我们的这个来电拦截应用,可以在用户设置开启以后,然后退出了我们的应用还可以正常拦截到来电。说到这时,有的同学或许会说可以在后台开一个进程或Service,嗯,这样是可以实现的。但我想这样的方法虽然可以实现来电,但是有一点不怎么完美。这里说点题外话,有用过Android手机的同学或许有这样的经历,就是我们不论清理了多少次内存,清理完成不一会,手机的内存又被占用了百分七八十。这就是后台有很多服务进程自启动了,这样不仅消耗了系统资源,同时也消耗电源。这样手机待机时间就直线下降了,这就是很多人在抱怨电池不够用。有人或许会说可以用软件来禁止这些后台的软件,那是站在用户的角度。站在开发者的角度,那假如我们应用开启的Service不幸被用户强行禁用了或kill掉了,此时再有来电,我想就没办法拦截了!这时用户会觉得:啊,那个来电拦截的应用怎么没用啊?好吧,卸掉……

为避免这个问题,我们可以换个思路,这里我们想到第二种实现方法,使用Broadcast Receiver,通过获取来电去电的广播,从而进行拦截操作,这样就避免上面说的一系列问题。那怎么弄呢?好我们先写一个继承BroadcastReceiver的类PhoneStatReceiver,如下代码所示,然后复写他的onReceive()方法

public class PhoneStatReceiver  extends BroadcastReceiver{

private static final String TAG = "PhoneStatReceiver";

private static boolean incomingFlag = false;

private static String incoming_number = null;

private Context mycon;

@Override

public void onReceive(Context context, Intent intent) {

//如果是去电

if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){

incomingFlag = false;

String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);

Log.i(TAG, "call OUT:"+phoneNumber);

}else{

//如果是来电

TelephonyManager tm =

(TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);

switch (tm.getCallState()) {

case TelephonyManager.CALL_STATE_RINGING:

incomingFlag = true;//标识当前是来电

incoming_number= intent.getStringExtra("incoming_number");

if(setting_nodesrap==1)  {

stopCall(incoming_number);//拦截来电

abortBroadcast();//截断广播

}

Log.i(TAG, "RINGING :"+ incoming_number);

break;

case TelephonyManager.CALL_STATE_OFFHOOK:

if(incomingFlag){

Log.i(TAG, "incoming ACCEPT :"+ incoming_number);

                          }

break;

case TelephonyManager.CALL_STATE_IDLE:

if(incomingFlag){

Log.i(TAG, "incoming IDLE");

}

break;

}

}

}

}

在此我们还要记得在AndroidManifest.xml配置文件中加入我们的PhoneStatReceiver注册代码以及权限申明代码,如下:

至于在其中实现拦截操作的方法stopCall()具体源码大家可以加入自己的操作,以下是我实现的一种:

//电话拦截

public void stop(String incoming_number) {

AudioManager mAudioManager = (AudioManager) mycon.getSystemService(Context.AUDIO_SERVICE);

mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);//静音处理

iTelephony = getITelephony(mycon); //获取电话接口

try {

iTelephony.endCall();//结束电话

} catch (RemoteException e) {

e.printStackTrace();

}

//再恢复正常铃声

mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);

Log.i("----", "来电 :"+ incoming_number);

}

在其中用到了ITelephony 类的对象iTelephony。其中ITelephony是Android系统Phone类中TelephonyManager提供给上层应用程序用户与telephony进行操作交互的接口。但是在Android 1.5以后的版本系统已经把Phone类给隐藏起来了,想要用代码实现挂断电话,就必须通过AIDL(Android Interface Definition Language,即Android接口定义语言)才行。

我们找到ITelephone的接口还要加入以下方法getITelephony()获取接口:

private static ITelephony getITelephony(Context context) {

TelephonyManager mTelephonyManager = (TelephonyManager) context

.getSystemService(Context.TELEPHONY_SERVICE);

Class c = TelephonyManager.class;

Method getITelephonyMethod = null;

try {

getITelephonyMethod = c.getDeclaredMethod("getITelephony",

(Class[]) null); // 获取声明的方法

getITelephonyMethod.setAccessible(true);

} catch (SecurityException e) {

e.printStackTrace();

} catch (NoSuchMethodException e) {

e.printStackTrace();

}

try {

ITelephony iTelephony = (ITelephony) getITelephonyMethod.invoke(

mTelephonyManager, (Object[]) null); // 获取实例

return iTelephony;

} catch (Exception e) {

e.printStackTrace();

}

return iTelephony;

}

获取ITelephone的接口的方法在我们的工程文件的src目录下建一个package命名为com.android.internal.telephony,将我们的ITelephony.aidl文件导入到这个包。ITelephony.aidl文件下载链接:http://pan.baidu.com/share/link?shareid=438259&uk=421763582

本次讲解到此结束,希望你看完本文能有所收获。这里说明一下以上讲解所用到的代码并不是完整的,是我们实现中用到的主要部分。还要说明的一个问题就是我们实现后,会发现在模拟器上可以直接挂断来电。而在真机上虽然能拦截掉来电但是,并不能直接挂断,而是将电话转移挂起,在拨打方,我们会听到:“你所拨打的电话正在通话中,请稍候再拨!(然后是英文的提示)”,这时我们的拦截方其实已经拦截掉来电了。还有真机在拦截之前会有“嘟”的一声提示,不能做到完全悄无声息的拦截。这个问题目前还没找到解决的好方法。不过360手机安全卫士拦截不知道能不能做到这样完全悄无声息的拦截,这个我没有测试,若能的话不知道他们是什么技术解决的。不过我也在网上查了,有人说这个是第三方软件没办法解决的,而要靠移动通讯服务商!若有哪位朋友有好方法可以解决这个问题,可以和大家分享一下!其他问题我们下次再讨论。若有问题,可以给我留言!希望你学习工作愉快!

转载于:https://www.cnblogs.com/wangdacui/p/3824112.html

Android 来电拦截的开发实现相关推荐

  1. Android屏蔽呼出电话提示音,Android来电拦截及拦截后的提示音

    Android电话拦截及拦截后的提示音 1. 电话拦截 这个功能大家可能都知道了,就是利用反射原理调用ITelephony的隐藏方法来实现.这个就不说了,在附件的代码里有. 2.拦截后提示忙音/空号/ ...

  2. android 来电拦截

    电话是 在TelephonyManager中有一个私有方法getITelephony(),能获得ITelephony接口实例,该接口中有endCall()方法,该方法能拦截电话. 1. 在服务中设置电 ...

  3. Android来电拦截及拦截后的提示音

    1. 电话拦截 这个功能大家可能都知道了,就是利用反射原理调用ITelephony的隐藏方法来实现.这个就不说了,在附件的代码里有. 2.拦截后提示忙音/空号/已关机/已停机 这个功能其实是要用到MM ...

  4. Android来电拦截及来电转移

    1. 电话拦截 这个功能大家可能都知道了,就是利用反射原理调用ITelephony的隐藏方法来实现.这个就不说了,在附件的代码里有. 2.拦截后提示忙音/空号/已关机/已停机 这个功能其实是要用到MM ...

  5. 基于Android RIL层实现来电拦截的技术原理(一)

    引入 目前市面上,Android上的防骚扰类应用非常多,比如腾讯手机管家.360手机卫士.金山手机卫士等.由于受Android OS设计框架,他们的来电拦截实现,都是通过接受com.android.p ...

  6. Android端来电拦截的模块实现

    安卓手机来电拦截模块 电话拦截这项功能google屏蔽了,所有得自己去找aidl文件来反射实现来电的拦截,下面是一个简单的来电拦截模块代码实现. ❶需要注意的是:所需要的权限 <!-- 权限 - ...

  7. Android 来电(包括铃声),短信拦截的实现方法

    关于拦截的文章我之前写过拦截Back按键和Home按键的处理方法,今天就开发过程中关于电话,短信的拦截做一个总结. 一:拦截来电的功能实现 现在的Android版本已经把Phone类的相关API给隐藏 ...

  8. android 自动挂断,android 来电自动接听和自动挂断(2.3以上)

    转自http://stephen830.iteye.com/blog/1181786java android 来电自动接听和自动挂断android 注意:android2.3版本不支持下面的自动接听方 ...

  9. Android智能手机网络防火墙开发的经验心得

    首届 Google 暑期大学生博客分享大赛--2010 Andriod 篇 Android 智能手机网络防火墙开发的经验心得 这篇博客主要讲述我实现一款Android手机上网防火墙的一个经验心得分享. ...

最新文章

  1. 一种消息和任务队列——beanstalkd
  2. 关于Java里面File类创建txt文件重复???
  3. H3C 交换机升级说明
  4. 计算机 维修 pdf,简单计算机维修..pdf
  5. 现金流量表整理及开发
  6. Uncaught (in promise) Error: Request failed with status code 500
  7. Slony-I双机备份
  8. 使用Jersey跨服务器上传图片 报405 Method Not Allowed错误
  9. 7-27 冒泡法排序 (20 分)
  10. @wraps 修饰器:让你的 Python 代码更加简短可爱 | 从简单实例来认识它
  11. 读书笔记-《人为什么活着》
  12. markdown html 注释,在 Markdown 注释
  13. NASA-TLX (Task Load Index)量表学习总结
  14. c语言必背数组函数100代码,C语言必背的典型程序设计题目 数组、函数参考答案.pdf...
  15. 人性的弱点 - 把握人际交往的关键
  16. Win10,Python 3.6环境下安装PyQt4
  17. 构建数据平台探索智能应用,做企业数字化升级的得力助手
  18. 微信JS-SDK实现自定义分享功能,分享给朋友,分享到朋友圈及QQ自定义分享--微信分享
  19. 阿里实现Redis亿级存储的方案
  20. Python 数据结构 之 串 的链式存储结构

热门文章

  1. MEPG4nbsp;Divxnbsp;Xvidnbsp;由来
  2. hive 中的case when嵌套与if用法实战
  3. oracle中wm_concat函数去重,oracle-常用函数-wm_contact
  4. 微信小程序统一分享,全局接管页面分享消息的一些技巧
  5. Error Writing E2PROM at AutoInc Address 0x0报错原因
  6. Kafka的leader选举
  7. 关于产品的一些思考——腾讯之QQ音乐
  8. iOS《study古诗》APP-隐私政策
  9. evince命令 pdf中文显示乱码解决办法
  10. 解决kafka消费积压问题