left-icon

Real-World Xamarin.Forms Succinctly®
by Alessandro Del Sole

Previous
Chapter

of
A
A
A

CHAPTER 2

Local Settings: Preferences and Secure Storage

Local Settings: Preferences and Secure Storage


Storing user preferences and app settings locally is a very common requirement with mobile applications. There are tons of examples, which might include (but are not limited to) storing the last access date and time, the consent to use a cellular network when Wi-Fi is not available, color scheme preferences, and so on. These options are not generally required to be secure, but sometimes you might need to store an encrypted password or information that identifies the user. In this case, you do need to secure preferences and settings. The Xamarin.Essentials library provides types that make it extremely easy to store local settings in both ways. This chapter describes both scenarios and provides details on the classes, and their methods, you can use for these purposes.

Managing local preferences

Local preferences in Xamarin.Forms can be easily managed via the Preferences class from the Xamarin.Essentials namespace. The Preferences class stores preferences in the native local storages, more specifically:

On each platform, preferences are key/value pairs. The value can be of one of the primitive .NET types. Before understanding how preferences work, it is important to list the methods exposed by the Preferences class, as summarized in Table 3.

Table 3: Methods exposed by the Preferences class

Method

Description

Set

Adds a preference to the local settings.

Get

Gets a preference value from the local settings.

Remove

Removes the specified preference.

Clear

Deletes all the preferences for the current app.

ContainsKey

Detects if the specified preference exists in the storage given its key.

Tip: Uninstalling the app will also remove all local preferences.

Let’s now start with an example. Suppose you want to store the last date and time the app was used. You can do this in the OnSleep method of the App.xaml.cs file as follows:

protected override void OnSleep()

{

    Preferences.Set("TimeOfLastUsage", DateTime.Now);

}

TimeOfLastUsage is the key, and the value is a DateTime object. Keys are always of type string. Retrieving a value from the local settings is easy. In the OnStart method, you can write something like the following:

internal static DateTime timeOfLastUsage;

protected override void OnStart()

{

    timeOfLastUsage = Preferences.Get("TimeOfLastUsage",

        DateTime.Now);

}

The generic Get method returns the value for the specified key and stores the result in a variable. Get also requires you to specify a default value in case the key does not exist in the storage, and this is true for all the supported data types. In this example, local preferences are used to store information that can be useful for the app logic at runtime, so it’s not really a user preference.

Let’s look at another example that will check if the phone is connected to a cellular network only, asking the user permission for using it and storing the result. Code Listing 8 contains the code that you want to add to the MainPage.xaml.cs file.

Code Listing 8

        private bool CheckCellularConnection()

        {

            var profiles = Connectivity.ConnectionProfiles;

            return profiles.Count() == 1 && 

                   profiles.Contains(ConnectionProfile.Cellular);

        }

        private bool useCellularNetwork;

        protected override async void OnAppearing()

        {

            if(CheckCellularConnection())

            {

                if (!Preferences.ContainsKey("UseCellularNetwork"))

                {

                    bool result = await DisplayAlert("Warning",

                        "Do you agree to using cellular data when Wi-Fi is not available?",

                        "Yes""No");

                    Preferences.Set("UseCellularNetwork", result);

                    useCellularNetwork = result;

                }

                else

                    useCellularNetwork = 

                         Preferences.Get("UseCellularNetwork"false);

            }

        }

The CheckCellularConnection method checks if only one connection is available, and if this is a cellular network. The remaining code is in the OnAppearing method for convenience so that the code is executed at the app startup, but you will likely create a separate method that will be invoked when the ConnectivityChanged event of the Connectivity class is raised.

In this second example, the code invokes the Preferences.ContainsKey method to detect if the preference was already saved, and then it still invokes the Set and Get methods to store and retrieve the preference value. The Preferences class is intended to store small pieces of information represented by primitive .NET types. If you need to locally save and retrieve more complex and structured data, a good option is to use a SQLite database, as discussed in Chapter 4.

Securing preferences and settings: the secure storage

Sometimes you need to store information locally, but you also need the information to be secured. Each of the supported operating systems offers a secure place to store encrypted information and the Xamarin.Essentials library provides the SecureStorage class, which exposes methods to work with secure storages in a cross-platform way. There are a few differences from the non-secured preferences discussed in the previous section:

  • While preferences are stored inside the app’s own cache, the secure storage can be accessed by multiple applications.
  • As an implication, data you save in the secure storage is not removed when you uninstall an app. This is extremely important to consider.
  • You still work with key/value pairs, but the value can be of type string only.

