【Win 10 应用开发】Toast通知激活应用——前台后台
原文:【W(wǎng)in 10 應(yīng)用開發(fā)】Toast通知激活應(yīng)用——前臺&后臺
老周最近熱衷于講故事,接下來還是講故事時間。
有人問我:你上大學(xué)的時候,有加入過學(xué)生會嗎?讀大學(xué)有沒有必要加入學(xué)生會?
哎喲,這怎么回答呢,從短期來說,加入學(xué)生會有點(diǎn)用,至少可以娛樂一下,運(yùn)氣好的話,說不定能遇到紅顏知己,但這概率相當(dāng)?shù)汀拈L遠(yuǎn)發(fā)展看嘛,是沒什么用。老周當(dāng)年讀了四年本科,在學(xué)生會混了四年,什么名堂也沒混出來。
一方面老周向來不求虛名,所以也沒去參選所謂的什么部長、主席之類的,這些“官銜”聽起來很高大上,實(shí)際上很庸俗蠢。既然沒興趣,因而老周更不需要去搞那些見不得人的勾當(dāng),什么勾當(dāng)?你懂的。其次,老周沒感覺到這些職務(wù),對將來的職業(yè)生涯發(fā)展有什么幫助,基本上屬于混日子罷了。
老周當(dāng)初一上大學(xué),本不想進(jìn)什么學(xué)生會天地會之類的,之所以進(jìn)了,純屬意外,簡直太意外了,事情是這樣的。話說那天學(xué)生會招新,盡管老周的母校比較老舊,但校園里還是被各處擺攤招新的學(xué)兄學(xué)姐們弄得像大觀園似的,熱鬧非常。
誰不知道,大觀園里美女多,于是我宿舍的室友開始動心了,有兩個人鼓起勇氣,決定明天去面試。本來跟我沒什么關(guān)系,誰想第二天,又有一位室友感興趣了,他們索性商量全宿舍一起出動。老周本不想去,就被他們硬拉著去。
一伙漫無目的地隨處看,我以為他們是去看美女的,原來他們還真的去面試了,走著走著,我們進(jìn)入了一個教室,里面坐著幾位師兄和師姐。進(jìn)去前要在門口登記,寫上個人信息,然后排隊(duì)面試(教室里都沒幾個人,排什么隊(duì)),我說我不是來面試的,是陪室友來玩玩的。聽我一說完,一位師兄叫我出去走廊外面等。
正當(dāng)我往外走時,另一位師兄又把我叫回來,說既然來了就面面試吧,沒事的。這時候我才知道,他們是要招書法高手的。老周雖不敢當(dāng)什么高手,但從小就握過幾年毛筆,不防耍耍。就這樣,老周就莫名其妙地進(jìn)了學(xué)生會。
想來有趣,本來想進(jìn)的,沒進(jìn);我本不想進(jìn)的,反而進(jìn)了。真是世事無常,禍福相依啊。
=========================================================
故事講完了,下面說正經(jīng)話。
話說上一回,老周給大伙伴們介紹了win 10中Toast通知的新型模板,既包含有舊版本的兼容格式,也有用于通用平臺的“自適應(yīng)”通知。前一文章中,老周主要介紹了XML文檔的基本格式,并演示了兩個例子。
今天,咱們探討一下如何在Toast通知中使用交互命令,并通過交互命令激活應(yīng)用程序。所謂交互命令,就是在Toast通知的界面上添加一些可以讓用戶操作的元素,來與應(yīng)用程序進(jìn)行互動。這些交互元素主要有:
1、按鈕。用action元素來指定,用戶點(diǎn)擊按鈕后會激活應(yīng)用程序,并把用戶所點(diǎn)擊的按鈕的參數(shù)作為激活參數(shù)傳遞給應(yīng)用程序。
2、輸入框。就是一個文本框,用戶可以在里面輸入文本。
3、選擇列表。類似于下拉列表框,用戶可以在里面選擇一個項(xiàng)。
這些交互元素都統(tǒng)一放到actions元素下面。
舉個例子,比如這樣:
<toast><visual><binding template="ToastGeneric"><text>唱山歌</text><text>一起去唱山歌吧.</text><image placement="appLogoOverride" src="c.png" /></binding></visual><actions><action content="報名" arguments="join" imageUri="jn.png" /><action content="不去" arguments="cancel" /></actions> </toast>大家可以想象一下這個Toast通知是什么樣子的,現(xiàn)在不截圖給你看,待會兒咱們做示例時再看。
首先,visual元素在前一篇爛文中講過,是描述toast通知的可視化部分,第一個text被視為標(biāo)題,所以顯示出來字體較大,第二個text作為正文,顯示一行文本。image元素指定一個圖像,因?yàn)樵O(shè)置了placement="appLogoOverride",表明這個圖像會替換應(yīng)用的默認(rèn)圖標(biāo),顯示在通知的左上角。
?
接下來,重點(diǎn)關(guān)注actions元素,actions元素下面專門用來放置交互命令,有兩個元素可用:
<action>:表示定義一個命令按鈕。例如:
<action content = "確定" arguments = "yes" activationType ="foreground或background" imageUrl="b.png" />content表示要在按鈕上顯示的文本,上面例子在按鈕上顯示“確定”。imageUrl表示顯示在按鈕上的圖標(biāo),如果不用圖標(biāo),就可以不設(shè)置imageUrl屬性。arguments用來指定一個參數(shù),這個參數(shù)是你自己定的,比如我這里叫yes,當(dāng)用戶點(diǎn)擊按鈕后,arguments的值會傳遞給應(yīng)用程序,這樣應(yīng)用程序才會知道你到底點(diǎn)擊了哪個按鈕。
activationType指示以何種方式激活應(yīng)用程序,如果值為foreground,則表明toast通知將在前臺激活應(yīng)用程序,這時候用戶可以看見應(yīng)用程序;如果值為background,表明toast通知通過后臺方式激活應(yīng)用,此時用戶看不到應(yīng)用程序,后臺激活必須指定一個后臺任務(wù),當(dāng)激活時就會執(zhí)行后臺任務(wù)。如果值為protocol,表示將通過協(xié)議來激活應(yīng)用程序。
?
如果希望用戶可以在Toast通知上輸入內(nèi)容,可以這樣定義XML:
<input id="name" type="text" />Toast通知上會顯示一個文本框,id屬性是必須指定的,而且必須是actions中的唯一值,不能重復(fù),這個id值在激活應(yīng)用程序時會傳遞給應(yīng)用。type屬性指定input元素的類型,text表示文本框,讓用戶輸入文本。如果是selection表示顯示一個列表選擇框,用戶只能從中選擇一個項(xiàng)。
如果type為selection,那么input元素下會包含N個selection元素,每個selection元素表示一個選項(xiàng),如
<input id="age" type="selection"><selection content="五歲" id="5" /><selection content="七歲" id="7" /> </input>上面例子,定義了兩個選項(xiàng),每個selection的id值必須唯一,它表示該項(xiàng)的值,這個id也會傳遞給被激活的程序。content表示項(xiàng)中顯示的文本,用來給你看的。即當(dāng)toast彈出時,在下拉列表中,你看到的是五歲、七歲兩個選項(xiàng)。
下面我們來實(shí)戰(zhàn)一下,先看Toast通知如何從前臺激活應(yīng)用。
首先構(gòu)造XML文檔。
string visual = "<visual>" +"<binding template=\"ToastGeneric\">" +"<text>宇宙第一應(yīng)用</text>" +"<text>應(yīng)用正在收集您的信息。</text>" +"</binding>" +"</visual>";string actions = "<actions>" +"<input id=\"name\" type=\"text\" placeHolderContent=\"請輸入姓名\" />" +"<input id=\"city\" type=\"text\" placeHolderContent=\"請輸入城市\(zhòng)" />" +"<action content=\"確定\" arguments=\"ok\" />" +"<action content=\"取消\" arguments=\"cancel\" activationType=\"foreground\" />" +"</actions>";string toastXml = $"<toast>{visual}{actions}</toast>";?有一點(diǎn)大伙要注意,當(dāng)input和action元素同時使用時,input元素必須放在action元素的前面。placeHolderContent屬性主要設(shè)置占位文本,即當(dāng)文本框中沒有輸入任何內(nèi)容時顯示的文本。
上面的Toast通知定義了兩個可供輸入的文本框,以及兩個命令按鈕。
?
下面代碼顯示通知。
// 加載XML文檔XmlDocument doc = new XmlDocument();doc.LoadXml(toastXml);// 顯示通知ToastNotification notification = new ToastNotification(doc);ToastNotifier notifier = ToastNotificationManager.CreateToastNotifier();notifier.Show(notification);
正因?yàn)閼?yīng)用程序是被前臺激活的,所以肯定要為Application類作激活處理,在App類中,重寫基類的OnActivated方法。
?先要通過方法參數(shù)的Kind屬性來判斷一下應(yīng)用程序是不是被Toast通知所激活的,如果值是ToastNotification,證明應(yīng)用程序是被Toast通知激活的。
然后要把方法參數(shù)的類型轉(zhuǎn)化為ToastNotificationActivatedEventArgs類型,ToastNotificationActivatedEventArgs類專用于Toast通知的激活。
Argument屬性中取得的值就是被點(diǎn)擊的action的arguments屬性中的值,上面我定義的toast有兩個action,arguments的值分別為ok和cancel,如果用戶點(diǎn)擊了確定按鈕,那么從ToastNotificationActivatedEventArgs對象的Argument屬性得到的值為ok,否則就是cancel。
UserInput屬性獲取的就是input元素的值,屬性類型為ValueSet,實(shí)際上是一個字典類型。Key為Toast通知中input元素的id,Value的值是input元素中輸入的內(nèi)容。通過UserInput屬性,程序就知道用戶在文本框中輸入了什么內(nèi)容。
運(yùn)行應(yīng)用程序,當(dāng)通知彈出時,輸入相關(guān)內(nèi)容,如下圖。
輸入一些文本后,然后點(diǎn)擊確定按鈕,然后應(yīng)用程序被激活,會看到主頁面上顯示從Toast通知傳遞到應(yīng)用程序的輸入數(shù)據(jù)。如下圖所示。
---------------------------------------------------------------------------------------------------
上面演示的是Toast通知從前臺激活應(yīng)用程序,下面來看看后臺激活。Toast通知從后臺激活應(yīng)用程序,用戶不會看到應(yīng)用程序界面,但應(yīng)用程序會在后臺任務(wù)中處理從Toast通知傳遞到應(yīng)用程序的數(shù)據(jù)。
要實(shí)現(xiàn)從后臺處理Toast通知,首先要實(shí)現(xiàn)一個后臺任務(wù)。記住后臺任務(wù)要在一個獨(dú)立的Runtime組件項(xiàng)目中。后臺的實(shí)現(xiàn)代碼如下:
public sealed class ToastBgTask : IBackgroundTask{public async void Run(IBackgroundTaskInstance taskInstance){var deferral = taskInstance.GetDeferral();ToastNotificationActionTriggerDetail details = taskInstance.TriggerDetails as ToastNotificationActionTriggerDetail;if (details != null){// 先確認(rèn)用戶點(diǎn)擊了yes按鈕string cmdargs = details.Argument;if (cmdargs == "yes"){// 獲取選擇的項(xiàng)object value = details.UserInput["ut"];// 保存數(shù)據(jù)StorageFolder local = ApplicationData.Current.LocalFolder;JsonObject jsobj = new JsonObject();jsobj.SetNamedValue("updatetime", JsonValue.CreateNumberValue(Convert.ToDouble(value)));StorageFile newFile = await local.CreateFileAsync("data.json", CreationCollisionOption.ReplaceExisting);await FileIO.WriteTextAsync(newFile, jsobj.Stringify(), Windows.Storage.Streams.UnicodeEncoding.Utf8);}}deferral.Complete();}}當(dāng)Toast通知激活后臺任務(wù)后,可以從?taskInstance.TriggerDetails屬性獲取到一個ToastNotificationActionTriggerDetail對象實(shí)例。和前臺激活一樣,通過Argument屬性可以獲取Toast通知中被用戶點(diǎn)擊的action元素的參數(shù)。從UserInput屬性可以獲取到input元素的id值。
后臺任務(wù)完成后,記得要在主項(xiàng)目中引用,這個老周已經(jīng)重復(fù)了幾千遍了。
然后打開清單文件,在Package/Applications/Application節(jié)點(diǎn)下添加后臺任務(wù)聲明。
<Extensions><Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTasks.ToastBgTask"><BackgroundTasks><Task Type="general"/></BackgroundTasks></Extension></Extensions>
?
由于在后臺任務(wù)中,是把用戶在Toast通知上選擇的項(xiàng)保存到本地文件中,所以在主應(yīng)用中,可以讀出文件的內(nèi)容,并顯示出來。
protected override async void OnNavigatedTo(NavigationEventArgs e){try{// 讀入后臺保存的內(nèi)容StorageFolder local = ApplicationData.Current.LocalFolder;StorageFile dataFile = await local.GetFileAsync("data.json");if (dataFile == null) return;string jsstr = await FileIO.ReadTextAsync(dataFile, Windows.Storage.Streams.UnicodeEncoding.Utf8);JsonObject jsobj = null;if (JsonObject.TryParse(jsstr, out jsobj)){double d = jsobj.GetNamedNumber("updatetime");tbResultFromBackActivate.Text = $"你選擇了每隔{d:N0}天更新一次。";}await dataFile.DeleteAsync();}catch(Exception ex){Debug.WriteLine($"文件讀取異常:{ex.Message},異常類型:{ex.GetType().Name}。");}}?
最后,我們實(shí)現(xiàn)顯示Toast通知的代碼。
string visual = "<visual>" +"<binding template=\"ToastGeneric\">" +"<text>無敵應(yīng)用</text>" +"<text>請選擇更新間隔天數(shù)。</text>" +"</binding>" +"</visual>";string actions = "<actions>" +"<input id=\"ut\" type=\"selection\" defaultInput=\"5\">"+"<selection id=\"3\" content=\"3天\" />" +"<selection id=\"5\" content=\"5天\" />" +"<selection id=\"10\" content=\"10天\" />" +"</input>" +"<action content=\"是\" activationType=\"background\" arguments=\"yes\" />" +"<action content=\"否\" activationType=\"background\" arguments=\"no\" />" +"</actions>";string toastXml = $"<toast>{visual}{actions}</toast>";XmlDocument doc = new XmlDocument();doc.LoadXml(toastXml);ToastNotification notification = new ToastNotification(doc);ToastNotifier notifier = ToastNotificationManager.CreateToastNotifier();notifier.Show(notification);?
input元素的type為selection,表示Toast通知上的輸入行為為列表選擇,并使用三個selection元素定義了三個選項(xiàng)。注意,在input元素中,defaultInput屬性指定輸入控件的默認(rèn)值。如果type為text,該屬性設(shè)置默認(rèn)的文本;在本例中,type為selection,所以默認(rèn)值就是希望默認(rèn)被選中的項(xiàng)的id值。
?
似乎一切就緒了,實(shí)際上我們還有很關(guān)鍵一步?jīng)]有做——注冊后臺任務(wù),清單文件中僅僅是聲明,而要希望讓Toast通知的操作激活后臺任務(wù),還需要對后臺任務(wù)進(jìn)行注冊。
private async void RegToastBackgroundTask(){// 判斷一下是否允許訪問后臺任務(wù)var res = await BackgroundExecutionManager.RequestAccessAsync();if (res == BackgroundAccessStatus.Denied || res == BackgroundAccessStatus.Unspecified){return;}Type taskType = typeof(BackgroundTasks.ToastBgTask);var task = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault(t => t.Name == taskType.Name);if (task == null){// 注冊后臺任務(wù)BackgroundTaskBuilder bd = new BackgroundTaskBuilder();bd.Name = taskType.Name;bd.TaskEntryPoint = taskType.FullName;// 聲明觸發(fā)器ToastNotificationActionTrigger trigger = new ToastNotificationActionTrigger();bd.SetTrigger(trigger);task = bd.Register();}}后臺的觸發(fā)器便用?ToastNotificationActionTrigger類型。
?
現(xiàn)在我們來看一下,運(yùn)行程序,等Toast通知出現(xiàn)后,把程序關(guān)了。然后在Toast通知上選擇一個項(xiàng),然后提交。
?
然后再次啟動應(yīng)用程序,可以看到結(jié)果了。
?
如何,這Win10的Toast通知是不是很牛X呢。由于小妹妹正在拿著我的920玩,所以就不用手機(jī)運(yùn)行了,手機(jī)模擬器沒有安裝,大伙兒有興趣的可以耍耍。
示例源碼:http://files.cnblogs.com/files/tcjiaan/toastActivationApp.zip
?
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的【Win 10 应用开发】Toast通知激活应用——前台后台的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: killall
- 下一篇: 进程通信QSharedMemory