Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

How to create a Company Hub app for Windows Phone

From Wiki
Jump to: navigation, search

This article explains how to develop a Company Hub for Windows Phone. It does not cover MDM (Mobile Devices Management) systems like Intune.

See Also
SignpostIcon XAML 40.png
WP Metro Icon WP8.png
SignpostIcon Code 52.png
Article Metadata
Code ExampleTested with
SDK: Windows Phone 8.0 SDK
Devices(s): Nokia Lumia 920
Compatibility
Platform(s):
Windows Phone 8
Platform Security
Signing Required: Symantec Certificate
Article
Created: GuruuMeditation (06 Oct 2013)
Last edited: BuildNokia (12 Jun 2014)

Contents

Introduction

Windows Phone 8 (and later) allows companies to publish and distribute apps directly to their employees and other users, bypassing the Windows Phone store. Users discover and install company-specific apps though an app referred to as a "Company Hub".

Companies can use the default Windows Phone 8 Company Portal App or create their own. Companies that create their own hubs typically provide a fully branded app, with company-relevant features and experiences, including company news, notifications and alerts.

Note.pngNote: Companies that manage their phones using Mobile Devices Management (MDM) systems like Windows Intune or System Center 2012 Configuration Manager will use the default Windows Phone 8 Company Portal App as a Company Hub. This article covers only company-created apps.

This article explains all the steps needed to create a company app and company apps, from registering as a company all the way through to sending the company certificate and company app through to users. It includes a code example (sources given at the end) which provides a simple company hub with a 2-tab panorama. One tab shows installed apps which can be launched with a single tap. The other tab lists available company apps which you can install with a single tap.

Company Hub code example

Create a "company" developer account

When you create your developer account, register as a company rather than as an individual. Once the company verification is done, you'll get a Symantec ID:

Company developer account with Symantec ID

Get a Symantec Certificate

Once you have your Symantec ID, you have to buy a $299/year certificate at this link: https://products.websecurity.symantec.com/orders/enrollment/microsoftCert.do

Develop company hub

The company hub should minimally have a company app discovery page where you can see which company apps are available to download, and a page where you can launch the already installed apps. Usually a hub will also have other company specific information - e.g. a company news or user company profile page.

Tip.pngTip: A company hub is just like an other Windows Phone application - you can make it do anything you want.

Microsoft makes available 5 methods specially for company hubs:


Get list of installed and available apps

First we define a PackageInfo class to store all needed information about the available apps (ID, name, description, URL, icon,…). It has some ViewModel-like properties to keep the design simple:

    [Serializable]
[DataContract]
public class PackageInfo
{
[DataMember]
public Guid ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public string Thumbnail { get; set; }
[DataMember]
public string XAPPath { get; set; }
[DataMember]
public object Icon { get; set; }
// To simplify the app, let's make this class a kind of VM with those properties :
[DataMember]
public bool Downloading { get; set; }
[DataMember]
public uint Progress { get; set; }
[DataMember]
public string ProgressString { get; set; }
[DataMember]
public object Package { get; set; }
}

The code snippet below shows how the already-installed app list is obtained. First get the list of installed apps using the FindPackagessForCurrentPublisher method. For each app installed, we get the thumbnail (icon) and copy it locally, and create a PackageInfo with all the information needed and add it to a list. Lastly, ass the company hub itself will be present, we remove it from the list

 // Clear the ObservableCollections
InstalledPackages.Clear();
AvailablePackages.Clear();[/br]
// Get all packages from web service
var allpackages = await GetPackageListAsync();
// get all package installed with same PublisherID as the Company hub
var installed = InstallationManager.FindPackagesForCurrentPublisher().ToList();
// Company Hub ProductID. Use to remove it from the installed list we just got
var hubid = "{27ed8894-9f3b-4bef-89c6-75e25bb6520a}";
 
foreach (var app in installed.Where(d => !d.Id.ProductId.Equals(hubid,StringComparison.OrdinalIgnoreCase)))
{
// get thumbnail token, and copy the file in local folder
var thumbtoken = app.GetThumbnailToken();
var name = SharedStorageAccessManager.GetSharedFileName(thumbtoken);
 
await SharedStorageAccessManager.CopySharedFileAsync(ApplicationData.Current.LocalFolder
, name,NameCollisionOption.ReplaceExisting, thumbtoken);
var file = await ApplicationData.Current.LocalFolder.GetFileAsync(name);
 
var stream = await file.OpenStreamForReadAsync();
 
var bitmap = new BitmapImage();
bitmap.SetSource(stream);
// create a package info and add it to the collection
var packageinfo = new PackageInfo { ID = new Guid(app.Id.ProductId),
Name = app.Id.Name, Icon = bitmap, Package = app };
 
InstalledPackages.Add(packageinfo);
}

