Showing posts with label Windows Phone Development. Show all posts
Showing posts with label Windows Phone Development. Show all posts

Thursday, April 7, 2016

WP App part 6 - Completing the app and various improvements

Goal:
Publish the App



Previous parts:


Part 1 - First setup
http://sometimesiliketopretend.blogspot.com/2014/09/windows-phone-app-part-1-manual.html

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

Part 3 - Using the FilePicker

http://sometimesiliketopretend.blogspot.com/2014/11/wp-app-part-3-manual-automatic-use.html

Part 4 - Saving and Loading images from and to a byte array
http://sometimesiliketopretend.blogspot.com/2015/02/wp-app-part-4-manual-automatic-saving.html

Part 5 - Copy Images to Local App Folder
http://sometimesiliketopretend.blogspot.com/2015/05/wp-app-part-5-manual-automatic-copy.html


Since the last post all the base functionality is in place and I started testing and tweaking the app.

Some of the improvements I made:

  • Storing thumbnails alongside the original image to reduce the load when previewing a Manual
  • Made it possible to attach multiple images to a Manual. This was quite a big change.
At the end I published the app to the store.
This was a easy and fast process. One thing I as struggeling with was getting the tile and store image in place.

But since my struggels the Dev center has been updated and it is a bit more clear now.

All in all it was fun to build an app.

For those interested you can find it here:


URL for Windows 10https://www.microsoft.com/store/apps/9nblgggz03qn
URL for Windows Phone 8.1 and earlierhttp://windowsphone.com/s?appid=7773e6f7-69e5-40dd-bdcf-57d5cab50de8



GNZ.

Friday, May 15, 2015

WP App part 5 - "the Manual Automatic" - Copy Images to Local App Folder

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



Previous parts:


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

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

Using the FilePicker in part 3:

http://sometimesiliketopretend.blogspot.com/2014/11/wp-app-part-3-manual-automatic-use.html

Saving and Loading images from and to a byte array in part 4:
http://sometimesiliketopretend.blogspot.com/2015/02/wp-app-part-4-manual-automatic-saving.html

Since in part 4 my efforts to store the images in a byte array backfired I decided to store the images in the local folder of my app.

In this post the goal would be to create a copy of the original image, store it in the local storage and store the imagename in my datamodel.

Step one - Modify the datamodel
In my datamodel I leave out the byte array and put in a string to store the only image name:



When storing the manual the Name of the image is saved.
In my ImageHelpers class I defined the public static variable for the location where I want to store the images and one with the default image.



Also two methods are available for showing an image from a RelativePath and one for converting a StorageFile to a BitmapImage

I used this page:

http://stackoverflow.com/questions/14883384/displaying-a-picture-stored-in-storage-file-in-a-metroapp


Step two - Copy the image
I want the images to be put in a seperate folder in my local app storage.

For some general function when working with the files and directory I create a Helper class named FileHelpers.

I have got the methods here, one to check if a file exists and one to check if a directory exists.



I used this page:
https://social.msdn.microsoft.com/Forums/windowsapps/en-US/570fcd6b-3270-4c47-b796-cf6bc5adb600/how-to-store-the-image-into-the-local-file-system

When adding a Manual, I check if the Directory is available, if not I create it and set the 'localFolder' to that directory:


//Create a copy of the picture
//Check for directory
bool folderExists = await FileHelpers.DoesFolderExistAsync(ImageHelpers.imagesFolder);
if (!folderExists)
{
    await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFolderAsync(ImageHelpers.imagesFolder);
}

//change to the image subfolder

StorageFolder localFolder = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFolderAsync(ImageHelpers.imagesFolder);



Then I check if the file I want to copy does not already exists (the name) and if it doesn't exist I copy the file

//check for fileexists in the subfolder
bool duplicateCheck = await FileHelpers.DoesFileExistAsync(imageFile.Name, localFolder);

//If file does not exists copy it
if (!duplicateCheck)
{
    await imageFile.CopyAsync(localFolder);
    //bmp = await ImageHelpers.LoadImage(imageFile);
    storeImageName = imageFile.Name;

}


If th file exists I add a timestamp to the filename and rename the file, This rename action also copies the file

else
{
    //Since the source is readonly, put it in a temp file, because we want to rename it.
    StorageFile tempFile = await localFolder.GetFileAsync(imageFile.Name);

    //Alter the Name with a unique timestamp number
    DateTime unixEpoch = new DateTime(1970, 1, 1);
    DateTime currentDate = DateTime.Now;
    long totalMiliSecond = (currentDate.Ticks - unixEpoch.Ticks) / 10000;
    string fileName = origDisplayName + "_" + totalMiliSecond.ToString() + tempFile.FileType.ToString();

    //The RenameAsync line also copies the file
    await tempFile.RenameAsync(fileName);
    storeImageName = fileName;

}

And finally I call the AddManual method in the Datamodel:


App.DataModel.AddManual(manualNameTextBox.Text, manualDescriptionTextBox.Text, storeImageName);
 
