Android四大组件应用系列——实现电话拦截和电话录音
| 一、问题描述 |
使用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四大组件应用系列——实现电话拦截和电话录音的更多相关文章
- Android四大组件应用系列5——使用AIDL实现跨进程调用Service
一.问题描述 Android应用程序的四大组件中Activity.BroadcastReceiver.ContentProvider.Service都可以进行跨进程.在上一篇我们通过ContentPr ...
- Android四大组件应用系列——使用BroadcastReceiver和Service实现倒计时
一.问题描述 Service组件可以实现在后台执行一些耗时任务,甚至可以在程序退出的情况下,让Service在后台继续保持运行状态.Service分本地服务和远程服务,Local地服务附在主进程上的m ...
- Android四大组件应用系列——Activity与Service交互实现APK下载
Servic与Activity相比它没有界面,主要是在后台执行一些任务,Service有两种启动方法startService()和bindService(),startService方式Service ...
- Android四大组件应用系列——使用ContentProvider实现跨进程通讯
一.问题描述 如何在Android中实现不同应用之间的通讯(既跨进程进行调用)?Android提供了多种实现方式,使我们可以实现跨进程访问Activity.通过ContentProvider跨进程访问 ...
- Android四大组件之——Activity的开启:StartActivity()和StartActivityForResult()(图文详解)
如需转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai 联系方式:JohnTsai.Work@gmail.com ...
- Android四大组件之——Activity的生命周期(图文详解)
转载请在文章开头处注明本博客网址:http://www.cnblogs.com/JohnTsai 联系方式:JohnTsai.Work@gmail.com [Andro ...
- android四大组件之Broadcast
广播的概念 现实中:我们常常使用电台通过发送广播发布消息,买个收音机,就能收听 Android:系统在产生某个事件时发送广播,应用程序使用广播接收者接收这个广播,就知道系统产生了什么事件.Androi ...
- 【Android开发日记】之入门篇(六)——Android四大组件之Broadcast Receiver
广播接受者是作为系统的监听者存在着的,它可以监听系统或系统中其他应用发生的事件来做出响应.如设备开机时,应用要检查数据的变化状况,此时就可以通过广播来把消息通知给用户.又如网络状态改变时,电量变化时都 ...
- Android四大组件之一“广播”
前言 Android四大组件重要性已经不言而喻了,今天谈谈的是Android中的广播机制.在我们上学的时候,每个班级的教室里都会装有一个喇叭,这些喇叭都是接入到学校的广播室的,一旦有什么重要的通知,就 ...
随机推荐
- java 类字面常量,泛化的Class引用
类名.class 就是字面常量,代表的就是该类的Class对象引用.常量需要赋值给变量 简单,安全. 编译期接受检查,不需要像forName一样置于try/catch块中. 加载后不会进行初始化,初始 ...
- Java 使用Jedis连接Redis数据库(-)
redis 安装: Linux 安装redis 1)下载jar包: 使用Jedis需要以下两个jar包: jedis-2.8.0.jar commons-pool2-2.4.2.jar 2)测试red ...
- vtiger自定上传图片的字段
废话不多说,上一篇有说到过vtiger新建模块的事 现在我新建了一个Score的模块,里面需要一个上传图片的功能 在Score界面新建一个字段叫grede 但是自定义类型里面是没有,图片这个选项的,只 ...
- 逃离迷宫 HDU1728 (bfs)
和连连看非常相似 都是求转向的BFS 改了一下就上交了... #include<cstdio> #include<cstring> #include<algorith ...
- 【Java】 剑指offer(16) 打印1到最大的n位数
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 输入数字n,按顺序打印出从1最大的n位十进制数.比如输入3,则打印 ...
- 014 在Spark中完成PV与UV的计算,重在源代码
1.代码 object LogPVAndUV{ def main(args:Array[String]):Unit={ val conf=new SparkConf() .setMaster(&quo ...
- ubuntu卸载opencv并重装opencv3.0.0
一. 卸载opencv2.4.9: Going to the "build" folder directory of opencv from terminal, and execu ...
- moodle3.15+,mysql完全的Unicode支持配置
https://docs.moodle.org/dev/Releases,moodle个版本升级的主要内容和改动 在windows是mysql.ini linux 下是mysql.cnf 因为MyS ...
- 通过pyqt5实现俄罗斯方块游戏例子
# *_* coding:utf-8 *_* # 开发团队:中国软件开发团队# 开发人员:Administrator# 开发时间:2019/3/17 2:13# 文件名称:RussiaBoard# 开 ...
- P3147 [USACO16OPEN]262144
P3147 [USACO16OPEN]262144一道非常有趣的游戏,不,题目.当数据水时,可以这样表示状态.f[i][j]表示合并[i,j]区间所能得到的最大值,有点floyed的小味道.if(f[ ...