This blog post is part of my Windows 8 metro-style application declarations series. Read more about declarations in the introductory post about application manifest.
User Tile Provider declaration allows you to register your application as a user tile provider. That means that user will be able to use your application to change her user tile.
One of many ways of changing the user tile can is by clicking your personal tile (avatar) on Windows 8 Start screen – four options are currently displayed, one of them is “Change user tile”:
Selecting the first option will take you to Control Panel’s Personalize page, set on User Tile:
2 options for changing the tile already available: the user can browse through her pictures and select the one that she likes or she can take a new one with the help of her web cam.
Your own application as a user tile provider
As with other declarations, you declare your application as a user tile provider in the application manifest. The easiest way to do that is through the manifest editor. You’ll see that when you add the User Tile Provider declaration to the Supported Declarations list, there are no declaration specific options to be set.
That’s good. After setting the declaration, run or just deploy your application and return to the Control Panel. You should now be looking at something like this:
Your application is now registered as the official user tile provider and by clicking on the application tile it will be launched.
And fail.
Of course, there is some wiring you have to do in your code to make this work properly.
Wiring the application logic
There isn’t a special kind of activation reserved for this type of activation, it’s activated through the special Protocol activation - I covered Protocol activation before – if you set up Protocol activation as described in that blog post, you can check for specific protocol in the OnProtocolActivated handler; you’ll see that Uri, passed in through provided arguments, looks something like UserTileProvider://, so you just have to check for a particular protocol to see how or why your application was invoked:
private void OnProtocolActivated(ProtocolActivatedEventArgs args) { if (args.Uri.Scheme == "usertileprovider") { PhotoView page = new PhotoView(); page.SetProfileImage(); Window.Current.Content = page; Window.Current.Activate(); return; } // ... other protocol handlers }
Here I’m bringing up a new PhotoView page (also discussed in my previous blog post) whenever my application is invoked for choosing a user tile.
Changing the user tile
OK, so application now responds to the user tile change call. But how do we actually change the tile? Well, there’s an API for that. You can get and set current user tile through asynchronous GetUserImageAsync() and SetUserImageAsync() methods of the UserInformation object.
In my demo application, I get the user tile from her profile, rotate it by 90° and display it to the user:
After user taps (selects) the image, she is first prompted for confirmation:
And if user confirms that (she can opt out by clicking somewhere outside of the dialog), the new image is set as her new user tile.
The code for dealing with images is a bit messy – I got it working but I suspect this will get easier as we progress towards the final runtime bits:
Read the user tile, rotate it by 90° and set as the Image source:
public async void SetProfileImage() { StorageFile file = UserInformation.GetUserImage(UserImageKind.LargeBitmap); BitmapDecoder decoder = await BitmapDecoder.CreateAsync(await file.OpenAsync(FileAccessMode.Read)); BitmapTransform transform = new BitmapTransform(); transform.Rotation = BitmapRotation.Clockwise90Degrees; PixelDataProvider pixelData = await decoder.GetPixelDataAsync(BitmapPixelFormat.Rgba8, decoder.BitmapAlphaMode, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.DoNotColorManage); WriteableBitmap bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight); pixelStream = bitmap.PixelBuffer.AsStream(); pixelStream.Seek(0, SeekOrigin.Begin); pixelBuffer = pixelData.DetachPixelData(); pixelStream.Write(pixelBuffer, 0, (int)pixelStream.Length); bitmap.Invalidate(); Viewer.Source = bitmap; }
Get the image from Image source, save it to a temporary file, set the user tile and delete the temporary file:
private async void SetUserTile() { WriteableBitmap bitmap = Viewer.Source as WriteableBitmap; StorageFile file = await Windows.Storage.ApplicationData.Current.TemporaryFolder.CreateFileAsync("temp"); BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, await file.OpenAsync(FileAccessMode.ReadWrite)); encoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 72.0, 72.0, pixelBuffer); await encoder.FlushAsync(); await Windows.System.UserProfile.UserInformation.SetUserImageAsync(file); await file.DeleteAsync(); }
Noticed a lot of asynchronous / await calls? Plenty of those in WinRT
There’s still many quirks and missing bits around the User Tile Provider declaration implementation, it’s obviously not complete yet. But the ability to provide users with your own application to change their user tiles just feels overwhelming. I bet we’ll get some pretty creative applications in this space when Windows 8 marketplace ships.