-1

I'm new to android and using the a tutorial to teach myself about SQLite databases in apps.

Currently, I'm having a problem with how to deal with images in SQLite and showing it in ListView with TextView description... These are my classes:

DatabaseHelper

public class DatabaseHelper extends SQLiteOpenHelper {

 // Table Name
 public static final String TABLE_NAME = "COUNTRIES";

 // Table columns
 public static final String _ID = "_id";
 public static final String SUBJECT = "subject";
 public static final String DESC = "description";
 public static final String KEY_IMAGE = "image";

 // Database Information
 static final String DB_NAME = "JOURNALDEV_COUNTRIES.DB";

 // database version
 static final int DB_VERSION = 5;

 // Creating table query
 private static final String CREATE_TABLE = "create table " + TABLE_NAME + "(" + _ID
         + " INTEGER PRIMARY KEY AUTOINCREMENT, " + SUBJECT + " TEXT NOT NULL, " + DESC + " TEXT," +
         KEY_IMAGE + " BLOB);";

 public DatabaseHelper(Context context) {
     super(context, DB_NAME, null, DB_VERSION);
 }

 @Override
 public void onCreate(SQLiteDatabase db) {
     db.execSQL(CREATE_TABLE);
 }

 @Override
 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
     db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
     onCreate(db);
 }

 public void insertBitmap(Bitmap bm)  {

     // Convert the image into byte array
     ByteArrayOutputStream out = new ByteArrayOutputStream();
     bm.compress(Bitmap.CompressFormat.JPEG, 100, out);
     byte[] buffer=out.toByteArray();
     // Open the database for writing
     SQLiteDatabase db = this.getWritableDatabase();
     // Start the transaction.
     db.beginTransaction();
     ContentValues values;

     try
     {
         values = new ContentValues();
         values.put("image", buffer);
         // Insert Row
         long i = db.insert(TABLE_NAME, null, values);
         Log.i("Insert", i + "");
         // Insert into database successfully.
         db.setTransactionSuccessful();

     }
     catch (SQLiteException e)
     {
         e.printStackTrace();

     }
     finally
     {
         db.endTransaction();
         // End the transaction.
         db.close();
         // Close database
     }
 }

 public Bitmap getBitmap(int id){
     Bitmap bitmap = null;
     // Open the database for reading
     SQLiteDatabase db = this.getReadableDatabase();
     // Start the transaction.
     db.beginTransaction();

     try
     {
         String selectQuery = "SELECT * FROM "+ TABLE_NAME+" WHERE id = " + id;
         Cursor cursor = db.rawQuery(selectQuery, null);
         if(cursor.getCount() >0)
         {
             while (cursor.moveToNext()) {
                 // Convert blob data to byte array
                 byte[] blob = cursor.getBlob(cursor.getColumnIndex("image"));
                 // Convert the byte array to Bitmap
                 bitmap= BitmapFactory.decodeByteArray(blob, 0, blob.length);

             }

         }
         db.setTransactionSuccessful();

     }
     catch (SQLiteException e)
     {
         e.printStackTrace();

     }
     finally
     {
         db.endTransaction();
         // End the transaction.
         db.close();
         // Close database
     }
     return bitmap;

 } }

DatabaseManager

public class DBManager {

  private DatabaseHelper dbHelper;

 private Context context;

 private SQLiteDatabase database;

 public DBManager(Context c) {
     context = c;
 }

 public DBManager open() throws SQLException {
     dbHelper = new DatabaseHelper(context);
     database = dbHelper.getWritableDatabase();
     return this;
 }

 public void close() {
     dbHelper.close();
 }

 public void insert(String name, String desc, String image) {
     ContentValues contentValue = new ContentValues();
     contentValue.put(DatabaseHelper.SUBJECT, name);
     contentValue.put(DatabaseHelper.DESC, desc);
     contentValue.put(DatabaseHelper.KEY_IMAGE, image);
     database.insert(DatabaseHelper.TABLE_NAME, null, contentValue);
 }

 public Cursor fetch() {
     String[] columns = new String[] { DatabaseHelper._ID, DatabaseHelper.SUBJECT, DatabaseHelper.DESC,
             DatabaseHelper.KEY_IMAGE };
     Cursor cursor = database.query(DatabaseHelper.TABLE_NAME, columns, null, null, null, null, null);
     if (cursor != null) {
         cursor.moveToFirst();
     }
     return cursor;
 }

 public int update(long _id, String name, String desc, String image) {
     ContentValues contentValues = new ContentValues();
     contentValues.put(DatabaseHelper.SUBJECT, name);
     contentValues.put(DatabaseHelper.DESC, desc);
     contentValues.put(DatabaseHelper.KEY_IMAGE, image);
     int i = database.update(DatabaseHelper.TABLE_NAME, contentValues, DatabaseHelper._ID + " = " + _id, null);
     return i;
 }

 public void delete(long _id) {
     database.delete(DatabaseHelper.TABLE_NAME, DatabaseHelper._ID + "=" + _id, null);
 }

 }

