Windows Store App 上架步驟 (及竅門分享)

Windows 8 App 是統一透過https://appdev.microsoft.com/StorePortals/ 網站作上傳,過程中基本上不會遇到什麼困難,因為步驟由上到下非常簡明易懂;若要知道各步驟的詳細說明,則可以見Windows 8 App 上傳步驟的分享。
image
以下則是列出一些請大家特別注易的眉角:
第一: 應用程式名稱
image
如您所見,應用程式名稱可以在 App 還沒開發完畢前就先行註冊! 而且可以保留一年;也就是說您心中若有理想的 App 名稱,是有可能被別人捷足先登喔! 另外,應用程式名稱取得好壞與否常常攸關被搜尋到的機會及下載量,這部份請務必作好選擇。
第二: 設定「試用版」(適用於付費軟體)
若您的 App 是要收費的話,在“銷售詳細資料”的步驟中,強烈建議您設定「免費試用期」;這樣您的App出現在 Windows Store 市集時,會多出一個「試用版」的選項讓使用者下載。
由Windows Phone marketplace 上的經驗,這麼作平均會提升70倍的下載量及10倍的總付費數目!
image
第三: 若您是遊戲類 App
而且有選擇在台灣市場上市的話,就要遵循台灣的分級法規上傳CSRR憑證檔案。詳細的作法請參考: 開發Windows 8 遊戲App? 教您如何符合台灣遊戲軟體分級規定
image
第四: 請填寫「測試人員注意事項」
如果要讓您的App能順利過關,強烈建議要填寫此項目,簡單告訴測試人員(用英文)如何操作您的App。
image
上傳完畢之後,你就可以隨時在「儀表版」(Dashboard )中查看 App 的審核進度,同時也會收到 Email 通知審核結果。
以我的例子而言,我於2012/9月就註冊 Windows Store 帳號,一直到2012年底都沒有完成信用卡身份驗證的部份,所以 App 上傳後就看到了以下的畫面,其中紅字的部份為: “在您驗證付款方式之前,我們無法在市集中列出您的應用程式。”
我完成證的方法請見信用卡驗證文章分享。
image
完成驗證之後,就靜待審核通知了!
附記:
(我這個小App是在2012/12/31晚上完成上傳,在2013/01/03就收到 Email 通知已通過審核了,但我的個人經驗不代表每個 App 的狀況喔!)
台北市公車動態 Windows Store App 下載 http://apps.microsoft.com/windows/zh-TW/app/6361e437-53ea-4dfe-9042-72f32ddd0643
image

從無到有- 程式碼小於 50 行的 Windows Store App 開發及上架之旅 (程式供下載)

本計畫是: 要趁著在 2012 年底時,撰寫一個程式碼小於50行的簡單小程式,並且將整個開發過程及上架流程作一個記錄讓大家參考:
首先我的 App 名稱為”台北市公車動態”,目標客戶是針對台北市的公車一族,讓他們能:
1. 隨時查詢想搭公車的預估到站時間。
2. 可以將常用公車加到「我的最愛」之中;同時希望讓使用者即便使用不同的裝置,也能看到一樣的「我的最愛」公車列表。
3. 實作「搜尋」合約,讓使用者可直接透過右側常用工具列 (Charms Bar) 來直接搜尋公車動態。
我首先簡單勾勒一下 App 的未來主畫面如下:
image
開始coding!
於 Visual Studio 2012 中開啟一個 C# 的空白 Windows 市集專案,打開 MainPage.xaml ,將以上的控制項由左側的「工具箱」中直接拉入設計畫面中,接下來在各控制項之中加入 x:Name 參數,以方便日後在程式碼中能直接操作這些控制項。 
image
接下來我需要台北市的公車列表清單,這資料可以在台北市公車動態資訊的公開網站 (http://pda.5284.com.tw/MQS/businfo1.jsp) 中找到,只要在此網站中按右鍵->檢視原始檔,就會看到一個 routeArray 變數中含有完整的公車列表:
image
直接拷貝這個 routeArray 清單,然後在 MainPage.xaml.cs 的 OnNavigatedTo() 方法中加到 comboBusLine 控制項中:
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        string[] routeArray = { "0南", "0東", "1", "108", "108區(二子坪)", "以下省略"};
        for(int i = 0; i < routeArray.Length; i++)
        {
            comboBusLines.Items.Add(routeArray[i]);
        }
        comboBusLines.SelectedIndex = 0;
    }
