Writing to and reading from text files in App Inventor programs

Update: When the program is run in AI2 Companion, it behaves differently than when run as a standalone “build” .apk app.

The updated tutorial explains where – and why – the files you create may appear to be hidden on the phone – how to find them and how to transfer the files to your PC.

An earlier blog post described how to store data using TinyDB so that an app’s data can persist between uses of the program, or even to share data between screens in a program.

Another way to save data is to write the data to a file on your Android device. App Inventor has introduced a File control that lets us write text data to a file and then read it back, later. As we will see, the File control is not the easiest thing to use but with some work, the control can be used to store data from our program into a file. (Once data is in a file, you could, hypothetically, email the file to yourself to read it on a computer, or transfer it from an Android to device to another computer using a USB cable and mounting the device as a simulated hard drive. But that is beyond the scope of this blog post!)

Let’s start our exploration of the File control in the Designer. Beneath the Palette heading, find the Storage item. Within Storage, find the File control. Drag and drop the File control on to your app. The control is placed below the user interface as it is an invisible control.

FileIOControl

 

After dragging the File control, you’ll see something like this at the bottom of the user interface Designer:

File1ControlThe real work begins over in the Blocks editor. For this example, we have just a few user interface components:

  • btnAddItem – when pressed, it writes some items out to a text file
  • btnTestFetch – when pressed, it starts the process of reading the data from the text file back into the program
  • txtBoxResult1 and txtBoxResult2 – a couple of text boxes that can be used to display the values read from the file.

In the Blocks editor, we will set up some blocks to write text to the file. We will start with a simple example:

FileIOSimpleEx

btnAddItem.Click is an event handler and you should already be familiar with the concept of event handlers. The new features are those in purple, which reference the File1 control. Assuming you are implementing this in your own app, you should find the File1 control, probably at the bottom of the list of Blocks, at the left side of the Blocks editor.

The first purple item above, AppendToFile, writes a piece of text to the file indicated at the filename component. Writing to the file is the easy part!

When our app’s TestFetch button is pressed, the code initiates a read operation by reference ReadFrom and giving it the name of the file to read the data from. But at this point, the data has not yet been read!

When the data has actually been read, an event occurs and we need to add an event handler for GotText to process the data that has been read in to the app.

In the example above, the original text is read back from the file and placed in an on screen text box to illustrate success.

Writing and reading a single line of text is easy. But writing and reading a series of data elements is a bit more complex. There are several possible ways to handle this but I have chosen to use the mechanism.

But before we get started, let’s add a piece of code to help us during development: let’s always start with a clean data file by deleting the old file (if any) first. We can do this by adding the following code to the screen’s Initialize event:

FileIOSimpleDelete

Find your screen’s name in the Blocks list and then click the mouse over the screen name. You should see the Initialize event handler appear in a pop up list – drag that initialize block over to the Blocks editing window.

Let us now take a look at writing a list – or list of lists to the text file. You’d best be familiar with lists (see volume 1 of my App Inventor 2: Tutorial) before starting on this.

FileIO-Lists

 

For this example, we want to store a typical name/address combination. This means storing several items for each individual record – in our example, we have two individuals but this could be easily expanded to support more.

The first block creates two lists (at far right) – one list per person to combine the name and address.

These two lists are converted to the “CSV” (comma separate values) format and the two CSV values lists are combined into a table. Think of this as being something like this:

  1. Alice Smith, 1234 Main St, Portlandia, USA
  2. Bob Smithy, 1234 Rural St, Portlandia, USA

Think of this as being like a spreadsheet with rows and columns, if you prefer. All those blue list processing blocks are converting our text input at right, into two CSV rows, combining those into a list, and then converting to a table. That’s a lot of work but its just a way of storing our more complex data into the file.

At the bottom block, the data read from the file is converted from text back in to table list format. And after this is done, individual list elements can be referenced. Since this table has two rows, index position 1 and index position 2 refer to first and second name records. Since each row is itself a list, we could also select the individual items from each name/address record if we wanted (but that is not shown in this example).

App Inventor’s new File control is helpful but remains cumbersome to use, as shown by the effort to read and write complex records.  It works only with text (which is how most of App Inventor works) and it reads the entire file all at once, rather than reading a line at at time. This limits the total size of the file that we can likely handle (maximum size is not known).

Where is testfile2.txt stored on your phone?

On my Nexus 5, there is a visible folder named AppInventor, and within that folder, there is a folder labeled data. This is where testfile2.txt is located.

This location also corresponds to /storage/emulated/0/AppInventor/data, a folder on the phone. You’ll need a file explorer app – or connect your phone to a PC using a USB cable and mount the phone as an external hard drive – to see the file structure on the phone.

To Learn More About App Inventor Databases and Files

My 322 page e-book provides extensive guidance on App Inventor databases and files, including TinyDB, TinyWeb, Fusion Tables and text files.

Learn about all my App Inventor guide books, including sample chapters – here!

  • App Inventor 2 Databases and Files (Volume 3 e-book)
    Step-by-step TinyDB, TinyWebDB, Fusion Tables and Files
    Buy from: Amazon, Google Books, Kobo Books

