Android Database to Array - java

I'm entirely new to Android Java, especially database linkage. So far I've got this, which all seems to work, I just now need to get the database values from the database to an array.
package com.example.sleepertrain5;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHelper extends SQLiteOpenHelper{
private static String DB_PATH = "/sleepertrain5/assets";
private static String DB_NAME="info2.sqlite";
private SQLiteDatabase myDatabase;
private final Context myContext;
public DataBaseHelper(Context context){
super(context, DB_NAME, null, 1);
this.myContext=context;
}
public void createDataBase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist){
//nothing needs done
}else{
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e){
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//no databases they don't exist
}
if (checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
private void copyDataBase() throws IOException{
InputStream myInput = myContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH +DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length=myInput.read(buffer))>0){
myOutput.write(buffer,0,length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException{
//Open database
String myPath = DB_PATH + DB_NAME;
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
public synchronized void close(){
if(myDatabase != null)
myDatabase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
How would I go about reading from this into an array? I'm struggling to make sense of this at the moment, so any help would be fantastic.
EDIT: The plan is to read the data, which is coordinates and names, into the array, which I can then use later to draw markers onto a GoogleMap. GoogleMap is all set up and I think I know what I'm doing from there, but this is the part I fall down on. The array would have to be multidimensional.

Ok, so the easiest way to work with SQLite in my opinion is using this three-class approach. I've read through a few tutorials and neither really did the trick for me....
So, here we go.
Table definition
package com.test.sqlite;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
public class ContactTable
{
//key identifiers / column names
public static final String KEY_ROWID = "_id";
public static final String KEY_NAME = "name";
public static final String KEY_URI = "uri";
public static final String TABLE_NAME = "contacts";
//useful stuff
public static final String[] TABLE_COLUMNS = { KEY_ROWID, KEY_NAME, KEY_URI }; //public makes it more useful
private static final String[] TABLE_COLTYPES = { "integer primary key autoincrement", "text not null", "text not null" };
// Database creation SQL statement in lazy-pretty version
private static final String TABLE_CREATE = "create table " + TABLE_NAME + "("
+ TABLE_COLUMNS[0] + " " + TABLE_COLTYPES[0] + ","
+ TABLE_COLUMNS[1] + " " + TABLE_COLTYPES[1] + ","
+ TABLE_COLUMNS[2] + " " + TABLE_COLTYPES[2] + ");";
private static final String LOGTAG = "ContactTable";
public static void onCreate(SQLiteDatabase database)
{
database.execSQL(TABLE_CREATE);
}
public static void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
{
Log.w(LOGTAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data");
database.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(database);
}
public static void scratch(SQLiteDatabase database)
{
database.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
database.execSQL(TABLE_CREATE);
}
}
Now that we have set that up, we need Database Helper class, to ease the use of it.
The helper class
package com.test.sqlite;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class ContactDBHelper extends SQLiteOpenHelper
{
// 'main' package name
private static final String PACKAGE_NAME = "com.test.demo";
private static final String DATABASE_PATH = "/data/data/" + PACKAGE_NAME + "/databases/";
private static final String DATABASE_NAME = "contactdata";
private static final int DATABASE_VERSION = 1;
private Context myContext;
public ContactDBHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
myContext = context;
}
// Method is called during creation of the database
#Override
public void onCreate(SQLiteDatabase database)
{
ContactTable.onCreate(database);
}
// Method is called during an upgrade of the database,
// e.g. if you increase the database version
#Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
{
ContactTable.onUpgrade(database, oldVersion, newVersion);
}
public void scratch(SQLiteDatabase database)
{
ContactTable.scratch(database);
}
/**
* Creates a empty database on the system and rewrites it with your own
* database.
* */
public void createDataBase() throws IOException
{
boolean dbExist = checkDataBase();
if (dbExist)
{
// do nothing - database already exist
} else
{
// By calling this method and empty database will be created into
// the default system path
// of your application so we are gonna be able to overwrite that
// database with our database.
File dirFile = new File(DATABASE_PATH);
if (!dirFile.exists())
{
dirFile.mkdir();
}
this.getReadableDatabase();
try
{
copyDataBase();
} catch (IOException e)
{
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each
* time you open the application.
*
* #return true if it exists, false if it doesn't
*/
private boolean checkDataBase()
{
SQLiteDatabase checkDB = null;
try
{
String myPath = DATABASE_PATH + DATABASE_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e)
{
// database does't exist yet.
}
if (checkDB != null) checkDB.close();
return checkDB != null ? true : false;
}
/**
* Copies your database from your local assets-folder to the just created
* empty database in the system folder, from where it can be accessed and
* handled. This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException
{
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DATABASE_NAME);
// Path to the just created empty db
String outFileName = DATABASE_PATH + DATABASE_NAME;
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0)
{
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
/*
public void openDataBase() throws SQLException
{
// Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
*/
}
And finally, the adapter, which totally does what you want.
DatabaseAdapter
package com.test.sqlite;
import java.util.ArrayList;
import com.test.demo.Contact;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import static com.test.sqlite.ContactTable.*; //contains database fields
public class ContactDBAdapter
{
private Context context;
private SQLiteDatabase db;
private ContactDBHelper dbHelper;
public ContactDBAdapter(Context context)
{
this.context = context;
}
public synchronized ContactDBAdapter open() throws SQLException
{
dbHelper = new ContactDBHelper(context);
db = dbHelper.getWritableDatabase();
return this;
}
public synchronized void close()
{
dbHelper.close();
}
/**
* Create a new Contact entry. If the entry is successfully created return the new
* rowId for that note, otherwise return a -1 to indicate failure.
*/
public long createRow(Contact contact)
{
ContentValues values = createContentValue(contact);
return db.insert(TABLE_NAME, null, values);
}
/**
* Update a row / entry
*/
public boolean updateRow(long rowIndex, Contact contact)
{
ContentValues values = createContentValue(contact);
return db.update(TABLE_NAME, values, KEY_ROWID + "=" + rowIndex, null) > 0;
}
/**
* Deletes a row
*/
public boolean deleteRow(long rowIndex)
{
return db.delete(TABLE_NAME, KEY_ROWID + "=" + rowIndex, null) > 0;
}
public void deleteAllRows()
{
for(int i = 0; i < fetchAllEntries().getCount(); i++)
deleteRow(i);
}
/**
* Return a Cursor over the list of all Contacts in the database
*
* #return Cursor over all contacts
*/
public Cursor fetchAllEntries()
{
return db.query(TABLE_NAME, TABLE_COLUMNS, null, null, null, null, null);
}
/**
* Return a Cursor positioned at the defined Contact
*/
public Cursor fetchEntry(long rowIndex) throws SQLException
{
Cursor mCursor = db.query(true, TABLE_NAME, TABLE_COLUMNS, KEY_ROWID + "=" + rowIndex, null, null, null, null, null);
if (mCursor != null)
{
mCursor.moveToFirst();
}
return mCursor;
}
/**
* Fetch all entries and rebuild them as Contact objects in an ArrayList.
* If no results are found, an empty list is returned.
*
* #return ArrayList of Contacts
*/
public ArrayList<Contact> fetchAllContacts()
{
ArrayList<Contact> res = new ArrayList<Contact>();
Cursor resultSet = fetchAllEntries();
if (resultSet.moveToFirst() != false)
for(int i = 0; i < resultSet.getCount(); i++)
{
String name = resultSet.getString(resultSet.getColumnIndex(KEY_NAME));
String URI = resultSet.getString(resultSet.getColumnIndex(KEY_URI));
Contact c = new Contact(name, URI);
res.add(c);
if(resultSet.moveToNext() == false)
break;
}
resultSet.close();
return res;
}
public synchronized void reflectWith(ArrayList<Contact> contacts)
{
// deleteAllRows();
dbHelper.scratch(db);
contacts.trimToSize();
//empty contact
Contact empty = new Contact();
empty.empty();
for(Contact c : contacts)
{
if(!c.getName().equals(empty.getName()))
createRow(c); //if not empty, add it
}
}
private ContentValues createContentValue(Contact contact)
{
ContentValues values = new ContentValues();
values.put(KEY_NAME, contact.getName());
values.put(KEY_URI, contact.getURI());
return values;
}
}
this is how it's used:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
dbAdapter = new ContactDBAdapter(getApplicationContext());
dbAdapter.open();
setContentView(R.layout.main);
// list stuff
contacts = new ArrayList<Contact>();
contacts = dbAdapter.fetchAllContacts();
//empty placeholders
if (contacts.size() < 5) for (int i = 0; i < 5 - contacts.size(); i++)
{
Contact c = new Contact();
c.empty();
contacts.add(c);
}
// contacts.addAll(dbAdapter.fetchAllContacts());
...
}
If you have questions, do ask.

Android uses SQLite database and SQLite query syntax for database accessing.
For querying the database directly through the SQLiteDatabase db variable you can do:
String table = CONTACT_TABLE;
String columns = {CONTACT_COLUMN_NAME};
String selection = CONTACT_COLUMN_NAME + "=" + MY_NAME;
String[] selectionArgs = {"wangyif2"};
Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null, null);
This will return you a Cursor object, which you can understand as an iterator that contains all the result matching your query. You can then step through the cursor like you would with any array that is converted to an iterator.
c.moveToFirst();
while (!c.isAfterLast())
{
arr[i] = cur.getString(0);
i++;
c.moveToNext();
}

Related

Querying already exsiting database returns empty cursor

I'm not very familiar with sql but what I'm am simply trying to do is get two values from an already created database file."Balance" and "VoucherBalance". While I attempt to query the database I get either get back an empty cursor when I add the third and forth params to the query method, or if I leave third and forth params as null I get back a count of 1 which is just the names of the two columns I'm trying to acquire.
Why am I not getting the values when I am specifying which ones I want?
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.widget.Toast;
import java.util.Arrays;
public class DataBaseReader extends SQLiteOpenHelper
{
private static final String TAG = "DataBaseReader";
private static String DB_PATH = "/data/data/PACKAGENAME/databases/DATABAENAME.db";
private static String DB_NAME = "TABLENAME";
private SQLiteDatabase database;
public double balance;
public int voucher;
private final Context myContext;
public String text = "";
public DataBaseReader(Context context)
{
super(context, DB_NAME, null, 1);
this.myContext = context;
}
public void getWireAccountBalance()
{
String[] projection = {DatabaseContract.Database.COLUMN_BALANCE, DatabaseContract.Database.COLUMN_VOUCHER};
String[] selectionArgs = {"Balance", "VoucherBalance"};
String selection = DatabaseContract.Database.COLUMN_BALANCE + "=?" + " AND " + DatabaseContract.Database.COLUMN_VOUCHER + "=?";
SQLiteDatabase db = SQLiteDatabase.openDatabase(DB_PATH, null, SQLiteDatabase.OPEN_READONLY);
Cursor cursor = db.query(DatabaseContract.Database.TABLE_NAME, projection, selection, selectionArgs, null, null, null);
Log.d(TAG, "Cursor count is " + String.valueOf(cursor.getCount()));
text = Arrays.toString(cursor.getColumnNames());
Toast.makeText(myContext, text, Toast.LENGTH_LONG).show();
if (cursor.moveToFirst())
{
while (!cursor.moveToNext())
{
balance = cursor.getFloat(cursor.getColumnIndex(DatabaseContract.Database.COLUMN_BALANCE));
voucher = cursor.getInt(cursor.getColumnIndex(DatabaseContract.Database.COLUMN_VOUCHER));
}
} else
{
Log.d(TAG, "Cursor count is " + String.valueOf(cursor.getCount()));
}
}
#Override
public synchronized void close()
{
super.close();
if (database != null)
{
close();
}
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase)
{
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1)
{
}
}
Using moveTofirst moves to the first row, you then use moveToNext, which will return false (when there is just the one row), skipping the first row.
I'd suggest using :-
while(cursor.moveToNext()) {
balance = cursor.getFloat(cursor.getColumnIndex(DatabaseContract.Database.COLUMN_BALANCE));
voucher = cursor.getInt(cursor.getColumnIndex(DatabaseContract.Database.COLUMN_VOUCHER));
}
instead of :-
if (cursor.moveToFirst())
{
while (!cursor.moveToNext())
{
balance = cursor.getFloat(cursor.getColumnIndex(DatabaseContract.Database.COLUMN_BALANCE));
voucher = cursor.getInt(cursor.getColumnIndex(DatabaseContract.Database.COLUMN_VOUCHER));
}
} else
{
Log.d(TAG, "Cursor count is " + String.valueOf(cursor.getCount()));
}

android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database- Logic issue in application

I am learning android yet and not expert. I think I have some logic issue in handle my sqllite database. Let me explain what I am doing and what I am getting.
I have one application of quotes. I am providing local database as well online. I have included database file in Assets and copying database from it during first time when user open application from splash screen. After that I am checking last author and last quote number of local database which are stored in user's device and comparing with online database. If there new data in online then I am downloading and storing it in splash screen.
Now my splash screen code for do same is like below
DAO database=DAO.getInstance(this);
int lastAuthor =database.getLastAuthor();
String updatesUrl = constant.MainUrl + String.valueOf(lastAuthor)+ "/" + String.valueOf(lastQuote);
My DAO class is looking like this
public class DAO {
private SQLiteDatabase database;
private DBHandler dbHandler;
private static final String TABLE_QUOTES = "quotes";
private static final String TABLE_AUTHORS = "authors";
private static final String TABLE_SETTINGS = "settings";
private static final String QU_ID = "_quid";
private static final String QU_TEXT = "qu_text";
private static final String QU_AUTHOR = "qu_author";
private static final String QU_FAVORITE = "qu_favorite";
private static final String QU_TIME = "qu_time";
private static final String AU_NAME = "au_name";
private static final String AU_PICTURE = "au_picture";
private static final String AU_PICTURE_SDCARD = "au_picture_sdcard";
private static final String AU_WEB_ID = "au_web_id";
private static DAO dBObject;
private final Object lockObj=new Object();
public static DAO getInstance(Context context){
if(dBObject==null)dBObject=new DAO(context);
return dBObject;
}
private DAO(Context context) {
synchronized (lockObj) {
dbHandler = new DBHandler(context);
try {
dbHandler.createDataBase();
} catch (IOException e) {
e.printStackTrace();
}
dbHandler.openDataBase();
open();
}
}
public int getLastAuthor() {
String query = "SELECT " + AU_WEB_ID + " FROM " + TABLE_AUTHORS
+ " ORDER BY " + AU_WEB_ID + " DESC LIMIT 1";
Cursor cursor = database.rawQuery(query, null);
cursor.moveToFirst();
int tmp = cursor.getInt(cursor.getColumnIndex(AU_WEB_ID));
cursor.close();
return tmp;
}
// ==============================================================================
public int getLastQuote() {
String query = "SELECT " + QU_ID + " FROM " + TABLE_QUOTES
+ " ORDER BY " + QU_ID + " DESC LIMIT 1";
Cursor cursor = database.rawQuery(query, null);
cursor.moveToFirst();
int tmp = cursor.getInt(cursor.getColumnIndex(QU_ID));
cursor.close();
return tmp;
}
// ==============================================================================
public void addAuthor(String au_name, String au_picture, int au_web_id) {
open();
ContentValues v = new ContentValues();
v.put(AU_NAME, au_name);
v.put(AU_PICTURE, au_picture);
v.put(AU_PICTURE_SDCARD, 1);
v.put(AU_WEB_ID, au_web_id);
database.insert(TABLE_AUTHORS, null, v);
}
// ==============================================================================
public void addQuote(String qu_text, int qu_author, int _quid, String qu_time) {
open();
ContentValues v = new ContentValues();
v.put(QU_TEXT, qu_text);
v.put(QU_AUTHOR, qu_author);
v.put(QU_FAVORITE, "0");
v.put(QU_ID, _quid);
v.put(QU_TIME, qu_time);
database.insert(TABLE_QUOTES, null, v);
}
// ==============================================================================
//method changed
private void open() throws SQLException {
if(database!=null&&database.isOpen())return; //changed line
database = dbHandler.getWritableDatabase();
}
// ==============================================================================
public void closeDAO(){
synchronized (lockObj){
if(dbHandler!=null)dbHandler.close();
dbHandler=null;
database=null;
}
}
public static void dispose(){
if(dBObject!=null){
dBObject.closeDAO();
}
dBObject=null;
}
}
And My database handler class looking like this
public class DBHandler extends SQLiteOpenHelper {
private static String DB_PATH;
private static String DB_NAME = "xxx";
private SQLiteDatabase myDataBase;
private final Context myContext;
public DBHandler(Context context) {
super(context, DB_NAME, null, constant.DATABASE_VERSION);
this.myContext = context;
DB_PATH = context.getDatabasePath(DB_NAME).toString();
}
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (dbExist) {
} else {
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
// ==============================================================================
/**
* Check if the database already exist to avoid re-copying the file each
* time you open the application.
*
* #return true if it exists, false if it doesn't
*/
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
// database does't exist yet.
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
private void copyDataBase() throws IOException {
InputStream myInput = myContext.getAssets().open(DB_NAME);
String outFileName = DB_PATH;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
// ==============================================================================
public void openDataBase() throws SQLException {
// Open the database
String myPath = DB_PATH;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
// ==============================================================================
#Override
public synchronized void close() {
if (myDataBase != null)
myDataBase.close();
super.close();
}
// ==============================================================================
#Override
public void onCreate(SQLiteDatabase db) {
}
// ==============================================================================
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
I am getting errors in logcat like this
Failed to open database '/data/user/0/com.newdeveloper.test/databases/xxx'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:835)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:820)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:723)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:692)
at com.newdeveloper.test.utility.DBHandler.checkDataBase(DBHandler.java:69)
at com.newdeveloper.test.utility.DBHandler.createDataBase(DBHandler.java:32)
at com.newdeveloper.test.utility.DAO.<init>(DAO.java:41)
at com.newdeveloper.test.utility.DAO.getInstance(DAO.java:31)
at com.newdeveloper.test.activities.SplashScreensActivity.checkForUpdate(SplashScreensActivity.java:111)
at com.newdeveloper.test.activities.SplashScreensActivity.access$000(SplashScreensActivity.java:41)
at com.newdeveloper.test.activities.SplashScreensActivity$1.onAnimationEnd(SplashScreensActivity.java:98)
at android.view.animation.AnimationSet.getTransformation(AnimationSet.java:400)
However application does not getting crashed and working fine as I
need. But This errors are confusing me what I need to change for
resolve this errors. I am trying to solve from last two days but not
found any working solution for it. Let me know if any senior developer
can help me for come out from this. Thanks
If you are not already using a bundled database with your apk, you have not actually created the database here in your code.
#Override
public void onCreate(SQLiteDatabase db) {
//you must create the database here
}
// ==============================================================================
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//Handle the database update here
}
You need to do something like this.
#Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(CREATE_STRING);
} catch (SQLException e) {
e.printStackTrace();
}
Log.e(TAG, "Table Created");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME_STRING);
onCreate(db);
Log.d(TAG, "Table upgraded to Version :" + newVersion);
}
I would also recommend to start using ROOM Android Architecture Component, which provides much better abstraction level for the Sqlite for the pattern are using.

Android Save And Get Image From Sqlite Database

Dears
How I can Android Save Image And Get Image From Sqlite Database I'm Using Android Studio ?
Might be too late. but useful for future readers..
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.util.HashMap;
/**
* Created by Noorul on 23-05-2016.
*/
#SuppressWarnings("ALL")
public class DBSplash extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "SplashDB.db";
public static final String SPLASH_TABLE_NAME = "splash_db";
private HashMap hp;
public DBSplash(Context context) {
super(context, DATABASE_NAME, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(
"create table " + SPLASH_TABLE_NAME + "( name TEXT, image BLOB)"
);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABLE IF EXISTS contacts");
onCreate(db);
}
public boolean insertImage(String name, Bitmap img) {
Bitmap storedBitmap = null;
String sql = "INSERT INTO " + SPLASH_TABLE_NAME + " (name,image) VALUES(?,?)";
SQLiteDatabase db = this.getWritableDatabase();
SQLiteStatement insertStmt = db.compileStatement(sql);
byte[] imgByte = getBitmapAsByteArray(img);
try {
storedBitmap = getImage(name);
} catch (Exception e) {
AppLog.exception(e);
}
if (storedBitmap == null) {
insertStmt.bindString(1, name);
insertStmt.bindBlob(2, imgByte);
insertStmt.executeInsert();
db.close();
}
return true;
}
public int numberOfRows() {
SQLiteDatabase db = this.getReadableDatabase();
int numRows = (int) DatabaseUtils.queryNumEntries(db, SPLASH_TABLE_NAME);
return numRows;
}
public Bitmap getImage(String name) {
String qu = "SELECT * FROM " + SPLASH_TABLE_NAME;
Cursor cur = null;
SQLiteDatabase db = this.getReadableDatabase();
try {
cur = db.rawQuery(qu, new String[]{});
} catch (Exception e) {
AppLog.exception(e);
}
if (cur != null) {
if (cur.moveToFirst()) {
int index = cur.getColumnIndexOrThrow("image");
byte[] imgByte = cur.getBlob(index);
cur.close();
return BitmapFactory.decodeByteArray(imgByte, 0, imgByte.length);
}
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
return null;
}
public byte[] getBitmapAsByteArray(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 0, outputStream);
return outputStream.toByteArray();
}
}
Use this code. But storing images in databases is not not best practices.change the image size if you need unblurred image. IMages are blob type with high memory . mobile is smaller device . so storing many images in sqlite db means, it will be ugly. so use #thuongle method
You can check this tutorial for implementing Sqlite in Android.
http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/
Instead working with Contact for example, you can implement this way
public class Image{
String imagePath; //it is your absolute image file path
}
And your DatabaseHandler can be implemented like below
public class DatabaseHandler extends SQLiteOpenHelper {
// All Static variables
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "imagedb";
// Contacts table name
private static final String TABLE_IMAGE = "images";
// Contacts Table Columns names
private static final String KEY_ID = "id";
private static final String KEY_IMAGE_PATH = "name";
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Creating Tables
#Override
public void onCreate(SQLiteDatabase db) {
String sqlQuery = "CREATE TABLE " + TABLE_IMAGE + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_IMAGE_PATH + " TEXT)";
db.execSQL(sqlQuery);
}
// Upgrading database
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_IMAGE);
// Create tables again
onCreate(db);
}
// Adding new image
public void addImage(Image image) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KEY_IMAGE_PATH, image.imagePath); // Image path
// Inserting Row
db.insert(TABLE_IMAGE, null, values);
db.close(); // Closing database connection
}
// Getting single image
public Image getImage(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_IMAGE, new String[] { KEY_ID,
KEY_IMAGE_PATH}, KEY_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
Image image = new Image(Integer.parseInt(cursor.getString(0)),
cursor.getString(1));
// return image
return image;
}
}