我們要到哪裡查詢公車即時動態呢? 我發現在 http://pda.5284.com.tw  的網站中,查詢公車動態頁面的Url只是加上”公車號”作為 query string:
image
所以我們可以實作「查詢」 Button 的方法如下:
    private void Button_Query_Click_1(object sender, RoutedEventArgs e)
    {
        string strSelectedBus = comboBusLines.SelectedValue.ToString();
        webviewQuery.Source = 
        new Uri(Uri.EscapeUriString("http://pda.5284.com.tw/MQS/businfo2.jsp?routeId=" 
        + strSelectedBus));
    }
其中使用了 EscapeUriString() 是要避免在 Uri string 之中出現中文亂碼。
按 F5 測試之後應該就能看到 WebView 控制項會顯示如下畫面:
image
之後,要開始實作「我的最愛」功能了。這部份同時要使用到 Windows 8 的資料漫遊 (Raoming) 機制,讓使用者若以同一個 Microsoft ID 登入不同的裝置,都能看到相同的「我的最愛」公車列表。
為達到此目標,首先在MainPage.xaml.cs class中宣告一個 Windows.Storage.ApplicationDataContainer 物件:
    public Windows.Storage.ApplicationDataContainer roamingSettings = 
Windows.Storage.ApplicationData.Current.RoamingSettings;
然後實作「加入我的最愛」 Button 的程式碼如下,記得在我的最愛及 roaming 物件中都要新增:
    private void addToFavorite_Click_1(object sender, RoutedEventArgs e)
    {
        string strBusToAdd = comboBusLines.SelectedItem.ToString();
        if (strBusToAdd.Length > 0 && !myFavorite.Items.Contains(strBusToAdd))
        {
            this.myFavorite.Items.Add(strBusToAdd);
            roamingSettings.Values["MyFavorites"] += strBusToAdd + ",";
        }
    }
同時,「刪除」Button的程式碼如下,記得要在我的最愛及 roaming 物件中皆要作刪除:
    private void delete_bus(object sender, RoutedEventArgs e)
    {
        if (myFavorite.SelectedItem != null)
        {
            string strTmp = roamingSettings.Values["MyFavorites"].ToString();
            roamingSettings.Values["MyFavorites"] =
                strTmp.Remove(strTmp.IndexOf(myFavorite.SelectedItem.ToString()), 
                myFavorite.SelectedItem.ToString().Length);
            myFavorite.Items.Remove(myFavorite.SelectedItem);
        }
    }
最後,記得要在程式一開始的時候,即 OnNavigatedTo() 的方法中,檢查是否存在既有的「我的最愛」清單並匯入:
    if (roamingSettings.Values["MyFavorites"] == null)
    {
        roamingSettings.Values["MyFavorites"] = "";
    }

    strFavorites = roamingSettings.Values["MyFavorites"].ToString().Split(',');
    for (int i = 0; i < strFavorites.Length-1; i++)
    {
        this.myFavorite.Items.Add(strFavorites[i]);
    }
至此,我們已經完成文章一開頭所要完成的第1、2項功能了!
接下來要實作第3項的「搜尋」功能,首先在專案中新增一個「搜尋合約」的新項目:
image
image
然後打開 SearchResultsPage1.xaml 後拉入一個 WebView 控制項。
之後在 SearchResultsPage1.xaml.cs 的 Filter_SelectionChanged() 方法中實作:
    void Filter_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        string[] routeArray = { "0南","0東","1","108","108區(二子坪)","以下省略"};

        if (routeArray.Contains(strQuery))
        {
            searchWebView.Source = 
            new Uri(Uri.EscapeUriString("http://pda.5284.com.tw/MQS/businfo2.jsp?routeId=" 
            + strQuery));
            VisualStateManager.GoToState(this, "ResultsFound", true);
        }
        else
        {
            VisualStateManager.GoToState(this, "NoResultsFound", true);
        }
    }
