Windows phone 8 学习笔记(5) 图块与通知
基于metro风格的Windows phone 8 应用提到了图块的概念,它就是指启动菜单中的快速启动图标。一般一个应用必须有一个默认图块,还可以有若干个次要图块。另外,通知与图块的关系比较密切,我们可以通过在接受到消息时动态更新图块来达到适时的效果。我们本节把图块和通知放在一起讲。
快速导航:
一、图块
二、图块更新计划
三、本地通知
四、推送通知
一、图块
1)定义默认图块
默认图块只能在清单文件中定义它,并且选定的图块模板后就不能再改变,除非重新发布应用,但是我们可以更新同类型的模板。应用安装后默认状态不会出现在开始菜单,需要在程序清单中右键选择固定到开始屏幕项。
图块模板类型:
1.图标模版:它可以包含大小两种图标,三种图块都可以用。必须为包含透明背景的png格式metro风格图片。
2.翻转模版:在中型、大型图块中可以实现翻转效果。
3.循环模板:在中型、大型图块中实现多张背景图轮流切换。
2)创建更新图块
图块的创建和更新可以通过两种方式,分别是定义模版xml或通过代码构建,下面的代码演示了如何创建和更新图块。
[C#] public partial class MainPage : PhoneApplicationPage{// 构造函数public MainPage(){InitializeComponent();// 用于本地化 ApplicationBar 的示例代码//BuildLocalizedApplicationBar();}protected override void OnNavigatedTo(NavigationEventArgs e){base.OnNavigatedTo(e);}private void Button_Click_1(object sender, RoutedEventArgs e){CreateTitle();}private void ShowTitle(){var tilte = ShellTile.ActiveTiles.FirstOrDefault();if (tilte != null){MessageBox.Show(tilte.NavigationUri.ToString());}}//图标图块IconicTileData iconicTileData = new IconicTileData(){Title = "标题",Count = 5,WideContent1 = "第一行文本",WideContent2 = "第二行文本",WideContent3 = "第三行文本",SmallIconImage = new Uri("/Assets/Tiles/IconLarge.png", UriKind.Relative),IconImage = new Uri("/Assets/Tiles/IconSamall.png", UriKind.Relative),//透明度设置为255才会显示自定义颜色背景,否则显示为系统背景BackgroundColor = new Color { A = 255, R = 0, G = 148, B = 255 }};//图标图块模板string iconicTileXml = @"<?xml version=""1.0"" encoding=""utf-8""?><wp:Notification xmlns:wp=""WPNotification"" Version=""2.0""><wp:Tile Id=""titleid1"" Template=""IconicTile""><wp:SmallIconImage>/Assets/Tiles/IconLarge.png</wp:SmallIconImage><wp:IconImage>/Assets/Tiles/IconSamall.png</wp:IconImage><wp:WideContent1>第一行文本</wp:WideContent1><wp:WideContent2 Action=""Clear"">第二行文本</wp:WideContent2><wp:WideContent3>第三行文本</wp:WideContent3><wp:Count>6</wp:Count><wp:Title>标题</wp:Title><wp:BackgroundColor>#FF524742</wp:BackgroundColor></wp:Tile></wp:Notification>";//可用于清除Count(如果加了Action="Clear",则清除该项的显示)string iconicTileXml2 = @"<?xml version=""1.0"" encoding=""utf-8""?><wp:Notification xmlns:wp=""WPNotification"" Version=""2.0""><wp:Tile Id=""titleid1"" Template=""IconicTile""><wp:Count Action=""Clear"">0</wp:Count></wp:Tile></wp:Notification>";//翻转图块FlipTileData flipTileData = new FlipTileData(){Title = "标题",BackTitle = "背面标题",BackContent = "背面的文本内容部分",WideBackContent = "在宽图块背面的文本内容",Count = 5,SmallBackgroundImage = new Uri("/Assets/Tiles/Samall.png", UriKind.Relative),BackgroundImage = new Uri("/Assets/Tiles/Medium.png", UriKind.Relative),//不设置背景图像则显示为系统背景色//BackBackgroundImage = new Uri("Assets/Tiles/FlipCycleTileMedium.png", UriKind.Relative),WideBackgroundImage = new Uri("/Assets/Tiles/Large.png", UriKind.Relative),//WideBackBackgroundImage = new Uri("/Assets/Tiles/IconicTileMediumLarge.png", UriKind.Relative)};//翻转图块模板string flipTileXml = @"<?xml version=""1.0"" encoding=""utf-8""?><wp:Notification xmlns:wp=""WPNotification"" Version=""2.0""><wp:Tile Id=""titleid2"" Template=""FlipTile""><wp:SmallBackgroundImage>/Assets/Tiles/Samall.png</wp:SmallBackgroundImage><wp:WideBackgroundImage>/Assets/Tiles/Large.png</wp:WideBackgroundImage><wp:WideBackBackgroundImage>/Assets/Tiles/IconicTileMediumLarge.png</wp:WideBackBackgroundImage><wp:WideBackContent>在宽图块背面的文本内容</wp:WideBackContent><wp:BackgroundImage>/Assets/Tiles/Medium.png</wp:BackgroundImage><wp:Count>6</wp:Count><wp:Title>标题</wp:Title><wp:BackBackgroundImage>Assets/Tiles/FlipCycleTileMedium.png</wp:BackBackgroundImage><wp:BackTitle>背面标题</wp:BackTitle><wp:BackContent>背面的文本内容部分</wp:BackContent></wp:Tile></wp:Notification>";//循环图块CycleTileData cycleTileData = new CycleTileData(){Title = "标题",Count = 10,SmallBackgroundImage = new Uri("/Assets/Tiles/Samall.png", UriKind.Relative),CycleImages = new Uri[]{new Uri("/Assets/Tiles/Title1.png", UriKind.Relative), new Uri("/Assets/Tiles/Title2.png", UriKind.Relative), new Uri("/Assets/Tiles/Title3.png", UriKind.Relative), }};//循环图块模板string cycleTileXml = @"<?xml version=""1.0"" encoding=""utf-8""?><wp:Notification xmlns:wp=""WPNotification"" Version=""2.0""><wp:Tile Id=""titleid3"" Template=""CycleTile""><wp:SmallBackgroundImage>/Assets/Tiles/Samall.png</wp:SmallBackgroundImage><wp:CycleImage1>/Assets/Tiles/Title1.png</wp:CycleImage1><wp:CycleImage2>/Assets/Tiles/Title2.png</wp:CycleImage2><wp:CycleImage3>/Assets/Tiles/Title3.png</wp:CycleImage3><wp:Count>6</wp:Count><wp:Title>标题</wp:Title></wp:Tile></wp:Notification>";private void CreateTitle(){//添加一个次要图块ShellTile.Create(new Uri("/Page1.xaml", UriKind.Relative), iconicTileData, true);//通过xml模板添加ShellTile.Create(new Uri("/Page1.xaml", UriKind.Relative), new IconicTileData(iconicTileXml), true);}private void ClearCount(){//清除CountShellTile.ActiveTiles.ElementAt(1).Update(new IconicTileData(iconicTileXml2));}private void UpdateTitle(){//更新默认图块的内容,我们定义的翻转模版,这里不能修改模版类型ShellTile.ActiveTiles.FirstOrDefault().Update(flipTileData);}}
二、图块更新计划
我们可以定义一个更新计划,定期的更新图块的背景图像。当应用退出以后,这个更新计划依然能够在后台运行。它的实现代码如下:
[C#] ShellTileSchedule SampleTileSchedule = new ShellTileSchedule();//计划是否已经执行bool TileScheduleRunning = false;//开始执行计划private void Button_Click_1(object sender, RoutedEventArgs e){//指定计划执行一次还是多次SampleTileSchedule.Recurrence = UpdateRecurrence.Interval;//指定计划的更新间隔时间SampleTileSchedule.Interval = UpdateInterval.EveryHour;//指定计划的执行次数,如果未设置,则为不确定次数SampleTileSchedule.MaxUpdateCount = 50;//指定计划的开始时间SampleTileSchedule.StartTime = DateTime.Now;//获取背景图像的网络URISampleTileSchedule.RemoteImageUri = new Uri(@"http://images.cnblogs.com/cnblogs_com/lipan/319399/o_Large.png");SampleTileSchedule.Start();}//停止计划private void Button_Click_2(object sender, RoutedEventArgs e){if (TileScheduleRunning) SampleTileSchedule.Stop();}
三、本地通知
通知分为本地通知和推送通知。我们可以通过本地通知实现本地消息和提醒功能。
1)本地消息和提醒
我们可以定义提醒和闹钟的功能,在应用退出以后,当计划的提醒时间达到时,提醒或者闹钟功能将自动别触发,其中闹钟的功能我们还可以自定义铃声。下面看看代码实现的过程。
[XAML] <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"><ListBox x:Name="listbox1" Width="440" MaxHeight="420" Margin="10,44,0,150"><ListBox.ItemTemplate><DataTemplate><Grid><StackPanel Orientation="Horizontal" Background="Blue" Width="440"><TextBlock Width="120" Text="{Binding Title}" /><TextBlock Text="{Binding BeginTime}" /><TextBlock Text="{Binding RecurrenceType}" /><TextBlock Text=" " /><TextBlock Text="{Binding IsScheduled}" /><TextBlock Text=" " /><Button Margin="0" Tag="{Binding Name}" Click="deleteButton_Click" Content="X" BorderBrush="Red" Background="Red" Foreground="{StaticResource PhoneBackgroundBrush}" VerticalAlignment="Top" BorderThickness="0" Width="50" Padding="0,0,0,0"></Button></StackPanel></Grid></DataTemplate></ListBox.ItemTemplate><ListBox.ItemContainerStyle><Style TargetType="ListBoxItem"><Setter Property="Margin" Value="5"/></Style></ListBox.ItemContainerStyle></ListBox><TextBlock HorizontalAlignment="Left" Margin="10,12,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="已注册的本地消息提醒:"></TextBlock><TextBox x:Name="textbox1" HorizontalAlignment="Left" Height="72" Margin="10,555,0,0" TextWrapping="Wrap" Text="标题" VerticalAlignment="Top" Width="125"/><RadioButton x:Name="radioButton1" IsChecked="True" GroupName="radioButtonGroup" Content="Reminder" HorizontalAlignment="Left" Margin="135,532,0,0" VerticalAlignment="Top"/><RadioButton x:Name="radioButton2" GroupName="radioButtonGroup" Content="Alarm" HorizontalAlignment="Left" Margin="134,604,0,0" VerticalAlignment="Top"/><Button Content="注册" HorizontalAlignment="Left" Margin="328,569,0,0" VerticalAlignment="Top" Click="Button_Click_1"/></Grid> [C#] public partial class Page1 : PhoneApplicationPage{public Page1(){InitializeComponent();}IEnumerable<ScheduledNotification> notifications;protected override void OnNavigatedTo(NavigationEventArgs e){ListboxInit();base.OnNavigatedTo(e);}private void ListboxInit(){//返回系统所有已注册的通知notifications = ScheduledActionService.GetActions<ScheduledNotification>();listbox1.ItemsSource = notifications;}//删除一个通知private void deleteButton_Click(object sender, RoutedEventArgs e){string name = (string)((Button)sender).Tag;ScheduledActionService.Remove(name);ListboxInit();}//新增一个通知private void Button_Click_1(object sender, RoutedEventArgs e){String name = System.Guid.NewGuid().ToString();if (radioButton1.IsChecked == true){//名称,唯一标识Reminder reminder = new Reminder(name);//消息标题reminder.Title = textbox1.Text;reminder.Content = "这里是提醒的正文部分。";//消息重现类型reminder.RecurrenceType = RecurrenceInterval.Daily;//开始时间reminder.BeginTime = DateTime.Now + new TimeSpan(0, 0, 30);//结束时间reminder.ExpirationTime = DateTime.Now + new TimeSpan(0, 0, 45);//从提醒启动应用程序时的启动URIreminder.NavigationUri = new Uri("/Page2.xaml?a=test", UriKind.Relative);//注册ScheduledActionService.Add(reminder);}else{//可以自定义铃声的通知Alarm alarm = new Alarm(name);alarm.Content = "这里是闹钟的正文部分。";//提醒时播放的文件alarm.Sound = new Uri("/1.mp3", UriKind.Relative);//消息重现类型alarm.RecurrenceType = RecurrenceInterval.Daily;//开始时间alarm.BeginTime = DateTime.Now + new TimeSpan(0, 0, 30);//结束时间alarm.ExpirationTime = DateTime.Now + new TimeSpan(0, 1, 30);//注册ScheduledActionService.Add(alarm);}ListboxInit();}}2)本地Toast
通过本地Toast可以在实现Toast消息弹出,但是当应用运行时则不会弹出,所以一般在后台计划中被调用。详细情况请见《Windows phone 8 学习笔记 多任务 后台代理》 。
四、推送通知
推送通知都需要借助于微软推送云服务器,因为一般来讲,应用退出以后是不会保留后台服务去等待接受消息的,这种做法比较费电。推送通知的做法是,当有消息推送过来的时候,由系统去统一完成消息的接收,用户选择性的去启动应用。
1. 推送通知的类型
推送通知主要有三种类型,如下:
1.磁贴通知:消息到达时,将会更新应用的默认图块,这样直观的现实当前应用有更新内容。
2.Toast推送通知:消息到达时,将会在屏幕上方弹出一个Toast提示,用户单击即可启动应用。
3.raw通知:这个通知在应用运行的前提下,提供灵活的消息处理,但是非允许状态下将无法接受消息。
2. 推送通知的实现
要实现推送通知,首先我们需要建立推送通道。在Windows phone 中建立推送通道,并且得到通道的URI。代码如下:
[C# Windows phone] //磁贴通知private void TileInit(){//推送服务通道HttpNotificationChannel pushChannel;//通道名称string channelName = "TileSampleChannel";InitializeComponent();//尝试发现是否已经创建pushChannel = HttpNotificationChannel.Find(channelName);var newChannel = false;//没有发现,新建一个if (pushChannel == null){pushChannel = new HttpNotificationChannel(channelName);newChannel = true;}//通知通道关联URI改变时:pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);//出错时:pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);if (newChannel){pushChannel.Open();//将通知订阅绑定到默认图块pushChannel.BindToShellTile();}else{MessageBox.Show(String.Format("通道URI: {0}", pushChannel.ChannelUri.ToString()));}}//Toast通知private void ToastInit(){//推送服务通道HttpNotificationChannel pushChannel;//通道名称string channelName = "ToastSampleChannel";InitializeComponent();//尝试发现是否已经创建pushChannel = HttpNotificationChannel.Find(channelName);var newChannel = false;//没有发现,新建一个if (pushChannel == null){pushChannel = new HttpNotificationChannel(channelName);newChannel = true;}//通知通道关联URI改变时:pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);//出错时:pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);//收到Toast消息时:(如果程序未启动则弹出Toast,否则触发该事件)pushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(PushChannel_ShellToastNotificationReceived);if (newChannel){pushChannel.Open();//将通知订阅绑定到ShellToastpushChannel.BindToShellToast();}else{MessageBox.Show(String.Format("通道URI: {0}", pushChannel.ChannelUri.ToString()));}}//Row通知private void RawInit(){//推送服务通道HttpNotificationChannel pushChannel;//通道名称string channelName = "RawSampleChannel";InitializeComponent();//尝试发现是否已经创建pushChannel = HttpNotificationChannel.Find(channelName);var newChannel = false;//没有发现,新建一个if (pushChannel == null){pushChannel = new HttpNotificationChannel(channelName);newChannel = true;}//通知通道关联URI改变时:pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);//出错时:pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);//收到Raw通知时:(只有应用运行时才触发本事件)pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);if (newChannel){pushChannel.Open();//这里并没有绑定操作}else{MessageBox.Show(String.Format("通道URI: {0}", pushChannel.ChannelUri.ToString()));}}//URI更新时void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e){Dispatcher.BeginInvoke(() =>{MessageBox.Show(String.Format("通道URI: {0}", e.ChannelUri.ToString()));});}//遇到错误时void PushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e){//处理错误}//收到Toast通知时void PushChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e){StringBuilder message = new StringBuilder();string relativeUri = string.Empty;message.AppendFormat("收到 Toast {0}:\n", DateTime.Now.ToShortTimeString());foreach (string key in e.Collection.Keys){message.AppendFormat("{0}: {1}\n", key, e.Collection[key]);if (key.ToLower() == "wp:param") relativeUri = e.Collection[key];}Dispatcher.BeginInvoke(() => MessageBox.Show(message.ToString()));}//收到Raw通知时:void PushChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e){string message;using (System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body)){message = reader.ReadToEnd();}Dispatcher.BeginInvoke(() =>MessageBox.Show(String.Format("收到 Row {0}:\n{1}",DateTime.Now.ToShortTimeString(), message)));}得到推送URI后,我们需要一个web服务端,这个服务端就是我们用来向自己的应用发送推送消息的地方,如果web端用.net实现,那么实现方式如下:
[C# .Net] //发送磁贴消息private void SendTile(){try{string subscriptionUri = TextBoxUri.Text.ToString();HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(subscriptionUri);httpWebRequest.Method = "POST";string tileMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +"<wp:Notification xmlns:wp=\"WPNotification\">" +"<wp:Tile>" +"<wp:BackgroundImage>/Assets/Tiles/FlipCycleTileMedium.png</wp:BackgroundImage>" +"<wp:Count>5</wp:Count>" +"<wp:Title>标题</wp:Title>" +"<wp:BackBackgroundImage></wp:BackBackgroundImage>" +"<wp:BackTitle>背面标题</wp:BackTitle>" +"<wp:BackContent>背面文本内容</wp:BackContent>" +"</wp:Tile> " +"</wp:Notification>";byte[] notificationMessage = Encoding.Default.GetBytes(tileMessage);httpWebRequest.ContentLength = notificationMessage.Length;httpWebRequest.ContentType = "text/xml";//X-WindowsPhone-Target设置为tokenhttpWebRequest.Headers.Add("X-WindowsPhone-Target", "token");//Tile消息类型为 1httpWebRequest.Headers.Add("X-NotificationClass", "1");using (Stream requestStream = httpWebRequest.GetRequestStream()){requestStream.Write(notificationMessage, 0, notificationMessage.Length);}HttpWebResponse response = (HttpWebResponse)httpWebRequest.GetResponse();string notificationStatus = response.Headers["X-NotificationStatus"];string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];}catch (Exception ex){}}//发送Toast消息private void SendToast(){try{//这个URI就是通道创建时由WP客户端获取到的,需要提交到服务端string uri = TextBoxUri.Text.ToString();HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);httpWebRequest.Method = "POST";string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +"<wp:Notification xmlns:wp=\"WPNotification\">" +"<wp:Toast>" +"<wp:Text1>标题</wp:Text1>" +"<wp:Text2>内容部分</wp:Text2>" +"<wp:Param>/Page2.xaml?NavigatedFrom=ToastNotification</wp:Param>" +"</wp:Toast> " +"</wp:Notification>";byte[] notificationMessage = Encoding.Default.GetBytes(toastMessage);//设置请求头httpWebRequest.ContentLength = notificationMessage.Length;httpWebRequest.ContentType = "text/xml";//X-WindowsPhone-Target设置为toasthttpWebRequest.Headers.Add("X-WindowsPhone-Target", "toast");//Toast消息类型为 2httpWebRequest.Headers.Add("X-NotificationClass", "2");using (Stream requestStream = httpWebRequest.GetRequestStream()){requestStream.Write(notificationMessage, 0, notificationMessage.Length);}HttpWebResponse response = (HttpWebResponse)httpWebRequest.GetResponse();//获取相应头包含的状态信息string notificationStatus = response.Headers["X-NotificationStatus"];string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];}catch (Exception ex){}}//发送Raw消息private void SendRaw(){try{string subscriptionUri = TextBoxUri.Text.ToString();HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(subscriptionUri);httpWebRequest.Method = "POST";//这里的消息内容完全自定义,也可以为非xmlstring rawMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +"<root>" +"<Value1>a<Value1>" +"<Value2>b<Value2>" +"</root>";byte[] notificationMessage = Encoding.Default.GetBytes(rawMessage);httpWebRequest.ContentLength = notificationMessage.Length;httpWebRequest.ContentType = "text/xml";//没有 X-WindowsPhone-Target 头//Raw消息类型为 3httpWebRequest.Headers.Add("X-NotificationClass", "3");using (Stream requestStream = httpWebRequest.GetRequestStream()){requestStream.Write(notificationMessage, 0, notificationMessage.Length);}HttpWebResponse response = (HttpWebResponse)httpWebRequest.GetResponse();string notificationStatus = response.Headers["X-NotificationStatus"];string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];}catch (Exception ex){}}作者:[Lipan]
出处:[http://www.cnblogs.com/lipan/]
版权声明:本文的版权归作者与博客园共有。转载时须注明原文出处以及作者,并保留原文指向型链接,不得更改原文内容。否则作者将保留追究其法律责任。 《上一篇:Windows phone 8 学习笔记 应用的启动 系列目录 下一篇:Windows phone 8 学习笔记 多任务》
转载于:https://www.cnblogs.com/lipan/archive/2013/06/05/3092266.html
总结
以上是生活随笔为你收集整理的Windows phone 8 学习笔记(5) 图块与通知的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: PostgreSQL在何处处理 sql查
- 下一篇: 实时个性化推荐系统简述