Click here to Skip to main content
Click here to Skip to main content

PocketPcAgent

, 7 Sep 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
PocketPcAgent is an application that can be installed on Windows Mobile devices that are running Windows Mobile 5.0 or higher. The application listens to events such as SMS Received, Call Missed, E-Mail Received, Battery Strength Changed, and much more on the Pocket PC.

Introduction

PocketPcAgent is an application that can be installed on Windows Mobile Devices that are running Windows Mobile 5.0 or higher. While running, the application listens to events such as SMS Received, Call Missed, E-Mail Received, Battery Strength Changed, and much more on the Pocket PC. Users can subscribe to events and select to be notified when an event is raised by a channel such as email, SMS, or phone call.

Background

The main idea of developing this software is to help people carrying two mobile phones. Sometimes you may not have one of your phones with you. In cases like this, you don't know who called you or sent a message to you. I thought, wouldn't it be great to be notified in situations like this via a mobile device that you are carrying or via email? And my answer was it would be amazing, so I developed this application.

Using the Code

When you open the solution, you will see three main folders. In the Agents folder, you can find Agent classes that listen to SMS, phone, or generic events on the Pocket PC. Classes in the helpers folder provides functions such as sending SMS, calling, serializing, and sending email. And, classes in the objects folder are mainly used to store user settings and to manage the other classes I mentioned above.

Let's sneak preview the helper classes first:

private static void AddRecipient(SmsMessage parSmsMessage, string parRecipient)
{
    AddRecipient(parSmsMessage, new Recipient(parRecipient));
}
public static void SendSms(string parBody, string parRecipient)
{
    SmsMessage insSmsMessage = new SmsMessage();
    insSmsMessage.Body = parBody;
    AddRecipient(insSmsMessage, parRecipient);
    insSmsMessage.Send();
}

private static string GetAccountName()
{
    OutlookSession insOutlookSession = new OutlookSession();
    return insOutlookSession.EmailAccounts[0].Name;
}
private static void AddRecipient(EmailMessage parEmailMessage, string parRecipient)
{
    AddRecipient(parEmailMessage, new Recipient(parRecipient));
}
public static void SendEmail(string parBody, string parRecipient)
{
    EmailMessage insEmailMessage = new EmailMessage();
    insEmailMessage.BodyText = parBody;
    AddRecipient(insEmailMessage, parRecipient);
    insEmailMessage.Send(GetAccountName());
}

public static void Call(string parNumber, bool parShowPrompt)
{
    Microsoft.WindowsMobile.Telephony.Phone p = 
              new Microsoft.WindowsMobile.Telephony.Phone();
    p.Talk(parNumber, parShowPrompt);
}

As you can see, the helper classes provide functionalities that can be taken as an action when an event is raised. Helper classes also have overloads of these methods. By downloading the source code, you can view them as well.

Now, let's see the Agent classes. The SmsAgent class uses the MessageInterceptor object to listen to messages received, and when a message is received of type SmsMessage, an SmsRecieved event of this class is raised.

public class SmsAgent
{
    MessageInterceptor msgInterceptor = 
      new MessageInterceptor(InterceptionAction.Notify, true);
    public delegate void SmsReceivedDelegate(SmsMessage msg);
    public event SmsReceivedDelegate SmsReceived;

    public SmsAgent()
    {
        msgInterceptor.MessageReceived += 
          new MessageInterceptorEventHandler(msgInterceptor_MessageReceived);
    }
    void msgInterceptor_MessageReceived(object sender, MessageInterceptorEventArgs e)
    {
        if (e.Message is Microsoft.WindowsMobile.PocketOutlook.SmsMessage)
        {
            if (SmsReceived != null)
            {
                SmsReceived((SmsMessage)e.Message);
            }
        }
    }
}

The EmailAgent class works the same way as SmsAgent but only checks for if the message type is EmailMessage.

The TelephonyAgent class uses the SystemState object to listen to the PhoneMissedCalls property. When this property is changed, the CallMissed event of this class is raised.

