One of the oldest and simplest ways to persist data in every system and on every language is to create a file, write our data into it, and eventually read that data at a determined time. Despite the perceived simplicity of reading and writing files, there are some obstacles to overcome in Android for security reasons. Indeed, applications are not allowed to write to/read from every part of the phone. Moreover, the file could be formatted in different ways. In this recipe, we will focus on how to read and write simple files.
In the introduction of this recipe we state that, for security reasons, applications aren't allowed to write/read whatever they wish:
AndroidManifest.xml
file, which is an XML file under the properties
folder of your Xamarin project. This file, among other things, is responsible for presenting the permissions your application might require. In order to read/write files, two permissions are needed. These two permissions are presented by the following code, which is a fragment of the AndroidManifest.xml
file:<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_OWNER_DATA"
string path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); string filename = Path.Combine(path, "myfile.txt"); using (var streamWriter = new StreamWriter(filename, true)) { streamWriter.WriteLine(DateTime.UtcNow); } using (var streamReader = new StreamReader(filename)) { string content = streamReader.ReadToEnd(); TextView textView = FindViewById<TextView> (Resource.Id.textView1); Console.WriteLine (content); }
In the upper code, we first retrieve the path in which we will create our files. This is done by invoking the GetFolderPath()
method of the Environment
class.
Note that we must fully qualify Environment, that is, write System.Environment
in order to use it. Indeed, there is a name collision between the class Environment
under the system and another Environment
class under Android OS. Therefore, the only way to compile and deploy our project is to specify which Environment
classes you intend to use.
After retrieving the path to the file, we create a string corresponding to the path, plus the filename using the Path.Combine()
method, which takes the former two as parameters. We are able to create a StreamWriter. In our first using
block, we simply use the WriteLine()
method of the StreamWriter. As an argument for the WriteLine()
method, we use the current date. At the end of this first using
block we have successfully written today's date in the file. The remaining using
block serves us by reading that file using the ReadToEnd()
method of a newly created StreamReader. The read file is then prompted into the console by means of the Console WriteLine
function. As proof, and seeing as data is really persisted, we compile and deploy our application five times. On the fifth run, the console shows the following outputs:
Forwarding debugger port 8937 Forwarding console port 8938 Detecting existing process [monodroid-gc] GREF GC Threshold: 1800 Loaded assembly: /data/data/OnPhoneData.OnPhoneData/files/.__override__/OnPhoneData.dll Loaded assembly: Mono.Android.dll [External] Loaded assembly: System.Core.dll [External] Loaded assembly: MonoDroidConstructors [External] 11/13/2013 8:55:36 PM 11/13/2013 8:57:01 PM 11/13/2013 8:57:43 PM 11/13/2013 8:59:27 PM 11/13/2013 9:00:03 PM [gralloc_goldfish] Emulator without GPU emulation detected.
As you can see, we have the date printed out five times at 8:55:36
, 8:57:01
, 8:57:43
, 8:59:27,
and 9:00:03
.
The theory behind file read and write is almost the same as on classical computers, but with a little difference. Therefore, we assume that the reader has mastered them.
Files you create using the FileWriter shown in the previous example are, by default, saved in the internal storage, that is, the phone's memory. Also, the file you are creating is completely and irrevocably private to your application, meaning that neither the user nor other applications can access these files. Finally, all the files your applications have created during this time and have been installed on the end-user phone, will be deleted at the same time as the application is uninstalled.
By default, files are written on the internal memory of the phone, however, there is a way to write on external storage. The external devices are, classically, SD cards that are inserted into the phone. To retrieve the path of such external storage, you will have to use the Environment
class provided by the Andoid.OS
namespace, as shown by the following code:
Android.OS.Environment.GetExternalStoragePublicDirectory ();
Starting from there, you can write files to the external device.
As the method GetExternalStoragePublicDirectory
name suggests, the directory in which you will write is public. Therefore, in this case, files are accessible to end-users and other applications. You should not store critical data on external devices as they can be unmounted and files can be externally altered.
There are plenty of file types that you could find utility for such as JSON and XML. In this case I suggest you do not reinvent the wheel and, instead, use wonderful components/modules, such as Newtonsoft.Json
(http://www.nuget.org/packages/Newtonsoft.Json), which are available in the Xamarin library.
Have a look at the Json.net
component online at: http://components.xamarin.com/view/json.net/ to understand more about the Json.net
component.
52.15.112.69