Universal App - 解決上傳 Dev Center 時,package version code 為日期問題
剛好最近在上架一個 universal app 至 dev center 上面,遇到了一個奇妙的問題:
〉要上架的版本號為:2.8.0.0,但利用 Visual Studio 建立好 package 之後上傳至 dev center 卻變成了:2015.0324.195.10?
這個問題困擾了我一陣子,後來剛好 Bill 叔 跟 Herman 有指導我怎麼處理這樣的問題。非常感謝他們。
詳細的處理方法可參考:<No build .appx now .appxboundle>的說明。
通常遇到上述的問題,一般來講會檢查 Project 裡的 Package.manifest 檢查是否有 bundle 後產生或修改了裡面的內容,
但是卻沒有發現。因此,要退一步往 Project 的 {WindowsPhone}.proj 檔案開始找方向。
以上便藉由<App packages and deployment (Windows Runtime apps)>該篇的說明,
針對 app packages 與 deployment 的重點部分加以說明:
〉app package:
指的是開發者將寫好的 app 經由 package 並上傳至 store,再由 store 下載安裝的那個 app 叫:app package。
app package 是一種 container,它是以 Open Packing Conventions (OPC) standard 所制定的標準所定義的一種結構化封裝
store data 與 resources 為 *.zip 的檔案。因此,開發人員可藉由 Visual studio 將 app 封裝出來,參考<Deploying Windows Runtime apps from Visual Studio>。
然而,在 Windows Runtime app 佈署時,藉由一個 Windows Runtime app model 的概念將這次 app package 要封裝的內容加以定義,
它屬於一種 state-drive process,所以每一個版本的 app package 均會有一份,讓系統在安裝或更新該 App 時才能明白那些內容要更新與移動。
在這個 model 裡描述的檔案也代表 app package 中會含有的檔案,它們是不可以被修改的,以增加安裝程式的可靠度。
詳細可參考<Deployment for Windows Runtime apps>。
〉Windows Runtime app package – .appx:
Windows Runtime app package 裡所定義需要的 components 均被儲存在 *.appx 當中。
本身是 ZIP-base container 內有 App 所用到的 payload files、resources…等,以協助安裝、驗證、佈署與更新。
藉由下表列出有那些項目:
名稱 | 說明 |
App payload | App code files and assets。 Payload files are the code files and assets that you author when you create your Windows Runtime app。 |
App manifest | App manifest file (Package.appxmanifest) The app manifest declares the identity of the app, the app's capabilities, and info for deploying and updating. For more info about the app manifest file, see App package manifest. |
App block map | App package’s block map file (AppxBlockMap.xml) The block map file lists all the app files contained in the package along with associated cryptographic hash values that the operating system uses to validate file integrity and to optimize an update for the app. For more info about the block map file, see App package block map. |
App signature | App package’s digital signature file (AppxSignature.p7x) The app package signature ensures that the package and contents haven't been modified after they were signed. If the signing certificate validates to a Trusted Root Certification Authorities Certificate, the signature also identifies who signed the package. The signer of the package is typically the publisher or author of the app. |
上述這些檔案是 Windows 8 與 Windows Phone 8.1 之後所開發的 App 均會產生的檔案。藉由 Visual Studio 在建立 app package 時會自動產生。
也可藉由手動的方式,可參考:<MakeAppx>與<SignTool>。
〉Package Identify:
開啟 Package.appmanifest 可以看到 <Package /> 標籤裡有定義一個 <Identify /> 的子元素,該份 Package.appmanifest 描述了 App 具有那些:
App 使用的或硬體特性(<Capabilities />)、App 進入點為何、使用那些額外的 Background Task 或是支持 Protocol、App tiles 的定義、支援畫面的方向,
更重要是 <Identify /> 定義了 App 的識別與 Bundle 的依據。主要幾個屬性如下:
屬性 | 說明 |
Name | A general name that is used for the app package. For example, "myCompany.mySuite.myApp". [注意] 這個 Name 跟 Tile 顯示的 Name 是不一樣的。 |
Publisher | The publisher refers to the publisher of the Windows Runtime app. In most cases, the publisher is the same as the account that was used to register for a developer account. |
Version | A four part version descriptor (major.minor.build.revision) that is used to service future releases of the app. For example, "1.0.0.0". [注意] 一定要符合 4 組的數字。 |
ProcesserArchitecture | The target architecture of the app package. This value can be "x86", "x64", "arm", or "neutral". In many cases, this field can be "neutral" to represent all architectures. |
ResoucesID | (Optional.) A publisher-specified string that specifies the resources of the app package. This part of the tuple is used primarily if the app package has assets that are specific to a region, such as, languages. [建議] 通常不會使用,如果你的 App 需要指定特定某種語系,這個要設定,但建議至少要英文,審核才易通過。 |
[注意]
a. App package 是 唯讀的。
雖然 *.appx 是依照 OPC 標準建立的 ZIP 結構檔案,但裡面因搭配 AppxBlockMap.xml,如果更動了 package 的內容或檔案,均需要重新建立
AppxBlockMap.xml。(通常藉由 Visual Studio Rebuild 專案來呼叫 MakeAppx pack command 或 IAppxPackageWriter APIs.)
b. App package payload files 的命名要符合 Uniform Resource Identifier (URI) 的定義。
如果 File paths 不符合 URI compliant,則需要先進行 percent-encoded,才會被儲存至 app package。等到安裝時才會被 decoded 至原本的位置。
例如:「 \my pictures\kids party[3].jpg 」會變成「/my%20pictures/kids%20party%5B3%5D.jpg」。
c. App package 的檔案限制:
最大內容可放檔案數: 100,000;整個 app package 最大的 size:100 GB。
d. App package reserved path and file names:
Reserved path and file names | Use |
/Package.appxmanifest | Reserved file name for the developer-authored app package manifest |
/AppxBlockMap.xml | Reserved file name for app package block map |
/AppxSignature.p7x | Reserved file name for app package Microsoft Authenticode digital signature |
/[Content_Types].xml | Reserved file name for content types metadata required by OPC for the app package |
/AppxMetadata/ | Reserved folder path for app package metadata files |
/Microsoft.System.Package.Metadata/ | Reserved folder path for Microsoft metadata files about deployed app packages |
e. App package digital signatures:
每一個 app package 都要加上 signature。在加入 signature 時需注意:
The subject name of the code signing certificate must match the Publisher attribute that is specified in theIdentity element of the AppxManifest.xml file in the app package. |
The hash algorithm that is used to sign the app package must match the hash algorithm that is used to generate the AppxBlockMap.xml file in the app package. This hash algorithm is specified in the HashMethod attribute of the BlockMap element. |
An app package can't be time stamped independently of signing. It must be time stamped during signing if time stamping is desired. |
App packages don't support multiple enveloped signatures. |
〉Declarative install:
上述介紹了 app package 的原理與封裝時要注意與產出的結果。接著往下說明,package.manifest 檔案裡也定義系統安裝該 App 時要處理的內容。
參考<App package manifest>的說明,可知道 Package.manifest 裡有一些標籤,例如:<Capabilities />、<Extensions />,這些均是用於告訴系統安裝
時該 App 需要向系統取得的資源或是註冊要處理的 Protocol(URI/File)。
重要的標籤如下:
標籤名稱 | 說明 |
<Prerequisites /> | To successfully deploy an app, the operating system must satisfy all of that app’s pre-requisites that are referenced in the app package manifest. (需注意如果 App 裡使用到的 APIs 是目前系統版本不支持的將會發生錯誤) 藉由二個重要的子標籤: <OSMinVersion />: Specifies the minimum version of the operating system and app model platform where this app is permitted to run. <OSMaxVersionTested />: Specifies the maximum version of the operating system where this app was tested by the developer and known to be in a working state. This pre-requisite field is used by the operating system to determine if there is any app compatibility issue that might arise during the app’s usage. |
<Capabilities /> | 宣告該 App 需要存取系統或設備的那些特性。詳細可參考<How to specify capabilities in a package manifest>或是<App capability declarations>。 |
〉App bundles:
開發 Windows 8.1 與 Windows Phone 8.1 會藉由 app bundle (or .appxbundle package) 來最佳化 packing 與 distribution 開發好的 App。
[注意] 藉由 Visual studio 會自動將 payload、resources、codes 分成不同的 packages,並產生對應的 block map 與加上需要的 signature 到 bundles 裡。
那麼加上 bundles 後會產生那些檔案呢?
檔案類型 | 說明 |
App packages (.appx) | The app bundle can contain more than one app package only if they each target a different specific architecture. For example, it can contain both an x86.appx and an amd64.appx package, but not two amd64.appx packages. |
Resource packages (.appx) | The app bundle contains resource packages (.appx files) for language, scale, and Microsoft DirectX feature level. Each app bundle can contain many different resource packages to support different device configurations. When directly referencing a resource package in your Windows Runtime app, we recommend that you make full use of the resource management system. Resource packages must never contain code. |
App bundle manifest (AppxBundleManifest.xml) | The app bundle manifest (.appxbundlemanifest file) contains all of the applicability info about the contained packages. For any particular package, it specifies the type of package ("Application" or "Resource") plus version and resource-targeting info. Specifically for app packages, the app bundle manifest includes info about the architecture. In general, the app bundle manifest allows the app model to understand the contents of the app bundle and determine at installation time which app package and resource packages to install on the user's device. <?xml version="1.0" encoding="UTF-8" standalone="no"?> <Bundle xmlns="http://schemas.microsoft.com/appx/2013/bundle" SchemaVersion="1.0"> <Identity Name="Example" Publisher="CN=ExamplePublisher" Version="2013.101.312.1053"/> <Packages> <Package Type="application" Version="1.0.0.5" Architecture="x86" FileName="AppPackage_X86.appx" Offset="49" Size="3207"> <Resources> <Resource Language="en-us"/> <Resource Scale="100" /> </Resources> </Package> <Package Type="application" Version="1.0.0.4" Architecture="x64" FileName="AppPackage_X64.appx" Offset="3329" Size="3204"> <Resources> <Resource Language="en-us"/> <Resource Scale="100" /> </Resources> </Package> <Package Type="resource" Version="1.0.0.0" ResourceId="French" FileName="ResourcePackage_French.appx" Offset="6606" Size="1423"> <Resources> <Resource Language="fr"/> <Resource Language="fr-fr"/> <Resource Language="fr-ca"/> </Resources> </Package> <Package Type="resource" Version="1.0.0.3" ResourceId="HiRes" FileName="ResourcePackage_HiRes.appx" Offset="8111" Size="1584"> <Resources> <Resource Scale="140"/> </Resources> </Package> </Packages> </Bundle> AppxBundleManifest.xml 定義了這個 *.appxbundle package 具有那些 *.appx,分別依照將屬於 Resources 支援的語系、畫面的大小比例與 App Packages 支援的平台加以分開描述。 其中 <Identify Version="2013.101.312.1053" /> 的 Version 最重要,這個也是該篇說明為何上傳至 DevCenter 後版本號不是按照自己需求的主要原因。 |
App block map (AppxBlockMap.xml) | The block map file lists all the files contained in the bundle (except app and resource packages), along with associated cryptographic hash values that the operating system uses to validate file integrity and to optimize an update for the app. For more info about the block map file, see App package block map. |
App signature (AppxSignature.p7x) | The app bundle signature ensures that the package and contents haven't been modified since they were signed. If the signing certificate validates to a Trusted Root Certification Authorities Certificate, the signature also identifies who signed the package. The signer of the package is typically the publisher or author of the app. |
提供讓 App 在開發時更容易支持 extras 的資源,例如:語系、不同 size 的螢幕大小…等,讓封裝 App 時可以分開這些內容,
依照用戶所需要的項目進行下載與安裝才不會造成空間的浪費。詳細可參考<App packages and deployment (Windows Runtime apps)>。
上述介紹了 app package 與建立 app bundles 的原理與關聯,接下來要說明怎麼解決上傳至 DevCenter 版本不一致的問題。
根據<建立應用程式套件>中提到「決定是否要產生應用程式套件組合」的說明:
a. 建立套件組合,減少使用者下載應用程式的大小。
b. 您的應用程式在使用者裝置上佔用的空間就比較少,而且他們因為只下載必要資產,下載所需時間也更少。
c. 如果不產生應用程式套件組合,則雖然應用程式也能正常運作,但使用者就必須下載較大的應用程式。
上述的好處主要是由於選擇了 bundle 之後會產生 AppxBundleManifest.xml 檔案,它裡面說明了什麼設備資源、系統版本、平台類型該下載什麼
App packages 與 Resources packages,所以才能達到。
回到在建立應用程式套件時,設定的畫面如下:
如果依照上述說明,我應該在 Generate app bundle 時選擇:If needed 或 Always 來達到上述說的好處。
但是如果你選擇了,那就會遇到在 AppxBundleManifest.xml 中定義的 Version 為依照日期建立的代碼,但這不是我們想遇到的。
所以建議選擇「never」雖然會需要讓用戶安裝或下載比較大的資源,但這樣的處理方向確實能解決我們的問題。
那這三個值的定義分別為什麼:
Use this option | To |
If Needed | Generate an app bundle only if you've defined language-specific assets, a variety of image-scale assets, or resources that apply to specific versions of DirectX.
這個選項是預設值,只要 App 裡有定義了多語系資源檔、支援不同 Scale 的 Image 該項目就會產生。 產生之後用戶在下載 App 時即會依照 AppxBundleManifest.xml 定義找到屬於該設備的 *.appx 下載與安裝。 |
Always | Generate an app bundle. |
Never | Don’t generate an app bundle.
You might choose this option if you plan to individually service each architecture that your app supports. 選擇該項目,則代表建立的 *.appx 會依賴設定的多個 platform 來產生。而每一份裡均會有必要的 Resources package. |
官方文件寫到:
「If you create an app bundle, you can submit your app to the Store more easily because, no matter how many architectures your app supports,
you must upload only one .appxupload file. If you don't create an app bundle, you must upload an .appxupload file for each supported architecture.」
關於這個項目,如果您開發的是 App 沒有特定需要依賴著 platform 來支持,我會建議你選擇「If Needed」;如果您開發的是需要依賴 platform,
例如:像是 Windows Phone App 因為用了 SQLite 所以只能支持 ARM 的設備,那就建議您直接選擇「Never」,因為您只需要支持一個 platform。
這樣的選擇對於專案中的 Package.manifest 有什麼影響嗎?其實不會。
因為 Package.manifest 只是定義了 App bundle 需要的描述,至於要不要依照這個 bundle 來建立 app package 的定義則是在 {Project Name}.proj。
解開一個 *.proj 來看:
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"
Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">arm</Platform>
<ProjectGuid>{710FA524-8630-4BEB-8400-1DD6D6600AF5}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MYAPP</RootNamespace>
<AssemblyName>MYAPP.WindowsPhone</AssemblyName>
<DefaultLanguage>en</DefaultLanguage>
<TargetPlatformVersion>8.1</TargetPlatformVersion>
<MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{13F1466A-886D-4E39-A767-685A16062A39};{FAE04E30-301F-1103-BF4B-00C02179EFBC}</ProjectTypeGuids>
<SynthesizeLinkMetadata>true</SynthesizeLinkMetadata>
<NuGetPackageImportStamp>278369e3</NuGetPackageImportStamp>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
<AppxBundlePlatforms>arm</AppxBundlePlatforms>
<AppxBundle>Never</AppxBundle>
</PropertyGroup>
....
</Project>
要注意的有三個標籤:<AppxAutoIncrementPackageRevision />、<AppxBundlePlatforms />、<AppxBundle />,分別其對應於上圖的設定值。
說明如下:
a. <AppxAutoIncrementPackageRevision />:設定是否在建立 package 時需要自動加一個版本號。(建議由手動來設定版本)
b. <AppxBundlePlatforms />:設定建立 package 時要支持的 platforms,例如:x64、x86、ARM、Any CPU、neutral。
c. <AppxBundle />:設定建立 package 時是否要按照 package.manifest 所定義的 bundle 描述來分別建立對應的 packages。
另外,針對封裝後的檔案至安裝到設備上時經過的檢查與流程,可詳細閱讀<應用程式封裝>的內容。
======
以上是介紹一下在建立 App packages 時需要注意與遇到問題的描述。
其實這個部分通常很容易被忽略,所以特別撰寫一下文件來記錄並分享給大家。
希望對大家有所幫助,謝謝。
References:
〉App packages and deployment (Windows Runtime apps) (重要)
〉No build .appx now .appxboundle
〉File access and permissions (Windows Runtime apps)
〉Guidance on using the App Specific Hardware ID (ASHWID) to implement per-device app logic
〉Accessing app data with the Windows Runtime (Windows Runtime apps)
〉App data (Windows Runtime apps)
〉Deployment for Windows Runtime apps.
相關於 app package 的建立可參考:
How to create an app package signing certificate
How to sign an app package using SignTool
How to troubleshoot app package signature errors
How to programmatically sign an app package
How to develop an OEM app that uses a custom file