Android Studio App Crash from Sqlite database

I'm hoping my question isn't too broad. What I would really like to know is how to tell exactly where my code is hitting a wall.
I'm not getting errors from my debugger, the app just crashes when the emulator starts an activity that uses a sqlite database (3rd activity in). I am positive it is the addition of sqlite into my code that causes the crash because it ran before I added it.
This code simply needs to access and read from an external database that I created and pasted into the assets folder. I reviewed the sqlite database in firefox's SQLite Manager; the information seems to be formatted correctly.
I created an assets folder within app/src/Main to facilitate the addition of the external database "ex3.db". Then I copied and pasted the database file there.
So here is the code. LetterImage is a class that holds strings retrieved from the sqlite database. MyDBHandler creates an empty database, copies the old one into it, and fills LetterImage with the values returned from a query based on a string. LoadSubjectActivity calls them both to search the database and return a string.
LetterImage:
public class LetterImage {
private Integer _ID;
private String _letter;
private String _bigfilename;
private String _littlefilename;
//Constructor(s)
public LetterImage(){
}
public LetterImage(Integer ID, String letter, String bigfilename, String littlefilename){
this._ID = ID;
this._letter = letter;
this._bigfilename = bigfilename;
this._littlefilename = littlefilename;
}
public LetterImage(String letter){
this._letter = letter;
}
//End Constructors
//Begin setters and getters
//ID is primary key
public void setID(Integer ID){
this._ID = ID;
}
public Integer getID(){
return this._ID;
}
//letter is main identifier used to search database
// passed to LoadSubjectActivity
// from ChooseSubjectABCActivity as extra from intent
public void setLetter(String letter){
this._letter = letter;
}
public String getLetter(){
return this._letter;
}
//Capital letter image file name
public void setBigFileName(String bigfilename){
this._bigfilename = bigfilename;
}
public String getBigFileName(){
return this._bigfilename;
}
//Lowercase Letter image file name
public void setLittleFileName(String littlefilename){
this._littlefilename = littlefilename;
}
public String getLittleFileName(){
return this._littlefilename;
}
}
Now, here is MyDBHandler:
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.content.Context;
import android.database.Cursor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
public class MyDBHandler extends SQLiteOpenHelper{
private final Context myContext;
private static Context context;
private static final int DATABASE_VERSION = 1;
private static String DB_PATH = "data/data" + context.getPackageName() + "/databases/";
private static final String DATABASE_NAME = "ex3.db";
public static final String TABLE_IMAGES = "tbl1";
private SQLiteDatabase myDataBase;
//Fields in Database
public static final String COLUMN_ID = "_id";
public static final String COLUMN_BIGIMAGEFILE = "bigImage";
public static final String COLUMN_LITTLEIMAGEFILE = "littleImage";
public static final String COLUMN_LETTER = "letter";
//Constructor
public MyDBHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.myContext = context;
}
//if there is no existing database, create an empty one
public void createDatabase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist) {
//do nothing
}else {
//call this method and create an empty database
this.getReadableDatabase();
try {
copyDataBase();
} catch(IOException e){
throw new Error("Error copying database");
}
}
}
//check to see if there is an existing database
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DATABASE_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e){
throw new Error("Unable to open database");
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;
}
//fills new empty database with existing database ex3
private void copyDataBase() throws IOException{
InputStream myInput = myContext.getAssets().open(DATABASE_NAME);
String outFileName = DB_PATH + DATABASE_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
//opens the new database
public void openDatabase() throws SQLException {
String myPath = DB_PATH + DATABASE_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
#Override
public synchronized void close(){
if(myDataBase != null)
myDataBase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db){
}
#Override
public void onUpgrade(SQLiteDatabase db, int OldVersion, int newVersion){
}
//creates an instance of letter LetterImage
//queries the new database by searching for the row with where the value of COLUMN_LETTER = letter
//fills LetterImage with the values from that row
public LetterImage findLetter(String letter) {
String query = "Select * FROM " + TABLE_IMAGES + " WHERE " + COLUMN_LETTER + " = \"" + letter + "\"";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
LetterImage LetterImage = new LetterImage();
if (cursor.moveToFirst()) {
cursor.moveToFirst();
LetterImage.setID(Integer.parseInt(cursor.getString(0)));
LetterImage.setBigFileName(cursor.getString(1));
LetterImage.setLittleFileName(cursor.getString(2));
LetterImage.setLetter(cursor.getString(3));
cursor.close();
} else {
LetterImage = null;
}
db.close();
return LetterImage;
}
}
Finally, here are the pertinent parts of the LoadSubjectActivity class:
public class LoadSubjectActivity extends MainActivity{
private DrawingView drawView;
private ImageButton currPaint;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_load_subject);
//receives string letter, from last activity
//letter will be used to search array and return files names of the images to be used
Intent intent = getIntent();
String letter = intent.getExtras().getString("letter");
//displayFN calls testDB(letter) to test the database
//It should simply display the string returned by testDB()
TextView displayFN = (TextView)findViewById(R.id.display_filenames);
displayFN.setText(testDB(letter.toLowerCase()));
//Eventually, button images will be filled dynamically
ImageButton bigLetter = (ImageButton)findViewById(R.id.big_letter);
ImageButton littleLetter = (ImageButton)findViewById(R.id.little_letter);
bigLetter.setImageResource(R.drawable.biga);
littleLetter.setImageResource(R.drawable.littlea);
drawView = (DrawingView)findViewById(R.id.drawing);
LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors);
currPaint = (ImageButton)paintLayout.getChildAt(0);
currPaint.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.paint_pressed));
}
//Function to test the database takes a string as an argument to search the database
public String testDB(String letter){
//create a new instance of dbHandler
MyDBHandler dbHandler = new MyDBHandler(this);
//try to either create an empty database or open the existing one
try{
dbHandler.createDatabase();
} catch (IOException ioe){
throw new Error("Unable to create database");
}
try{
dbHandler.openDatabase();
} catch(SQLException sqle){
sqle.printStackTrace();
throw new Error ("unable to open database");
}
LetterImage letterImage = dbHandler.findLetter(letter);
String blFileName = letterImage.getBigFileName();
//return the big letter image file name;
return blFileName;
}
Anyway, I apologize in advance for any obvious problems. I have traced the logic to the best of my ability...I am teaching myself java and sql...this is my first android project. Any and all insight is greatly appreciated.
I figured out one way to fix this:
1.) rewrite checkDatabase(). I referenced this tutorial: How to use an existing database with an Android application, and found this:
private boolean checkDataBase(){
File dbFile = new File(DB_PATH + DATABASE_NAME);
//Log.v("dbFile", dbFile + " "+ dbFile.exists());
return dbFile.exists();
}
2.) Hard code DB_PATH name, since context.getFilesDir and getDatabasePath() weren't returning the paths I needed.
***going through logcat and tracing the errors back to the exact place the problem started was how I found what I needed to change. In this instance, checkDatabase() wasn't returning false to createDatabase(), so the code was trying to open a database that didn't exist.

