如何调用windows phone 7.1的后台闹钟功能 step by step

自从 WP7.1之后,windows phone 开放一些后台调用,包括音乐,闹钟,播放器等,相信在做windows phone开发时,有可能会调用后台, 恰好我们的软件工程中需要用到闹钟提醒功能,现在就把具体的细节一步一步告诉大家。

包括实现多项提醒,存储和显示等功能。

1. 简介

Reminder是我们Microsoft Academic Search (MAS) 的Windows Phone 7的一个应用的模块,用来提醒用户会议中每个session的开始。用户可以设置reminder的开始时间,结束时间,reminder的消息以及铃声,同时用户也可以删除已经存在的reminder。我需要做的就是提供创建和删除reminder的API,已经管理现有的reminders。下面我就谈一谈我在实现过程中的方法,遇到的困难,教训以及解决方案。

2. 如何在Memory中存储ReminderList

程序运行时,需要在内存中存储临时的ReminderList的信息。下面我谈谈这个部分我的经验与总结。

2.1. 数据结构

选择何时的数据结构是非常重要的。我一开始打算使用C#的Dictionary和Tuple,结果发现Windows Phone并不支持Tuple,于是我自己定义了一个class Tuple5并且把它用作Dictionary的Value的Type。Class Tuple5的代码如下:

 1 public class Tuple5
 2 {
 3     public T1 Item1 { get; set; }
 4     public T2 Item2 { get; set; }
 5     public T3 Item3 { get; set; }
 6     public T4 Item4 { get; set; }
 7     public T5 Item5 { get; set; }
 8 
 9     public Tuple5(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
10     {
11         Item1 = item1;
12         Item2 = item2;
13         Item3 = item3;
14         Item4 = item4;
15         Item5 = item5;
16     }
17 }

 

存储ReminderList的Dictionary的type如下:

Dictionary<uint, Tuple5string, RecurrenceInterval, Uri>>

 

其中uint是我给每个Reminder分配的一个Universally Unique Identifier (UUID),Tuple5里面五个参数分别为Reminder的开始时间,结束时间,消息,重复响铃频率和声音文件的地址。这样我就可以用这个Dictionary来存储我们的ReminderList了。

2.2. 使用Windows Phone的Alarm

为了让我们的Reminder能在设定的时间响铃,我们使用了Windows Phone SDK 7.1的新功能——Alarm。我首先参考了MSDN官方的代码示例,地址如下:

http://msdn.microsoft.com/en-us/library/hh202965(v=vs.92).aspx

然后自己开始编写代码。下面我主要讲一下如何设置一个Alarm。

首先我们需要使用Windows Phone的scheduler的namespace,代码如下:

using Microsoft.Phone.Scheduler;

然后就是使用传进来的开始时间beginTime,结束时间stopTime,消息message,重复响铃频率recurrence和声音文件的地址sound来创建一个Alram对象并且加入Scheduler,代码如下:

1 Alarm alarm = new Alarm(name);
2 alarm.Content = message;
3 alarm.Sound = sound;
4 alarm.BeginTime = beginTime;
5 alarm.ExpirationTime = stopTime;
6 alarm.RecurrenceType = recurrence;
7 ScheduledActionService.Add(alarm);

 

3. 如何在文件系统中存储ReminderList

因为用户设置的Alarm在下次启动程序的时候还要求能够删除和修改,所以必须要将现有的Alarms存在文件系统里。下面我讲一下我的经验。

3.1. Serialization的失败

我一开始尝试使用C#的XmlSerializer和DataContractSerializer来存储我的Dictionary,但是我经过一天的尝试,最终以失败结束。下面我就XmlSerializer谈谈我的实现方法。

我一开始尝试使用XmlSerializer来将我的Dictionary存成xml文件,然后下次直接从xml文件读取这个Dictionary。代码如下:

 1 XmlSerializer ser = new XmlSerializer(typeof(Dictionary<uint, Tuple5string, RecurrenceInterval, Uri>>));
 2 
 3 // write
 4 using (var stream = File.Create("ReminderList.xml"))
 5 {
 6     ser.Serialize(stream, ReminderList); // your instance
 7 }
 8 
 9 // read
10 using (var stream = File.OpenRead("ReminderList.xml"))
11 {
12     ReminderList = (Dictionary<uint, Tuple5string, RecurrenceInterval, Uri>>)ser.Deserialize(stream);
13 }


最后编译时提示我Uri不能被Serialized。于是我将Uri改成string,他还是提示我Tuple5的Serialization出错,于是我仔细研究这个,尝试了几种方法,包括在我的class Tuple5的定义加上[Serializable()]的属性,最后还是没有成功,于是我开始考虑自己将Dictionary转化成文件。

3.2. 自己将Dictionary转化成文件

因为使用Serialization失败,我开始自己将Dictionary存入文件,我使用了最简单的方法,就是将每个item一行行以string形式存入文件,代码如下:

 1 // Obtain the virtual store for the application.
 2 IsolatedStorageFile myStore = IO.GetUserStore();
 3 myStore.CreateDirectory("Reminder");
 4 
 5 // Specify the file path and options.
 6 using (var isoFileStream = new IsolatedStorageFileStream("Reminder\\ReminderList.dat", FileMode.OpenOrCreate, myStore))
 7 {
 8     //Write the data
 9     using (var isoFileWriter = new StreamWriter(isoFileStream))
10     {
11         foreach (KeyValuePair<uint, Tuple5string, RecurrenceInterval, Uri>> kvp in ReminderList)
12         {
13             isoFileWriter.WriteLine(Convert.ToString(kvp.Key));
14             isoFileWriter.WriteLine(kvp.Value.Item1.ToString());
15             isoFileWriter.WriteLine(kvp.Value.Item2.ToString());
16             isoFileWriter.WriteLine(kvp.Value.Item3);
17             isoFileWriter.WriteLine(kvp.Value.Item4.ToString());
18             if (kvp.Value.Item5 != null)
19             {
20                 isoFileWriter.WriteLine(kvp.Value.Item5.AbsoluteUri);
21             }
22             else
23             {
24                 isoFileWriter.WriteLine("");
25             }
26         }
27     }
28 }

 

有一点要说明的是,Windows Phone使用的是独立的存储文件IsolatedStorageFile,与PC上并不一样。

3.3. 从文件中读取ReminderList

每次启动时,都要能够从文件中读取ReminderList。我是写了一个静态构造函数来从文件读取ReminderList。静态构造函数有一个对象被声明就会调用,且整个程序只调用一次,从文件读取ReminderList的代码如下:

 1 // Obtain a virtual store for the application.
 2 IsolatedStorageFile myStore = IsolatedStorageFile.GetUserStoreForApplication();
 3 
 4 try
 5 {
 6     // Specify the file path and options.
 7     using (var isoFileStream = new IsolatedStorageFileStream("Reminder\\ReminderList.dat", FileMode.Open, myStore))
 8     {
 9         // Read the data.
10         using (var isoFileReader = new StreamReader(isoFileStream))
11         {
12             string line = null;
13             while ((line = isoFileReader.ReadLine()) != null)
14             {
15                 uint newId = Convert.ToUInt32(line);
16                 line = isoFileReader.ReadLine();
17                 DateTime startTime = DateTime.Parse(line);
18                 line = isoFileReader.ReadLine();
19                 DateTime stopTime = DateTime.Parse(line);
20                 line = isoFileReader.ReadLine();
21                 string message = line;
22                 line = isoFileReader.ReadLine();
23                 RecurrenceInterval recurrence = RecurrenceInterval.None;
24                 switch (line)
25                 {
26                 case "None": recurrence = RecurrenceInterval.None; break;
27                 case "Daily": recurrence = RecurrenceInterval.Daily; break;
28                 case "EndOfMonth": recurrence = RecurrenceInterval.EndOfMonth; break;
29                 case "Monthly": recurrence = RecurrenceInterval.Monthly; break;
30                 case "Weekly": recurrence = RecurrenceInterval.Weekly; break;
31                 case "Yearly": recurrence = RecurrenceInterval.Yearly; break;
32                 default: recurrence = RecurrenceInterval.None; break;
33                 }
34 
35                 line = isoFileReader.ReadLine();
36                 Uri sound = null;
37                 if (line != "")
38                 {
39                     sound = new Uri(line, UriKind.Relative);
40                 }
41                 Tuple5string, RecurrenceInterval, Uri> newReminder = new Tuple5string, RecurrenceInterval, Uri>(startTime, stopTime, message, recurrence, sound);
42                 ReminderList.Add(newId, newReminder);
43             }
44         }
45     }
46 }
47 catch
48 {
49     // TODO:
50 }

 

4. 其他细节

虽然实现了Reminder的模块,我还是考虑了很多需要完善的细节,下面举出两个例子。

4.1. 重复的Reminder

用户在设置同一个session的reminder的时候,可能会修改设置,但是在我的程序里就会导致设置两个alarms,于是调用者对于同一个session必须先delete这个alarm(用之前create alarm返回的ID),然后才能创建新的。

4.2. 删去过期的Reminder

有些Alarms已经过了stopTime了,系统需要定期删掉这些Alarms。我是在每次创建新的alarm之前清理过期的alarms。

下面就是我花了将近三天时间研磨总结出来的,如果感觉对你有用,请推荐我们,相信这是对我们新手开发windows phone过程中的鼓励!

你可能感兴趣的:(如何调用windows phone 7.1的后台闹钟功能 step by step)