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查
- 下一篇: HDU 3874 Necklace (数