0 Comments

Title Image showing a library

When it comes to file handling and Xamarin Forms you can find all you need in the official Documentation. However, when it comes to where the data should be stored the documentation leaves some points open. Moreover, might even lead to, dear I say it, your rejection in the App Store...

Also when writing Cross-Platform Code, with .Net Standard, it does depend on the Operating System (OS) that the app is being executed on, where to store your data. So let's dive into the platforms which are primarily supported by Xamarin Forms.

Xamarin.Essentials

The most comfortable way is using Xamarin.Essentials. Currently still in preview and requires Android 7.1 or higher. However, if that does not make you blink, these are the options:

  • Local Storage which is also backed up.
  • Cache Storage which is, well for caching files but are more on the non-permanent side.
  • Files bundled with the app, i.e. read-only files.

You can access the folder paths as follows:

var rootDirectory = FileSystem.AppDataDirectory;

Currently Xamarin.Essentials supports Android, iOS and UWP. So if all the platforms your app requires are named, and you do not need any other location. Be sure to check out Xamarin.Essentials and check the documentation for more details.

Do it yourself

In most cases the folders offered by Xamarin.Essentials will suffice, but if you require a different folder, i.e. the document folder under iOS, you can always set the path to the location on your own. So let's have a look at how you can achieve this.

Android

Now when it comes to Android, you can follow the documentation from Microsoft and use the following path for storing your files:

_rootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

Looking to cache some files, then we can take the path and with Path.Combine set the path to the cache folder:

_cacheDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "..", "cache");

If you want to store files to the SD-Card, i.e. external storage under Android. You have to pass in the path from a platform Project to the .Net Standard project or use multitargeting to achieve this. You can get the path as follows:

var sdCardPath = Environment.ExternalStorageDirectory.AbsolutePath;

Note that the Environment here is Android.OS.Environment and not System.Environment. So if Android is this easy how hard can iOS be?

iOS

When storing files under iOS, there is a bit more documentation to read. The reason being that Apple uses multiple subfolders within the Sandbox container. The ones that are important for file storage are the following:

  • Documents: In this folder, only user-created files should be stored. No application data, which includes that JSON file of your app, should be stored here. This folder is backed up automatically.

  • Library: The ideal spot for any application data you do not want the user should have direct access to. This folder is backed up automatically.

    • Library/Preferences: A subdirectory which you should not directly access. Better use the Xamarin.Essentials library for storing any key/value data. This data is backed up automatically.
    • Library/Caches: This is an excellent place to store data which can easily be re-created. This data is not backed up.
  • tmp: Good for temporary files, which you should delete when no longer used.

For a more detailed listing check out the docs. So when storing files, you are under iOS this code will point to the Documents folder:

_rootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

If you intend to store information into the Library folder you can change the directory as follows:

_rootDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "..", "Library");

Equally, you can change your path to one of the other locations described above.

UWP

UWP apps usually also store their data in a sandbox. Only if in the app's metadata the permission is set and a good reason was given, which Microsofts validates on submission to the store, can the app access other file locations outside of the sandbox. UWP apps also live in a sandbox. The ApplicationData offers to store data locally, roaming or in a temporary location. The local folder can be accessed as follows:

_rootDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);

Similar the other locations can be accessed for example the roaming folder (which is synced automatically across all of your different devices):

_rootDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "..", "RoamingState");

The following directories are present in a UWP apps sandbox:

UWP Container folders: AC, AppData, LocalCache, LocalState, RoamingState, Settings, SystemAppData, TempState

However, what if I am targeting other platforms?

Since Xamarin Forms is no longer limited to Android, iOS and UWP, you might find yourself wanting to write files on another system such as Tizen. The best solution is to check the documentation of the given platform where data should be stored and then run the following code on the platform:

class Gnabber 
{ 
    // ... 
    private IEnumerable<DirectoryDesc> DirectoryDescriptions() 
    { 
        var specialFolders = Enum.GetValues(typeof(Environment.SpecialFolder)).Cast<Environment.SpecialFolder>(); 
        return specialFolders.Select(s => new DirectoryDesc(s.ToString(), Environment.GetFolderPath(s))).Where(d => !string.IsNullOrEmpty(d.Path)); 
    } 
    // ... 
} 
 
