前文已经介绍了基本的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
    }
}

       android通话状态监听源码