一、问题描述

  使用BordercastReceiver和Service组件实现下述功能:

1.当手机处于来电状态,启动监听服务,对来电进行监听录音。

2.设置电话黑名单,当来电是黑名单电话,则直接挂断。

  当拨打电话或电话状态发生改变时,系统就会发出有序广播,因此我们可以使用BordercastReceiver接受广播,因BordercastReceiver执行时间短不能执行耗时任务也不能使用子线程,因此我们应启动一个Service来监听电话并进行处理

二、加入AIDL文件

  Android没有对外公开结束通话的API,要结束通话就必须使用AIDL与电话管理服务进行通信,并调用服务中的API实现结束通话,这样需要android 源码文件NeighboringCellInfo.aidl和ITelephony.aidl添加到项目中,如图所示:

Android Studio 会自动编译产生对应的类文件

三、编写TelReceiver组件
public class TelReceiver extends BroadcastReceiver {
public TelReceiver() {
} @Override
public void onReceive(Context context, Intent intent) {
Intent i=new Intent(context,ListenPhoneService.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setAction(intent.getAction());
i.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER,
intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER));//电话号码
i.putExtra(TelephonyManager.EXTRA_STATE,
intent.getStringExtra(TelephonyManager.EXTRA_STATE));//电话状态
context.startService(i);//启动服务
}
}

  注册广播:

<receiver android:name=".TelReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
四、编写ListenPhoneService组件
public class ListenPhoneService  extends  Service {
private AudioManager mAudioManager;
private TelephonyManager tm;
public ListenPhoneService() {
} @Override
public void onCreate() {
super.onCreate();
mAudioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE);
tm=(TelephonyManager)getSystemService(Service.TELEPHONY_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){//去电广播,android没有来电话广播
}else{//去掉拨打电话就是来电状态了
//方法1
//获得来电电话
// String number=intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
//获得电话状态
// String state=intent.getStringExtra(TelephonyManager.EXTRA_STATE);
// Log.d("jereh", "incoming phone:" + number);
// Log.d("jereh","call state:"+state);
// TelephonyManager.EXTRA_STATE_IDLE: 没有来电 或者 挂断
// TelephonyManagerEXTRA_STATE_OFFHOOK: 接起电话
// TelephonyManager.EXTRA_STATE_RINGING:当电话呼入时,响铃时
// if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
// if(number.equals("13280998858")){//拦截指定的电话号码
// mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
// Log.d("jereh","电话被拦截");
// stopCall();
// mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);//恢复铃声
// }
// }else if(state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
//接起电话
// recordCall();//开始录音
// }else if(state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
// stopCall();//停止录音
// }
//方法2
// 设置一个监听器,监听电话状态
tm.listen(listener,PhoneStateListener.LISTEN_CALL_STATE);
} return super.onStartCommand(intent, flags, startId);
} /**
* 挂断电话
*/
private void stopCall(){
try {
//Android的设计将ServiceManager隐藏了,所以只能使用反射机制获得。
Method method=Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
IBinder binder=(IBinder)method.invoke(null, new Object[]{"phone"});//获得系统电话服务
ITelephony telephoney=ITelephony.Stub.asInterface(binder);
telephoney.endCall();//挂断电话
stopSelf();//停止服务
} catch (Exception e) {
e.printStackTrace();
}
}
PhoneStateListener listener=new PhoneStateListener(){
@Override
public void onCallStateChanged(int state,String incomingNumber){
switch (state){
//手机空闲了
case TelephonyManager.CALL_STATE_IDLE:
stopCall();//停止录音
break;
//接起电话
case TelephonyManager.CALL_STATE_OFFHOOK:
recordCall();//开始录音
break;
// 响铃时
case TelephonyManager.CALL_STATE_RINGING:
Log.e("jereh", "来电号码是:"+ incomingNumber);
// 如果该号码属于黑名单
if (incomingNumber.equals("123456")) {
// 如果是黑名单,就进行屏蔽
stopCall();
}
break;
}
}
}; /**
* 停止录音
*/
private void stopRecord(){
if(recording){
recorder.stop();
recorder.release();
recording=false;
stopSelf();//停止服务
}
}
/**
* 电话录音
*/
private MediaRecorder recorder;
private boolean recording ;
private void recordCall(){
Log.d("jereh", "record calling")
if( Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
recorder=new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);//读麦克风的声音
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//设置输出格式
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 编码方式
File file=new File(Environment.getDownloadCacheDirectory().getAbsolutePath(),"recorder");
if(!file.exists()){
file.mkdir();
}
recorder.setOutputFile(file.getAbsolutePath() + "/"
+ System.currentTimeMillis() + "3gp");// 存放的位置是放在sd卡recorder目录下
try {
recorder.prepare();
recorder.start();
recording=true; } catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
Service XML配置
<service
android:name=".ListenPhoneService"
android:enabled="true"
android:exported="true" >
</service>
五、最后别忘了一些权限的设置
<!-- 添加访问手机电话状态的权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 拨打电话权限 -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<!-- 监听手机去电的权限 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
作者:杰瑞教育
出处:http://www.cnblogs.com/jerehedu/ 
版权声明:本文版权归烟台杰瑞教育科技有限公司和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

技术咨询:
 

Android四大组件应用系列——实现电话拦截和电话录音的更多相关文章

  1. Android四大组件应用系列5——使用AIDL实现跨进程调用Service

    一.问题描述 Android应用程序的四大组件中Activity.BroadcastReceiver.ContentProvider.Service都可以进行跨进程.在上一篇我们通过ContentPr ...

  2. Android四大组件应用系列——使用BroadcastReceiver和Service实现倒计时

    一.问题描述 Service组件可以实现在后台执行一些耗时任务,甚至可以在程序退出的情况下,让Service在后台继续保持运行状态.Service分本地服务和远程服务,Local地服务附在主进程上的m ...

  3. Android四大组件应用系列——Activity与Service交互实现APK下载

    Servic与Activity相比它没有界面,主要是在后台执行一些任务,Service有两种启动方法startService()和bindService(),startService方式Service ...

  4. Android四大组件应用系列——使用ContentProvider实现跨进程通讯

    一.问题描述 如何在Android中实现不同应用之间的通讯(既跨进程进行调用)?Android提供了多种实现方式,使我们可以实现跨进程访问Activity.通过ContentProvider跨进程访问 ...

  5. Android四大组件之——Activity的开启:StartActivity()和StartActivityForResult()(图文详解)

                如需转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai       联系方式:JohnTsai.Work@gmail.com   ...

  6. Android四大组件之——Activity的生命周期(图文详解)

        转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai       联系方式:JohnTsai.Work@gmail.com       [Andro ...

  7. android四大组件之Broadcast

    广播的概念 现实中:我们常常使用电台通过发送广播发布消息,买个收音机,就能收听 Android:系统在产生某个事件时发送广播,应用程序使用广播接收者接收这个广播,就知道系统产生了什么事件.Androi ...

  8. 【Android开发日记】之入门篇(六)——Android四大组件之Broadcast Receiver

    广播接受者是作为系统的监听者存在着的,它可以监听系统或系统中其他应用发生的事件来做出响应.如设备开机时,应用要检查数据的变化状况,此时就可以通过广播来把消息通知给用户.又如网络状态改变时,电量变化时都 ...

  9. Android四大组件之一“广播”

    前言 Android四大组件重要性已经不言而喻了,今天谈谈的是Android中的广播机制.在我们上学的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦有什么重要的通知,就 ...

随机推荐

  1. wpf 加阴影效果导致内容模糊的问题解决

    这个和GPU有关,参考地址 https://www.cplotts.com/2009/02/25/gpu-effects-blurry-text/ 产生问题的代码如下: <Window x:Cl ...

  2. hdu1698

    /*区间更新*/#include <cstdio> #include <algorithm> using namespace std; #define lson l , m , ...

  3. hdu4533 线段树维护分段函数

    更新:x1,y1,x2,y2不用long long 会wa.. #include<iostream> #include<cstring> #include<cstdio& ...

  4. linux下如何使用gdb调试

    gdb是linux下非常好用的一个调试工具,虽然它是命令行模式的调试工具,但是它的功能强大到你无法想象,这里简单介绍下gdb下常用的命令. 首先编译生成可执行文件(这里的test.c是一个简单的求前n ...

  5. 《剑指offer》-找到数组中重复的数字

    题目描述 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度为 ...

  6. poj 3233 S = A + A^2 + A^3 + … + A^k A是一个n X n矩阵 (矩阵快速幂)

    S = A + A^2 + A^3 + … + A^k A是一个n*n矩阵 Sample Input 2 2 4 //n k MOD0 11 1Sample Output 1 22 3 先求 I +  ...

  7. Web前端开发最佳实践(13):前端页面卡顿?可能是DOM操作惹的祸,你需要优化代码

    文档对象模型(DOM)是一个独立于特定语言的应用程序接口.在浏览器中,DOM接口是以JavaScript语言实现的,通过JavaScript来操作浏览器页面中的元素,这使得DOM成为了JavaScri ...

  8. Docker+Jenkins持续集成环境(1)使用Docker搭建Jenkins+Docker持续集成环境

    本文介绍如何通过Jenkins的docker镜像从零开始构建一个基于docker镜像的持续集成环境,包含自动化构建.发布到仓库\并部署上线. 0. 前置条件 服务器安装docker,并启动docker ...

  9. List实体去重

    public static ArrayList<Room> removeDuplicate(List<Room> room) { Set<Room> set = n ...

  10. go语言中goroute使用:=遇到的坑

    先看下源代码,预想从1至N总取出所有能被a或b整除的正整数之和,为了利用go语言的并行优势,特使用goroute特性来实现,同时使用普通顺序计算进行效率比较分析 package chango impo ...