Sunday, November 9, 2014

WP App part 3 - "the Manual Automatic" - Use images / Taking photo's and storing them in the DataModel

Goal:
Create the functionality to use images from the phone / take image with my phone for my Windows Phone App 'The Manual Automatic" 



Check the first setup in part 1:
http://sometimesiliketopretend.blogspot.com/2014/09/windows-phone-app-part-1-manual.html

Check the setup of the DataModel in part 2:
http://sometimesiliketopretend.blogspot.com/2014/09/wp-app-part-2-manual-automatic-setting.html



Part 3 - Use images / Taking photo's and storing them in the DataModel

An important part of my App are the images / photo's of the manuals you can add to the title and description. They contain the part of the manual you need. So I need the use to be able to take a picture of choose a file from his phone.



Step 1 - Enabling camera functionality

First we need to enable access to the Camera and the Storage card. This is done in the Package.appxmanifest.




Step 2 - Using the FilePicker

In order to Pick a file from the phone or snap a picture, I use the FilePicker finctionality of the phone. This is standard phone behaviour and would be nice to use. 

I searched for an example of this and found a series of jumpstart lessons.

Jumpstart series - Building Apps for Windows Phone 8.1:
http://channel9.msdn.com/Series/Building-Apps-for-Windows-Phone-8-1

I watched lesson 17 - Camera, Media and Audio in Windows Phone 8.1: http://channel9.msdn.com/Series/Building-Apps-for-Windows-Phone-8-1/17

I use the code form the first demo from the jumpstart lesson.

I also need the Reference WriteableBitmapEx.WinRT because when I added some of the code from the lesson I ecountered this error when building:


'Windows.UI.Xaml.Media.Imaging.WriteableBitmap' does not contain a definition for 'FromStream' and no extension method 'FromStream' accepting a first argument of type 'Windows.UI.Xaml.Media.Imaging.WriteableBitmap' could be found (are you missing a using directive or an assembly reference?)

I right click on the References, and choose "Manage NuGet Packages"



I search for 'writable' and install the pakage




Then when buildign I ran into this Build error:

The type or namespace name 'FileOpenPickerContinuationEventArgs' could not be found (are you missing a using directive or an assembly reference?)

After searching on MSDN I found out it is in the 'Windows.ApplicationModel.Activation' namespace. check http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.applicationmodel.activation.fileopenpickercontinuationeventargs.aspx

But that is already added to my using list. 

My using list of the App.xaml.cs:




So I did some digging on the internet and stumbled upon this post:
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/dn614994.aspx

Seems like since I used a Blank Template and that's why I am missing some basic functions...

Quote from the msdn site:
To call a FileOpenPicker and continue your app
  1. Include the SuspensionManager helper class in your project. This class simplifies lifecycle management for your app. To get the SuspensionManager helper class, create a new Windows Phone app that uses a project template other than the Blank App template. The SuspensionManager.cs file is in the Common folder of the project.
  1. Include a helper class like the custom ContinuationManager helper class in your project. This class includes interfaces and methods that make it easier to continue your app. To get the code for the ContinuationManager helper class, download the File picker sample, or see How to continue your Windows Phone app after calling an AndContinue method.

So I open a Hub App Template and check whats inside the Common folder.



I copied the Common folder of the Hubapp template to the Shared namespace of my own app in Visual Studio.



I renamed the namespace (just type a new name and choose the option to rename the namespace that becomes available:



Then I opened the File picker example folder to copy the ContinuationManager.cs



After adding the code I still get the Build error:

The type or namespace name 'FileOpenPickerContinuationEventArgs' could not be found (are you missing a using directive or an assembly reference?)

Aaarrgggg. 

So back to google...
After searching and trying different things I see that some code can but put specifically in for Windows Phone. You just have to put it between these tags: 

#if WINDOWS_PHONE_APP

#endif


When I put the code with the FileOpenPickerContinueEventsArgs between these statements it compiles!

Like so in the App.xaml.cs:

#if WINDOWS_PHONE_APP
        
        // Entry point for new WP 8.1 Contract-based activation like FileOpenPicker
        protected override void OnActivated(IActivatedEventArgs args)
        {
            var fopArgs = args as FileOpenPickerContinuationEventArgs;
            if (fopArgs != null)
            {
                // Pass the picked files to the subscribed event handlers
                // In a real world app you could also use a Messenger, Listener or any other subscriber-based model
                if (fopArgs.Files.Any() && FilesOpenPicked != null)
                {
                    FilesOpenPicked(fopArgs.Files);
                }
            } 
        }

#endif


So I clean up my code and start over with the example from the jumpstart lesson.
I include the above in the App.xaml.cs and the code below in the AddManual.xaml.cs

These are just snippets of the code, I can't post all the code here, but it should give a good idea of what I am doing.

private void addImageButton_Click(object sender, RoutedEventArgs e)
{
    // Pick photo or take new one
    var fop = new FileOpenPicker();
    foreach (var fileType in SupportedImageFileTypes)
    {
        fop.FileTypeFilter.Add(fileType);
    }
    fop.PickSingleFileAndContinue();                        

}


private async void OnFilesOpenPicked(IReadOnlyList<StorageFile> files)
{
    // Load picked file
    if (files.Count > 0)
    {
        // Check if image and pick first file to show
        var imageFile = files.FirstOrDefault(f => SupportedImageFileTypes.Contains(f.FileType.ToLower()));
        if (imageFile != null)
        {
            // Use WriteableBitmapEx to easily load from a stream
            using (var stream = await imageFile.OpenReadAsync())
            {
                originalBitmap = await new WriteableBitmap(1, 1).FromStream(stream);
                RandomAccessStreamReference rasr = RandomAccessStreamReference.CreateFromStream(stream);
                var streamWithContent = await rasr.OpenReadAsync();
                buffer = new byte[streamWithContent.Size];
                await streamWithContent.ReadAsync(buffer.AsBuffer(), (uint)streamWithContent.Size, InputStreamOptions.None);
            }
                    
            Image.Source = originalBitmap;

        }
    }
}


Next I put up a button to add and image.



When I click on it the Button the FilePicker is opened




I can snap a picture and/or choose a photo. Then the picture is shown on the page. :)

Next step is to actually save the picture in my json. I wll do that part in a next post because this is getting a bit long now.


GNZ.



References:

From the jumpstart series - Building Apps for Windows Phone 8.1:
http://channel9.msdn.com/Series/Building-Apps-for-Windows-Phone-8-1

I watched lesson 17 - Camera, Media and Audio in Windows Phone 8.1: http://channel9.msdn.com/Series/Building-Apps-for-Windows-Phone-8-1/17

Done some reading in these posts, but didn;t really used them: Quickstart: Capturing video by using the MediaCapture API:
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/dn642092.aspx