public class TelephonyAgent
{
    public delegate void CallMissedDelegate(string callerName, 
                                            string callerNumber);
    public event CallMissedDelegate CallMissed;
    SystemState insSystemState = 
                new SystemState(SystemProperty.PhoneMissedCalls);

    Guid insGuid = Guid.NewGuid();
    
    public TelephonyAgent()
    {
        insSystemState.Changed += new ChangeEventHandler(phoneMissedCalls_Changed);
    }

    void phoneMissedCalls_Changed(object sender, ChangeEventArgs args)
    {
        if (CallMissed != null)
        {
            if (SystemState.PhoneLastIncomingCallerNumber == 
                               Helpers.TelephonyHelper.ActionCall)
            {
                Helpers.TelephonyHelper.ActionCall = "";
            }
            else
            {
                CallMissed(SystemState.PhoneLastIncomingCallerName, 
                           SystemState.PhoneLastIncomingCallerNumber);
            }
        }
    }
}

The GenericAgent class listens to all property changes on the Pocket PC using the SystemState object. When a property is changed, the Changed event of this class is automatically raised.

public class GenericAgent
{
    public delegate void ChangedDelegate(object sender, 
                         ChangeEventArgs args);
    public event ChangedDelegate Changed;

    List<systemstate> stateList = new List<systemstate>();
    public GenericAgent()
    {
        for (int i = 0; i <= 140; i++)
        {
            SystemState s = new SystemState((SystemProperty)i);
            s.Changed += new ChangeEventHandler(changedevent);
            stateList.Add(s);
        }
    }

    void changedevent(object sender, ChangeEventArgs args)
    {
        if (Changed != null)
        {
            Changed(sender, args);
        }
    }
}

Now, let's preview the Subscription class that keeps user subscription information such as parameters of events and actions to be taken. Instead of pasting the complete class code here, I will list only the important methods. For the full class information, you can download the source code.

public class Subscription
{
    public enum SubscriptionTypes
    {
        EmailRecieved = 0,
        SmsRecieved = 1,
        MissedCall = 2,
        Generic = 3,
    }
    public enum ActionTypes
    {
        SendSms = 0,
        SendEmail = 1,
        Call = 2,
    }
    public Subscription(SubscriptionTypes parSubscriptionType, 
                        ActionTypes parActionType, string parNotifyTo)
    {
        _SubscriptionType = parSubscriptionType;
        _ActionType = parActionType;
        _NotifyTo = parNotifyTo;
    }
    public Subscription(SubscriptionTypes parSubscriptionType, 
           ActionTypes parActionType, SystemProperty parSystemProperty, 
           string parNotifyTo)
    {
        _SubscriptionType = parSubscriptionType;
        _ActionType = parActionType;
        _NotifyTo = parNotifyTo;
        _Property = parSystemProperty;
    }
    public void InvokeAction(string parBody)
    {
        switch (_ActionType)
        {
            case ActionTypes.SendSms:
                Helpers.SmsHelper.SendSms(parBody, _NotifyTo);
                break;
            case ActionTypes.SendEmail:
                Helpers.EmailHelper.SendEmail(parBody, _NotifyTo);
                break;
            case ActionTypes.Call:
                Helpers.TelephonyHelper.Call(_NotifyTo);
                break;
            default:
                break;
        }
    }
}

As I mentioned before, you can subscribe by setting the subscription type, action type (the action will be taken when an event is raised), action parameters (such as phone number or email address), or the SystemProperty to be listened for the GenericAgent. The InvokeAction method that uses helpers is called from the PocketPcAgent object when an event is raised.

PocketPcAgent is the main class of the application. It carries a collection of Subscription objects, and it has instances of each Agent class and is subscribed to events that are raised by agent classes. When an event is raised, it checks if an appropriate subscription exists. If a subscription is found, its InvokeAction method is called to notify the user.

TelephonyAgent insTelephonyAgent = new TelephonyAgent();
SmsAgent insSmsAgent = new SmsAgent();
EmailAgent insEmailAgent = new EmailAgent();
GenericAgent insGenericAgent = new GenericAgent();