class DirectoryDesc 
{ 
    public DirectoryDesc(string key, string path) 
    { 
        Key = key; 
 
        Path = path == null 
            ? "" 
            : string.Join(System.IO.Path.DirectorySeparatorChar.ToString(), path.Split(System.IO.Path.DirectorySeparatorChar).Select(s => s.Length > 18 ? s.Substring(0, 5) + "..." + s.Substring(s.Length - 8, 8) : s)); 
    } 
 
    public string Key { get; set; } 
    public string Path { get; set; } 
}

The code above lists all used folders from the System.Environment.SpecialFolder for the given environment, and also provides you with the absolute path. If none of the special folders is the target location, you desired. Try using Path.Combine and a path nearby to get to your desired location.

Conclusion

Storing files is not tricky but put some thought into where to store your applications data can go a long way. Xamarin.Essentials may provide all the functionality you need, but if not you usually use the System.Environment.SpecialFolders and the System.Environment.GetFolderPath to get access to different folders offered by the platform you are on.

0 Comments

pexels-photo-64774

Update: Hey there thank you for reading my blog, since I wrote this post I have learnt a lot and have found a better way to migrate your Xamarin Apps so please check out my latest blogpost on this matter.

If you haven’t heard or dived into .Net Standard you are in for a treat. In short it provides a way to share code across platforms but in contrast to the PCL it gives you so many more platform specific features. For an in depth overview check out the official docs.

Note: If you are starting a new Project today with Visual Studio (VS) 2015.4, you will not be able to select .Net Standard by default. But the new templates for .Net Standard will be included in Visual Studio 15.5.

Creating the .Net Standard Class Library

Migrating an existing app to .Net Standard is pretty straight forward. Step one add a .Net Standard Library to replace your PCL project.

The VS Add New Project dialog, under Visual C# select Class Library (.Net Standard)

Migrating your source code

Then drag and drop all of your existing files from the PCL project to your .Net Standard library. Note that you don’t want to copy the packages.config or any of the files under properties.

CopyFiles

Now you can delete your PCL project that you have migrated. If you do so from Visual Studio note that the Project is still available in the file system. Which means you still have it if you forgot something, but also means that you will have to delete it later on if you want to remove it from the source control workspace.

Next step is to add all the NuGet packages you have used in the PCL project. If you are having trouble adding some of the packages look out for NuGet packages that are no longer needed due to .Net Standard support such as file system access. In other cases it could be because the NuGet package has not (hopefully yet) migrated to .Net Standard. In that case check out this post and don’t forget to ask the maintainers of the project when the project will be available for .Net Standard Winking smile

Hooking up the projects

You can now add the reference to the .Net Standard in your Android and iOS project. If you created a new namespace I strongly recommend you refactor them after adding them to your projects. Or else your refactoring tool of choice will only do half the magic and you will still have some work left to do.

If you are using a UWP project please read the section bellow as you will need to make some additional steps to make it work.

Fixing the csproj for Xamarin Forms

Unfortunately when moving a Xamarin Forms app over to .Net Standard you will get weird compilation errors. The cause of this is that the XAML files are referenced in the csproj file:

02_1_RemoveEmbeddedResources

Simply remove them as they are not needed and the compile errors should be history.

When using UWP

If you are using UWP as a target (I.e. using the default Project provided up to VS 2015.4). You will have to remove and add the project anew:

If you are unsure if you really have to update your UWP project. Check if you have a project.json file in your UWP project. If the answer is yes, I’m afraid you will have to follow the following steps.

  1. Remove the UWP project from the solution in Visual Studio
  2. Rename the UWP project folder in the file explorer
  3. Add a new UWP project in Visual Studio (with the same name as the one just removed)
  4. Set the minimal supported Windows 10 version to the Fall creators update

    VS Dialog Window with Target and Minimum Version set to Fall Creators Update
  5. Add any NuGet references the just removed project had (you can peek into the project.json file in the renamed location if you are unsure which packages to add)
  6. Copy and paste all your UWP files (except the project.json)
  7. Add a reference to the Standard Library project

If you know an easier way to upgrade a UWP project, please let me know in the comments bellow Smile

Conclusion

In this post we went over the steps required to migrate an existing PCL project to .Net Standard. All the steps were done with Visual Studio 15.4.

0 Comments

pexels-photo-277803

