Introduction
I got myself a SmartPhone Sagem myS-7 for my b'day this year. Having used a lot of other phones I was a bit disappointed by the Alarm option within SmartPhone. It's very very basic. You can only select the time. (Under Settings / More / Date and Time. The Snooze option sleeps for 10 minutes and you don't have an option to change that. So I got myself to writing an alarm which did most of the things I wanted.)
I started with the Timer
object and it was firing the event at the right time. The only problem I was having was that it just wouldn't take the phone out of Standby mode. I Googled around a bit and I realized that I was supposed to set system notification in order for the phone to come out of standby. I looked around to executing native code but I found OpenNetCF. It's got a good set of classes and it had the notification functionality as well.
Using the code
The code is pretty straightforward. Set a Timer
object to do an hourly check for upcoming Alarm events. If an alarm is found within the next hour it sets another Timer
object to execute and set a Notify.RunAppAtTime
from OpenNETCF.Win32.Notify
. The application actually playing the alarm (rooster at its best) is a standalone SmartPhone app and plays the Wav file using the SoundPlayer
control from OpenNETCF.Windows.Forms
.
For persisting alarm data, I used DataSet
's ReadXml
and WriteXml
.
private void GetNextNotificationInfo()
{
this.nextAlarmUp = 0;
DataSet dsAlarms = new DataSet();
if(File.Exists(ConfigFile) == true)
{
dsAlarms.ReadXml(ConfigFile);
if(dsAlarms.Tables.Count != 0 && dsAlarms.Tables[0].Rows.Count != 0)
{
DateTime dtCurrent = DateTime.Now;
long CurrentTimeInTicks = dtCurrent.TimeOfDay.Ticks;
int currentDayOfWeek = (int)dtCurrent.DayOfWeek;
string filterExpression = "Enabled = true AND TimeInTicks >= "
+ CurrentTimeInTicks + " AND Days LIKE '%" +
Convert.ToString(currentDayOfWeek) + "%'";
string sortExpression = "TimeInTicks DESC";
DataRow[] drActiveAlarms =
dsAlarms.Tables[0].Select(filterExpression,
sortExpression);
if(drActiveAlarms.Length > 0)
{
DataRow drSelectedAlarm = drActiveAlarms[0];
long SelectedTimeInTicks =
Convert.ToInt64(drSelectedAlarm["TimeInTicks"]);
if(SelectedTimeInTicks > CurrentTimeInTicks)
{
TimeSpan tsSelectedTime = new TimeSpan(SelectedTimeInTicks);
TimeSpan tsCurrentTime = dtCurrent.TimeOfDay;
TimeSpan tsDifference = tsSelectedTime - tsCurrentTime;
if(tsDifference.TotalSeconds < 3600)
{
this.nextAlarmUp = Convert.ToInt32(drSelectedAlarm["ID"]);
this.timerNotify.Interval =
Convert.ToInt32(tsDifference.TotalMilliseconds - 60*1000);
this.timerNotify.Enabled = true;
}
else
{
this.nextAlarmUp = 0;
this.timerNotify.Enabled = false;
}
}
}
}
}
}
private void timerNotify_Tick(object sender, System.EventArgs e)
{
this.timerNotify.Enabled = false;
Notify.RunAppAtTime(this.AppPath + "SDAlarmExec.exe",
DateTime.Now.AddMinutes(1));
this.ExecuteDisable();
GetNextNotificationInfo();
}
Points of Interest
By default when you save data as XML, the file is created in the root directory. To get the application's path, you need to use Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName
. This returns /Storage Card/Program Files/SmartAlarm.exe. Fetch the assembly name using Assembly.GetExecutingAssembly().GetModules()[0].Name
and replace it with "" and you have the path.
I noticed the following points which might help when creating SmartPhone apps:
- The Build Cab option fails. But it does create a Build.bat file under the Obj/Release folder (if you are doing a release build package).
- Update the batch file for Cab generation to use C:\Program Files\Windows CE Tools\wce420\SMARTPHONE 2003\Tools\CabwizSP.exe instead of C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\bin\cabwiz.exe.
- Copy vsd_setup.dll from C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\wce400\armv4 to C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Smartphone\wce400\armv4.
- Copy vsd_setup.dll from C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\wce400\x86 to C:\Program Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\Smartphone\wce400\x86.
- For OpenNetCF, manually install OpenNETCF.SDF.smp.armv4.cab in the phone.
- If you are using OpenNetCF, the emulator doesn't work any more by default. If you would like to use the emulator add the OpenNetCF referenced assemblies as content in the Project.
- Lastly when the
DateTime
control receives control, it doesn't allow any other elements to have focus that easily. That is the reason why I have set its receive focus at the very end. It's a limitation of the control.