The native implementation for the secure storage can be summarized as follows:

  • For iOS, it is located in the KeyChain.
  • For Android, it is located in the KeyStore.
  • For UWP, data is encrypted with the DataProtectionProvider algorithms.

When working with iOS, if you want to test your apps on a simulator, you will need to perform a couple more steps:

  • Double-click the Entitlements.plist file in Solution Explorer.
  • When the editor opens, locate the KeyChain element and enable it.
  • In the iOS project properties, select the iOS Bundle Signing tab and assign the Entitlements.plist file as the source for Custom Entitlements.

These entitlements should be removed when working on physical devices, and before distribution. The biggest benefit of the secure storage is that it automatically encrypts the information with the highest levels of security possible offered by each operating system.

The SecureStorage class exposes two simple methods: SetAsync and GetAsync. The first method saves the specified key and value, and the second method retrieves the value for the specified key. If the key does not exist, it returns null, but you cannot specify a default value like you do with local preferences. To understand how the class works, suppose you have the following user interface where the user can enter a password:

    <StackLayout VerticalOptions="CenterAndExpand"

                 HorizontalOptions="FillAndExpand"

                 Orientation="Vertical">

        <Label Text="Enter your password: "

               FontSize="Large"

               Margin="0,20,0,0"/>

        <Entry IsPassword="True"

               x:Name="PasswordEntry"

               Margin="0,10,0,0"/>

        <Button Text="OK" Margin="50,20,50,0" x:Name="OkButton"

                Clicked="OkButton_Clicked"/>

</StackLayout>

The Clicked event handler for the button contains the code that stores the password in the local storage:

private async void OkButton_Clicked(object sender, System.EventArgs e)

{

    // Perform password validation here...

    await SecureStorage.SetAsync("Password", PasswordEntry.Text);

}

Obviously, you will implement your logic for password validation, but for the sake of simplicity, the code stores the password directly. The key points are the two string parameters—key and value—for the SetAsync method, and the usage of the await operator, as this is an asynchronous call. The code you need to write to retrieve information from the secure storage looks like the following, related to the current example:

// Assuming you have declared a bool field called hasPassword

string password = await SecureStorage.GetAsync("Password");

if (password != null)

    hasPassword = true;

GetAsync returns the value for the specified key if the key exists in the secure storage; otherwise, it returns null, so a null check is necessary to avoid exceptions. As you can see, reading and writing data against the secure storage is very straightforward, though I recommend you use this feature only with very sensitive information.

Secure storage tips and tricks

As I mentioned previously, when you uninstall an app that stores information in the secure storage, such information is not removed because the secure storage is at the operating system level, not at the app level (though the OS knows what app is associated to the key). You cannot control when an app is uninstalled, but you can control if the app is running on the device for the first time (including after reinstall), checking if a key already exists in the secure storage so that it can be removed, and providing a fresh environment to the user. The following method demonstrates how to accomplish this:

private async Task CheckAppFirstRun()

{

    if (VersionTracking.IsFirstLaunchEver)

    {

        string password = await SecureStorage.GetAsync("password");

        if (password != null)

            SecureStorage.Remove("password");

    }

The VersionTracking class from the Xamarin.Essentials library provides properties and methods that help working with the app’s versions and builds. IsFirstLaunchEver returns true if the app is running for the first time on the device. The SecureStorage.Remove method deletes the key and its value from the secure storage. You can avoid this code if you instead want to reuse the value of an existing key.

Note: Remember to invoke VersionTracking.Track the very first time; otherwise, the class will not be able to generate version information.

Chapter summary

Storing preferences and user settings is a very common task in mobile applications, and the Xamarin.Essentials library provides the Preferences class, which allows saving key/value pairs in the app’s local storage. Supported data types are .NET primitive types. If the information you need to store locally requires encryption, you can leverage the operating system’s secure storage, for which the Xamarin.Essentials library offers the SecureStorage class, which supports key/value pairs of type string.

In the next chapter, you will see a very practical example of using the secure storage, which is the implementation of biometric authentication.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.