When writing an app that only allows access to certain or all parts of the app when a user is logged in requires a login screen which can be presented to the user at every screen in the app I.e. as soon as he is required to login or re-login.

In this post you will see how to create a view that can be used to enter the username and password. Further we will look at how we can use this screen regardless of which screen is currently displayed to the user.

Writing a login view

Let’s consider a view as follows.

LoginScreen

It requires a username and password, the user can confirm his entry by hitting a button which will validate his entry.

After entering a correct login the user will be presented with the apps content. In our case a simple screen containing a logout button.

So far so good, but how will we ensure that the user only sees the content after she has logged in? How do we prevent the user form simply dismissing the page? Well let’s dive into this topic as next.

Login sites and Navigation

So implementing the view and even the business logic of a login site are quite straight forward but how do can we pop up the login view whenever the user is required to authenticate himself I.e. has to re-authenticate? And how do we prevent him from leaving the screen. Luckily all this can be solved by using the modal navigation backed in to Xamarin Forms. Utilizing a simple navigation service from a previous post, we can ensure invoke the navigation to the login page from any page or even when resuming the app or on start up:

Using modal navigation with a simple  navigation service allows us to implement a login dialog that can be pop over any view currently displayed and return the user to the sensitive content once he is properly authenticated.

No way back

Though modal pages do not provide the user with a software button in the navigation bar to return to the previous page. The dedicated OS back button on Android and Windows 10 can still be used by the user. To ensure the user can not leave the page via the OS button the OnBackButtonPressed method has to be override as follows:

Instant Login View navigation

When requiring the user to log in on the initial start up of the app or resume. Often it is desired to simply overlay the login view over the page that should be displayed when the user is successfully authenticated. Want we do not want is the user to ever see the landing page before being logged in. To achieve this effect we can want to insert our check before the page is displayed to the user and then navigate without animation to the login page:

Improve user input experience

When creating the user login what would be nice is if the user could simply navigate from the username to the password field via the enter button on the keyboard. After completing the password it could directly verify the username and password when pressing enter. This can be done in the code behind of the login view as follows:

Conclusion

In this blog post we saw how we can create a view for a login page and also implement the logic behind it. Through modal navigation we saw how we can “capture” a user on a view and prevent him from leaving the view before he has entered some valid credentials.

We then improved the UX by showing the login page instantly when resuming or starting the app. Plus improving the entry of username and password.

You can find a sample of the login view on GitHub.

2 Comments

pexels-photo-297755

If you have ever written a Xamarin Forms app and wanted to navigate from within a View Model to another page. Then you have come over the issue that the navigation logic usually resides in the view. Since every best practice blog post, course and video tells us that the view and business/control logic should be separate. We are often left with the question how to integrate a View Model based navigation.

What we want to do

The goal of this post is to show you how we can initiate a navigation call from the View Model. Without adding dependencies to your view or writing call back methods.

Navigation 101

In Xamarin Forms there are two fundamental ways of navigating between pages:

  • Push
  • Modal

Push navigation is the most straight forward way for navigating in an app. The main page in the App.xaml.cs is a NavigationPage which contains the main page displayed to the user:

When navigating to the next page, the page gets pushed onto the navigation stack. The user can then navigate back via Screen (iOS & Windows) or Hardware button (Android & Windows). Navigating back will dispose the current page, pop a page from the navigation stack and display it to the user.

When navigating to a page using Modal. The target page is displayed in a separate navigation context. This results in the behaviour that the user is no longer displayed with a software back button from the OS. The back navigation call differs from Push. Thus it requires invoking a different method of the Navigation Page.

Modal navigation is a great option to capture the user on a view. This is not generally what we intend to do with a user. But if the user has to login or the users consent is required (are you really sure...) filling out a form. Then modal navigation allows keeping the user on a page and handling the navigation via custom defined logic.

Note: Modal navigation is an iOS concept in it’s origins. Under Android and Windows the user has system buttons to navigate the app. If the user should not be able to leave the page and return to the previous page I.e. user has to login first. The developer will have to override the OnBackButtonPressed with a return true in the code behind of the view.

Navigation TL;DR;

We have two navigation methods in Xamarin.Forms. These are Push and Modal. Each has different ways of invoking the navigation. Which also applies to the back navigation.

Using a navigation service

