Silent Receiving of SMS messages
来源:互联网 发布:风雅软件 编辑:程序博客网 时间:2024/05/16 03:33
If you ever wanted to receive an SMS without user notification, it might have occurred to you that using standard CSmsClientMtm APIs is not the best option. Sometimes it's possible to delete an incoming message before your phone beeps, but we can't rely on this. Luckily, we have a different approach which will help us to take care about user's rest. I'm talking about receiving SMS through sockets.
We will need the TSmsAddr class which is not a part of the public SDK since Series60 3rd MR. Now you can find it inside the SMSUtilities folder of the API plug-in package.
The basic idea is to bind a RSocket to the SMS channel and wait till something would appear there. We have several different ways of opening the SMS socket defined in the TSmsAddrFamily enum:
enum TSmsAddrFamily { ESmsAddrUnbound = 0, // Not bound yet ESmsAddrSendOnly = 1, // Only for sending, no reception ESmsAddrMessageIndication = 2, // Matches on IEI 0x01 and DCS 0x110(1)0(1)xxxx ESmsAddrMatchIEI = 3, // For matching Information Element Identifiers ESmsAddrMatchText = 4, // For matching any text patterns ESmsAddrRecvAny = 5, // Receive all messages. Only one client allowed ESmsAddrStatusReport = 6, // For receiving Status Reports ESmsAddrLocalOperation = 7, // For local SIM operations ESmsAddrApplication8BitPort = 8, // For sock port identification ESmsAddrApplication16BitPort = 9, // For sock port identification ESmsAddrEmail = 10 // For matching of email messages };
ESmsAddrRecvAny looks tempting, but the built-in SMS application has already bound it. Our next choice is ESmsAddrMatchText. We can catch any message that starts with the required symbol sequence defined through SetTextMatch(). I'm using '#:' as an example, but you are free to setup any necessary pattern, even an empty one, that will allow you to intercept all messages.
Alternatively, you can select messages not by a prefix, but by a port number using ESmsAddrApplication8BitPort or ESmsAddrApplication16BitPort. It's useful for the inter-application communication. For example, client/server applications can exchange messages via SMS on the defined port.
One more note before digging into the code. Even after you read the message from the SMS socket, the actual data is still persisted in the receiving queue. You have to sent the KIoctlReadMessageSucceeded command using the Ioctl() function to indicate, that the message was successfully received. Otherwise, all the messages you intercepted will appear in the native SMS inbox on the next reboot.
And now less talk, more code.
SmsSocketEngine.h
#ifndef SMSSOCKETENGINE_H#define SMSSOCKETENGINE_H// INCLUDES #include <e32base.h>#include <es_sock.h> // RSocketServ#include <f32file.h> // RFs// LIBS// esock.lib (RSocketServ), smsu.lib (TSmsAddr), gsmu.lib (CSmsBuffer),// efsrv.lib (RFs), estor.lib (RSmsSocketReadStream)// CAPS// NetworkServices (RSocket::Bind), ReadUserData (RSocket::Bind), // WriteUserData (RSocket::Bind)// FORWARD DECLARATIONSclass MSmsEngineObserver;// CLASS DECLARATION/** * CSmsSocketEngine class. * CSmsSocketEngine declaration. * */class CSmsSocketEngine : public CActive { public: // Constructors and destructor /** * NewL() * Creates new CSmsSocketEngine object. * @param aObserver Reference to the MSmsEngineObserver object. * @return Pointer to the created instance of CSmsSocketEngine. */ static CSmsSocketEngine* NewL(MSmsEngineObserver& aObserver); /** * NewLC() * Creates new CSmsSocketEngine object. * @param aObserver Reference to the MSmsEngineObserver object. * @return Pointer to the created instance of CSmsSocketEngine. */ static CSmsSocketEngine* NewLC(MSmsEngineObserver& aObserver); /** * ~CSmsSocketEngine() * Destructor. */ ~CSmsSocketEngine(); protected: // From CActive /** * DoCancel() * Implements cancellation of an outstanding request. */ void DoCancel(); /** * RunL() * Handles an active objects request completion event. */ void RunL(); /** * RunError() * Handles a leave occurring in the request completion event handler RunL(). * @param aError The leave code. * @return KErrNone if error was handled, otherwise system-wide error. */ TInt RunError(TInt aError); private: // New functions /** * Start() * Starts waiting for the actual socket data. */ void Start(); public: // New functions /** * StartListeningL() * Starts listening for an incoming SMS. */ void StartListeningL(); /** * StopListening() * Stops listening. */ void StopListening(); private: // Constructors /** * CSmsSocketEngine() * Default C++ constructor. * @param aObserver Reference to the MSmsEngineObserver object. */ CSmsSocketEngine(MSmsEngineObserver& aObserver); /** * ConstructL() * Default EPOC constructor. */ void ConstructL(); private: // enum enum TSmsSocketEngineState { ESmsIdle, ESmsListening, ESmsSystemNotyfing }; private: // data MSmsEngineObserver& iObserver; RSocketServ iSocketServ; RSocket iReadSocket; RFs iFs; TBool iWait; TPckgBuf<TUint> iBuf; TSmsSocketEngineState iState; };#endif // SMSSOCKETENGINE_H
SmsSocketEngine.cpp
// INCLUDE FILES #include "SmsSocketEngine.h" // CSmsSocketEngine#include "SmsEngineObserver.h" // MSmsEngineObserver#include <smsuaddr.h> // TSmsAddr#include <gsmubuf.h> // CSmsBuffer#include <smsustrm.h> // RSmsSocketReadStream#include <gsmumsg.h> // CSmsMessage // ================= MEMBER FUNCTIONS ========================================//// ---------------------------------------------------------------------------// CSmsSocketEngine::CSmsSocketEngine(MSmsEngineObserver& aObserver)// Default C++ constructor.// ---------------------------------------------------------------------------//CSmsSocketEngine::CSmsSocketEngine(MSmsEngineObserver& aObserver) : CActive(EPriorityStandard), iObserver(aObserver) { }// ---------------------------------------------------------------------------// CSmsSocketEngine::~CSmsSocketEngine()// Destructor.// ---------------------------------------------------------------------------//CSmsSocketEngine::~CSmsSocketEngine() { // cancel any request, if outstanding Cancel(); iReadSocket.Close(); iFs.Close(); iSocketServ.Close(); }// ---------------------------------------------------------------------------// CSmsSocketEngine::NewL(MSmsEngineObserver& aObserver)// Two-phased constructor.// ---------------------------------------------------------------------------//CSmsSocketEngine* CSmsSocketEngine::NewL(MSmsEngineObserver& aObserver) { CSmsSocketEngine* self = CSmsSocketEngine::NewLC(aObserver); CleanupStack::Pop(self); return self; }// ---------------------------------------------------------------------------// CSmsSocketEngine::NewLC(MSmsEngineObserver& aObserver)// Two-phased constructor.// ---------------------------------------------------------------------------//CSmsSocketEngine* CSmsSocketEngine::NewLC(MSmsEngineObserver& aObserver) { CSmsSocketEngine* self = new (ELeave) CSmsSocketEngine(aObserver); CleanupStack::PushL(self); self->ConstructL(); return self; }// ---------------------------------------------------------------------------// CSmsSocketEngine::ConstructL()// Default EPOC constructor.// ---------------------------------------------------------------------------//void CSmsSocketEngine::ConstructL() { CActiveScheduler::Add(this); User::LeaveIfError(iSocketServ.Connect()); User::LeaveIfError(iFs.Connect()); StartListeningL(); }// ---------------------------------------------------------------------------// CSmsSocketEngine::DoCancel()// Implements cancellation of an outstanding request.// ---------------------------------------------------------------------------//void CSmsSocketEngine::DoCancel() { iReadSocket.CancelIoctl(); iState = ESmsIdle; }// ---------------------------------------------------------------------------// CSmsSocketEngine::RunL()// Handles an active objects request completion event.// ---------------------------------------------------------------------------//void CSmsSocketEngine::RunL() { if (iStatus == KErrNone) { if (iState == ESmsListening) { // allocate SMS buffer CSmsBuffer* buffer = CSmsBuffer::NewL(); CleanupStack::PushL(buffer); // create new incoming message, pass ownership of the buffer! CSmsMessage* message = CSmsMessage::NewL(iFs, CSmsPDU::ESmsDeliver, buffer); CleanupStack::Pop(buffer); CleanupStack::PushL(message); // open socket read stream RSmsSocketReadStream readStream(iReadSocket); CleanupClosePushL(readStream); // read message message->InternalizeL(readStream); CleanupStack::PopAndDestroy(&readStream); TPtrC number = message->ToFromAddress(); // extract the message body HBufC* body = HBufC::NewLC(message->Buffer().Length()); TPtr bodyPtr(body->Des()); message->Buffer().Extract(bodyPtr, 0, message->Buffer().Length()); iObserver.MessageReceived(number, *body); CleanupStack::PopAndDestroy(2, message); // body, message // notify system about successful receiving iReadSocket.Ioctl(KIoctlReadMessageSucceeded, iStatus, NULL, KSolSmsProv); iState = ESmsSystemNotyfing; SetActive(); } else { Start(); } } else { iObserver.HandleError(iStatus.Int()); } }// ---------------------------------------------------------------------------// CSmsSocketEngine::RunError(TInt aError)// Handles a leave occurring in the request completion event handler RunL().// ---------------------------------------------------------------------------//TInt CSmsSocketEngine::RunError(TInt aError) { iObserver.HandleError(aError); return KErrNone; }// ---------------------------------------------------------------------------// CSmsSocketEngine::Start()// Starts waiting for the actual socket data.// ---------------------------------------------------------------------------//void CSmsSocketEngine::Start() { // wait for an incoming data iReadSocket.Ioctl(KIOctlSelect, iStatus, &iBuf, KSOLSocket); iState = ESmsListening; SetActive(); }// ---------------------------------------------------------------------------// CSmsSocketEngine::StartListeningL()// Starts listening for an incoming SMS.// ---------------------------------------------------------------------------//void CSmsSocketEngine::StartListeningL() { // we can't handle several requests simultaneously if (IsActive()) { User::Leave(KErrNotReady); } // just in case iReadSocket.Close(); // open read socket User::LeaveIfError(iReadSocket.Open(iSocketServ, KSMSAddrFamily, KSockDatagram, KSMSDatagramProtocol)); _LIT8(KMathTag, "#:"); // set match pattern TSmsAddr smsAddr; smsAddr.SetSmsAddrFamily(ESmsAddrMatchText); smsAddr.SetTextMatch(KMathTag); // put KNullDesC8 to catch all messages // use this to read the message from a certain port //smsAddr.SetSmsAddrFamily(ESmsAddrApplication8BitPort); //smsAddr.SetPort(16500); // GSM Application port from 16000 to 16999 // bind the socket User::LeaveIfError(iReadSocket.Bind(smsAddr)); iBuf() = KSockSelectRead; Start(); }// ---------------------------------------------------------------------------// CSmsSocketEngine::StopListening()// Stops listening.// ---------------------------------------------------------------------------//void CSmsSocketEngine::StopListening() { Cancel(); iReadSocket.Close(); }
P.S.: There is such an example on Wiki Nokia, unfortunately it's very buggy.
- Silent Receiving of SMS messages
- Receiving SMS Messages Inside a Managed Application
- Receiving and Dispatching Messages
- 5 Sending and Receiving Messages
- Create WAP Push SMS Messages
- 知识库--Sending and Receiving Messages By Akka Using Java(139)
- Concatenated SMS Messages and Character Counts
- 如何创建WAP Push SMS Messages
- List of Windows Messages
- List Of Windows Messages
- android wearable-Transferring Assets,Sending and Receiving Messages,Handling Data Layer Events
- Create WAP Push SMS Messages (From C# to JAVA)
- How to with 7bit encoding in concatenated sms messages
- Android SMS intercept without notification icon or WAP-PUSH messages
- Create WAP Push SMS Messages By Adam Bird
- The Underlying Technology of Messages
- Sending SMS WAP Push messages using the ActiveXperts SMS and MMS Toolkit.
- GSM Hacking:静默短信(Silent SMS)在技术侦查中的应用 20160617
- DOM常用操作
- 选择Java接口还是抽象类--转载
- 用Djunit报告代码测试覆盖率
- 页面跳转VS框架包含
- 交叉线与直通线的区别
- Silent Receiving of SMS messages
- “WPF/E”入门
- 解决MySQL不能显示中文问题
- 读oracle one on one笔记
- c#第四次上机总结
- button标签
- 李开复:算法的力量
- struts1.2里链接详解
- java实现实时视频传送