Step three - Testing
In order to test this I first used the command line tool to check the Isolated Storage of my app.
I used: https://msdn.microsoft.com/en-us/library/windows/apps/hh286408(v=vs.105).aspx to check the file from a command line.

But then I came across this nifty tool: https://isostorespy.codeplex.com/
Does the same but then with a nice GUI :)
So I checked if the directory was created, the file was copied and if, in case of duplicate names, the name was altered correctly. 

Works like a charm, very nice tool.



Next post will be on completing the app and various modifications I did.


GNZ.

Saturday, February 7, 2015

WP App part 4 - "the Manual Automatic" - Saving and Loading images from and to a byte array

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


Previous parts:


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

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

Using the FilePicker in part 3:

http://sometimesiliketopretend.blogspot.com/2014/11/wp-app-part-3-manual-automatic-use.html

It has been a little while since I posted about my project of developing the Manual Automatic app for Windows Phone. But a lot of work has been done since then. So now first I will show how I managed to store images in my Json datamodel.


Part 4 - Saving and Loading images in JSON

I want the images to be stored and not just referenced if all possible. That way it isn't lost if you delete the picture from your camarea library, because you might not want to have all those pictures of pages in your library.

So it would be great if the image can be stored in json.


Step 1 - Converting the image to a byte array and saving it
I want to store the picture in a array of ytes, so in my datamodel it looks like this:

    public class Manual
    {
        public int ID { get; set; }
        public string ManualName { get; set; }
        public string Description { get; set; }
        public DateTime Created { get; set; }
        public DateTime Changed { get; set; }
        public byte[] Image { get; set; }
    }

I have a byte array named Image.
After selecting the image with the FilePicker (see previous part) the WriteableBitmap originalBitmap variabele and the byte[] buffer variabele are filled. I used the originalBitmap to bind it to the Image control on the XAML.

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)
        {
            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;

        }

    }
}


The buffer needs to be stored.
Since that allready is a byte[] I can simply store it in my DataModel.

So on the saveButton click event I do some checks and then call

App.DataModel.AddManual(manualNameTextBox.Text, manualDescriptionTextBox.Text, buffer);


There I set the buffer to the manual.Image ad call the sveManualDataAsync(); function

manual.ManualName = manualname;
manual.Description = description;
manual.Created = DateTime.Now;
manual.Changed = DateTime.Now;
manual.Image = buffer;

_manuals.Add(manual);


await saveManualDataAsync();

There the data will be save, see the previous post for more details.


Step 2 - Loading the Image and converting it back from byte[] to WritableBitmap.

From the Main page, where the user can search for records, they can click on the results and then it neds to open on a seperate page. On that page I want to show detailed record information and also the image. So there the byte{} needs to be converted back to an image.


On the Main page I use the code below to generate results;

private void genResult(DataModel.Manual manual)
        {
            TextBlock NameText = new TextBlock();
            NameText.Text = "Manual Name: " + manual.ManualName;
            NameText.FontSize = 22;
            //Store the manual in the Tag so we can pass it along
            NameText.Tag = manual;
            NameText.TextTrimming = TextTrimming.CharacterEllipsis;        
            NameText.Tapped += new TappedEventHandler(NameClickedEvent);
            
            
            TextBlock DescText = new TextBlock();
            DescText.Text = "Description: " + manual.Description;
            DescText.FontSize = 12;
            DescText.TextWrapping = TextWrapping.WrapWholeWords;

            TextBlock CreateText = new TextBlock();
            CreateText.Text = "Created on: " + manual.Created;
            CreateText.FontSize = 12;
            
            TextBlock IDText = new TextBlock();
            IDText.Text = "ID: " + manual.ID;
            IDText.FontSize = 12;

            TextBlock ImageStringText = new TextBlock();
            ImageStringText.Text = "ImageString: " + manual.ImageString;
            ImageStringText.FontSize = 12;

            
            resultStack.Children.Add(NameText);
            resultStack.Children.Add(DescText);
            resultStack.Children.Add(CreateText);
            resultStack.Children.Add(IDText);
            resultStack.Children.Add(ImageStringText);


        }

In the NameClickedEvent I navigate to the RecordPage

private void NameClickedEvent(object sender, TappedRoutedEventArgs e)
        {
            //Get the manual from the textblock tag and pass it along to the ReordPage
            TextBlock textBlock = sender as TextBlock;
            DataModel.Manual manual = textBlock.Tag as DataModel.Manual;

            Frame.Navigate(typeof(RecordPage), manual);
        }