In general the navigation service will have to contain a Navigation Page to handle the navigation stack. Further it needs to offer a Method for navigating to a page via push or modal navigation and allow navigating back.

The initialisation of the navigation service can now be done in the App.xaml.cs by registering all the views with a corresponding key.

In a view model we can now navigate to a page by providing the service with the key of the target page. If required we can also pass in a parameter. Since the parameter is of type object there are no limitations there.

As mentioned before modal navigation leaves the current navigation stack and displays the page on it’s own. If we want to navigate from a modal root page via push to a child page. The modal root page has to be in a Navigation Page itself. This is what the navigation service does automatically. It further removes the navigation header of the modal root page.

Back navigation checks what back navigation is intended for the current page. A root page in a navigation stack is either the root page of the app or a root page in a modal navigation stack. In either case it will choose the appropriate back navigation method.
If the page is not the root page we simple navigate back to the previous page that was pushed onto the navigation stack.

Conclusion

Using the navigation service described in this blog post. It is possible to navigate from the view model to other pages. Doing so we do not add dependencies to the view stack e.g. Xamarin Forms. Nor do we have to write cumbersome call back methods for each navigation action over and over again.

I would like to thank Laurent Bugnion at this point who laid down the base of the described navigation service above in with his initial implementation of a Navigation Service for Xamarin Forms when using MVVM Light.

You can find a running sample on GitHub.

0 Comments

Xamarin Test Cloud Logo

Automatically testing apps is not only a huge time saver but it also ensures that bugs introduced into the system get quickly caught. This leads to a shorter timespan to fixing these bugs since the memory of what has changed is still fresh in the head of the developers so overall shorter time means less money spent on hunting down bugs and more time to implement the next juicy feature. When developing a Xamarin application one can choose to run the Unit- and Integration Tests on a device/simulator to get a feeling how the logic will behave and perform in the real world. But with Xamarin Test Cloud we can go one step further and test the UI i.e. the entire stack of the application automatically. If you are interested into a general introduction into the topic I recommend you read this post before diving into the technical details of the lines to follow.

For writing a Xamarin Test Cloud (XTC) test the Xamarin Toolchain has to be installed. This post was written using Visual Studio 2015 Update 2.

Having a look at the app

Since this post focuses on writing UI tests the app is rather simple but will show the basic steps required to write maintainable UI tests. The app under test is a basic app with an input field, a button and a button that displays the entry of the input field. The app is based on the MVVM pattern (using MVVM Light) and is based on Xamarin.Forms.

Screenshot of app that is going to be tested.

When a user enters a message and submits it, it will appear on the label bellow. Now that the basic outline is defined, lets have a look at how we can implement a UI test for the app.

Writing UI Tests

If you created your Xamarin.Android and iOS projects with UI tests from the beginning you can skip the next steps and just start writing the tests. If not do not despair a few easy steps will allow you start writing those UI tests in no-time.

Setup

To start writing UI tests we first have to add a UI testing project to an existing project. Simply selecting the UI Test Project will create the Project in the solution. What is still left to do is associate the Project we want to test with the test project. Right click onto References, select the Android and/or iOS Project you want to test and simply add them:

Adding iOS And Android App Projects to a UITestProject

If you take the default UI testing project from Visual Studio you might want to check if you have the latest version for Xamarin Test Cloud. Update XTC to 1.1.0 or higher or else you will get an error when executing the tests which is asking for an API key.

Starting with Xamarin Test Cloud 1.1.0 or higher you no longer need a subscription for Xamarin Test Cloud to execute the tests locally.

iOS and XTC

To run UI tests on iOS there is an additional library required that is included in the app - only the debug version, this will not be deployed to the store. Add the Xamarin Test Cloud Agent package to your iOS Project, then edit the App Delegate to look the following:

Next open the Properties of your iOS project and ensure that Debug build configuration under the Build tab defines the Symbol: ENABLE_TEST_CLOUD

iOSProjectConfiguration

Now this symbol must only be set for Debug builds. Trying to submit an app with the calabash package included will lead to a rejection when trying to submit the app to the store.

Writing tests

Enough chit chat, lets start writing those tests already. In the UI test project the Tests.cs class file contains the basic setup for a test. Lets change the AppLaunches method to this:

