In the earlier issues of PCQuest, we have already discussed SMS Interception
support in Windows Mobile 5.0 and how we can build applications that can
intercept the incoming SMS and perform some custom tasks. Now, there are also
scenarios where in you would like your mobile application to perform some task
when a system condition is true. For eg, if you get a missed call, you would
like an application to automatically send an SMS to the caller with a preset
message. Another scenario could be if the battery power levels go low, you may
want to hibernate your application state until the device is charged.
|
Windows Mobile 5.0 has introduced a new component called the State and
Notification Broker that allows your applications to be registered with it for a
given state change and when the state change happens, your code will be
automatically invoked. In this article, we introduce the State and Notification
Broker, how it works and what goes into writing an application that leverages it
to do something useful.
Introducing the State Notification Broker
Different Windows Mobile applications store their state information at different
locations, including the core system state details such as number of missed
calls, number of unread e-mail, etc. The problem with this approach is that if
another application wishes to leverage this information to perform a custom
task, it would not know where to look for the information and what all kinds of
information would be available for it.
To solve this problem, Windows Mobile 5.0 has introduced the State and
Notification Broker. According to this:
- There will be documented locations in the Windows CE registry where the
information can be published by the source of state change. - Windows Mobile 5.0 will provide a set APIs that will monitor the changes
published in the registry locations. - Applications that wish to know about a state change will register with the
OS using the APIs and will be invoked (or have their code called) when the
state change takes place.
The architecture of the State Notification Broker lets the Windows Mobile developer use its API in eVC++ or .NET (compact) applications |
These APIs are available in the native form (for development using eVC++) and
also in managed form (when writing applications for the .NET Compact Framework).
Architecturally, the State and Notification Broker looks as shown in the
adjoining figure.
The entire functionality is based on the Microsoft.WindowsMobile.Status
assembly that contains a namespace with the same name which needs to be
referenced in your application. There are a whole lot of states about which the
application can be notified.
The SystemProperty class encapsulates most of these states, ranging from new
incoming e-mail or SMS to missed phone calls to signal strenght and so on. The
best way to understand this would be to write an application that leverages this
functionality.
Understanding AutoReply
AutoReply is an application that is invoked by Windows Mobile 5.0 in a case
someone calls you on your phone and you miss the call. It sends an SMS to the
caller informing about your unavailability. You can also customize the message
to be sent. We start off by building a Windows Mobile 5.0 PocketPC application.
You will need VS 2005 and the PocketPC 5.0 SDK installed. You can download
the SDK from http://www.microsoft.com/downloads/details.aspx?FamilyID=83a52af2-f524-4ec5-9155-717cbe5d25ed&DisplayLang=en.
Once everything is installed, we design the UI as shown in the figure above.
The textbox will contain the custom message to be sent and the 'SaveAutoReply
Message' button implementation will be used to persist the custom message on
the device. The code for this implementation looks like this.
Clicking on the Activate button will let the app receive notifications when new messages/calls arrive |
private bool SaveAutoReplyMessage()
{
TextWriter fsAutoReply = null;
string strCurPath = GetCurrentPath();
try
{
fsAutoReply = File.CreateText(strCurPath+"AutoReply.txt");
}
catch (Exception ex)
{
return false;
}
// Save the message to the file
fsAutoReply.Write(txtAutoReplyMessage.Text);
strAutoReplyMessage = txtAutoReplyMessage.Text;
fsAutoReply.Close();
fsAutoReply = null;
return true;
}
The 'GetCurrentPath' method is the crucial one as it helps calculate the
path to application's folder on the device. The code for that is:
// Returns the executing assembly path
private string GetCurrentPath()
{
System.Reflection.Module curMod = (System.Reflection.Assembly.GetExecutingAssembly().GetModules())<0>;
int iLastSlashPos = curMod.FullyQualifiedName.LastIndexOf("\\");
return curMod.FullyQualifiedName.Substring(0, iLastSlashPos+1);
}
Activating the notification
The real crux lies in the Activate button implementation. Since we want to be
notified when there's a missed call , we use the
'SystemProperty' class to inform the 'State and Notification Broker'
about it, as shown below.
if (btnActivate.Text.IndexOf("Activate")
!= -1)
{
// Setup the missed call handler
stateMissedCall = new SystemState(SystemProperty.PhoneMissedCall);
stateMissedCall.Changed += new
ChangeEventHandler(stateMissedCall_Changed);
stateMissedCall.EnableApplicationLauncher(strAppID);
btnActivate.Text = "&Deactivate";
MessageBox.Show("Autoreply activated!");
}
else
{
// Deactivate the missed call handler..
SystemState.DisableApplicationLauncher(strAppID);
btnActivate.Text = "&Activate";
MessageBox.Show("Autoreply deactivated!");
}
The 'SystemState' class is the managed API that informs the State and
Notification Broker about what state we want to be notified about. The
SystemProperty representing the state (we are interested in getting notified
about) is passed as an argument to the SystemState constructor. Next, we wire up
to the 'ChangeEventHandler' that will be invoked whenever the state changes.
We also invoke 'EnableApplicationLauncher' method against the SystemState
instance. This registers our application with the State and Notification Broker
such that even if your application is not running, it will be invoked whenever
the state change is detected and your event handler invoked.
To disable this registration, we invoke the 'DisableApplicationLauncher'
method.
The ChangeEventHandler checks whether there is a missed call and if so, we
attempt to send them an SMS, with the custom message that was saved by the user.
The code for this application looks like:
// When a missed call happens, this code gets
invoked
void stateMissedCall_Changed(object sender, ChangeEventArgs args)
{
// Did we miss a call?
object objMissed = args.NewValue;
bool bMissed = ((int)objMissed == 0) ? false : true;
if (bMissed == false)
return;
Contact cntCaller = SystemState.PhoneLastIncomingCallerContact;
string strCallerNumber = SystemState.PhoneLastIncomingCallerNumber;
// Send an SMS to them
SmsMessage sms = new SmsMessage();
// If we got the contact details from POOM, then use cell
// from there, else use the incoming caller number
if ((cntCaller != null) && (cntCaller.MobileTelephoneNumber != null))
sms.To.Add(new Recipient(cntCaller.MobileTelephoneNumber));
else if (strCallerNumber != null)
sms.To.Add(new Recipient(strCallerNumber));
else
return;
sms.Body = strAutoReplyMessage;
sms.Send();
}
The ChangeEventHandler gets an argument of the type 'ChangeEventArgs'
that has a 'NewValue' property. In case of true/false checks (eg, our
scenario where we want to check if there was a missed call or not), it will
contain a 0 (zero) for false and 1 (one) for true.
If there is a missed call, we use the SystemState class's 'PhoneLastIncomingCallerContact'
property to extract POOM (Pocket Outlook Object Model) Contact object for the
caller and then extract his cellphone number. If the Contact object is not
available, we use SystemState class's 'PhoneLastIncomingCallerNumber'
property to get the phone number from which the missed call was received.
Once we have the phone number, we use the 'SmsMessage' class (based on
Microsoft.WindowsMobile.PocketOutlook) to create a SMS and send it to the number
from which the call came. And we have AutoReply working for us!
To sum up
State and Notification Broker enables scenarios for conditional application
development that were not possible before.
Not only that, you can author your own custom states to which applications
can subscribe to and be notified when those states change. This article is
accompanied with the source code of AutoReply application to help you understand
the concept better.