前文已经介绍了基本的android对系统事件的监听,假如对这些还不了解的请移步:Android监听器实现(一)Broadcast方式监听系统事件
因为目前我写的一个应用需要对通话挂断进行处理,经过对api和网上资料的查询,发现对通话状态的监听只有3种:
public static final int CALL_STATE_IDLE = 0 //无通话状态 public static final int CALL_STATE_RINGING = 1 //响铃状态 public static final int CALL_STATE_OFFHOOK = 2 //通话中
经过查资料发现官方没有提供对通话结束的api,但是通过对于通话状态改变的通知不能够满足我对于挂机的处理,那我们先分析一下如何能够更精细的获得当前通话状态(来电,通话,挂机)。
1、我们要取得当前通话状态
2、取得之前通话状态
3、对这两个状态进行对比
针对于这些分析过程,我们需要保存之前的通话状态,这个可以通过各种方式实现(文件流、sqiite等等),我是使用sqiite方式实现的,主要是因为我写的项目需要使用到sqlite,所以干脆直接拿来用了。对于不熟悉这些的童鞋可以使用文件流或者其他的方式。有些童鞋会问:“为什么不直接在Broadcast类中使用一个静态变量保留原通话状态?”。这是因为每次系统通话状态发生改变之后会调用broadcast类的onrecieve()方法,方法执行完就被系统回收了,每次都是重新创建出来的类,所以每次这个变量都是初始值。
好了,废话不多说了,我们直接上代码,本次我使用的依然是上次文章中的源码,所以我只写出本例中的关键部分,其他的请各位看下面下载链接中的源码。
package com.ls.broadcast; import com.ls.broadcast.util.SqliteUtil; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; /** * 系统事件监听器监听器 * * @author ls * @version 2013-07-29 8:18 * */ public class MyPhoneBroadcastListener extends BroadcastReceiver { /** * 手机没有通话,在一般的状态值 */ public static final int CALL_TYPE_IDEL = 0; /** * 手机通话状态值 */ public static final int CALL_TYPE_CALLING = 1; /** * 手机响铃状态值 */ public static final int CALL_TYPE_RING = 2; /** * 当前手机通话状态值 */ private int currentState = CALL_TYPE_IDEL ; /** * 手机原来的通话状态值 */ private int oldState = CALL_TYPE_IDEL ; /** * 数据库Helper类,只是帮助我们存取状态值,可以改成用文件流实现 */ private SqliteUtil sqlUtil = null; private MyPhoneListener listener; @Override//当发生监听的事件,系统会调用这个方法 public void onReceive(Context context, Intent intent) { //进行细节上的监控,我们需要操作TelephonyManager,为它设置监听器,他就给我们反馈 //拿到系统的TelephonyManager TelephonyManager tpManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); listener = new MyPhoneListener();//创建监听器 tpManager.listen( listener, PhoneStateListener.LISTEN_CALL_STATE);//设置监听器 sqlUtil = new SqliteUtil(context); } private class MyPhoneListener extends PhoneStateListener { @Override//当电话状态发生改变的时候,系统会调用这个方法 public void onCallStateChanged(int state, String incomingNumber) { //首先取得当前的状态值 oldState = sqlUtil.getOldState(); switch( state ){ case TelephonyManager.CALL_STATE_IDLE : currentState = CALL_TYPE_IDEL; break; case TelephonyManager.CALL_STATE_OFFHOOK : currentState = CALL_TYPE_CALLING; break; case TelephonyManager.CALL_STATE_RINGING : currentState = CALL_TYPE_RING; break; } //当通话状态发生改变 if( oldState == CALL_TYPE_RING && currentState == CALL_TYPE_CALLING ){ System.out.println( "接听" ); } else if( oldState == CALL_TYPE_CALLING && currentState == CALL_TYPE_IDEL ){ System.out.println( "挂断" ); } if( oldState == CALL_TYPE_IDEL && currentState == CALL_TYPE_CALLING ){ System.out.println( "拨号" ); } sqlUtil.updateState( currentState); } } }
本例子中的sqlutil是专门对上次通话状态进行存储和读取的,为了与当前状态进行对比分析的,假如童鞋们对sqiite方面的处理不是很了解,请大家换成自己熟悉的实现方式。
2、SqliteUtil类
package com.ls.broadcast.util; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import com.ls.broadcast.MyPhoneBroadcastListener; /** * 数据库帮助类 * @author ls * @version 2013-08-02 9:07 */ public class SqliteUtil extends SQLiteOpenHelper { private static final String DB_NAME = "broadcast.db"; private static final String TABLE_NAME = "config"; private SQLiteDatabase db = null; public SqliteUtil(Context context ) { super(context, DB_NAME, null, 1); // TODO Auto-generated constructor stub } public int getOldState(){ int state = 0; db = getReadableDatabase(); Cursor cursor = db.rawQuery("select * from " + TABLE_NAME , null); if( cursor.moveToFirst() ){ state = cursor.getInt( cursor.getColumnIndex("flag") ); } db.close(); return state; } public void updateState(int state ){ db = getWritableDatabase(); db.beginTransaction(); db.execSQL("update " + TABLE_NAME + " set flag=" + state); db.setTransactionSuccessful(); db.endTransaction(); db.close(); } /** * 第一次创建数据库(即DB_NAME这个数据库在机器上面不存在)的时候调用 * <br>系统会帮你创建DB_NAME这个数据库文件,你只需用建表就行了。 */ @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub this.db = db; db.execSQL("create table " + TABLE_NAME + "(flag Integer)"); db.execSQL("insert into " + TABLE_NAME + " values(" + MyPhoneBroadcastListener.CALL_TYPE_IDEL + ")"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } }