Mittwoch, 19. Dezember 2012

Windows Phone 8 Using SQLite

After using a flat file to persists my local data within my WorkTime app and sync them to SkyDrive I asked myself: Why not using a local database to store the data?

So what the database systems that will be supported by Windows Phone 8:

(1) With Windows Phone 7.5 (Mango) Microsoft has introduced an old technology with a new database access layer. SQL CE as database engine and LINQ to SQL to manipulate and define tables using classes.

(2) At the Build Microsoft introduces a new solution for Windows Phone 8: SQLite. That the right decision, because with SQLite you have the chance to share your local application data across several platforms Windows Phone 8, Windows 8, Android and iOS. Microsoft has worked with the SQLite team to provide an easy way to add SQLite to our Windows 8 and Windows Phone 8 projects. The result are two extensions in the  Visual Studio Gallery. One to support Windows 8 projects and an other one to use with Windows Phone 8.

Writing native code for Windows Phone 8?

But what his? These extensions are only the SQLite database engine and written in native code.To use them you have to write native code to interact with the SQLite database engine and perform operations with the database. So what to do: Searching a library which supports a wrapper that you can use C# to use the SQLite database engine.

Peter Torr – who introduces SQLite at the Build - actual posts about the current development process for such an wrapper from Microsoft: http://blogs.msdn.com/b/ptorr/archive/2012/11/27/update-on-sample-code.aspx – so we have to wait for the demoed solution from Microsoft.

So Microsoft gives us a new SQLite database engine but unfortunately no wrapper library to access this by C#.

What’s about csharp-sqlite?

csharp-sqlite is published on Google Code that allows to use the native SQLite engine directly in a C# application. I have worked with this library already on Windows Phone 7 and the library works fine with Windows Phone 8 and can be used as it is.

But if you want to use the same data access layer within Windows Phone 8 and Windows 8 (which should be the main goal for developing apps for these platforms)? The solution: Usage of a additional library sqlite-net which could be found and installed via Nuget:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="sqlite-net" version="1.0.5" targetFramework="wp80" />
</packages>

Sqlite-net works for my Windows 8 and my Windows Phone 8 test projects and capsulated the data access in a very nice way.

The data class:

public class Contact
    {
        [PrimaryKey]
        public string UnqiqueId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

The CRUD methods:

public async Task CreateContactAsync(Contact contact)
{
    var conn = GetConnection();
    await conn.InsertAsync(contact);
}
 
public async Task UpdateContactAsync(Contact contact)
{
    var conn = GetConnection();
    var existingContact = await conn.FindAsync<Contact>(c => c.UnqiqueId == contact.UnqiqueId);
    if (existingContact != null)
    {
        await conn.UpdateAsync(contact);
    }
}
 
public async Task DeleteContactAsync(Contact contact)
{
    var conn = GetConnection();
    await conn.DeleteAsync(contact);
}
 
private SQLiteAsyncConnection GetConnection()
{
    return new SQLiteAsyncConnection("contacts");
}

Some helper methods:

private async void CreateTableAsync<T>() where T : new()
{
    var conn = GetConnection();
    await conn.CreateTableAsync<T>();
}
 
private bool ExistsTable<T>()
{
    var connStr = new SQLiteConnectionString("contacts", false);
    using (var conn = new SQLiteConnection(connStr.DatabasePath))
    {
        var command = new SQLiteCommand(conn)
        {
            CommandText =
                "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='" +
                typeof(T).Name + "'"
        };
        return (command.ExecuteScalar<int>() > 0);
    }
}

 

So in case you are developing a Windows Phone application and you need to use a database, which are the possible solutions?

 

What database solutions for Windows Phone 8?

The first one I mentioned above: still keep using the old SQL CE which works just fine in Windows Phone 8. But then your database could not be used by other apps from different platforms.

A alternative approach is to use SQLIte and the csharp-sqlite library. Together with sqlite-net you can implement the same data access layer for Windows 8 and Windows Phone 8 by changing the underlying SQLite database engine for both platforms.

Sonntag, 16. Dezember 2012

Windows Phone 8–Speech Recognition problem Can’t access network

In my current Windows Phone 8 project WorkTime I used the very nice new feature of the Windows Phone 8 speech recognition Api. With Windows Phone 7 you have to handle with the Bing translation services, but now you have a capsulated API in the Windows.Phone.Speech.Recognition namespace. Here is a sample code which uses the default Dictation grammar for Recognition. It is also possible to define your own grammar (expected words) by code or using a SRGS grammar file.

W3C Standard definition: http://www.w3.org/TR/speech-grammar/

Microsoft MSDN documentation: http://msdn.microsoft.com/en-us/library/hh361633(v=office.14).aspx

SpeechRecognizerUI speechRecognizer;
 
public TimeSheetEntryPage()
{
    InitializeComponent();
 
    this.BindingValidationError += TimeSheetEntryPageBindingValidationError;
 
    this.speechRecognizer = new SpeechRecognizerUI();
 
}
 
void TimeSheetEntryPageBindingValidationError(object sender, ValidationErrorEventArgs e)
{
    this.HandleBindingValidationError(sender, e);
}
 
#region Events
 
private void PhoneApplicationPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
{
    var vm = DataContext as TimeSheetEntryDetailViewModel;
    if (vm != null)
    {
        vm.GoBackCommand.Execute(null);
    }
}    
 
#endregion
 
private async void Search_ActionIconTapped(object sender, EventArgs e)
{
    this.speechRecognizer.Recognizer.Grammars.Clear();
 
    // Use the short message dictation grammar with the speech recognizer.
    speechRecognizer.Recognizer.Grammars.AddGrammarFromPredefinedType("message", SpeechPredefinedGrammar.Dictation);
 
    await speechRecognizer.Recognizer.PreloadGrammarsAsync();
 
    var sr = new SpeechRecognizerUI();
    sr.Settings.ListenText = AppResources.VoiceListenTextDescription;
    sr.Settings.ReadoutEnabled = true;
    sr.Settings.ShowConfirmation = true;
 
    try
    {
        // Use the built-in UI to prompt the user and get the result.
        SpeechRecognitionUIResult recognitionResult = await sr.RecognizeWithUIAsync();
 
        if (recognitionResult.ResultStatus == SpeechRecognitionUIStatus.Succeeded)
        {
            // Output the speech recognition result.
            DescriptionTextBox.Text = recognitionResult.RecognitionResult.Text;
        }
    }
    catch (Exception ex)
    {
        //TODO change
        MessageBox.Show(ex.Message);
    }
}

But there is an issue with the Speech recognition API, if you localize the app title with a C++ resource-only DLL.

WindowsPhoneSpeechRecognition

If you use this way of localization for your app title you get an error message from the Speech Recognition API “We're sorry, but we can't access the network right now” ?!? (costs me several hours to find out this correlation)

But if you remove the reference to the AppResLib.dll it works properly.

Windows Phone 8: Voice command support

I really love it, if the implementation of rich user functions is easy – and the addition of voice command support for a Windows Phone 8 app is very easy.

With Windows Phone 8 you can add additional startup commands for your app which can be used to deep link in your app functions (see details here: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206959(v=vs.105).aspx)

In my WorkTime app I want to have a new voice command “WorkTime add entry”.

What are the necessary steps?

Adding a new Voice Command Definition file to the project. I used two CommandSets for each supported language.

<?xml version="1.0" encoding="utf-8"?>
 
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
  <CommandSet xml:lang="de">
    <CommandPrefix>WorkTime</CommandPrefix>
    <Example> neuer Eintrag </Example>
 
    <Command Name="NewEntry">
      <Example> neuer Eintrag </Example>
      <ListenFor> neu </ListenFor>
      <ListenFor> [ein] neuer Eintrag </ListenFor>
      <ListenFor> [und] [ein] neuer Eintrag </ListenFor>
      <Feedback> WorkTime erzeugt einen neuen Eintrag... </Feedback>
      <Navigate Target="/MainPage.xaml" />
    </Command>
 
  </CommandSet>
  <CommandSet xml:lang="en-US">
    <CommandPrefix>WorkTime</CommandPrefix>
    <Example> new entry </Example>
 
    <Command Name="NewEntry">
      <Example> new entry </Example>
      <ListenFor> new </ListenFor>
      <ListenFor> [a] new entry </ListenFor>
      <ListenFor> [and] [a] new entry </ListenFor>
      <Feedback> WorkTime creating a new entry... </Feedback>
      <Navigate Target="/MainPage.xaml" />
    </Command>
 
  </CommandSet>
</VoiceCommands>

After that you have to enable the following capabilities in the AppManifest.xml

<Capabilities>
     <Capability Name="ID_CAP_NETWORKING" />
     <Capability Name="ID_CAP_MICROPHONE" />
     <Capability Name="ID_CAP_SPEECH_RECOGNITION" />
   </Capabilities>

In the constructor of the App or your start page it is necessary to tell Windows Phone that your app supports new voice commands, which are defined in your added Voice Command Definition file (VoiceCommandDefinitionWorkTime.xml in my case)

public App()
   {
       // Global handler for uncaught exceptions.
       UnhandledException += Application_UnhandledException;
 
       // Standard XAML initialization
       InitializeComponent();
 
       // Phone-specific initialization
       InitializePhoneApplication();
 
       // Language display initialization
       InitializeLanguage();
 
       // Add voice command support
       InitalizeVoiceCommands();
 
       //Readies the DispatcherHelper for usage throughout application
       DispatcherHelper.Initialize();
private async Task InitalizeVoiceCommands()
{
    //VoiceCommandService.InstalledCommandSets.ContainsKey("en-US")
    await
        VoiceCommandService.InstallCommandSetsFromFileAsync(
            new Uri("ms-appx:///VoiceCommandDefinitionWorkTime.xml"));
}

The last step is to check on the start page or your target page (see Voice Command Definition file) if the user starts the app by this command. You can do this by overriding the OnNavigatedTo event:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
 
    if (e.NavigationMode == NavigationMode.New)
    {
        if (NavigationContext.QueryString.ContainsKey("voiceCommandName"))
        {
            var command = NavigationContext.QueryString["voiceCommandName"];
 
            if (command == "NewEntry")
            {
                var vm = this.DataContext as MainViewModel;
                if (vm != null)
                {
                    vm.AddCommand.Execute(null);
                }
            }
        }
    }
}

The result is that your app will now support a command “NewEntry” which will be executed if the user presses the Windows button for a few seconds and speaks:

“WorkTime add new entry” or “WorkTime new” or “WorkTime add a new entry”

wp_ss_20121216_0001

Windows Phone 8: Nuget Windows Phone Toolkit language issues

In my current project I want to support English (en-US (default)) and German (de) for all German speaking countries like Austria, Switzerland, Germany. Therefore my supported language setting in my project properties looks like this:

WindowsPhoneLanguages

If you install the Windows Phone Toolkit via Nuget (https://nuget.org/packages/WPtoolkit) there are two issues which you have to resolve.

First: Nuget does not install the language specific satellite assemblies

Second: The Windows Phone Toolkit does not support the basic culture “de”. Only the country specific “de-DE” culture.

To solve this issues, I have downloaded the Windows Phone Toolkit project from Codeplex (http://phone.codeplex.com/) and duplicated the resource file “de-DE” also as “de” in the Windows Phone Toolkit project. After a compilation of the project I copied the resource assemblies to my Nuget package folder:

WindowsPhoneToolkitLanguages

After this I will have the desired support from the Windows Phone Toolkit for the basic culture “de”.

Mittwoch, 5. Dezember 2012

Microsoft Roadshow–Windows 8 Professional

The Professional Touch” - Entwicklung moderner Line-Of-Business Apps!

„Touch-Bedienung, Mobilität, Ergonomie, Design und Produktivität – Nutzer und Kunden erwarten heute von modernen Business-Applikationen die gleichen Qualitäten, die bei Consumer-Anwendungen mittlerweile Standard sind. Darin liegt die Chance, mit modernen Business-Apps Kunden und Mitarbeiter zu begeistern – wenn es gelingt, die neuen Möglichkeiten zu nutzen und gleichzeitig die speziellen Anforderungen der Unternehmens-IT zu erfüllen. Zudem müssen sich Entwicklungsteams in Unternehmen neuen Herausforderungen stellen.

Mit der „SDX Privatbilanz“ bietet die SDX AG einen Showcase, der zeigt, wie die besonderen Merkmale von Windows 8-Apps für attraktive Enterprise Business-Apps genutzt werden können.
An einem Nachmittag geben wir einen kompakten Einstieg in die Thematik.
Informieren Sie sich über die wichtigsten Konzepte, Technologien und Tools und erfahren Sie, wie Sie und Ihr Team in die Entwicklung moderner Business-Apps einsteigen können.


Nur noch eine Plätze frei, also melden Sie sich jetzt an.

Zielgruppe:
Entwickler, technische Entscheider und Entwicklungsleiter

Kosten: €49, inklusive Kaffee und Abendessen

Dienstag, 4. Dezember 2012

Windows Phone 8–Parallel async access fixed

Yesterday I have changed my file IO operations from IsolatedStorage (Windows Phone 7) to Windows.Storage classes (WinRT API for Windows Phone 8). One problem with the asynchronous call is that there could now be parallel calls to the same resource (in this case a file). With async methods you cannot use the common lock mechanism :-(

But my colleague Matthias (@JauMatt) has already found in the web a very nice solution for that: http://qedcode.com/content/awaitable-critical-section

My new code which using the class AwaitableCriticalSection looks than like this and works properly for Windows Phone 8, too:

        public static async Task SaveList<T>(string folderName, string dataName, List<T> dataList) where T : class
        {
            StorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
 
            if (!await applicationFolder.FolderExistsAsync(folderName))
            {
                applicationFolder.CreateFolderAsync(dataName);
            }
 
            string fileStreamName = string.Format("{0}\\{1}.dat", folderName, dataName);
 
            using (var section = await CriticalSection.EnterAsync())
            {
 
                StorageFile file =
                    await
                    applicationFolder.CreateFileAsync(fileStreamName, CreationCollisionOption.ReplaceExisting);
                using (IRandomAccessStream randomAccessStream = await file.OpenAsync(FileAccessMode.ReadWrite))
                {
                    using (IOutputStream outStream = randomAccessStream.GetOutputStreamAt(0))
                    {
                        var serializer = new DataContractSerializer(typeof (List<T>));
                        serializer.WriteObject(outStream.AsStreamForWrite(), dataList);
                        await outStream.FlushAsync();
                    }
                }
            }
        }

Montag, 3. Dezember 2012

Windows Phone 8–Usage of Windows.Storage

If you want to implement a file access operation for Windows 8 you have the spoilt of choice: Old style with System.IO.IsolatedStorage or new style with the new WinRT API and classes in the Windows.Storage namespace. The first one will work for Windows Phone 7 and the second one only for Windows Phone 8 but also for a Windows 8 operating system and Metro styled apps.

I tried both solutions and here are the two code fragments which loading a file in a folder and deserialize them to a List of type <T>:

The solution using Isolated Storage:

        public static List<T> LoadList<T>(string folderName, string dataName) where T : class
        {
            var retval = new List<T>();
 
            if (!IsoStore.DirectoryExists(folderName))
            {
                IsoStore.CreateDirectory(folderName);
            }
 
            string fileStreamName = string.Format("{0}\\{1}.dat", folderName, dataName);
 
            using (var stream = new IsolatedStorageFileStream(fileStreamName, FileMode.OpenOrCreate, IsoStore))
            {
                if (stream.Length > 0)
                {
                    var dcs = new DataContractSerializer(typeof(List<T>));
                    retval = dcs.ReadObject(stream) as List<T>;
                }
            }
            return retval;
        }

And the same with using the new WinRT API and the classes in the Storage namespace:

        public static async Task<List<T>> LoadList<T>(string folderName, string dataName) where T : class
        {
            StorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
 
            if (!await applicationFolder.FolderExistsAsync(folderName))
            {
                applicationFolder.CreateFolderAsync(dataName);
            }
            var retval = new List<T>();
 
            string fileStreamName = string.Format("{0}\\{1}.dat", folderName, dataName);
 
            if (await applicationFolder.FileExistsAsync( fileStreamName))
            {
 
                IStorageFile storageFile = await applicationFolder.GetFileAsync(fileStreamName);
 
                using (var inStream = await storageFile.OpenSequentialReadAsync())
                {
                    var serializer = new DataContractSerializer(typeof(List<T>));
                    retval = (List<T>)serializer.ReadObject(inStream.AsStreamForRead());
                }
            }
            return retval;
        }