就簡單完成我們的第3項功能了! 最後為了讓畫面不致太單調,我加入一個台北的夜景作為背景:
首先將圖片檔直接拉到 Assets 的資料夾之中,就能在 Grid 中作好背景設定:
image
為了能讓此程式順利上架 Windows Store ,需要準備一些 logos ,如程式一開始的 Splash screen logo、出現在 Windows Store市集時的logo等,這部份我是用一個 Syncfusion 公司提供,目前免費的工具來製作http://www.syncfusion.com/downloads/metrostudio. 製作時記得在.appxmanifest之中查一下所需logos的大小喔!
image
同時,因為我的確使用了網際網路 (Internet) 的功能,所以必需宣告隱私權原則 (延伸閱讀:  最常見的退件原因- 隱私權聲明),我的作法如下:
第一步: 我在Windows Azure Web Site上直接建立了一個「網站」,並套用了WordPress Blog的範本。
第二步: 我草擬了一份簡單的隱私權聲明後,發佈在以上剛建立的Blog網站中 (http://mengtsai.azurewebsites.net/?p=51)。
第三步: 在App.xaml.cs中加入以下程式碼,讓使用者可以在Charms Bar的設定中找到「隱私權」的連結:
        private void OnCommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
        {
            UICommandInvokedHandler handler = 
                     new UICommandInvokedHandler(onSettingsCommand);

            SettingsCommand privacy1Command = 
                     new SettingsCommand("privacystatementPage", "隱私權原則", handler);

            args.Request.ApplicationCommands.Add(privacy1Command);
        }
        async void onSettingsCommand(IUICommand command)
        {
            SettingsCommand settingsCommand = (SettingsCommand)command;
            if (settingsCommand.Id.ToString().Equals("privacystatementPage"))
            {
                var success = 
                     await Windows.System.Launcher.LaunchUriAsync(
                             new Uri(@"http://mengtsai.azurewebsites.net/?p=51"));
            }
        }
並記得在同一檔案的 OnLanuched() 方法最後,加入以下這行,以登記 OnCommandsRequested() 這個 event:
   // Register handler for CommandsRequested events from the settings pane
   SettingsPane.GetForCurrentView().CommandsRequested 
                                   += OnCommandsRequested;
  
我親自撰寫的程式碼部份僅止於此,若不計開發工具自動產生的程式碼的話,是個總計不到50行statements的簡單App。這個第一版本的 App 跑起來的長相大致如下:
screenshot_01012013_204042
搜尋畫面的部份:
screenshot_01012013_204338
下一篇文章則會記錄上架的過程及需要注意的眉角!
程式碼下載 (Source code download)

隱私權聲明-最常見的退件原因

Windows 8上的Windows Store市集開張以來,目前為止最常看到App被退件的原因,大約就屬4.1.1這條認證需求了:
4.1.1 如果您的應用程式具備網路通訊功能,則必須包含隱私權聲明
如果您的應用程式具備可傳輸資料的技術能力,您就必須維持一份隱私權原則。您還必須在應用程式的「描述」頁面以及 Windows 設定快速鍵顯示的應用程式設定中,提供您的隱私權原則存取方法。
讓您的應用程式具備網路通訊功能的應用程式能力宣告包含:internetClient、internetClientServer 以及 privateNetworkClientServer。
您的隱私權原則必須告知使用者有關應用程式傳輸個人資訊以及使用、儲存、保護和揭露個人資訊的方式,並且說明使用者在使用和分享其資訊時可用的控制權以及存取資訊的方式,而且必須遵守適用的法律與規定。
簡單來說,只要您的App內有宣告使用網際網路(Internet)、網路攝影機 (WebCam)或個人文件庫(Documents Library),就必預提供隱私權聲明;而您若是以Visual Studio 2012的範本來開發的話,請注意使用網際網路的宣告預設是打開的喔!
image
而這也解釋了為何4.1.1這條會成為退件的首要原因了! 微笑
所以,基本上您有兩種選擇:
1、您的App完全不會使用到Internet,那請記得到.appxmanifest中取消勾選!
2、若您的App的確會使用網際網路(Internet)、網路攝影機 (WebCam)或個人文件庫(Documents Library),那就請準備隱私權聲明吧,您將有以下三件事要完成。
首先,您的隱私權聲明必需有一個公開網址(Public Url);比如您的公司網站、個人網站甚至一篇Blog的文章,都可以放置您的隱私權聲明(沒有個人網站? 可考慮Windows Azure Web Site)。而在您上架至Windows Store的步驟之中就會看到填入此公開網址的欄位:
Provide Privacy Policy During Submission
其次,隱私權聲明中到底要寫些什麼呢? 請參考”解決認證錯誤”之中的描述:
  • 告知使用者您應用程式所收集的個人資訊
  • 告知使用者該資訊的使用、儲存、保護及揭露方式
  • 說明使用者對於該資訊的使用及共用有何控制權
  • 說明使用者可以如何存取他們的資訊
  • 遵守適用的法令與規定
當然各位也可以參考同類型App的隱私權聲明,如台灣蘋果日報隱私權聲明
最後,就是要在App的Charms Bar”設定”(Settings)中,提供一個隱私權聲明的連結即可:

image

如果您不熟悉如何在Settings Charm中作設定,可參考以下文章的最後一段,提到我實作隱私權宣告的程式碼: http://blogs.msdn.com/b/mengtsai/archive/2013/01/02/50-windows-store-app.aspx
另外也可參考以下的正式範例:
App settings sample: 基本上演示如何使用ApplicationSettings API;有C#, VB.NET, JavaScript & C++的版本可供下載。
Windows Camp in a Box: 這個其實是微軟在全球作TTT(Train-The-Trainer)教育訓練時使用的教材,其中的Lab 6就是有關Settings charm方面的習作;有C#及JavaScript的版本可供下載。