SQLite database is not getting created..Why?

I was trying to add the data i receive from some specific messages to SQLite database..
But when i run my application i am getting error which says ... Fatal Exception : Main caused by Java Null Pointer exception at the InsertTitle Function in my DBAdapter.java
This is my DBAdapter Class
package com.lalsoft.janko;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter
{
public static final String KEY_ROWID = "_id";
public static final String KEY_GQTY = "gqty";
public static final String KEY_NQTY = "nqty";
public static final String KEY_DATE = "ddate";
private static final String TAG = "DBAdapter";
private static final String DATABASE_NAME = "lalaqua";
private static final String DATABASE_TABLE = "nsales";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_CREATE =
"create table titles (_id integer primary key autoincrement, "
+ "gqty text not null, nqty text not null, "
+ "ddate text not null);";
private final Context context;
private DatabaseHelper DBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx)
{
this.context = ctx;
DBHelper = new DatabaseHelper(context);
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(DATABASE_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion)
{
Log.w(TAG, "Upgrading database from version " + oldVersion
+ " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS titles");
onCreate(db);
}
}
//---opens the database---
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
//---closes the database---
public void close()
{
DBHelper.close();
}
//---insert a title into the database---
public long insertTitle(String gqty, String nqty, String ddate)
{
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_GQTY, gqty);
initialValues.put(KEY_NQTY, nqty);
initialValues.put(KEY_DATE, ddate);
return db.insert(DATABASE_TABLE, null, initialValues);
}
//---deletes a particular title---
public boolean deleteTitle(long rowId)
{
return db.delete(DATABASE_TABLE, KEY_ROWID +
"=" + rowId, null) > 0;
}
//---retrieves all the titles---
public Cursor getAllTitles()
{
return db.query(DATABASE_TABLE, new String[] {
KEY_ROWID,
KEY_GQTY,
KEY_NQTY,
KEY_DATE},
null,
null,
null,
null,
null);
}
//---retrieves a particular title---
public Cursor getTitle(long rowId) throws SQLException
{
Cursor mCursor =
db.query(true, DATABASE_TABLE, new String[] {
KEY_ROWID,
KEY_GQTY,
KEY_NQTY,
KEY_DATE
},
KEY_ROWID + "=" + rowId,
null,
null,
null,
null,
null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
//---updates a title---
public boolean updateTitle(long rowId, String gqtr,
String nqty, String ddate)
{
ContentValues args = new ContentValues();
args.put(KEY_GQTY, gqtr);
args.put(KEY_NQTY, nqty);
args.put(KEY_DATE, ddate);
return db.update(DATABASE_TABLE, args,
KEY_ROWID + "=" + rowId, null) > 0;
}
}
This is the class which extends from BroadcastReceiver, which is calling the inserttitle function..
package com.lalsoft.janko;
import java.util.Calendar;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.gsm.SmsManager;
import android.telephony.gsm.SmsMessage;
import android.util.Log;
public class SMSReceiver extends BroadcastReceiver
{
public String SendMsgBody;
private static final String LOG_TAG = "JankoSMS";
public DBAdapter db;
public Integer isDone=0;
public Double GrossQty,NetQty;
#Override
public void onReceive(Context context, Intent intent)
{
db = new DBAdapter(context);
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
String PhNo;
String MsgBody;
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
PhNo=msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
MsgBody=msgs[i].getMessageBody().toString();
str += "\n";
// EncodeSMS(MsgBody);
String GQtyS,NQtyS,sDate;
GQtyS="Ok";
NQtyS="Done";
sDate=getDate();
Log.i(LOG_TAG, "Date" +" "+ sDate +" "+ GQtyS +" "+ NQtyS);
long id;
id = db.insertTitle(GQtyS ,NQtyS,sDate);
}
}
}
public static String getDate()
{
Calendar c = Calendar.getInstance();
String sDate = c.get(Calendar.DAY_OF_MONTH) + "-"
+ c.get(Calendar.MONTH)
+ "-" + c.get(Calendar.YEAR);
//+ " at " + c.get(Calendar.HOUR_OF_DAY)
//+ ":" + c.get(Calendar.MINUTE);
return sDate;
}
}
Also i have checked the database is not getting created..
So what should be the possible cause of this issue and how can i solve this?? Please help me out of this trouble.
The problem is in line db.insert() of insertTitle() method. You have to assign the value of db before using so use open the database before using by calling open() as first statement inside insertTitle() method
Your code will be something like the below
public long insertTitle(String gqty, String nqty, String ddate)
{
open();
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_GQTY, gqty);
initialValues.put(KEY_NQTY, nqty);
initialValues.put(KEY_DATE, ddate);
return db.insert(DATABASE_TABLE, null, initialValues);
}
I guess you haven't called db.open(); that is this method
public DBAdapter open() throws SQLException
{
db = DBHelper.getWritableDatabase();
return this;
}
Follow the above 2 suggestions given by sunil & lalit
include the below one also i.e place db.execSQL(DATABASE_CREATE); in try catch block
public void onCreate(SQLiteDatabase db) {
System.out.println("table created....");
try{
db.execSQL(DATABASE_CREATE);
}catch (Exception e) {
// TODO: handle exception
}
}

Categories