-
Windows Phone and SQL Lite: what’s the current situation?
The last week I spoke at a Italian conference in Microsoft Italy called Windows Phone Developer Day about sharing code between Windows Phone and Windows 8. One of the topics was data access and how to share code to interact with a database between Windows Phone and Windows 8.
People was a bit confused and I got many questions because I told them that SQL Lite is supported by Windows Phone 8 but can’t be used at the moment. What does it mean?
Let’s make a step back: Windows Phone 7.5 has introduced support to relational databases thanks to SQL CE (as database engine) and LINQ to SQL (as manipulation library, to interact with the database using objects and classes instead of making queries). In Windows Phone 8 Microsoft has decided to go another way, in order to use a solution easier to port to Windows 8 and to other platforms: SQL Lite. In fact, this technology is cross platform and it’s available for Android, iOS, web application, client applications and much more. Probably you’ll have to rewrite the data access layer (due to the differences between technologies and languages), but you’ll be able to reuse the database.
Microsoft has worked with the team to provide an easy way to add SQL Lite to your Windows 8 and Windows Phone 8 project: the result is that, in the Visual Studio Gallery, you’ll find two extensions (one per platform) that can be used to add the SQL Lite engine to your project. The engine is written in native code: this means that you’ll need native code to interact with it and perform operations with the database.
And here comes the confusion I talked about in the beginning of the post: this extension allows you just to add the SQL Lite engine to your application, but doesn’t include a library to work with it using a high level language like C# or VB.NET. The problem is that, for the moment, this library doesn’t exist for Windows Phone 8: the result is that, even if you can add it, you don’t have a way to perform operations with a SQL Lite database, unless you write by yourself a wrapper to the native libraries.
Microsoft is committed into delivering a library as soon as possible, but at the moment we don’t have a release date yet.
On Windows 8 the situation is a bit different, because such libraries already exist: one of the most popular is sqlite-net, on which I talked about in a previous post. Unlucky, this library doesn’t work on Windows Phone 8, because it uses some features of the Windows Runtime that aren’t available in the Windows Phone subset.
In case you’re developing a Windows Phone application and you need to use a database, which are the possible solutions?
The first one is to keep using SQL CE, that works just fine in Windows Phone 8: it’s a very good solution in case you don’t need to port your application to Windows 8 or to another platform.
The second one is to use csharp-sqlite, that is a library published on Google Code that allows to use the SQL Lite engine in a C# application. The library is supported by Windows Phone 8, so you can use it to reuse your SQL Lite database in a Windows Phone application. The downside? The C# library is based on code that is part of the .NET framework and that is not available in the Windows Runtime. This means that you’ll be able to reuse the database, but not the data access layer of your application.
And the third solution? Simply just wait that a native library for Windows Phone 8 will be available
in
-
How to deal with WebView and overlaying elements in Windows 8
The WebView control is very useful to display HTML pages and elements into a Windows Store application. For example, I use in my blog’s application to display the content of a post, formatted to be easily read on a tablet using the Instapaper engine.
If you have played a bit with the WebView control you would have find that it has a particular behavior: no matter how many XAML controls you are going to place over the WebView, they will always be displayed below the view. This is not a bug, but a specific security feature: since in the past developers were able to do dirty tricks by simply placing an hidden web view and by executing dangerous Javascript code in the back, Microsoft has chosen not to allow this anymore. No matter how many efforts you’ll spend trying to find a workaround, you won’t be able to place a WebView below another control (neither fully or partial).
During the development of my blog’s application this security feature caused me some troubles: in the latest version I’ve developed I’ve added support both for Italian and English. The application automatically sets the correct language according to the language of the operating system, but the user is able to change it from the Settings panel. For this reason I’ve added an item in the Settings panel called Language: when the user taps on it, a flyout panel with two radio buttons is displayed.
The problem is that, if the user tries to change the language while he’s reading a post, the flyout goes behind the WebView and he’s not able to fully see it. You can see what I’m talking about in the image below:
How to fix it? Since, as I’ve already said, there’s absolutely no way to change the overlay of the WebView control, the only available workaround is to hide the WebView until the user has done interacting with the controls and the elements that are placed over it.
In my case, I needed to hide the WebView every time the Settings panel was displayed and to show it back as soon as the Settings panel was closed. Since there’s no way, within a Windows Store apps, to know when the charm bar is activated, we have to find another approach: by managing the page’s focus.
The page exposes two events, LostFocus and GotFocus: the first one is invoked when the current page lost its focus (because, for example, the user is interacting with the settings flyout), the second one instead when the focus is reassigned to the app.
You can subscribe to these two events in the XAML and, more precisely, in the page’s declaration, like in the following example:
<common:LayoutAwarePage x:Name="pageRoot" x:Class="qmatteoq.com.Views.DetailPage" LostFocus="pageRoot_LostFocus" GotFocus="pageRoot_GotFocus">
Once you’ve done it, you can mange these events in the code behind. In my case I simply change the WebView’s control (which, in my app, is called PostDetail) visibility according to the focus:
private void pageRoot_LostFocus(object sender, RoutedEventArgs e) { PostDetail.Visibility = Visibility.Collapsed; } private void pageRoot_GotFocus(object sender, RoutedEventArgs e) { PostDetail.Visibility = Visibility.Visible; }
And here is the final result: when the settings panel is opened the WebView is hided. Plus, I’ve added a message to notify the user that the post is just hidden and that will reappear when the settings panel will be closed.
in
-
A lap around Windows Phone 8 SDK: file association – Part 2
In the previous post we started to take a deep look to one of the most interesting new features in Windows Phone 8: file association. The example we’re using in this tutorial is made by two applications: in the last post we’ve created the “launcher” app, that generates a text file and tries to open it. In this post, instead, we’re going to create the “reader” app, that will receive the file from the launcher app and will open and display it.
The “reader” app: how to register for a file extensions
Let’s start to create the reader application: create a new Windows Phone 8 project (you can just use the basic Windows Phone App template) and let’s edit the manifest file. Unlucky, as I’ve already mentioned in the post I wrote with a summary of all the new Windows Phone 8 features, the new visual editor is not perfect and it doesn’t support all the scenarios: to register the file extensions we’ll need to manually edit the file, so you have to right click on the WMAppManifest.xml file into the Properties folder and choose View code.
File and protocol associations are registered in the Extensions section: in case it’s missing, you have to manually add it below the Tokens section. Here is how we register the .log extension:
<FileTypeAssociation Name="LogFile" TaskID="_default" NavUriFragment="fileToken=%s"> <SupportedFileTypes> <FileType ContentType="text/plain">.log</FileType> </SupportedFileTypes> </FileTypeAssociation>
Every file type association is identified by a FileTypeAssociation node, with a unique Name property. The attributes TaskID and NavUriFragment defines how the file is passed: these two values are fixed and can’t be changed, they should always be exactly like you see in the code example.
Inside this node you can specify the file types you’re going to support, by adding a FileType node with the correct content type and extension. You have also the option to include a logo that identifies the custom file type, that is displayed by the operating system when needed (for example, near the file name of an attachment inside the Mail application). In this case, you have to create three different images (with size 33×33, 69×69 and 176×176), add them to your project and include them in the FileTypeAssociation definition, like in the following example:
<FileTypeAssociation Name="LogFile" TaskID="_default" NavUriFragment="fileToken=%s"> <Logos> <Logo Size="Small">log-33x33.png</Logo> <Logo Size="Medium">log-69x69.png</Logo> <Logo Size="Large">log-176x176.png</Logo> </Logos> <SupportedFileTypes> <FileType ContentType="text/plain">.log</FileType> </SupportedFileTypes> </FileTypeAssociation>
Once you’ve registered your application it’s time to write some code. There are two steps here: to define a UriMapper and to create a page that will handle the received file.
The UriMapper
Before talking about the UriMapper, it’s better to explain how the OS handles file association. When an application is launched as a consequence of a file request (in our example, another application is trying to open a .log file), it’s opened using a special Uri that has the following structure:
/FileTypeAssociation?fileToken=89819279-4fe0-4531-9f57-d633f0949a19
After the fixed keyword FileTypeAssociation there’s a unique parameter called fileToken, which is a GUID that identifies the file. As we’ll see later, Windows Phone 8 exposes an API to get the file using this token.
Now that you have understood how file association works under the hood, it should be easy to understand what is the UriMapper class: basically, it’s a central class that gets called when the application is started and it’s able to check if the app was called using a special Uri so that it can redirect the user to a specific page of the application.
In our case, we’re going to check if the app was opened since another application has requested to open a log file: if the answer is yes, we’re going to redirect the user to a specific detail page, where the log will be displayed. Here is the code:
public class UriMapper : UriMapperBase { private string tempUri; public override Uri MapUri(Uri uri) { tempUri = uri.ToString(); // File association launch if (tempUri.Contains("/FileTypeAssociation")) { // Get the file ID (after "fileToken="). int fileIDIndex = tempUri.IndexOf("fileToken=") + 10; string fileID = tempUri.Substring(fileIDIndex); // Get the file name. string incomingFileName = SharedStorageAccessManager.GetSharedFileName(fileID); // Get the file extension. int extensionIndex = incomingFileName.LastIndexOf('.') + 1; string incomingFileType = incomingFileName.Substring(extensionIndex).ToLower(); // Map the .log files to the appropriate pages. switch (incomingFileType) { case "log": return new Uri("/LogDetail.xaml?fileToken=" + fileID, UriKind.Relative); default: return new Uri("/MainPage.xaml", UriKind.Relative); } } // Otherwise perform normal launch. return uri; } }
First you have to create a new class in your project, that should inherit from the UriMapperBase class. This way you’ll have to implement the MapUri method, that is called when the application is initialized and that carries, as a parameter, the Url.
If the Url contains the FileTypeAssociation string the app is opened after that another application has requested to open a file: in this case we get the token of the file by simply playing with string properties (since FileTypeAssociation and fileToken are always fixed). After that, let’s welcome the SharedStoreAccessManager, which is the class that is able to handle operations with files that are opened this way: for this scenario we’ll use just the GetSharedFileName method that, passing the token, returns the name of the file as it was defined by the original application.
Using the name, and using some other strings voodoo magic, we finally get the information we need: the extension of the file. This way we’re able to identify the file type and we’re able to redirect the user to the page that is able to process that kind of file. In our example we manage just the .log extension, so the switch statement contains just two entries: the log extension and the default, which is a redirect to the MainPage of the application.
In case we receive a log file, we redirect the user to a specific page called LogDetail.xaml and we attach the token to the Uri: as we’ll see in a few moments, the token will be needed to get the real file.
The last thing we have to do is to tell the application that we have a UriMapper, that should be parsed every time a navigation is issued: to do this we have to go in the App.xaml.cs and, in the InitializePhoneApplication() method, right after the RootFrame has been initialized, set the UriMapper property to the class we have created, like in the following example:
private void InitializePhoneApplication() { if (phoneApplicationInitialized) return; // Create the frame but don't set it as RootVisual yet; this allows the splash // screen to remain active until the application is ready to render. RootFrame = new PhoneApplicationFrame(); RootFrame.Navigated += CompleteInitializePhoneApplication; RootFrame.UriMapper = new Helpers.UriMapper(); // Handle navigation failures RootFrame.NavigationFailed += RootFrame_NavigationFailed; // Handle reset requests for clearing the backstack RootFrame.Navigated += CheckForResetNavigation; // Ensure we don't initialize again phoneApplicationInitialized = true; }
Let’s get this file!
Now it’s time to create the LogDetail.xaml page, that we’re going to use to display the content of the file. Add a new empty Windows Phone page to the application and give it the name LogDetail.xaml: in the code behind we’re going to manage the OnNavigatedTo event, that is invoked when the user navigates towards this page.
In this event we’re going to get the file token and use it to get the real file that has been “sent” by the other application. Here is the code:
protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); if (NavigationContext.QueryString.ContainsKey("fileToken")) { await SharedStorageAccessManager.CopySharedFileAsync(ApplicationData.Current.LocalFolder, "rss.log", NameCollisionOption.ReplaceExisting, NavigationContext.QueryString["fileToken"]); } }
The mechanism should be familiar if you’re a Windows Phone developer, since it’s similar to the one adopted by the OS for other scenarios (like navigation from a secondary tile): if the NavigationContext contains a query string parameter which name is fileToken we’re going to use again the SharedStorageAccessManager class and, this time, specifically the CopySharedFileAsync.
This method simply translates the token into a real file and copies it into the local storage of the current application. The requested parameter are:
- The folder in the storage where to save the file, identified by a StorageFolder object. In the example we simply pass the LocalFolderobject: this way the file is copied into the root of the storage.
- The name of the file to save.
- What to do in case the file already exists (in the example, we overwrite it).
- The file token (that we retrieve from the query string parameter)
Once we have the file in our storage, we can simply do whatever we want. For example, we can read it as a string and display it in a TextBlock using the following ReadFromFile extension method:
public static class FileExtensions { public static async Task<string> ReadFromFile(string fileName,StorageFolder folder = null) { folder = folder ?? ApplicationData.Current.LocalFolder; var file = await folder.GetFileAsync(fileName); using (var fs = await file.OpenAsync(FileAccessMode.Read)) { using (var inStream = fs.GetInputStreamAt(0)) { using (var reader = new DataReader(inStream)) { await reader.LoadAsync((uint)fs.Size); string data = reader.ReadString((uint)fs.Size); reader.DetachStream(); return data; } } } } }
Now, thanks to this extension method, in the OnNavigatedTo event of the LogDetail page we can do something like this:
protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); if (NavigationContext.QueryString.ContainsKey("fileToken")) { SharedStorageAccessManager.CopySharedFileAsync(ApplicationData.Current.LocalFolder, "rss.log", NameCollisionOption.ReplaceExisting, NavigationContext.QueryString["fileToken"]); string content = await FileExtensions.ReadFromFile("rss.log"); log.Text = content; } }
It’s debugging time!
Debugging this scenario is very easy: just deploy both applications in the emulator or in the device (by right clicking on the two projects and choosing Deploy from the menu). Then execute the launcher app we’ve developed in the previous post, create the log file and then launch it using the Open file button. If you did everything correctly, you’ll see the reader application open up directly in the LogDetail, with the content of the RSS that has been downloaded by the launcher app.
How cool is that?
You can download a sample project from here.
in
subscribe via RSS