private bool _IsAgentRunning = false;
public PocketPcAgent()
{
    insTelephonyAgent.CallMissed += 
      new TelephonyAgent.CallMissedDelegate(insTelephonyAgent_CallMissed);
    insSmsAgent.SmsReceived += 
      new SmsAgent.SmsReceivedDelegate(insSmsAgent_SmsReceived);
    insEmailAgent.EmailReceived += 
      new EmailAgent.EmailReceivedDelegate(insEmailAgent_EmailReceived);
    insGenericAgent.Changed += 
      new GenericAgent.ChangedDelegate(insGenericAgent_Changed);
}

void insGenericAgent_Changed(object sender, 
               Microsoft.WindowsMobile.Status.ChangeEventArgs args)
{
    if (IsAgentRunning)
    {
        var result = (from s in this.Subscriptions where s.SubscriptionType == 
                      Subscription.SubscriptionTypes.Generic && 
                      s.Property == ((SystemState)sender).Property select s);
        if (result.Count() > 0)
        {
            string parBody = string.Format("value of {0} changed to :{1}", 
                             result.First().Property.ToString(), args.NewValue.ToString());

            RaiseEventCaptured(result.First().Property.ToString() + ":" + parBody);

            foreach (Subscription s in result)
            {
                s.InvokeAction(parBody);
            }
        }
    }
}

void insEmailAgent_EmailReceived(Microsoft.WindowsMobile.PocketOutlook.EmailMessage msg)
{
    if (IsAgentRunning)
    {
        string parBody = string.Format("You have received an email message " + 
                         "at your pocket pc\r\nFrom : {0}\r\nBody:{1}", 
                         msg.From, msg.BodyText);
        var result = (from s in Subscriptions where s.SubscriptionType == 
                                Subscription.SubscriptionTypes.EmailRecieved select s);
        if (result.Count() > 0)
        {
            RaiseEventCaptured("Email Agent : " + parBody);
        }
        foreach (Subscription s in result)
        {
            s.InvokeAction(parBody);
        }
    }
}

void insSmsAgent_SmsReceived(Microsoft.WindowsMobile.PocketOutlook.SmsMessage msg)
{
    if (IsAgentRunning)
    {
        string parBody = string.Format("You have received an sms message " + 
                         "at your pocket pc\r\nFrom : {0}\r\nBody:{1}", msg.From, msg.Body);
        var result = (from s in Subscriptions where s.SubscriptionType == 
                                Subscription.SubscriptionTypes.SmsRecieved select s);
        if (result.Count() > 0)
        {
            RaiseEventCaptured("SmsAgent : " + parBody);
        }
        foreach (Subscription s in result)
        {
            s.InvokeAction(parBody);
        }
    }
}

void insTelephonyAgent_CallMissed(string callerName, string callerNumber)
{
    if (IsAgentRunning)
    {
        string parBody = string.Format("You have a missed call at " + 
                         "your pocket pc\r\nCaller Name : {0}\r\nNumber:{1}", 
                         callerName, callerNumber);
        var result = (from s in Subscriptions where s.SubscriptionType == 
                                Subscription.SubscriptionTypes.MissedCall select s);
        if (result.Count() > 0)
        {
            RaiseEventCaptured("TelephonyAgent : " + parBody);
        }
        foreach (Subscription s in result)
        {
            s.InvokeAction(parBody);
        }
    }
}

And besides these functionalities, user subscriptions and agent settings are stored in a file that represents the serialized PocketPcAgent object. The PocketPcAgent application also logs every event raised or every action taken to a log file.

Contact

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Tamer Oz
Team Leader
Turkey Turkey
Tamer Oz is a Microsoft MVP and works as Assistant Unit Manager.
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 5 PinmemberAmir Mehrabi-Jorshary25-Oct-10 11:26 
GeneralNice Article PinmemberFatih Birkan8-Sep-09 6:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 8 Sep 2009
Article Copyright 2009 by Tamer Oz
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid