Android Save and Retrieve Image Path From Database

In this post, I will show you how to save and retrieve image path from database in Android. Images are standard component of many software application. One of the most common use cases of image is to associate an image with an object so that each time the object is shown it is shown with its associated image. This object could be a user profile, an item in a list, etc. Whatever the item is, you want the same image of the user to show up whether you are showing the user in a listview or in a details view.

In this post, I will build a demo project showing a user profile. I will show how to obtain a picture of the user either from an image that already exists in the user’s device or if the user wants to take new image with the Android device camera. Once the image is obtained then we need to save this image path so we can reuse it later. This path can be saved in sharedPreference or can be save in Database and I will be showing here how to save it to a database. Here is what the completed demo application will look like.

This demo project uses the skeleton project that I shared in this post. Please visit that post to download the template if you want to follow along. For brevity I will not show all the lines of code required to achieve the above demo, however you can find the link to the full source code here.

This demo project shows a custom listview of customers showing their thumbnail to the right and their names and email addresses to the left. When you click on the row it will open up a Customer Details screen that shows the full image. And we actually use the same screen to create the customer and show the details. If this is a new customer, we show a blank screen and if it is an existing customer we show the customer details.

Customer Class
Before we can capture an image we have to define where we will save it. For this demo I save the image path as a field to the Customer object. So please go ahead and add a Customer.java file to the Models Package. Add the following fields to the Customer.java file:

1

2

3

4

5

6

7

8

9

10

11

publicclassCustomer{

privateintmId;

privateStringmName;

privateStringmEmailAddress;

privateStringmPhoneNumber;

privateStringmStreetAddress;

privateStringmCity;

privateStringmState;

privateStringmPostalCode;

privateStringmImagePath;

}

Notice the String field ImagePath, this is where we save the image path for the customer. Use your IDE to add getters and setters for the Customer class. Still in the Customer file, we need to add four methods to this class that will help us with displaying the images in the customer’s profile. Add the following files to the Customer class and ignore the red warnings for now.

HasImage method: this checks to see if the customer has an image,

1

2

3

4

publicbooleanhasImage(){

returngetImagePath()!=null&amp;&amp;!getImagePath().isEmpty();

}

GetThumbnail method: this gets thumbnail version of the customer’s image for display in say listview.

1

2

3

4

publicDrawable getThumbnail(Context context){

returngetScaledImage(context,128,128);

}

GetImage method: this gets the full size (rather bigger size) of the image

1

2

3

4

publicDrawable getImage(Context context){

returngetScaledImage(context,512,512);

}

GetScaledImage method: this is the method that actually gets the image and this is what the getThumbnail and getFullImage methods call into.

Notice the call to a method in FileUtils. In your Helper Package, please create a file called FileUtils.java. This file will hold a lot of the important code required to accomplish this use case. Once you add the FileUtils.java file, you can go ahead add this two methods:

// Calculate ratios of height and width to requested height and width.

finalintheightRatio=Math.round((float)height/(float)reqHeight);

finalintwidthRatio=Math.round((float)width/(float)reqWidth);

// Choose the smallest ratio as sample size value. This will guarantee a final image

// with both dimensions larger than or equal to the requested height and width.

inSampleSize=heightRatio&lt;widthRatio?heightRatio:widthRatio;

}

// Return sample size.

returninSampleSize;

}

I have commented the above code to provide explanation of what it is doing. It is simply following the Android recommended best practice for displaying images. With this we are done with the Customer class and next we move on to how to actually save this customer object to SQLite database.

Save Customer to SQLite Database
I created a package called Data, and in this package I added a file called DatabaseHelper.java. And just a reminder, I define all my literals as constants in a file Constants.java under the Helpers package. Here is the first part of the database file that creates the Customer table.

Below is the addCustomer SQL statement, for brevity see the Github repository for the rest of the SQL statements.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

publicLongaddCustomer(Customer customer){

Longret=null;

//Lock database for writing

synchronized(databaseLock){

//Get a writable database

SQLiteDatabase database=getWritableDatabase();

//Ensure the database exists

if(database!=null){

//Prepare the customer information that will be saved to the database

ContentValues values=newContentValues();

values.put(Constants.COLUMN_NAME,customer.getName());

values.put(Constants.COLUMN_EMAIL,customer.getEmailAddress());

values.put(Constants.COLUMN_PHONE,customer.getPhoneNumber());

values.put(Constants.COLUMN_CITY,customer.getCity());

values.put(Constants.COLUMN_STREET,customer.getStreetAddress());

values.put(Constants.COLUMN_STATE,customer.getState());

values.put(Constants.COLUMN_ZIP_CODE,customer.getPostalCode());

values.put(Constants.COLUMN_IMAGE_PATH,customer.getImagePath());

//Attempt to insert the client information into the transaction table

try{

ret=database.insert(TABLE_CUSTOMERS,null,values);

}catch(Exceptione){

Log.e(TAG,"Unable to add Customer to database "+e.getMessage());

}

//Close database connection

database.close();

}

}

returnret;

}

We are don with the database and next we need to create the layout files for adding and displaying customers.

Layout Files
Like I mentioned at the beginning, we are using the same layout file for both creating the customer and displaying the customer detail and here is the layout file for the Customer Details Fragment.

1

This layout allows us to capture basic information about the customer and you can customize as you fit for your app. Notice that the ImageButton widget, this is so that we can click event on the image. Since this tutorial is focusing on the image, I will ignore the other widgets in the screen mostly the EditTexts and focus on the ImageButton. The CustomerListFragment layout, simply contains a listView that shows the list of customer’s and here is the layout;

1

This listview needs a custom row to display the customers in the list, so below is the custom row layout that displays the customer’s image on the right and the name and email address on the left. I have named this layout file row_customer_list.xml and you will find in the source code.

1

With that we are done with the layout. Please look under the menu folder to get the menu files used for this project and all the drawables used are included in the source code.

Java Code
Below are the steps we want to accomplish in code now that we have the layout and the database setup

On start, show a blank customer list if there is no customer already added to the list

If the user touch the image button during add customer process, launch an Intent chooser

Notice that we attached an onClick event handler to the image button and when this event is triggered by clicking on the image, we call a method to handle choosing image for this customer’s profile. Since we want to give the user the option to either choose an existing image or take a new picture we actually need two Intents one for picking the image and one for taking a new image with the camera. We then merge the two Intents together into an IntentChoose intent like so:

Again, I have commented the code to provide visibility into what it is doing. The next important step is to get the data back from the intent when it come back. This could be very tricky and is a source of quite a few frustration expressed at StackOverflow. The challenge stems from how every device handle the location of the image. Luckily a group of people created a method at this Github repo that helps get the image path successfully on the most devices.

When the Intent completes, the onActivityResult is called and here is my code to handle the result.

Notice the call to getPath, that is very important because we need the actual String file path to save to the database otherwise we will not be able to get the image when we need it next time. And I got the method for that Paul Burkes aFileChooser.

Summary
That is it, you should now be able to select an image from anywhere in the device and save to the database associating it to one user.Points to Note

Remember to add the relevant permission to your manifest. I added READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions.

Remember to add use-feature android.hardware.camera

Remember to call onActivityResult on the Activity and return super so that the Fragment will have a chance to handle the onActivityResult.