Android platform provides several ways to store data in our application.
1. SQLite database
2. SharedPreferences etc
For our post, we will only work with SQLite database.
First and foremost, we need to understand what an SQLite database is?
SQLite database is an open source SQL database that stores data to a text file on a device. It executes SQL Commands to perform a set of functions, that is, create, read, update and delete operations.
On my previous post, I showed how to store data in SQLite database from edit text, retrieve and populate it in a listview. For this post, I will show the SQLite CRUD operations with images from gallery and text from EditText.
We need to understand this; images are stored in SQLite database as BLOB data type.
A BLOB is a large binary object that can hold a variable amount of data.
Note, we can only store images in the database as BLOB data type. We need to convert our image path to a bitmap then to bytes.
Also, note, storing image path to our database as a string is not a good way to save images to the SQLite database in Android programmatically.
I believe everybody reading through this tutorial, is an experienced programmer, so I will not show the procedures of creating a new project.
Then create a new project to demonstrate our tutorial.
Now let us lay out our interface to explain this android post. The following are the list of our project files.
list of our activity classes
Contact.java
dataAdapter.java
DatabaseHandler.java
MainActivity.java
list of our XML files
activity_main.xml
listcontacts.xml
activity_main.xml
This XML file provides the interface for selecting our images from the gallery or captured images. It contains the following widgets.
ImageView widget - to select our image from the gallery
Edittext widget- to key in text.
Listview widget - display the data from the database
save and display button - save button - to send the data to the database and display button - to populate the data to the listview
Entire activity_main.xml code
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView android:text="Profile"
android:layout_gravity="center"
android:textSize="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:onClick="buttonClicked"
android:id="@+id/pic"
android:src="@drawable/choose_up"/>
<EditText
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="@+id/txt1"
android:hint="Enter your first name"
android:layout_margin="10dp"/>
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:gravity="center"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="buttonClicked"
android:id="@+id/save"
android:text="Save"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="buttonClicked"
android:id="@+id/display"
android:text="Display"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/list1"/>
</LinearLayout>
</LinearLayout>
listcontacts.xml
This XML file Lays out the interface for the items of the listview. Determines how the populated data is displayed from the SQLite database to the listview.
Entire listcontacts.xml code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:id="@+id/txtViewer"
/>
<ImageView
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="@+id/imgView"/>
</LinearLayout>
MainActivity.java
Entire code.
package info.whats_online.sqlitedbwithimages;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
public class MainActivity extends Activity {
private EditText fname;
private ImageView pic;
private DatabaseHandler db;
private String f_name;
private ListView lv;
private dataAdapter data;
private Contact dataModel;
private Bitmap bp;
private byte[] photo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Instantiate database handler
db=new DatabaseHandler(this);
lv = (ListView) findViewById(R.id.list1);
pic= (ImageView) findViewById(R.id.pic);
fname=(EditText) findViewById(R.id.txt1);
}
public void buttonClicked(View v){
int id=v.getId();
switch(id){
case R.id.save:
if(fname.getText().toString().trim().equals("")){
Toast.makeText(getApplicationContext(),"Name edit text is empty, Enter name", Toast.LENGTH_LONG).show();
} else{
addContact();
}
break;
case R.id.display:
ShowRecords();
break;
case R.id.pic:
selectImage();
break;
}
}
public void selectImage(){
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, 2);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode) {
case 2:
if(resultCode == RESULT_OK){
Uri choosenImage = data.getData();
if(choosenImage !=null){
bp=decodeUri(choosenImage, 400);
pic.setImageBitmap(bp);
}
}
}
}
//COnvert and resize our image to 400dp for faster uploading our images to DB
protected Bitmap decodeUri(Uri selectedImage, int REQUIRED_SIZE) {
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o);
// The new size we want to scale to
// final int REQUIRED_SIZE = size;
// Find the correct scale value. It should be the power of 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE) {
break;
}
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2);
}
catch (Exception e){
e.printStackTrace();
}
return null;
}
//Convert bitmap to bytes
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
private byte[] profileImage(Bitmap b){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 0, bos);
return bos.toByteArray();
}
// function to get values from the Edittext and image
private void getValues(){
f_name = fname.getText().toString();
photo = profileImage(bp);
}
//Insert data to the database
private void addContact(){
getValues();
db.addContacts(new Contact(f_name, photo));
Toast.makeText(getApplicationContext(),"Saved successfully", Toast.LENGTH_LONG).show();
}
//Retrieve data from the database and set to the list view
private void ShowRecords(){
final ArrayList<Contact> contacts = new ArrayList<>(db.getAllContacts());
data=new dataAdapter(this, contacts);
lv.setAdapter(data);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
dataModel = contacts.get(position);
Toast.makeText(getApplicationContext(),String.valueOf(dataModel.getID()), Toast.LENGTH_SHORT).show();
}
});
}
}
MainActivity.java functions
selectImage() -navigates to the gallery on the image button click action.
onActivityResult() -returns the selected image path.
decodeUri() -converts the image path to a bitmap image. Also, it has resize function to reduce the size of selected image thus lessen the time of sending the image to the SQLite database.
getValues() - gets the values from our imageview and our edittext widgets
ShowRecords() - Populates the retrieved images and texts to the listview
addContact() - Stores our bitmap image as byte data type and text as a string in the database.
profileImage() - Convert our bitmap image to byte array data type.
Note that, retrieving image string from the database and display it in listview might not work. We are only storing our images as BLOB data type that is why we are converting the images to byte data type.
Contact.Java
Contains the set and get methods to set the values of our attributes and retrieve the values of our attributes
Entire code
package info.whats_online.sqlitedbwithimages;
public class Contact {
//private variables
int _id;
String _fname;
byte[] _img;
// Empty constructor
public Contact(){
}
// constructor
public Contact(int id, String fname, byte[] img){
this._id = id;
this._fname = fname;
this._img = img;
}
// constructor
public Contact(String fname, byte[] img){
this._fname = fname;
this._img = img;
}
// getting ID
public int getID(){
return this._id;
}
// setting id
public void setID(int id){
this._id = id;
}
// getting first name
public String getFName(){
return this._fname;
}
// setting first name
public void setFName(String fname){
this._fname = fname;
}
//getting profile pic
public byte[] getImage(){
return this._img;
}
//setting profile pic
public void setImage(byte[] b){
this._img=b;
}
}
DatabaseHandler.java
Performs all CRUD operations, that is, Insert, Read, Update, Delete.
It has the methods to insert data to the table contact, select data, update and delete data from the table.
Entire DatabaseHandler.java code
package info.whats_online.sqlitedbwithimages;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.ArrayList;
import java.util.List;
/**
* Created by sada on 1/31/2017.
*/
public class DatabaseHandler extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "contactsManager";
// Contacts table name
private static final String TABLE_CONTACTS = "contacts";
// Contacts Table Columns names
private static final String KEY_ID = "id";
private static final String KEY_FNAME = "fname";
private static final String KEY_POTO = "poto";
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
//Create tables
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_TABLE_CONTACTS="CREATE TABLE " + TABLE_CONTACTS + "("
+ KEY_ID +" INTEGER PRIMARY KEY,"
+ KEY_FNAME +" TEXT,"
+ KEY_POTO +" BLOB" + ")";
db.execSQL(CREATE_TABLE_CONTACTS);
}
// Upgrading database
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);
// Create tables again
onCreate(db);
}
/**
* All CRUD(Create, Read, Update, Delete) Operations
*/
//Insert values to the table contacts
public void addContacts(Contact contact){
SQLiteDatabase db = this.getReadableDatabase();
ContentValues values=new ContentValues();
values.put(KEY_FNAME, contact.getFName());
values.put(KEY_POTO, contact.getImage() );
db.insert(TABLE_CONTACTS, null, values);
db.close();
}
/**
*Getting All Contacts
**/
public List<Contact> getAllContacts() {
List<Contact> contactList = new ArrayList<Contact>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_CONTACTS;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Contact contact = new Contact();
contact.setID(Integer.parseInt(cursor.getString(0)));
contact.setFName(cursor.getString(1));
contact.setImage(cursor.getBlob(2));
// Adding contact to list
contactList.add(contact);
} while (cursor.moveToNext());
}
// return contact list
return contactList;
}
/**
*Updating single contact
**/
public int updateContact(Contact contact, int id) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_FNAME, contact.getFName());
values.put(KEY_POTO, contact.getImage());
// updating row
return db.update(TABLE_CONTACTS, values, KEY_ID + " = ?",
new String[] { String.valueOf(id) });
}
/**
*Deleting single contact
**/
public void deleteContact(int Id) {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_CONTACTS, KEY_ID + " = ?",
new String[] { String.valueOf(Id) });
db.close();
}
}
dataAdapter.java
Contains the list adapter to display our data using a listview.
Remember, our image was saved as bytes to we need to convert our byte array image to a bitmap image.
Entire dataAdapter.java
package info.whats_online.sqlitedbwithimages;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class dataAdapter extends ArrayAdapter<Contact>{
Context context;
ArrayList<Contact> mcontact;
public dataAdapter(Context context, ArrayList<Contact> contact){
super(context, R.layout.listcontacts, contact);
this.context=context;
this.mcontact=contact;
}
public class Holder{
TextView nameFV;
ImageView pic;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Contact data = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
Holder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
viewHolder = new Holder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.listcontacts, parent, false);
viewHolder.nameFV = (TextView) convertView.findViewById(R.id.txtViewer);
viewHolder.pic = (ImageView) convertView.findViewById(R.id.imgView);
convertView.setTag(viewHolder);
} else {
viewHolder = (Holder) convertView.getTag();
}
viewHolder.nameFV.setText("First Name: "+data.getFName());
viewHolder.pic.setImageBitmap(convertToBitmap(data.getImage()));
// Return the completed view to render on screen
return convertView;
}
//get bitmap image from byte array
private Bitmap convertToBitmap(byte[] b){
return BitmapFactory.decodeByteArray(b, 0, b.length);
}
}
Thanks for your visit to our site. Subscribe to our newsletter to get the latest updates directly to your mailbox.
how to delete the images??
ReplyDelete