We get the available app list from a web service. For each available package we first check if it is already installed by comparing product IDs. If it is not present on the device then it is added to the list of available apps that are not installed yet (AvailablePackages):

foreach (var package in allpackages)
{
// if available package is already installed, do nothing
if (installed.Any(d => d.Id.ProductId.Equals(string.Format("{{{0}}}", package.ID.ToString()),
StringComparison.OrdinalIgnoreCase)))
continue;
// otherwise add it the the vailable collection
AvailablePackages.Add(package);
}

Display the lists

The lists are displayed in a simple LongListSelector. When you tap on an item, the app is downloaded or installed (depending on the list).

This is what my available package list look like in XAML:

 <phone:LongListSelector Margin="0,-38,-22,2"
ItemsSource="{Binding AvailablePackages}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Grid Margin="0,-6,0,12"
d:DataContext="{d:DesignInstance entrepriseService:PackageInfo}"
toolkit:TiltEffect.IsTiltEnabled="True"
Tap="Package_OnTap">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="{Binding Thumbnail}"
Width="80"
Height="80"
Grid.RowSpan="2"
Margin="10"
VerticalAlignment="Top" />
<TextBlock Text="{Binding Name}"
Grid.Column="1"
TextWrapping="Wrap"
Style="{StaticResource PhoneTextExtraLargeStyle}"
FontSize="{StaticResource PhoneFontSizeExtraLarge}" />
<TextBlock Grid.Row="1"
Grid.Column="1"
Text="{Binding Description}"
Visibility="{Binding Downloading,Converter={StaticResource BoolToInvertedVisibilityConverter}}"
Foreground="DarkGray"
TextWrapping="Wrap"
Margin="15,0,0,0" />
<StackPanel Orientation="Vertical"
Grid.Column="1"
Grid.Row="1"
x:Name="IntallStackPanel">
<ProgressBar IsIndeterminate="False"
x:Name="IntallProgressBar"
Value="{Binding Progress}"
Visibility="{Binding Downloading,Converter={StaticResource BoolToVisibilityConverter}}" />
<TextBlock Text="{Binding ProgressString}" />
</StackPanel>
</Grid>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

How to install a selected package

This is the code-behind to install a selected package:

        // Install app
private void Package_OnTap(object sender, GestureEventArgs e)
{
// Get package info
var package = (sender as Grid).DataContext as PackageInfo;
 
try
{
package.Downloading = true;
// install app package
var result = InstallationManager.AddPackageAsync(package.Name, new Uri(package.XAPPath, UriKind.Absolute));
 
result.Progress += (info, progressInfo) => Dispatcher.BeginInvoke(() =>
{
package.Progress = progressInfo;
package.ProgressString = string.Format("Installing ({0}%)...", progressInfo);
});
 
result.Completed = (info, status) => Dispatcher.BeginInvoke(async () =>
{
MessageBox.Show(info.ErrorCode == null
? string.Format("{0} installed", package.Name)
: string.Format("Error installing : {0}", info.ErrorCode.Message));
package.Downloading = false;
await LoadingPackagesListAsync();
});
 
}
catch (Exception exception)
{
Console.WriteLine(exception);
}
 
}

Use InstallationManager.AddPackageAsync to add the package. It returns a IAsyncOperationWithProgress<PackageInstallResult, UInt32>, so you can follow the progress thanks to the Progress event. Use the Completed delegate to warn user it is installed or if there was an error.

Note.pngNote: The Progress event will be called 4 times only. At 5% (Phone asking confirmation from the user), 10% (User accepted), 55% (Download done) and 100% (Installation done)

Warning.pngWarning: There is something subtle with Completed: it is a delegate, not an event ! Use = and not +=. If you have weird exception on that line, this is probably the cause.

How to launch installed app

To launch an app is straightforward:

// Lauch app
private void LaunchApp_OnTap(object sender, GestureEventArgs e)
{
var packageInfo = (sender as Grid).DataContext as PackageInfo;
 
var package = packageInfo.Package as Package;
 
package.Launch("");
}

How to develop "company apps"

