標籤:des style blog http 使用 os strong io
Windows phone 8 的應用除了可以直接從開始菜單以及應用列表中開啟外,還可以通過其他的方式開啟。照片中心、音樂+視頻中心提供擴充支援應用從此啟動。另外,我們還可以通過檔案關聯、URI關聯的方式啟動應用。
快速導航:
一、擴充音樂+視頻中心
二、擴充照片中心
三、檔案關聯以及SD卡訪問
四、URI關聯
五、啟動我的其他應用和啟動內建應用程式 一、擴充音樂+視頻中心 1)在音樂+視頻中心啟動應用
擴充音樂+視頻中心第一步就是要保證應用可以從音樂+視頻中心啟動,我們需要手工修改 Windows Phone 的應用資訊清單檔,在WMAppManifest.xml檔案上右鍵,選擇開啟檔案,用XML文字編輯器開啟,我們需要設定App 節點下 HubType 值為1,代碼如下:
[XML]
<App xmlns="" HubType="1" ProductID="{4887def4-a91a-465f-8eda-a3b07d8c12c2}" Title="音視擴充樣本" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal" Author="Phone音視擴充 author" Description="Sample description" Publisher="Phone音視擴充">......</App>
2)更新記錄、最新上市列表
應用整合到音樂+視頻中心後,我們可以更新音樂+視頻中心的歷程清單、記錄現正播放圖塊、最新上市列表等,下面代碼描述了更新的方式。
[C#]
//根據song構建MediaHistoryItem(媒體項目資訊) private MediaHistoryItem getMediaHistoryItem(Song song) { MediaHistoryItem mediaHistoryItem = new MediaHistoryItem(); //當前歌曲專輯的縮圖 mediaHistoryItem.ImageStream = song.Album.GetThumbnail(); mediaHistoryItem.Source = string.Empty; //音樂名,會顯示在縮圖上 mediaHistoryItem.Title = song.Name; mediaHistoryItem.PlayerContext.Add("KeySring", song.Name); return mediaHistoryItem; } //更新記錄列表中的現正播放 private void updatePlaying(Song song) { MediaHistory.Instance.NowPlaying = getMediaHistoryItem(song); } //更新記錄列表 private void updateHistoryList(Song song) { MediaHistory.Instance.WriteRecentPlay(getMediaHistoryItem(song)); } //更新最新上市列表 private void updateNewList(Song song) { MediaHistory.Instance.WriteAcquiredItem(getMediaHistoryItem(song)); }
我們除了可以對媒體庫的音樂進行更新記錄和最新上市列表外,也可以自訂其他音樂。這樣非媒體庫的的音樂也可以更新。但是可能會存在一些問題。下面代碼示範了把安裝資料夾的音樂播放出來,並更新現正播放列表。
[C#]
//從安裝資料夾讀取專輯縮圖StreamResourceInfo jpgStreamResourceInfo = Application.GetResourceStream(new Uri("myImg.jpg", UriKind.Relative));MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();//當前歌曲專輯的縮圖mediaHistoryItem.ImageStream = jpgStreamResourceInfo.Stream;mediaHistoryItem.Source = string.Empty;//音樂名,會顯示在縮圖上mediaHistoryItem.Title = "我的音樂";mediaHistoryItem.PlayerContext.Add("KeySring", "我的音樂");//準備播放mediaElement1.Source = new Uri("1.mp3", UriKind.Relative);mediaElement1.Play();//更新音樂視頻中心的現正播放,非媒體庫音樂貌似要重啟手機才可以看到效果,不知道是不是BUG。MediaHistory.Instance.NowPlaying = mediaHistoryItem;
3)從記錄和最新上市啟動時的播放處理
當使用者在音樂+視頻中心點擊對應項目時,則會自動啟動我們的應用,這個時候我們需要進行一些處理,來確定播放哪一個音樂。我們這裡的處理邏輯僅僅考慮媒體庫中存在的音樂。
[C#]
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { //從音樂視頻中心啟動時,播放相應項。 MediaLibrary library = new MediaLibrary(); Song _playingSong = null; if (NavigationContext.QueryString.ContainsKey("KeySring")) { String songToPlay = NavigationContext.QueryString["KeySring"]; foreach (Song song in library.Songs) { if (songToPlay == song.Name) { _playingSong = song; break; } } if (_playingSong != null) MediaPlayer.Play(_playingSong); } base.OnNavigatedTo(e); }
二、擴充照片中心
某些時候,使用者可能希望直接從照片中心啟動與照片處理相關的應用,或者在瀏覽照片時隨手美化渲染照片,或者共用上傳到網路、發送到其他應用,這個時候,我們就需要對照片中心進行擴充,擴充之後我們的應用就可以在這裡直接啟動。1)相關擴充點介紹
1.照片中心:擴充之後使用者可以直接在照片中心啟動您的應用。如:
2.擴充共用選取器:可以從“共用”連結啟動應用,並提供將使用者的照片分享到其他位置、網路,或者電子郵件。效果如:
3.擴充相片編輯選取器:可以從“編輯”連結啟動應用並允許使用者編輯他們的照片,如果沒有應用擴充此處,則開啟內建相片編輯,否則彈出選擇頁面。效果如:
4.擴充富媒體應用:可如果照片是用當前應用儲存或者修改後的,則照片會顯示特殊的開啟連結,富媒體並不是指對照片本身編輯,而是包含圖片文字說明等,以及用於網路互動等富編輯,比如微博應用。效果如:
5.擴充照片應用選取器:這個擴充僅僅在WP7中被支援,以後版本已經棄用。相當於WP8中的編輯以及富編輯。2)擴充照片中心
擴充照片中心需要編輯資訊清單檔,右鍵點擊WMAppManfiest.xml 檔案,選擇開啟檔案,在快顯視窗中選擇XML文字編輯器開啟。在 Tokens 元素之後,在 Extensions 元素內添加如下代碼:
[XML]
<Extensions> <!--擴充照片中心--> <Extension ExtensionName="Photos_Extra_Hub" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" TaskID="_default" /> </Extensions>
3)擴充相片檢視器
上面已經介紹過了圖片查看器的相關擴充點,下面我們通過代碼示範如何?這些擴充。首先,每個擴充點都需要資訊清單檔的支援,下面我們需要在同樣的位置添加 Extensions項。代碼如下:
[XML]
<Extensions> <!--擴充照片中心--> <Extension ExtensionName="Photos_Extra_Hub" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" TaskID="_default" /> <!--擴充共用選取器--> <Extension ExtensionName="Photos_Extra_Share" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" TaskID="_default" /> <!--擴充富媒體應用--> <Extension ExtensionName="Photos_Rich_Media_Edit" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" TaskID="_default" /> <!--擴充相片編輯選取器--> <Extension ExtensionName="Photos_Extra_Image_Editor" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5632}" TaskID="_default" /> </Extensions>
在資訊清單檔支援這些擴充之後,當使用者通過擴充啟動應用,照片中心預設啟動我們應用的MainPage.xaml,同時通過URI參數告訴我們是哪張圖片,該做什麼處理。下面我們通過在MainPage.xaml中解析URI參數來實現接受相關處理參數資訊。如果您的應用有專門的頁面處理,則需要實現URI映射,URI映射請看這裡。
[XAML]
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Image x:Name="image1" HorizontalAlignment="Left" Height="480" Margin="10,80,0,0" VerticalAlignment="Top" Width="436"/> <TextBlock HorizontalAlignment="Left" Margin="10,36,0,0" TextWrapping="Wrap" Text="圖片來源方式:" VerticalAlignment="Top"/> <Button Content="儲存" HorizontalAlignment="Left" Margin="315,609,0,0" VerticalAlignment="Top" Click="Button_Click_1"/> <TextBlock x:Name="textBlock1" Foreground="Yellow" HorizontalAlignment="Left" Margin="170,36,0,0" Grid.Row="1" TextWrapping="Wrap" Text="未知" VerticalAlignment="Top"/> </Grid>
[C#]
Picture selectedPicture; protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { IDictionary<string, string> queryStrings = this.NavigationContext.QueryString; if (!queryStrings.ContainsKey("Action")) { textBlock1.Text = "無來源"; } else { string action = queryStrings["Action"]; switch (action) { case "ShareContent": textBlock1.Text = "共用選取器"; break; case "RichMediaEdit": textBlock1.Text = "富媒體應用"; break; case "EditPhotoContent": textBlock1.Text = "相片編輯選取器"; break; } MediaLibrary library = new MediaLibrary(); if (queryStrings.ContainsKey("FileId")) selectedPicture = library.GetPictureFromToken(queryStrings["FileId"]); else if (queryStrings.ContainsKey("token")) selectedPicture = library.GetPictureFromToken(queryStrings["token"]); else return; BitmapImage bitmapFromPhoto = new BitmapImage(); bitmapFromPhoto.SetSource(selectedPicture.GetImage()); image1.Source = bitmapFromPhoto; } base.OnNavigatedTo(e); } //儲存圖片 private void Button_Click_1(object sender, RoutedEventArgs e) { MediaLibrary library = new MediaLibrary(); library.SavePicture(selectedPicture.Name, selectedPicture.GetImage()); }
4)擴充方式總結
上面我們發現通過相片檢視器啟動的URI中都有一個Action參數,還有一個參數要麼是FileId,要麼是token。下面列表歸納一下:
擴充點
資訊清單檔中的副檔名稱
URI啟動關聯地址
支援的平台
照片中心
Photos_Extra_Hub
WP7\WP8
共用選取器
Photos_Extra_Share
/MainPage.xaml?Action=ShareContent&FileId=[GUID]
WP7\WP8
富媒體應用
Photos_Rich_Media_Edit
/MainPage.xaml?Action=RichMediaEdit&token=[GUID]
WP8
相片編輯選取器
Photos_Extra_Image_Editor
/MainPage.xaml?Action=EditPhotoContent&FileId=[GUID]
WP8
照片應用選取器
Photos_Extra_Viewer
/MainPage.xaml?token=[GUID]
WP7三、檔案關聯以及SD卡訪問
檔案關聯,顧名思義,就類似於Windows系統中註冊預設的啟動程式一樣。我們也可以註冊我們的應用為某些尾碼名檔案的預設啟動程式。之前我們講過,一個應用可訪問的儲存位置只有安裝資料夾、本地檔案夾、媒體庫這三個位置,但是我們可以通過註冊檔案關聯的方式,只要是關聯的檔案,就算在其他位置我們也有可能訪問的到,這個檔案可能來自於SD卡,也可能來自於其他應用。1. 如何註冊檔案關聯
要處理特定的檔案類型,請在應用資訊清單檔中註冊檔案關聯。同樣我們還是需要右鍵開啟檔案,選擇Xml文字編輯器的方式開啟WMAppManifest.xml檔案。必須在Tokens節點後,添加 Extensions 節點,在Extensions中我們定義了關聯的檔案尾碼名,已經檔案的大中小型徽標。代碼如下:
[XML]
<Extensions> <FileTypeAssociation Name="檔案關聯描述資訊" TaskID="_default" NavUriFragment="fileToken=%s"> <Logos> <!--定義被關聯檔案類型顯示徽標,大中小三種--> <Logo Size="small" IsRelative="true">medium33x33.png</Logo> <Logo Size="medium" IsRelative="true">medium69x69.png</Logo> <Logo Size="large" IsRelative="true">large176x176.png</Logo> </Logos> <!--定義被關聯副檔名--> <SupportedFileTypes> <FileType ContentType="application/myfile1">.myfile3</FileType> <FileType ContentType="application/myfile2">.myfile2</FileType> </SupportedFileTypes> </FileTypeAssociation> </Extensions>
2. 偵聽檔案啟動
當使用者通過SD卡或者其他應用開啟您所關聯的檔案類型時,系統將啟動您的應用,並發送如下格式的URI:
/FileTypeAssociation?fileToken=[GUID]
但是我們發現這個URI並不能直接關聯到我們應用的某個頁面,所以現在我們需要定義一個URI映射來處理這個特殊的URL。把它轉換成標準URI來引導MainPage.xaml。註冊URI轉換:
首先,我們需要定義一個UriMapper,實現URI轉換的邏輯。建立類檔案AssociationUriMapper.cs,輸入代碼如下:
[C#]
public class AssociationUriMapper : UriMapperBase { public override Uri MapUri(Uri uri) { string tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString()); //驗證Uri,是否為檔案關聯引發 if (tempUri.StartsWith("/FileTypeAssociation?fileToken=")) { string fileToke = tempUri.Substring(31); //整理成規範URL,回傳到MainPage.xaml return new Uri("/MainPage.xaml?fileToke=" + fileToke, UriKind.Relative); } return uri; } }
然後,我們需要在App.cs的InitializePhoneApplication方法中註冊我們的URI轉換類。添加方式如:
下面,我們將要把偵聽到的檔案識別為文字檔,並顯示出來,代碼如下:
[C#]
protected async override void OnNavigatedTo(NavigationEventArgs e){ //擷取URI參數 IDictionary<string, string> queryStrings = NavigationContext.QueryString; if (queryStrings.ContainsKey("fileToke")) { var fileToke = queryStrings["fileToke"]; //擷取檔案名稱 var fileName = SharedStorageAccessManager.GetSharedFileName(fileToke); //本地檔案夾 var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder; //將檔案拷貝到本地檔案夾同名檔案中 var file = await SharedStorageAccessManager.CopySharedFileAsync(localFolder, fileName, NameCollisionOption.ReplaceExisting, fileToke); var stream = await file.OpenAsync(FileAccessMode.Read); StreamReader s = new StreamReader(stream.AsStream(), System.Text.Encoding.Unicode); var fileText = s.ReadToEnd(); MessageBox.Show("檔案名稱:" + fileName + "\n內容:" + fileText); } base.OnNavigatedTo(e);}
3. 啟動關聯檔案
當第三方應用想開啟關聯檔案時,自己本身並不想實現解析檔案的邏輯,則可以自動啟動我們的應用來開啟。
[C#]
//初始設定檔案列表private async void filesInit(){ //本地檔案夾 var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder; var files = await localFolder.GetFilesAsync(); listboxFiles.ItemsSource = files.Where(x => x.Name.EndsWith(".myfile1") || x.Name.EndsWith(".myfile2"));}//開啟選擇的檔案,跳轉到關聯檔案的應用private async void Button_Click_2(object sender, RoutedEventArgs e){ StorageFile file = listboxFiles.SelectedItem as StorageFile; if (file == null) return; //啟動指定檔案關聯的應用去開啟檔案 Windows.System.Launcher.LaunchFileAsync(file);}
通過圖示顯示啟動並執行效果:
4. 訪問SD卡
如果在SD卡中有我們關聯的檔案類型,我們同樣可以主動遍曆去訪問它。實現訪問SD卡並讀取檔案文本類容的代碼如下:
[XAML]
<!--ContentPanel - 在此處放置其他內容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox x:Name="listboxFiles" Margin="10,92,135,288"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name}"/> </DataTemplate> </ListBox.ItemTemplate> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property="Margin" Value="5"/> <Setter Property="Background" Value="Blue"/> </Style> </ListBox.ItemContainerStyle> </ListBox> <TextBlock Text="SD卡可讀檔案清單:" HorizontalAlignment="Left" Margin="10,53,0,0" TextWrapping="Wrap" VerticalAlignment="Top"> </TextBlock> <Button Content="開啟選擇" HorizontalAlignment="Left" Margin="315,465,0,0" VerticalAlignment="Top" Click="Button_Click_1"/> </Grid>
[C#]
protected override void OnNavigatedTo(NavigationEventArgs e) { filesInit(); base.OnNavigatedTo(e); } //初始設定檔案列表,只包含可識別檔案 private async void filesInit() { //擷取插入手機的SD卡集合,一般最多一張SD卡。 var externalStorageDevices = await ExternalStorage.GetExternalStorageDevicesAsync(); //擷取集合第一張SD卡 ExternalStorageDevice sdCard = externalStorageDevices.FirstOrDefault(); if (sdCard == null) { MessageBox.Show("並沒有發現SD卡,請檢查SD卡是否插好。"); return; } //擷取根目錄下全部檔案 var files = await sdCard.RootFolder.GetFilesAsync(); listboxFiles.ItemsSource = files.Where(x => x.Name.EndsWith(".myfile1") || x.Name.EndsWith(".myfile2")); } //開啟檔案清單選擇的檔案 private async void Button_Click_1(object sender, RoutedEventArgs e) { ExternalStorageFile file = listboxFiles.SelectedItem as ExternalStorageFile; if (file == null) return; //讀取檔案 var stream = await file.OpenForReadAsync(); StreamReader s = new StreamReader(stream, System.Text.Encoding.Unicode); var fileText = s.ReadToEnd(); MessageBox.Show("檔案名稱:" + file.Name + "\n內容:" + fileText); }
四、URI關聯
設想這樣的應用情境,我們在應用A中,想利用應用B的功能。我們自己不想實現同樣的功能是因為B已經做得相當成熟了,沒有必要重複實現。比如:我們單擊一個電話號碼,就想直接開啟撥號軟體開始撥打到電話;單擊一個電子郵件,直接開啟電子郵件的應用去編寫郵件,單擊一個視頻名,就可以開啟視頻播放器播放該視頻。這個時候,都需要利用URI關聯的功能。1. 註冊URI關聯
URI關聯的註冊同樣也需要編輯資訊清單檔,右鍵點擊WMAppManfiest.xml 檔案,選擇開啟檔案,在快顯視窗中選擇XML文字編輯器開啟。在 Tokens 元素之後,在 Extensions 元素內添加如下代碼:
[XML]
<Extensions> <!--註冊關聯URI,Name部分為您特定的URI首碼--> <Protocol Name="testuri" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" /> </Extensions>
註冊好後,第三方應用可以通過如下URI導航到我們的應用:
testuri:[參數部分]2. 偵聽URI
註冊好了URI關聯後,系統中其他應用所有首碼為testuri的URI請求都被我們的應用捕獲,我們還需要定義一個URI轉換來讓MainPage.xaml擷取。
[C#]
class AssociationUriMapper : UriMapperBase { private string tempUri; public override Uri MapUri(Uri uri) { tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString()); //驗證Uri,是否為登入的關聯 if (tempUri.StartsWith("/Protocol?encodedLaunchUri=testuri:")) { string uriMsg = tempUri.Substring(35); return new Uri("/MainPage.xaml?Msg=" + uriMsg, UriKind.Relative); } return uri; } }
我們還需要在InitializePhoneApplication 方法中註冊URI轉換
[C#]
/* 在App InitializePhoneApplication 方法中,我們需要註冊URI轉換 */ // 請勿向此方法中添加任何其他代碼 private void InitializePhoneApplication() { if (phoneApplicationInitialized) return; // 建立架構但先不將它設定為 RootVisual;這允許初始 // 螢幕保持活動狀態,直到準備呈現應用程式時。 RootFrame = new PhoneApplicationFrame(); RootFrame.Navigated += CompleteInitializePhoneApplication; //我們插入的代碼部分!!! //註冊我們的URI轉換 RootFrame.UriMapper = new AssociationUriMapper(); // 處理導航故障 RootFrame.NavigationFailed += RootFrame_NavigationFailed; // 在下一次導航中處理清除 BackStack 的重設請求, RootFrame.Navigated += CheckForResetNavigation; // 確保我們未再次初始化 phoneApplicationInitialized = true; }
在MainPage.xaml中處理URI關聯請求,代碼如下:
[C#]
protected override void OnNavigatedTo(NavigationEventArgs e) { IDictionary<string, string> queryStrings = NavigationContext.QueryString; if (queryStrings.ContainsKey("Msg")) MessageBox.Show("來自URI關聯調用方資訊:\n" + queryStrings["Msg"]); base.OnNavigatedTo(e); }
3. 啟動URI
調用方是如何啟動這個關聯URI呢?代碼如下:
[C#]
private async void Button_Click_1(object sender, RoutedEventArgs e) { var c = await Windows.System.Launcher.LaunchUriAsync(new System.Uri("testuri:"+textbox1.Text)); }
最後,我們看看示範效果:
五、啟動我的其他應用和啟動內建應用程式1. 啟動我的其他應用
我的應用程式是指發行者ID一樣的應用,我們可以在資訊清單檔裡面設定這個ID,下面的代碼展示了啟動我發布的應用列表中第二個應用。
[C#]
//啟動我發布的其他應用 private void Button_Click_1(object sender, RoutedEventArgs e) { //查詢本機其他與當前應用發行者ID相同的其他應用 IEnumerable<Package> apps = Windows.Phone.Management.Deployment.InstallationManager.FindPackagesForCurrentPublisher(); //啟動第二個應用 apps.Skip(1).First().Launch(string.Empty); }
2. 啟動內建應用程式
內建應用程式指WP8手機系統本身內建的應用,我們可以通過固定的方式啟動它們。下面代碼示範了如何使用。
[C#]
//啟動內建應用程式 private void Button_Click_2(object sender, RoutedEventArgs e) { //開啟IE訪問百度 //Windows.System.Launcher.LaunchUriAsync(new Uri("http://www.baidu.com")); //開啟內建郵箱發送郵件 //Windows.System.Launcher.LaunchUriAsync(new Uri("mailto:[email protected]")); //呼叫手機 //Windows.System.Launcher.LaunchUriAsync(new Uri("tel:13900000000")); //啟動Wi-Fi 設定 //Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings-wifi:")); //其他的 //ms-settings-accounts: 啟動帳戶設定應用。 //ms-settings-airplanemode: 啟動飛航模式設定應用。 //ms-settings-bluetooth: 啟動藍芽設定應用。 //ms-settings-cellular: 啟動行動電話通訊設定應用。 //ms-settings-emailandaccounts: 啟動電子郵件和帳戶設定應用。 //ms-settings-location: 啟動位置設定應用。 //ms-settings-lock: 啟動鎖屏設定應用。 //ms-settings-wifi: 啟動 Wi-Fi 設定應用。 //啟動 Windows Phone 商店 並顯示特定應用的詳細資料頁面。 //Windows.System.Launcher.LaunchUriAsync(new Uri("zune:navigate?appid=fdf05477-814e-41d4-86cd-25d5a50ab2d8")); //啟動 商店 並顯示調用應用的查看頁面。 //Windows.System.Launcher.LaunchUriAsync(new Uri("zune:reviewapp")); //啟動 商店 並顯示特定應用的查看頁面 //Windows.System.Launcher.LaunchUriAsync(new Uri("zune:reviewapp?appid=appfdf05477-814e-41d4-86cd-25d5a50ab2d8")); //啟動 商店 並搜尋 //Windows.System.Launcher.LaunchUriAsync(new Uri("zune:search?keyword=關鍵字&publisher=發行者名稱&contenttype=app")); }