9.6. Persisting Photos Tutorial and Projects (Optional)¶
Time Estimate: 90 minutes
In PaintPot projects, we added a Camera button to take a photo with the device’s Camera and use that photo as the Canvas’s background image. In this tutorial, we will learn how to save that photo to a database on the device, so that whenever the app is run, the photo can be retrieved from the database.
By using a database in this way we will turn the photo into an example of persistent data -- i.e., data that persists between different uses of the app. We will use App Inventor’s Tiny DB component to allow the app to save the user’s photos on the device.
Objectives: In this lesson you will:
9.6.2. Introduction: What is TinyDb?¶
Up until now, the data in our apps has been stored either in global variables or as the value of the properties of the app’s various components. For example, when you store a piece of text in a Label, that data is stored in the computer’s main memory, in its RAM — random access memory. And as we’ve learned, RAM is volatile, meaning that any data stored there will be destroyed when the app is exited.
By contrast, data stored in the computer’s long-term storage — e.g., on the phone’s flash drive — will persist as long as the app is kept on the device. There are various ways to store data permanently on a computer. For example, you could store it in a file, such as a document or image file. Another way to store persistent data is in a database. App Inventor provides us a very simple, easy-to-use database in its TinyDb component. Any data that we store in the TinyDb, will not disappear when the app is exited. Instead, it will persist between uses of the app -- even if you turn off the device.
Before working on incorporating TinyDb into our app, the following video provides a brief overview of this very important component.
9.6.3. Incorporating TinyDb into Paint Pot¶
To get started, click here to open App Inventor with the PaintPotTinyDbTemplate in a separate tab and follow along with the video tutorial. Once the template project opens use Save As to rename your project PaintPotTinyDb. Note: If the blocks don’t appear well in the Blocks Editor, right-click on the background and use the Arrange Vertically option.
If you prefer, you can follow the text version of this lesson.
In the projects below, you will extend this version of PaintPot to save multiple photos for the canvas background in a list in TinyDB. The simplest data abstraction in programming is a variable, but there are more complex data structures available in all programming languages. App Inventor has a data structure called list which allows the storage of multiple items under one name in memory. The items are indexed which means they are numbered from 1 to the length of the list. The Lists drawer contains all the blocks available for manipulating lists. We first create a global variable to hold a list which can be an empty list or a list of items using make a list:
In the projects below, you will use List blocks such as insert item into list and select random item from list.
In the AP CSP exam pseudode, lists are represented using square brackets [ ] like below. The assignment operator ← can be used to assign a list to a variable. The list items can be numbers or text which are called strings; strings are usually indicated by quotes "" to distinguish them from variables.
list ← [ "kitty.png", "android.png" ]
9.6.5. Creative Mini Projects¶
Now that you've learned the basics of using TinyDb, it's time to add some additional features and enhancements to the Paint Pot app. Working in pairs, implement each of the following enhancements.
- As we saw in the overview video, one can also store lists of data in TinyDb. So rather than just having a single photo to use as the Canvas background, we could have a selection of photos to choose from. As a first step, initialize a global variable for this list of backgrounds to the create empty list block from the Lists drawer. In the When Camera1.AfterPicture event handler, add the photo that's taken to that list using the add items to list block. Store the variable for the whole list in the TinyDb. Don't forget! You'll need a unique tag to associate with the list.
- If/else Algorithm. What about when the app starts up? This can be a little tricky because now you'll be retrieving a list of photos, rather than a single photo. (What should the default value be when you are retrieving a list from TinyDb?) So you can't assign the list as the background image. You could select a random item (photo) from the list and make that your background. But what if this is the first time the app runs? When the list is empty? This would be a good place for an if/else algorithm controlled by whether or not the list retrieved from the TinyDb is empty or not. To solve this problem, you'll have to look through the Lists drawer in the Blocks Editor for some useful functions to use.
- Add a ListPicker component to the app's user interface to let the user select the background image. Read more about the Listpicker component here. The ListPicker looks like a button but it displays a list of items to choose from. In its blocks, it has a BeforePicking and an AfterPicking event handler. One of the ListPicker properties is the Elements property which is the list of choices shown to the user. You can set this Elements property to your list of background photos in the BeforePicking event handler. Note that what will appear in the ListPicker are the file paths of the images, not the images themselves. There's no easy way around this. After the user has picked an element from the ListPicker, their choice will be in ListPicker1.Selection and can be put on the Canvas background.
9.6.7. Reflection: For Your Portfolio¶
Create a page named Persistent Photos Tutorial in your portfolio and give brief answers to the following questions:
- What does it mean to say that data is 'persistent'?
- What's the difference in terms of where data is located between data stored in a global variable and data stored in a database?
- When and how often does App Inventor's Screen1.Initialize block fire and what is its purpose?
- Include a screenshot of your if/else algorithm for retrieving photos from TinyDB.