15 thoughts on “Writing to and reading from text files in App Inventor programs”

  1. I need some help. I used the exact code above in a program running on an Xperia Z2, but neither the append to file neither the save file where able to actually create a file in the phone memory. I really can’t find out what’s going wrong. Do you have any suggestions?

    1. My guess:
      1. The file is in the phone’s memory but in a different location than expected. I downloaded an app named “File Manager” (there are several like this) from the Google Play store and use that to look at the folders/files on the phone. I suspect you have already done that. Or mount the phone’s file storage as a hard drive, by connecting to a PC with a USB cable, which you probably already tried too.
      2. Or the App Inventor functionality has changed. I will be looking at file operations again soon and will see if they have made changes. There have been some updates recently, such as use of the new AI Companion.

      Ed

  2. Hi Ed,
    Sorry to bother you over the holidays but, the same thing is happening to me as Roberto.
    While connected to MIT AI2 wirelessly the File component works fine it saves my data to “/AppInventor/data/filename.txt” and I can read it no problem, but If I package the app to an .apk nothing happens, no file saved, no error message, nothing.
    I’ve used ES file explorer and can’t find any files with names I’ve used.
    If I type in the path “/AppInventor/data/myfilename.txt” into the packaged app it works, so maybe its a problem with the path?
    I hope you can help and anyway have a nice one Ed.
    Cheers
    Colin

    1. Hi Colin,
      I am out this weekend but i will look at that on Tuesday of the coming week. Your findings on this are interesting and suggest there is something not implemented properly by Appinventor as the code, obviously, should work the same in AI2 Companion or as a compiled .apk file.

      If file i/o does not work in the .apk file, there may be a work around. There used to be a code library in the Google Play store that can be used by Appinventor programs. This code library supports file read/write, and is accessed through the Start Activity block component. I suspect the library is still available – I just need to find it! One way or another, I think we can find a solution so this works!

      More in the next few days!

      Ed

      1. Some progress!

        IF the phone has an actual micro SD card installed, and IF the file name is prefaced with a forward slash “/”, then the file is created on the SD card in its root directly.

        Example filename:
        /testfile3.txt

        This works the same way in both AI2 Companion and as a built .apk file.

        If you change the filename to
        /download/testfile4.txt
        It is created and stored on the sdcard in the /download folder.

        I have also gotten this to work on the Nexus 5 and now know where the file is. Not yet sure how to copy it back to a Windows PC, though.

        Much progress has been made. I’ll be making a new blog post once I get this all sorted out! We will get this working for you!

        Ed

    2. Colin and Roberto,
      I do not yet have this solved – however, it appears the file has been created and retained on the phone – but where?

      I made a small app to create a file and write one line of text to the file. I ran one version using AI2 Companion and looked at the phone’s file using a File Manager app (on the phone). The file I created “testfile2.txt” was located inside the Appinventor/data directory. However, when I look at this phone’s file directory when plugging the phone over USB into a computer, the file “textfile2.txt” is not visible in the directory!

      I plugged the phone in to Windows – and the file is not there. I plugged into Mac OS X and used Android File Transfer to look at the Android file system on the phone and “textfile2.txt” is not visible there either.

      I went back to the File Manager app on the phone and it still sees the file.

      I created a separate test app and built it as an .apk file, installed that, and had the same result. This version creates a “textfile3.txt” file. I can run my test app and read the textfile3.txt into my program just fine, meaning it must exist somewhere.

      What I think is happening is that Android works with more than one kind of file system. Parts of the file structure are “partitioned” using a Windows FAT32 compatible file system – and this is visible when the device is plugged into to Windows or into Mac OS X (with the write software installed on Mac OS X). However, Android also uses a Linux-based filed system called EXT4 and this is, I think, not visible to Windows or Mac OS X.

      I think I can get an EXT4 driver for either my Windows or Mac computers and will check this out further.

      Ed

    3. Some additional info – I tried to run the AI2 companion version of my file i/o app on an old Android 2.2 phone that has an SD card slot – but no micro SD card installed.

      When I run the test code, it gives an error that it cannot access /mnt/sdcard/AppInventor/data/textfile2.txt – which is correct because on that phone, the SD card is not installed.

      I can not run the .apk version since all downloads go to the sdcard. I do have a spare micro SD card somewhere around. I have a hunch if I install that, this might actually run and the file may be hidden on it.

      I vaguely think that Android 2.2 may have used the FAT32 file system and did not have the EXT2, 3 or 4 file systems.

    1. Do you mean you want to copy a remote web site text to the phone? Or you want to create a bunch of html text files on your phone?

      Ed

    1. Mohammed,
      Am trying to think of a way to solve this … App Inventor itself cannot do a lot with Dropbox but there may be some ways to work with this.

      1. On Windows and Mac OS X, the Dropbox file transfer program runs in the background. As new files are added to the Dropbox, they are synchronized to and from the Dropbox server and your computer. I do not know if the Android Dropbox app works this way, but if it does, it may be possible to read and write files in the Android folder that holds the Dropbox file.

      2. There is way using the Sharing component (See Social | Sharing in the Palette) to hand a file to another “Sharing” app. The way this works is that Android apps register something called and “intent” – meaning a list of functions that they can provide other applications. Let’s say we have an app that would like to send an EMAIL message. You can use the Sharing component. This leads to Android displaying a list of applications that can “Share” items (Gmail is one of them, in this case). You select GMail (And even make it the default for future sharing) and you can pass to it a piece of text or an entire file. What I am thinking is that Sharing might also bring up the Android Dropbox app and you might be able to send a file to Dropbox for uploading to Dropbox. This does not solve the problem with getting or reading a file from Dropbox, but is a possible idea for the other direction.

      I will add this to my list of items to experiment with and see if I might come up with something later.

      Ed

Comments are closed.