On the RecordPage in the OnNavigatedTo I do the following:

 protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            //get the vars and get the one manual
            var manual = (DataModel.Manual)e.Parameter;
            
            
            //should not occur that the passed manual is empty but check anyway
            if (manual != null)
            {
                ManualNameTextBlock.Text = manual.ManualName.ToString();
                CreatedTextBlock.Text = CreatedTextBlock.Text + manual.Created.ToString();
                DescriptionTextBlock.Text = manual.Description.ToString();

                if (manual.Image != null)
                {
                    MemoryStream _stream = new MemoryStream(manual.Image);
                    ManualImage.Source = await new WriteableBitmap(1, 1).FromStream(_stream);
                }

                //Show a blank Image if no image is returned
                if (ManualImage.Source == null)
                    ManualImage.Source = ImageFromRelativePath(this, "Assets/empty.png");  
               
            }
            else
            {
                //show a message that searchterm is required
                string messageText = "Something went wrong, please go back and re-select a Manual";
                MessageDialog msgBox = new MessageDialog(messageText);

                await msgBox.ShowAsync();
            }


        }

So the byte[] is converted back to in WriteableBitmap and set to the source of the Image.

But an error occurs when I do just that:




An exception of type 'System.Exception' occurred in mscorlib.ni.dll but was not handled in user code

Additional information: The component cannot be found. (Exception from HRESULT: 0x88982F50)


If there is a handler for this exception, the program may be safely continued


I have no idea why this happens, and after searchig online for hours I still can't get it to work.
I use the same loading image from byte[] method to show the image after picked by the file picker and no error occurs. But when first storing it in the json file and the retreiving it messes it up...

At some point it worked, but after a few mote tests it broke again... Sounds stupid, but I cannot find a way to reproduce the corect working again... Something must be off.


After testing and searching I realize that this maybe isn't the best way to store images. In one of my tests I crate maybe 10 records with images and the json files grew to 11MB. So I van only imagine how big the files becomes after a while...
This will not be the correct way I gues

So i decide to not store the images in the json file. I now want to store a copy of the images in a folder in the Localfolder of the app. 

Once that is done I will post about it in a new blog post.

GNZ

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

Monday, September 29, 2014

WP App part 2 - "the Manual Automatic" - Setting up the DataModel

Goal:
Create the Datamodel for my Windows Phone App 'The Manual Automatic" 




See my first post on Windows Phone App Development here:
http://sometimesiliketopretend.blogspot.com/2014/08/how-to-start-with-windows-phone.html

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


Part 2 - the Datamodel

The datamodel I will use works with json. Like XML it is just a format to store data in. I have followed some online lessons and did some exercises with json and it seems to be the default in the templates so I would like to ue it in my own App.

Then I use the structure from one of the lessons I posted in my previous post about app development:
http://sometimesiliketopretend.blogspot.nl/2014/08/how-to-start-with-windows-phone.html

it is a lesson from this series:
http://channel9.msdn.com/Series/Windows-Phone-8-1-Development-for-Absolute-Beginners


In one of those lessons a complete app is created, I will use a lot from those examples, so don't go off thinking I came up with all the programming myself ;)


DataSource
I add a new class file 'DataSource' to the 'DataModel' folder in the Shared Namespace:




In the opened DataSourcec class file I add a public class called "Manual" and I add some properties for my Datamodel.

Tip:
You can safe some typing time by typing 'prop' and then hit the [Tab] button twice, this will add a empty property.

Tip:
I use a ObservableCollection for my dates, there must be a using statement filled in in order for it to function. Stand on the text you typed and press CTRL + .  (period) The following will pop-up:



This is needed for more options, like the 'Task'. Everytime you see a red line under an text, you should check for spelling and if the 'Using' statement is present. Simply check by pressing CTRL + . and add if needed. You can use this for other additions to. Try it :) 

I also want to store the image in the json object, don't know if it is possible, but I'll try. This way, the picture can be deleted from the phone, but will still be available in thte app. Also I think it will be easier to create a backup or synchronise date in later versions. 

I created the following properties:



Then in the DataSource class I create the Tasks and Methods to save and load data. Again, these are all from one of those great lessons of the channel 9 website. 





There are better tutorials on the internet to explain all this, just search for it. This is just my first little Windows Phone App adventure ;)


Reference DataSource from xaml pages

Next I need to make sure the DataModel can be referenced from the xaml pages.

In the App.xaml I add the following lines:



Now that this is done I can do reference the datamodel from the pages, so I can add the code in the addButton event to store the inserted data.



So now Ihave the Datamodel and the page to save new data.

Finally in this part I will need to show the stored data.


Show the Data

I want to show the inserted data on the MainPage.xaml, just below the search box. I don't know if this ill be the final layout, but I need to test the data input and retreival.

So on the MainPage.xaml.cs on the OnNavigatedTo event I add the following code:

var manuals = await App.DataModel.GetManuals();

this.DataContext = manuals;


And then on the MainPage.xaml I add layout to display it like so:



So now to test it:

It starts up :)
I click the Add icon



I add a Manual:




After clicking the Add button I return to the MainPAge, and the data is shown :)


There are some issues, like the ChangeDate isn't showing correctly and I need to autonumber the ID, but hey this works :)

No while the app runs I go to Visual Studio and choose "Lifecycle Events" and choose "Suspend and shutdown"



This will emulate the app being shutdown. Then I start the App again. 

And jeeeee, the data is still there:



OK, so much for this part, next part I will work on getting images stored.

GNZ.