Windows Phone 7 - 動態轉換初始的Default Page
開發Windows Phone 7的App也好,iPhone或Android的程式也好,它們都有一份用於描述App基本設定或參數的文件,
以WP7為例:「WMAppManifest.xml」。這一份檔案是每個WP7 Project自動產生,如下描述內容:
1: <?xml version="1.0" encoding="utf-8"?>
2:
3: <Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.0">
4: <App xmlns="" ProductID="{8158919a-d617-424c-af45-b20370f3ea5f}" Title="AdvTest" RuntimeType="Silverlight"
5: Version="1.0.0.0" Genre="apps.normal" Author="AdvTest author"
6: Description="Sample description" Publisher="AdvTest">
7: <IconPath IsRelative="true" IsResource="false">ApplicationIcon.png</IconPath>
8: <Capabilities>
9: <Capability Name="ID_CAP_GAMERSERVICES"/>
10: <Capability Name="ID_CAP_IDENTITY_DEVICE"/>
11: <Capability Name="ID_CAP_IDENTITY_USER"/>
12: <Capability Name="ID_CAP_LOCATION"/>
13: <Capability Name="ID_CAP_MEDIALIB"/>
14: <Capability Name="ID_CAP_MICROPHONE"/>
15: <Capability Name="ID_CAP_NETWORKING"/>
16: <Capability Name="ID_CAP_PHONEDIALER"/>
17: <Capability Name="ID_CAP_PUSH_NOTIFICATION"/>
18: <Capability Name="ID_CAP_SENSORS"/>
19: <Capability Name="ID_CAP_WEBBROWSERCOMPONENT"/>
20: </Capabilities>
21: <Tasks>
22: <DefaultTask Name ="_default" NavigationPage="MainPage.xaml"/>
23: </Tasks>
24: <Tokens>
25: <PrimaryToken TokenID="AdvTestToken" TaskName="_default">
26: <TemplateType5>
27: <BackgroundImageURI IsRelative="true" IsResource="false">Background.png</BackgroundImageURI>
28: <Count>0</Count>
29: <Title>AdvTest</Title>
30: </TemplateType5>
31: </PrimaryToken>
32: </Tokens>
33: </App>
34: </Deployment>
該文件代表整個Silverlight或XNA的WP7 App的主要描述檔,其內容包括:Product IDs、版本資訊、執行環境、資源檔位置等,
並且這份文件會隨著每次建置專案時,更新其中的內容。然而,這份文件的主要目的在於:
(1) 當作App上傳至Marketplace的使用資訊(類似:App的身份證):用於識別該App支援的硬體、環境與資源;
(2) Marketplace根據此文件將上傳的App歸納至對應的Application database之中;
以下詳細說明每段MetaData的定義:
(1) Deployment: < Deployment ></ Deployment >
此範例主要定義XML的Namespace與AppPlatformVersion的資訊。
此標籤中的屬性是真正描述該App的重要資訊,包括:App ID、Title、Runtime Type等;詳細的內容,可以參考上述的連結;
但在Application標籤中,有幾個要特別注意的,以下我將列舉出來:
a. Capabilities: <Capabilities></Capabilities>
此標籤的定義在描述App支援的主要標籤,它與Application標籤中屬性描述的部分比較不相同,它強調在於使用WP7本身於硬
體資訊的取得,因此,通常除非開發的App有特別需要調整針對硬體資訊取得之外,Capabilities裡的內容,比較不會去動到它,
以下簡介從MSDN擷取出來的內容:
Capability ID/Name (Type: String) |
Description |
ID_CAP_NETWORKING | 描述該App會使用到網路連線的能力,如果App需用到網路即一定要加上,用於向使用者宣告此App將會需要網路連線可能會需要用戶付擔漫遊與網路費用。 |
ID_CAP_IDENTITY_DEVICE | 描述該App使用特定的設備訊息,例如:device ID、製造商名稱…等。 |
ID_CAP_IDENTITY_USER | 描述App使用anonymous LiveID (匿名LiveID)識別用戶。這個通常不太會去在意,因為除非你的App需要結合Live ID這個可能會影響,例如:登入MSN、打卡等。 |
ID_CAP_LOCATION | 描述App可與Location Service結合。 |
ID_CAP_SENSORS | 描述App可使用Windows Phone sensors。 |
ID_CAP_MICROPHONE | 描述App可使用麥克風。加了這個標籤,代表App可以在沒有視覺畫面呈現下,使用麥克風來記錄所述說的內容。 |
ID_CAP_MEDIALIB | 描述App可以連結Media Library。 |
ID_CAP_GAMERSERVICES | 描述App將與XBOX Live APIs進行連結。這需要被宣告出來,因為代表App將會與XBOX共享資料內容。 |
ID_CAP_PHONEDIALER | 描述App可與電話功能結合,也支援在沒有視覺畫面呈現下繼續使用。 |
ID_CAP_PUSH_NOTIFICATION | 描述App可以支援Push Notification Service的使用,這需要被宣告出來,讓用戶知道該App可能會造成他們需要付擔網路費用。 |
ID_CAP_WEBBROWSERCOMPONENT | 描述App可以使用Web Browser元件,也代表Web Browser使用時需要注意有安全性影響的Script。 |
b. Tasks標籤
該標籤定義了每一個App啟動時,預設第一個啟動的Page,不過這只支援於Silverlight App,XNA的App除外,主要二個屬性:
Attribute | Description |
Name | Type: String. The default name is “_default.” |
NavigationPage | Type: String. This is the navigation page that a task will navigate to in the application when it starts. |
c. Tokens標籤
該標籤主要是針對標示在Start Page中的Tile的呈現,比較接近Push Notification Service比較會使用到。例如:
Count、Title與BackgroundImageURI這些都是定義Tile呈現需要的東西。
了解了WMAppMainfest.xml之後,接下來是本篇的重點,「如何動態調整App的初始頁面?」
這個問題不知道大家沒有跟我一樣遇到過,舉個例子來說:「像公車動態查詢提供用戶可以先設定當用的縣市,這樣就不需每次登入
都先從第一頁開始選要去的縣市再來選公車。」理解了這個情境之後,接下來提供程式與圖示來加以說明:
〉實作流程架構:
當App啟動時主要載入第一個要啟動的畫面流程,如上圖所示,其中有一個關鍵的事件:「RootFrame.Navigate(“/MainPage.xaml”)」。
如果熟悉整個WP7 App在Page運作的原理<Windows Phone 7 – Navigation Framework原理概論>,應該很清楚知道,一個App只有一個Frame,
從App.xaml.cs裡進去,就可以找到它PhoneApplicationFrame,那就是RootFrame了。RootFrame管理整個App中所有Page運作的方式,
因此,如果要達到動態修改預設載入的第一個Page,那勢必要對RootFrame下手了。
〉範例程式:
(1) 先為RootFrame增加一個Navigating的事件處理,為了是擷取每一次RootFrame進行Page導航時的事件補捉;
1: //在App.xaml.cs中的建構子,為RootFrame增加Navigating的事件處理;
2: public App()
3: {
4: ....
5: // Standard Silverlight initialization
6: InitializeComponent();
7:
8: // Phone-specific initialization
9: InitializePhoneApplication();
10:
11: //增加RootFrame針對Navigating的事件處理;
12: RootFrame.Navigating += new NavigatingCancelEventHandler(RootFrame_Navigating);
13: }
(2) 針對RootFrame_Navigating提供事件處理的邏輯內容;
1: void RootFrame_Navigating(object sender, NavigatingCancelEventArgs e)
2: {
3: //識別目前RootFrame要前往的頁面是否為MainPage.xaml
4: if (e.Uri.ToString().Contains("/MainPage.xaml") != true)
5: {
6: //不是,讓RootFrame繼續完成自己的任務
7: return;
8: }
9: //是,代表要轉換RootFrame指定的頁面到我們要的頁面
10: //先取消原本RootFrame要導航的動作
11: e.Cancel = true;
12: //再透過Delegate移動要去的指定頁面
13: RootFrame.Dispatcher.BeginInvoke(delegate
14: {
15: RootFrame.Navigate(new Uri("/Second.xaml", UriKind.Relative));
16: });
17: }
如上的程式碼,就可以讓App啟動時,自動轉到別的頁面去,而不是預設到MainPage.xaml。
‧重點元素說明
〉NavigatingCancelEventHandler & NavigatingCancelEventArgs:
針對Navigating事件的處理方法,提供可以取消事件的功能,透過這個方法,即可以在RootFrame進行Navigating時,
識別要導航的對象,加以進行轉向與取消原有要移動的事件。由於它是一個委派的方法,因此,當要從此事件通知
RootFrame進行新的導航時,需要再透過Dispatcher.BeInvoke來進行畫面的切換。
〉UriMapper
另外,也可以透過UriMapper類別來達到相同的處理結果。以後擷錄<Redirecting an initial navigation>的程式碼:
1: void SetupUriMapper()
2: {
3: // Get the UriMapper from the app.xaml resources, and assign it to the root frame
4: UriMapper mapper = Resources["mapper"] as UriMapper;
5: RootFrame.UriMapper = mapper;
6:
7: // Our dummy check -- does the current time have an odd or even number of seconds?
8: DateTime time = DateTime.Now;
9: int seconds = time.Second;
10: bool isOdd = (seconds % 2) == 1;
11:
12: // Update the mapper as appropriate
13: if (isOdd)
14: mapper.UriMappings[0].MappedUri = new Uri("/odd.xaml?method=UriMapper&time=" + time.ToLongTimeString(), UriKind.Relative);
15: else
16: mapper.UriMappings[0].MappedUri = new Uri("/even.xaml?method=UriMapper&time=" + time.ToLongTimeString(), UriKind.Relative);
17: }
UriMapper是透過事先定義好於資源檔(Resources)中的Key/Value值,來進行轉換。
透過UriMapper可以把每一個Uri之間轉換的集合或規則,先定義完成,再藉由Uri的指定來要求RootFrame進行畫面的移動。
====
以上是我針對這次NavigateService類別操作時,遇到一個很好玩的情境,把它整理清楚以理解可以實作的範圍。
References:
‧Redirecting an initial navigation (必讀)
‧How to: Use the Capability Detection Tool for Windows Phone
‧NavigatingCancelEventHandler 委派
‧Types of Push Notifications for Windows Phone
‧System.Windows.Navigation 命名空間