自己负责一个类似来电显示的小软件,来电监听模块使用TAPI实现,之前一直不忙,日常工作只是版本维护。这次公司提出新需求,就想借这次机会,把来电监听模块重写。
总结了一些Windows Mobile平台电话监听的几种实现方式:
1.TAPI :此方法较为简单,脱离了底层硬件,协议统一,所以使用TAPI实现电话监听不会有特例性,各家手机均支持。但是TAPI所在层比较高,得到电话信息也就较慢一些。
2.RIL: 硬件之上就是它了,最先得到电话信息,但是有OEM特性,各家实现方式不统一,所以不好匹配所有机型。不过使用它灵活性最大。所以如果使用RIL做电话监听,最大的问题就是如何去异求同。
3.监控注册表: 所有电话信息都会写注册表,所以监控注册表也就成了电话监听的一种“歪门邪道”。这种方式肯定不能第一时间得到电话事件,并且需要不停的监控注册表,实在是下策。故不采用。
4.AT指令:通过AT指令也可以实现(2010.9.26 更新)
RIL的简单使用
sdk里是没有带ril库的,自己下载ril.lib。
把.h .lib添进工程
1.实现这两个函数
void CALLBACK RilNotifyProc(DWORD dwNotifyCode, const void* pData, DWORD dwDataSize, DWORD dwParam);
void CALLBACK RilResultProc(DWORD dwResultCode, HRESULT hrCommandID, const void* pData, DWORD dwDataSize, DWORD dwParam);
2.初始化RIL
HRIL g_hRil;
HRESULT hr = RIL_Initialize(1, RilResultProc, RilNotifyProc, RIL_NCLASS_CALLCTRL, NULL, &g_hRil);
3.卸载RIL
RIL_Deinitialize(g_hRil);
测试RIL寻求共性
测试发现Windows Mobile的一款手机(WM5.0),它只响应 RIL_NOTIFY_RING;RIL_NOTIFY_CONNECT;RIL_NOTIFY_DISCONNECT这3个事件,并且来电时,如果不接听则会连续产生RIL_NOTIFY_RING事件。当本机接听来电,则会产生RIL_NOTIFY_CONNECT事件。 不管哪方挂断电话产生RIL_NOTIFY_DISCONNECT事件。
经过模拟器,Windows Mobile5/6其它实机的测试,总结做来去电监听的思路如下:
对每个事件(RIL_NOTIFY_RING;RIL_NOTIFY_CONNECT;RIL_NOTIFY_DISCONNECT)只响应一次,假定A、B两方。
A给B打电话:A响应一次RIL_NOTIFY_CONNECT表示去电(除RIL_NOTIFY_DISCONNECT再不响应其它事件);B响应一次RIL_NOTIFY_RING表示来电(除RIL_NOTIFY_DISCONNECT再不响应其它事件)。
贴出部分代码(不要觉得奇怪,没办法不同手机响应不同,所以写的比较奇怪。不能直接使用,只是让大家看一下逻辑,怎么实现共性的可以通用在不同手机上)
/******************************************************* Copyright (C), 2010, tamer FileName: CRilMonitor.cpp Author: tamer Version : 1.0.0 Date: 2010/08/28 Description: Version: 1.0.0 Function List: History: <author> <time> <version > <desc> tamer 2010/08/28 1.0.0 build this moudle ********************************************************/ #include <windows.h> #include "CRilMonitor.h" #pragma comment(lib, "ril/ril.lib") #define RIL_CALLDIR_NONE (0x00000000) CRilMonitor* CRilMonitor::s_pThis = NULL; void CALLBACK CRilMonitor::RilResultProc(DWORD dwResultCode, HRESULT hrCommandID, const void* pData, DWORD dwDataSize, DWORD dwParam) { switch ( dwResultCode ) { case RIL_RESULT_OK: { RILCALLINFO *pCallInfo = ((RILCALLINFO *)pData); // must call RIL_GetCallList if ( pCallInfo != NULL) { if (RIL_CALLDIR_INCOMING == pCallInfo->dwDirection) { //DEBUGMSG(TRUE, (TEXT("Result status:%d\n"), pCallInfo->dwStatus)); DEBUGMSG( TRUE, ( TEXT("来电号码:%s\n"), pCallInfo->raAddress.wszAddress) ); _tcscpy(s_pThis->m_szPhoneNum, pCallInfo->raAddress.wszAddress); if (s_pThis->m_lpfnIncomingCall != NULL) { s_pThis->m_lpfnIncomingCall(s_pThis->m_szPhoneNum); } } if (RIL_CALLDIR_OUTGOING == pCallInfo->dwDirection) { DEBUGMSG( TRUE, ( TEXT("去电号码:%s\n"), pCallInfo->raAddress.wszAddress) ); _tcscpy(s_pThis->m_szPhoneNum, pCallInfo->raAddress.wszAddress); if (s_pThis->m_lpfnDialingCall != NULL) { s_pThis->m_lpfnDialingCall(s_pThis->m_szPhoneNum); } } } break; } } } void CALLBACK CRilMonitor::RilNotifyProc(DWORD dwNotifyCode, const void* pData, DWORD dwDataSize, DWORD dwParam) { //DEBUGMSG(TRUE, (TEXT("RilNotifyCode:%d\n"), dwNotifyCode^RIL_NCLASS_CALLCTRL)); switch(dwNotifyCode) { case RIL_NOTIFY_RING: if (!s_pThis->m_bFlag) { s_pThis->m_bFlag = TRUE; RIL_GetCallList( s_pThis->m_hRil ); } break; case RIL_NOTIFY_CONNECT: if (!s_pThis->m_bFlag) { s_pThis->m_bFlag = TRUE; RIL_GetCallList( s_pThis->m_hRil ); } break; case RIL_NOTIFY_DISCONNECT: if (s_pThis->m_bFlag) { s_pThis->m_bFlag = FALSE; DEBUGMSG(TRUE, (TEXT("挂断电话!\n"))); if (s_pThis->m_lpfnDisconnectedCall != NULL) { s_pThis->m_lpfnDisconnectedCall(s_pThis->m_szPhoneNum); } } break; case RIL_NOTIFY_CALLSTATECHANGED: if (s_pThis->m_bFlag) { s_pThis->m_bFlag = FALSE; DEBUGMSG(TRUE, (TEXT("挂断电话!\n"))); if (s_pThis->m_lpfnDisconnectedCall != NULL) { s_pThis->m_lpfnDisconnectedCall(s_pThis->m_szPhoneNum); } } break; case RIL_NOTIFY_CALLPROGRESSINFO: { //DEBUGMSG(TRUE, (TEXT("Notify Direction:%d, status:%d\n"),prci->dwDirection, prci->dwStatus)); if (s_pThis->m_bFlag) { RILCALLINFO* prci = (RILCALLINFO*)pData; if (RIL_CALLDIR_NONE == prci->dwDirection && RIL_CALLSTAT_ALERTING == prci->dwStatus) { s_pThis->m_bFlag = FALSE; DEBUGMSG(TRUE, (TEXT("挂断电话!\n"))); if (s_pThis->m_lpfnDisconnectedCall != NULL) { s_pThis->m_lpfnDisconnectedCall(s_pThis->m_szPhoneNum); } } } } break; } } int CRilMonitor::InitMonitor(LPVOID lpParamer) { HRESULT hr = RIL_Initialize(1, RilResultProc, RilNotifyProc, RIL_NCLASS_CALLCTRL/*RIL_NCLASS_ALL*/, NULL, &m_hRil); if (FAILED(hr)) { DEBUGMSG(TRUE, (TEXT("RIL_Initialize err:%d\n"), GetLastError())); return -1; } return 0; } void CRilMonitor::UninitMonitor(LPVOID lpParamer) { RIL_Deinitialize(m_hRil); m_hRil = NULL; }
只是简单的实现,其它功能还有待挖掘。
几个重要的参数
/////////////////////////////Call status values//////////////////////////////////////
RIL_CALLSTAT_ACTIVE Active call.
RIL_CALLSTAT_ONHOLD Call on hold.
RIL_CALLSTAT_DIALING In the process of dialing.
RIL_CALLSTAT_ALERTING In the process of ringing.
RIL_CALLSTAT_INCOMING Incoming (unanswered) call.
RIL_CALLSTAT_WAITING Incoming call waiting call.
////////////////////////////////Call direction/////////////////////////////
RIL_CALLDIR_INCOMING Incoming call.
RIL_CALLDIR_OUTGOING Outgoing call.
下载: