If you've ever worked with the State and Notifications Broker API's primary class SystemState, you'll find working with the MessageInterceptor class to be very similar. In both cases, you create an instance of the class, associate a filtering condition, and provide an event handler that the system calls each time an event or message meeting the criteria occurs. Unlike the SystemState class, which monitors a variety of different values, the MessageInterceptor monitors only arriving SMS messages.
Note: |
|---|
|
Like the SystemState class, the MessageInterceptor class must remain in-scope otherwise it may stop monitoring. For this reason, you rarely, if ever, create an instance of the MessageInterceptor class as a local variable. Instead, you'll almost always create instances of the MessageInterceptor class as a class-level field
|
To use the MessageInterceptor class you must add references to the Microsoft.WindowsMobile and Microsoft.WindowsMobile.PocketOutlook assemblies. The classes are all contained within the "Microsoft.WindowsMobile.PocketOutlook" and "Microsoft.WindowsMobile.PocketOutlook.MessageInterception" namespaces. C# developers need to include the appropriate using statements; Visual Basic .NET developers need to include the namespaces in the Microsoft Visual Studio® Imported namespace list.
Note: |
|---|
|
The topics discussed in the following subsections are demonstrated in Examples 1 and 2 located near the end of this paper.
|
Deciding Whether to Share the Message
When you create an instance of the MessageInterceptor class, the first thing you need to decide is whether you would like the intercepted messages to be available to other interceptor applications including the Windows Mobile Text Message reader. If you would like the message to be available to other interceptor applications, create the MessageInterceptor instance passing the InterceptionAction.Notify enumeration value to the MessageInterceptor constructor. In this case, the messaging system passes a copy of the message to your application and continues notifying other interceptor applications. If you instead pass InterceptionAction.NotifyAndDelete, the messaging system deletes the message when your application finishes with it. If you create an instance of the MessageInterceptor class with a constructor that does not accept a InterceptionAction parameter, the value defaults to InterceptionAction.Notify.
Note: |
|---|
|
Setting the InterceptionAction to InterceptionAction.NotifyAndDelete prevents the Windows Mobile Text Message reader from receiving the message but does not guarantee that no other message interceptor receives the message. An InterceptionAction value of InterceptionAction.NotifyAndDelete does not affect any interceptors that process the message prior to the messaging subsystem notifying your application.
|
Filtering Messages
In most situations, the user's mobile device is not used exclusively for your application. The user likely uses the device for a variety of work and personal purposes. For this reason, when registering to intercept SMS messages, you should provide a filter condition. Creating a copy of the message and routing the copy to your application consumes device resources, therefore you should register your SMS interceptor so that it receives only those messages that meet a specific criteria. Allowing the messaging system to filter the incoming messages is much more efficient than performing the filtering in your application.
To create a filter condition you simply assign an instance of the MessageCondition class to the MessageInterceptor instance's MessageCondition property. The MessageCondition class requires four pieces of information for a complete condition. First you must identify the part of the message to which the condition applies; you specify this value with the MessageProperty enumeration. Second is the type of comparison to perform such as equal, contains, starts-with, and so on; you specify the comparison using the MessagePropertyComparisonType enumeration. Finally, the condition needs the value to use for the comparison and whether the comparison should be case-sensitive. Tables 1 and 2, respectively, show the values for the MessageProperty and MessagePropertyComparisonType enumerations.
Table 1. MessageProperty enumeration values
| Value | Description |
| Body | Perform the comparison using the message body contents. |
| MessageClass | Perform the comparison using the message class. For all standard SMS messages the MessageClass value is the same, IPX.SMSText; an application would normally only check this value when working with a custom message type. |
| Sender | Perform the comparison using the sender information. When working with SMS messages, this value always includes the sender's phone number as consecutive digits with no separators such as a period, hyphen, or parenthesis. If the sender is contained in your Contacts list, the sender will also contain the sender's name as it appears in the Contact FileAs field. |
| Subject | Perform the comparison using the message subject field. SMS messages do not have a subject therefore this value is not normally used. |
Table 2. MessagePropertyComparisonType enumeration values
| Value | Description |
| Equal | The message property and the comparison value must be an exact match. Use this comparison type with caution as any small change in the message property or the comparison value will result in a failed comparison. |
| NotEqual | The message property and comparison value must be different. |
| Contains | The comparison value appears within the message property. |
| StartsWith | The message property starts with the comparison value. |
| EndsWith | The message property ends with the comparison value. |
By default, the comparisons are case-sensitive. You can specify a case-insensitive comparison by passing false to the caseSensitive parameter of the MessageCondition constructor that accepts four parameters.
Handling Message Notifications
The MessageInterceptor class exposes a single event named MessageReceived that accepts a MessageInterceptorEventHandler delegate. The MessageInterceptor class signals the MessageReceived event when the device receives an SMS message meeting the condition associated with the MessageInterceptor instance.
When the MessageReceived event signals, it passes a MessageInterceptorEventArgs reference to your event handler method. The MessageInterceptorEventArgs class has only one public member: the Message property that returns a reference to the received SMS message. The Message property return type is the base class Message, which does not provide a reference to the message body; therefore, to access the message body you must cast the Message reference to a SmsMessage reference.
Once your application associates an event handler with the MessageReceived event, you cannot make any modifications to the MessageInterceptor instance; therefore, you must associate the MessageCondition with the MessageInterceptor instance before associating the event handler. For this reason, Visual Basic .NET developers cannot use the WithEvents declaration modifier. The WithEvents declaration modifier automatically associates an event handler when the MessageInterceptor instance is created, which does not give you an opportunity to associate a MessageCondition. To associate a MessageCondition with the MessageInterceptor class in Visual Basic .NET, you must declare the MessageInterceptor reference without the WithEvents keyword and use the AddHandler keyword to attach an event handler to the MessageInterceptor instance after you assign the MessageCondition.
Handling Message Notification Cleanup
When you create an instance of the MessageInterceptor class and attach a delegate to the MessageReceived event, the MessageInterceptor class creates a temporary registry entry under HKLM\Software\Microsoft\Inbox\Rules. The registry entry contains information about the MessageInterceptor instance, which the messaging subsystem uses to notify the MessageInterceptor instance when a message arrives. Once you are done with the MessageInterceptor instance, the registry entry should be removed. Unfortunately, the MessageInterceptor class does not always clean up the registry properly. As a result, the registry entry may remain in the registry indefinitely even though the MessageInterceptor class will never use that entry again. These excess entries clutter the registry and over time, as the number of these unused entries grows, they may negatively impact message processing performance.
The MessageInterceptor class creates the registry entry when you attach an event handler to the MessageReceived event; the MessageInterceptor will also delete the entry if you remove the event handler from the MessageReceived event. Most applications do not explicitly remove event handlers and instead just let the .NET Compact Framework garbage collector remove them. Due to the problem in the MessageInterceptor class' cleanup process, you must explicitly remove the event handlers to assure that the MessageInterceptor class properly removes its registry entries.