Now when we start the test for i.e. Android the App will be started and a Read Eval Print-Loop (Repl) console will open. One of the most used commands when using the Repl is treenow if we execute the command the following output will be printed:

Shows the XTC Repl tree command when a UI has no Ids set.

Now we can identify some of the controls, but it would be a lot better if we could just identify the elements over Ids. So lets just do that. Lets start by adding an AutomationId to all of our controls:

Next we will have to add a couple of lines of code to the AppDelegate.cs in the iOS Project:

And the MainActivity.cs of the Android project:

If we rerun the test again and execute the command tree we will now see the following output:

XTC Repl showing Ids after executing the tree command

Working against Ids is considered best practice. For instance if the app is required to be available in multiple languages the UI test will work when the device is set to a different locale and can be used to acquire screenshots

In the Repl, we can now type in the following commands which will write a text in the Entry control, then submit the message and read out the text value of the label displaying the last submitted message:

Repl with the entered commands.

One can use the copy Repl command to copy all of the executed commands to the clipboard (the tree command will be discarded from copying). We can create a new test method and simply paste the copied commands from the Repl. Add an Assert for the Text input et voila, we have created our first basic UI test. Smile

Now the test has been added with some additional lines that capture a screenshot of the app. These screenshots can be of great value when not observing the test while it is running. And since automation is all about freeing up the human to do other tasks you should enable your tests to take a screen shot after any meaning full step.

Please note that taking screenshots does increase the runtime of your tests slightly so you might want to enable a global constant which allows you to easily en- i.e. disable the screenshots.

Further when running your tests on the Xamarin Test Cloud the screen shot will allow you to get a lot more information about each step such as CPU & RAM usage at the time of the screenshot. So it also allows you to get more telemetry of the app when the screenshot is taken. The string you pass to the method will also appear as under the test.

Executing Tests

After creating the test we can run it on either Android or iOS. Per default the IDE settings are taken for executing the test so it is possible to select different emulators e.g. in Visual Studio you can select different Android Emulators to execute the tests on. If one hooks a device to the computer it is even possible to execute the test on the device. Again for all this there are no licenses required. The tests are base on NUnit, so as long as a NUnit Testrunner is installed the tests should just simply execute.

Showing test run result with the app in the background. The resharper NUnit Testrunner was used to perform the testrun.

At the time of writing this blog post the iOS execution is only possible on a Mac.

A small side note regarding the execution time of the test. Due to the fact that the app has to be deployed and then executed on the device the test takes a couple of seconds to run through. If we would think about an Integration Test performing the same task we would have a much shorter runtime, but would not be able to see if the information is correctly displayed on the screen for the user. Just keep in mind that UI Tests in general take a while longer to perform the same test that a integration test would need and that it is worth to choose beforehand which tests to execute.

Running in the cloud

As stated before it is possible to execute the tests locally. This could even be integrated into an automated build process. But there are some limitations when executing the tests locally. For instance if we decide to attach a device we have to maintain that device. Ever heard of bloated batteries, broken cables and the like? Well those things can/will happen, further it is not possible to parallelise the tests locally out of the box. Another aspect is easily adding devices to the test set, well all this is what is the great strength of running your tests on Xamarin Test Cloud. Running the tests on the Xamarin Test Cloud can easily be integrated into a build server and allows to easily run the app on multiple devices (in parallel) and even allows to parallelize the execution of tests on multiple devices of the same type. So in short Xamarin Test Cloud offers a wide collection of devices with different OS versions that do not have to maintained and choosing which devices to use during the tests can be easily configured and changed. The results are displayed on a dashboard:

Screenshot showing the dashboard of XTC results for a testrun.

There is even an API that allows to control the execution and collect the results of a test run.

Currently there are still some details missing from being available for the extraction. Such as the snapshots taking during a test run. If you would like the team to add this or other features please feel free to rate it up or tell them here.

Conclusion

In this blog post we saw how a UI Test based on Xamarin Test Cloud is created. How the UI for Xamarin.Forms should be adapted to make writing of UI tests more robust. Further we saw how we can configure the tests to capture screenshots from steps performed during a test run. Capturing screenshots of a test run not only allows to see more easily where a functional error occurred but also allows to see how the screen looks for a given device and if the layout is behaving as expected.

You can find the sample project and the test code on GitHub.

HTH

Further Reading

Getting started with iOS.