Company apps are the same as any other apps - special in no other way than that they are "company relevant". Therefore there is nothing special to say about creating company apps.

Sign hub and apps

Before you deploy everything, you need to sign the app.

To do so, you have to install the certificate you got from Symantec and export it as PFX (example here : http://msdn.microsoft.com/en-us/library/gg432987.aspx). Then you can generate the AET (Application Enrollment Token) that you will have to send to the users. They have to install it on their phone in order to use your apps. There is an AET generator with the Phone SDK. To launch :

%ProgramFiles(x86)%\Microsoft SDKs\Windows Phone\v8.0\Tools\AETGenerator\AETGenerator.exe PFXFile Password

It will generate 3 files. It is the AET.aetx that you send to users. The AET.aet is for MDM systems. The other is raw AET in XML. More info here : http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj735576(v=vs.105).aspx)

Now to sign your apps, there are several ways as explained here: http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn168929(v=vs.105).aspx

The easiest is to use the BuildMDILXap.ps1 that is in the %ProgramFiles(x86)%\Microsoft SDKs\Windows Phone\v8.0\Tools\MDILXAPCompile as it does all the steps for you.

I added it in post build that way :

CompanyHub2.jpg

Here is it, for one of the example company app:

del "$(TargetDir)\AriesApp_new.xap"
powershell.exe -ExecutionPolicy ByPass -File "%ProgramFiles(x86)%\Microsoft SDKs\Windows Phone\v8.0\Tools\
MDILXAPCompile\BuildMDILXap.ps1" -xapfilename "$(TargetDir)\AriesApp.xap"
–pfxfilename "$(SolutionDir)\Keys\mycert.pfx" -password mypassword
copy /y "$(TargetDir)\AriesApp_new.xap" "$(SolutionDir)\WcfService1\XAP\AriesApp.xap"

I delete the older version of the signed xap, I execute the script (my keys are stored in a Keys directory) and finally I copy the xap on my service website, where it can be downloaded by the users.

Tip.pngTip: Don’t forget to set your publisher ID in the manifest of the apps. The publisher ID can be generated that way : take your Symantec ID (Example : 541255) . Convert it to hex (0x84247) and create a GUID out of it : 00084247-0000-0000-000000000000)

Create app discovery service

It is not necessarily a service. It can be XML file, etc…

I made a very simple one, it just read, deserialize an XML file and send it :

 public class EntrepriseService : IEntrepriseService
{
public List<PackageInfo> GetEntreprisePackages()
{
// just read the XML file, deserialize it and then send
var appPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
 
PackageInfo[] packages;
 
using (var sr = new StreamReader(appPath + "/Packages.xml"))
{
var dcs = new XmlSerializer(typeof(PackageInfo[]), new[] { typeof(PackageInfo) });
packages = dcs.Deserialize(sr.BaseStream) as PackageInfo[];
}
 
return packages.ToList();
}
}

The XML is like this :

<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfPackageInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PackageInfo>
<ID>{16823216-c5b1-4613-a50c-9fb9bbddc571}</ID>
<Name>Aries</Name>
<Description>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In aliquam convallis elit, ac aliquam neque vulputate eget. Sed consequat non nibh quis pharetra. </Description>
<Thumbnail>http://192.168.0.110:19475/Thumb/Astro-Aries.png</Thumbnail>
<XAPPath>http://192.168.0.110:19475/XAP/AriesApp.XAP</XAPPath>
</PackageInfo>
<PackageInfo>
<ID>{52957e14-91ef-485d-9fb4-e69086facb6e}</ID>
<Name>Taurus</Name>
<Description>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In aliquam convallis elit, ac aliquam neque vulputate eget. Sed consequat non nibh quis pharetra. </Description>
<Thumbnail>http://192.168.0.110:19475/Thumb/Astro-Taurus.png</Thumbnail>
<XAPPath>http://192.168.0.110:19475/XAP/TaurusApp.XAP</XAPPath>
</PackageInfo>
</ArrayOfPackageInfo>

Send the certificate and the company app to users

Send the keys and the app to the user by email. Or have them download it from a website. Anyway, do it securely.

To install the AET, just double click on it.

Downloads

The source for the code example is available here: File:MyCompanyHub.zip

The app appears as below:

HubExample.png


(Original article and a French translation can be found here : http://www.guruumeditation.net/developing-a-company-hub-for-windows-phone-8)

This page was last modified on 12 June 2014, at 23:20.
473 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×