CountryListActivity

public class CountryListActivity extends ActionBarActivity {

 private DBManager dbManager;

 private ListView listView;

 private SimpleCursorAdapter adapter;


 final String[] from = new String[] {
         DatabaseHelper.SUBJECT, DatabaseHelper.DESC, DatabaseHelper.KEY_IMAGE };

 final int[] to = new int[] { R.id.title, R.id.desc, R.id.ivSlika };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);

     setContentView(R.layout.fragment_emp_list);

     dbManager = new DBManager(this);
     dbManager.open();
     Cursor cursor = dbManager.fetch();

     listView = (ListView) findViewById(R.id.list_view);
     listView.setEmptyView(findViewById(R.id.empty));

     adapter = new SimpleCursorAdapter(this, R.layout.activity_view_record, cursor, from, to, 0);
     adapter.notifyDataSetChanged();

     listView.setAdapter(adapter);

     // OnCLickListiner For List Items
     listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long viewId) {
             //TextView idTextView = (TextView) view.findViewById(R.id.id);
             TextView titleTextView = (TextView) view.findViewById(R.id.title);
             TextView descTextView = (TextView) view.findViewById(R.id.desc);
             ImageView slikaImageView = (ImageView) findViewById(R.id.ivSlika);

             //String id = idTextView.getText().toString();
             String title = titleTextView.getText().toString();
             String desc = descTextView.getText().toString();
             String image = slikaImageView.toString();

             //ByteArrayOutputStream blob = new ByteArrayOutputStream();
             //byte[] bitmapdata = blob.toByteArray();
             //Bitmap bm = BitmapFactory.decodeByteArray(bitmapdata, 0, bitmapdata.length);

             Intent modify_intent = new Intent(getApplicationContext(), ModifyCountryActivity.class);
             modify_intent.putExtra("title", title);
             modify_intent.putExtra("desc", desc);
             //modify_intent.putExtra("id", id);
             modify_intent.putExtra("image", image);


             startActivity(modify_intent);
         }
     });
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
     getMenuInflater().inflate(R.menu.main, menu);
     return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {

     int id = item.getItemId();
     if (id == R.id.add_record) {

         Intent add_mem = new Intent(this, AddCountryActivity.class);
         startActivity(add_mem);

     }
     return super.onOptionsItemSelected(item);
 }

 }

I've tried putting the image into ListView, however it don't not appear to be working as the ListView only shows text. I've tried using the above code, but it did not work.

What should I do to display an image in ListView and also save it in SQLite, so that reappears after the app is restarted?

Thanks!

Kuffs
  • 35,581
  • 10
  • 79
  • 92
Subject
  • 7
  • 1
  • 3
  • No, please, no. You **MUSTN'T** store images in database. Store it where ever you want but `database` and `sharedpreferences` –  Ekalips Jan 20 '17 at 15:35
  • Don't store images in database. Store images in your app's private storage and store their paths in the database table. 2nd Use a custom adaptor to show images in `ListView` – Sharp Edge Jan 20 '17 at 15:37
  • @SharpEdge can you help me correct my code? – Subject Jan 20 '17 at 16:36

1 Answers1

0

First of all, you shouldn't store images in a database. You should store images as files in your app's directory or cache, and store the URIs to those files in your database. Or include them in your app as resources.

Secondly, where do your images come from? Are they something generated by the app itself or you download them from your server? If it's the latter, then you should look into a library to help you handle that, something like Picasso would do nicely.

Finaly, don't make your life harder by using ListView. Look into RecyclerView as it's a better API.

vkislicins
  • 3,331
  • 3
  • 32
  • 62
  • Hi vkislicins, could i quickly ask regarding first of all of your answer above, what about encoding image to base64 and storing the string in database? Is that something ok to do? – chirag90 Jan 20 '17 at 15:54
  • 1
    hey @chirag90. Is there a reason why you'd like to do that? Base64 encoding doesn't change the fact that you're storing a file representation in the db. In my opinion - store a reference, not a file. You don't want to read/write too much data to/from your database. Also, you don't want your database to be too bloated as it's normally backed up by Android. – vkislicins Jan 20 '17 at 15:59
  • Hi, no that makes perfect sense its just something that i wanted to know. Thanks for explaining. – chirag90 Jan 20 '17 at 16:00
  • @vkislicins ok, could you help me make changes in the code, regarding not saving images in the database? – Subject Jan 20 '17 at 16:07
  • @vkislicins the images are in the res/drawable folder – Subject Jan 20 '17 at 16:07
  • @Subject I'm not sure what you're trying to do. It looks like you're passing an image as a string inside an intent? What's the purpose of that? To open a details view from a list? You could possibly store your references in an array in XML, then pass on the index of the clicked item, retrieving the required image from resources in the next activity. Have a look here: http://stackoverflow.com/questions/6945678/storing-r-drawable-ids-in-xml-array – vkislicins Jan 20 '17 at 17:12