SQLite onUpgrade() frustration - java

I'm working with a prepopulated database. Using SQLite Manager in Mozilla, right now I have a dummy database and just wanted to test out the onUpgrade method, so I altered a string in one of the columns, exported it as a new database and as you'll see in my code, tried to open the newly updated version. Also important note, I'm updating the version number by one manually in the code
private static final int DB_VERSION = 3;
and in the onUpgrade
if (newVersion == 3) {
Log.e("WORKED!!", "onUpgrade executed");
so next time I would update these two numbers to 4. Not sure if I'm doing this right or what's wrong but I'm getting the log message, just not seeing the data updated in the app.
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.util.Log;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class DataBaseHelper extends SQLiteOpenHelper {
private static String DB_PATH;
private static final String DB_NAME = "DummyTestOne.sqlite";
private static final int DB_VERSION = 3;
private static final String DB_NAME2 = "DummyTestFive.sqlite";
private SQLiteDatabase mDataBase;
private final Context mContext;
public static final String DBTABLENAME = "questiontable";
public static final String DBATABLENAME = "answertable";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "question";
public static final String COLUMN_CATEGORY = "category";
public static final String COLUMN_FID = "fid";
public static final String COLUMN_ANSWER = "answer";
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.mContext = context;
DB_PATH = context.getDatabasePath(DB_NAME).getPath();
}
public void createDataBase() {
boolean dbExist = checkDataBase();
if (dbExist) {
} else {
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
checkDB = SQLiteDatabase.openDatabase(DB_PATH, null, SQLiteDatabase.OPEN_READWRITE);
} catch (SQLiteException e) {
Log.e(this.getClass().toString(), "Error while checking db");
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
private void copyDataBase() throws IOException {
InputStream externalDbStream = mContext.getAssets().open(DB_NAME);
OutputStream localDbStream = new FileOutputStream(DB_PATH);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = externalDbStream.read(buffer)) > 0) {
localDbStream.write(buffer, 0, bytesRead);
}
localDbStream.flush();
localDbStream.close();
externalDbStream.close();
}
public void openDataBase() throws SQLException {
mDataBase = this.getWritableDatabase();
}
#Override
public synchronized void close() {
if (mDataBase != null) {
mDataBase.close();
}
super.close();
}
public Cursor getCursorForAllQs() {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(DBTABLENAME);
String[] asColumnsToReturn = new String[]{COLUMN_ID, COLUMN_NAME, COLUMN_CATEGORY, COLUMN_FID};
Cursor mCursor = queryBuilder.query(mDataBase, asColumnsToReturn, null,
null, null, null, "_id");
return mCursor;
}
public List<String> getAnswersForQ(int questionFid) {
List<String> answers = new ArrayList<>();
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(DBATABLENAME);
String[] tableColumns = new String[]{DataBaseHelper.COLUMN_ANSWER};
String where = "fid = ?";
String[] selectionArgs = new String[]{String.valueOf(questionFid)};
String orderBy = DataBaseHelper.COLUMN_ID;
Cursor c = queryBuilder.query(mDataBase, tableColumns, where, selectionArgs, null, null, orderBy);
if (c.moveToFirst()) {
do {
try{
answers.add(c.getString(c.getColumnIndex(DataBaseHelper.COLUMN_ANSWER)));
} catch (Exception e) {
Log.e("FAILED", c.getString((c.getColumnIndex(DataBaseHelper.COLUMN_ANSWER))));
}
} while (c.moveToNext());
}
Log.d("getAnswersForQ", answers.toString());
return answers;
}
public String getName(Cursor c) {
return (c.getString(1));
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion == 3) {
Log.e("WORKED!!", "onUpgrade executed");
}
if (newVersion > oldVersion) {
InputStream inputStream = null;
OutputStream outputStream = null;
String dbFilePath = DB_PATH + DB_NAME;
try {
inputStream = mContext.getAssets().open(DB_NAME2);
outputStream = new FileOutputStream(dbFilePath);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (IOException e) {
throw new Error("Problem copying database from resource file.");
}
}
}
}

Upgrading a database means changing it in place while keeping the old data intact as much as possible.
So if you want to add or rename a column, you have to execute the proper SQL command to do this in the onUpgrade callback.
(Note: SQLiteAssetHelper makes using a prepopulated database easier, and you should use it, but upgrading still needs a separate SQL script.)
If you do not care about the contents of the old database, then you should not upgrade it. Just give your new database version a new file name, so that it is simply copied over, and delete the old file.

Related

java.lang.Error: Error Copying Database in SQLite Database from assets folder

I have designed the database in SQLlite Browser. And now I got this error.
the database cannot copy from assets folder.
it shows me this error
2021-01-13 13:35:26.126 9933-9933/com.example.wallpaperapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.wallpaperapp, PID: 9933
java.lang.Error: Error Copying Database
at com.example.wallpaperapp.utils.SqliteHelperClass.onCreateDatabase(SqliteHelperClass.java:50)
at com.example.wallpaperapp.MainActivity.onCreate(MainActivity.java:39)
SQLiteHelper Class
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.os.Environment;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class SqliteHelperClass extends SQLiteOpenHelper {
Context context;
SQLiteDatabase db = null;
public static final String dbname = "wallpaperApp.db";
public String dbPath = "";
public SqliteHelperClass(Context context) {
super(context, dbname, null, 1);
this.context = context;
if (Build.VERSION.SDK_INT >= 15) {
this.dbPath = context.getApplicationInfo().dataDir + "/databases/";
} else {
this.dbPath = Environment.getDataDirectory() + "/data/" + context.getPackageName() + "/" + "database/";
}
}
//Create the Database
public void onCreateDatabase() throws IOException {
boolean dbExist = checkDatabase();
if (dbExist) {
} else {
try {
this.getReadableDatabase();
copyDatabase();
} catch (Exception e) {
throw new Error("Error Copying Database");
}
}
}
//check Database
private boolean checkDatabase() {
SQLiteDatabase checkDb = null;
try {
String mypath = dbPath + dbname;
checkDb = SQLiteDatabase.openDatabase(mypath, null, SQLiteDatabase.OPEN_READONLY);
}
catch (Exception e) {
}
if (checkDb != null) {
checkDb.close();
}
return checkDb != null? true : false;
}
private void copyDatabase() throws IOException {
InputStream inputStream = context.getAssets().open(dbname);
String outFilename = dbPath = dbname;
OutputStream myOutput = new FileOutputStream(outFilename);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
inputStream.close();
}
public void openDatabase() throws Exception {
String mypath = dbPath + dbname;
db = SQLiteDatabase.openDatabase(mypath, null, SQLiteDatabase.OPEN_READONLY);
}
#Override
public synchronized void close() {
if (db != null) {
db.close();
}
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion > newVersion) {
try {
copyDatabase();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public Cursor readData(String query){
SQLiteDatabase sqLiteDatabase = this.getReadableDatabase();
Cursor cursor = sqLiteDatabase.rawQuery(query, null);
return cursor;
}
public void updateDataForFavorite(String id, String isFav)
{
SQLiteDatabase database = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("isFav",isFav);
database.update("wallpapers",contentValues,"id=?",new String[]{id});
}
}
MainActivity.java
package com.example.wallpaperapp;
import androidx.appcompat.app.AppCompatActivity;
import android.database.Cursor;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.widget.GridView;
import android.widget.Toast;
import com.example.wallpaperapp.adapters.GridViewAdapter;
import com.example.wallpaperapp.models.ImagesConstant;
import com.example.wallpaperapp.utils.SqliteHelperClass;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
GridView gridView;
GridViewAdapter gridViewAdapter;
List<ImagesConstant> imagesConstantList;
SqliteHelperClass sqLiteHelperClass;
Cursor cursor = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView = (GridView) findViewById(R.id.gridView);
imagesConstantList = new ArrayList<>();
sqLiteHelperClass = new SqliteHelperClass(MainActivity.this);
try {
sqLiteHelperClass.onCreateDatabase();
sqLiteHelperClass.openDatabase();
} catch (Exception e) {
e.printStackTrace();
}
addData();
}
private void addData() {
cursor = sqLiteHelperClass.readData("SELECT id, images, isFav from wallpapers;");
if (cursor.moveToFirst()){
do {
int id = cursor.getInt(0);
String image = cursor.getString(1);
int isFav = cursor.getInt(2);
ImagesConstant imagesConstant = new ImagesConstant(id,image,isFav);
imagesConstantList.add(imagesConstant);
}while (cursor.moveToNext());
showGrid();
}else {
Toast.makeText(MainActivity.this, "Data Not Found", Toast.LENGTH_SHORT).show();
}
}
void showGrid(){
gridViewAdapter = new GridViewAdapter(MainActivity.this,imagesConstantList);
gridView.setAdapter(gridViewAdapter);
}
}

My Activity cannot be connected with my Database

I have an activity named Awal.java and the code :
public class Awal extends Activity implements OnItemClickListener {
private Cursor kategori;
private MyDatabase db;
private List<String> ktg;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = new MyDatabase(this, null);
ktg = db.getKategori();
String namaKtg[] = ktg.toArray(new String[ktg.size()]);
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(new ArrayAdapter<String>(this, R.layout.list, R.id.label, namaKtg));
listView.setOnItemClickListener(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
kategori.close();
db.close();
}
public void onItemClick(AdapterView<?> adapter, View v, int pos, long l) {
Intent intent = new Intent(Awal.this,Detail.class);
intent.putExtra("namaKategori", adapter.getItemAtPosition(pos).toString());
startActivity(intent);
}
}
and also databaseHelper named MyDatabase.java and here is the code :
package com.mroring.belajarperancis;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MyDatabase extends SQLiteOpenHelper {
// Variable declaration
private static String DB_PATH = "/data/data/com.mroring.belajarperancis/databases/";
public static String DB_NAME = "MY_DATABASE";
private final Context myContext;
private String strMypath;
public MyDatabase(Context context, String DB_NAME) {
super(context, DB_NAME, null, 1);
this.myContext = context;
try {
MyDatabase.DB_NAME = DB_NAME;
} catch (Exception e) {
e.printStackTrace();
}
}
public void createDatabase() throws IOException {
try {
// check if the database exists
boolean dbExist = checkDatabase();
if (!dbExist) {
// database is not present copy databse
this.getReadableDatabase();
try {
copyDatabse(DB_NAME);
} catch (IOException e) {
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 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() {
try {
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
} catch (Exception e) {
e.printStackTrace();
}
return 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.
* */
public void copyDatabse(String DB_NAME) throws IOException {
try {
// Open your local db as the input stream
Input`enter code here`Stream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_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 * 2];
int length;
while ((length = myInput.read(buffer)) > 0) {
try {
myOutput.write(buffer, 0, length);
} catch (Exception e) {
}
}
if (myOutput != null) {
myOutput.flush();
myOutput.close();
}
if (myInput != null)
myInput.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* This function is used to open the database
*
* #throws SQLException
*/
public void openDatabase() throws SQLException {
SQLiteDatabase checkDB = null;
// Open the database
try {
strMypath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(strMypath, null,
SQLiteDatabase.OPEN_READWRITE);
} catch (Exception e) {
e.printStackTrace();
}
if (checkDB != null) {
checkDB.close();
}
}
public List<String> getKategori() {
String query = "SELECT _id FROM kategori";
List<String> kategori = new ArrayList<String>();
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery(query, null);
//looping through
if (cursor.moveToFirst()) {
do {
kategori.add(cursor.getString(0)); // add id & nama
}
while (cursor.moveToNext());
}
cursor.close();
db.close();
return kategori;
}
public List<List<String>> getDetail(String namaKategori) {
String query = "select pra, ina, baca from kata,kategori where kata.id_kategori=kategori._id and kategori.nama = '"+namaKategori+"'";
List<List<String>> detail = new ArrayList<List<String>>();
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery(query, null);
//looping
if (cursor.moveToFirst()) {
do {
List<String> item = new ArrayList<String>();
item.add(cursor.getString(0)); //add french word
item.add(cursor.getString(1)); //add indonesian word
item.add(cursor.getString(2)); //add baca
detail.add(item);
}
while (cursor.moveToNext());
}
cursor.close();
db.close();
return detail;
}
#Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
try {
copyDatabse(DB_NAME);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
And this combination always makes errors and here are the error :
06-18 01:23:01.694: E/AndroidRuntime(17219): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mroring.belajarperancis/com.mroring.belajarperancis.Awal}: android.database.sqlite.SQLiteException: no such table: kategori: , while compiling: SELECT _id FROM kategori
06-18 01:23:01.694: E/AndroidRuntime(17219): Caused by: android.database.sqlite.SQLiteException: no such table: kategori: , while compiling: SELECT _id FROM kategori
I have a database named 'MY_DATABASE' in .../BelajarPerancis/assets/databases/MY_DATABASE and also .../BelajarPerancis/assets/MY_DATABASE (I tried to put the DB in two places).
I have tried to pull the database from DDMS, and it returns the same Database with the same contents/tables and it has table 'Kategori'.
My 'Kategori' table contains the field of '_id' and here is the proof 3 Rows returned from: select nama from kategori; (took 5ms).
You are passing database name as null in line db = new MyDatabase(this, null);
I can not see code to create 'kategori' table
and in query you are trying to get data from table name as 'kategori' String query = "SELECT _id FROM kategori"; which do not exists..
Change db = new MyDatabase(this, null); to
db = new MyDatabase(this, "SOME_DATABASE_NAME");
and then write code to create table in database.
Activity launch is not working because db.getKategori(); is called from onCreate() method and which is throwing exception.
please go through http://www.vogella.com/tutorials/AndroidSQLite/article.html
Hope this helps you !!
Are you sure that you create the database?
I say that because you're using a absolute path to get the file of the database, the best thing to do in that case is create a database as the standard of Google.
here is a good answer, of how do that:
How do I create a database in android?
You can check too the name of your table, if you use with the first letter in uppercase you must use in that way all time.
att.

Empty database being created but copying of tables from Assets not happening

I have packaged a database with my application, and I can see in my File Explorer that the databases folder along with the workoutsDatabase.sqlite file is being created. When I look at the contents of the database, though, the only table in there is the android_metadata table. I have been searching for hours and have seen many people with similar problems, however, I cannot seem to figure out the correct solution.
Can anyone spot why the tables dont seem to copy over? I have validated the workoutsDatabase.sqlite in my assets folder DOES contain the table "workout" and it does have data in it.
WorkoutsDatabaseHelper
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
import android.util.Log;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class WorkoutsDatabaseHelper extends SQLiteOpenHelper {
private String DATABASE_PATH = "/data/data/com.rcd.myworkouts/databases/";
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "workoutsDatabase.sqlite";
private static final String TABLE_WORKOUTS = "workouts";
private static final String KEY_ID = "_id";
private static final String KEY_WORKOUT_NAME = "workout_name";
private static final String KEY_LAST_NAME = "last_name";
private static final String KEY_FIRST_NAME = "first_name";
private static final String KEY_MIDDLE_NAME = "middle_name";
private static final String KEY_DESCRIPTION = "description";
private static final String KEY_DATE_ADDED = "date_added";
private static final String KEY_WORKOUT = "workout";
private static final String KEY_MEASUREMENT = "measurement";
private static final String KEY_PHOTO = "photo";
private SQLiteDatabase myDatabase;
private final Context myContext;
public WorkoutsDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.myContext = context;
}
// Creates a empty database on the system and rewrites it with your own database.
public void createDatabase() throws IOException {
boolean dbExist = checkDatabase();
SQLiteDatabase db_Read = null;
if(dbExist) {
// Do nothing - database already exist
} else {
//By calling this method an 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.
db_Read = getReadableDatabase();
db_Read.close();
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 doesn'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 {
getWritableDatabase();
Log.d("Database", "New database is being copied to device!");
try
{
// Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DATABASE_NAME);
// transfer bytes from the inputfile to the
// 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 form the inputfile to the output file
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();
Log.i("Database", "New database has been copied to device!");
}
catch(IOException e)
{
e.printStackTrace();
}
}
protected Boolean openDatabase() {
if(checkDatabase())
{
// Open the database
String myPath = DATABASE_PATH + DATABASE_NAME;
try
{
Log.i("Database", "Trying to Open Database!");
if(myDatabase != null)
{
if(!myDatabase.isOpen())
{
Log.i("Database", "Database is closed now opening it!");
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
else
{
Log.i("Database", "Database is already Open!");
}
Log.i("Database", "Database is Opened successfully in OPEN_READWRITE Mode !");
return true;
}
else
{
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
Log.i("Database", "Database is Opened successfully in OPEN_READWRITE Mode !");
return true;
}
}
catch(Exception e)
{
Log.e("Database", "Some error occured while opening Database Error:" + e.getMessage());
myDatabase = null;
return false;
}
}
else
try {
copyDatabase();
Log.d("WorkoutsDatabaseHelper.java", "Copy Database..");
} catch (IOException e) {
throw new Error("Error copying database");
}
return false;
}
#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) {
}
}

how to make MyDBHelper As Global Variable?

This is my DataBaseHelper.java
package com.example.abc2;
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.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHelper extends SQLiteOpenHelper{
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/com.example.abc2/databases/";
private static String DB_NAME = "DB_BusData";
private SQLiteDatabase myDataBase;
private final Context myContext;
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* #param context
*/
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
/**
* 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.
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 + DB_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(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_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);
}
#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) {
}
// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.
}
MainActivity.java
public void DatabaseConn(){
DataBaseHelper myDbHelper = new DataBaseHelper(this.getApplicationContext());
myDbHelper = new DataBaseHelper(this);
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
myDbHelper.openDataBase();
}catch(SQLException sqle){
throw sqle;
}
SQLiteDatabase db = myDbHelper.getReadableDatabase();
//SQLiteDatabase db = SQLiteDatabase.openDatabase("/data/data/com.example.abc2/databases/DB_BusData", null, 0);
Cursor c = db.rawQuery("SELECT * FROM Tbl_Driver", null);
if(c.moveToFirst()) {
String username = c.getString(c.getColumnIndex("Driver_Code")).trim();
String password = c.getString(c.getColumnIndex("Driver_Name")).trim();
Log.d(null, username);
}
db.close();
}
Any Idea to make my myDbHelper as global variable, otherwise every function i want to call the database i need to declare it, it is inconvenience.
Just add this
DataBaseHelper myDbHelper = new DataBaseHelper(this.getApplicationContext());
Over onCreate in your MainActivity, and remove it from public void DatabaseConn(){.
Create a Singleton Database class:
public class Database extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "yourDatabaseName";
//Declare a String for each Table name
public static final String TABLE_NAME1 = "tableName1";
public static final String TABLE_NAME2 = "tableName2";
//Declare a SQL string for create each table
private static final String CREATE_TABLE1 =
"CREATE TABLE if not exists " + TABLE_NAME1 ..............";
private static final String CREATE_TABLE2 =
"CREATE TABLE if not exists " + TABLE_NAME2 .................";
private static Database Singleton = null;
private Context context;
private static SQLiteDatabase Db;
private Database(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
public static synchronized Database getInstance(Context c){
if(Singleton == null) {
Singleton = new Database(c.getApplicationContext());
Db = Singleton.getWritableDatabase();
}
return Singleton;
}
public SQLiteDatabase getDatabase() {
return Db;
}
public synchronized void close() {
if (Singleton != null && Db.isOpen()) Db.close();
}
#Override
protected void finalize() throws Throwable {
try{
close();
}
finally{
super.finalize();
}
#Override
public void onCreate(SQLiteDatabase db) {
//Create Tables
db.execSQL(CREATE_TABLE1);
db.execSQL(CREATE_TABLE2);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
When you need a database object:
SQLiteDatabase Db = Database.getInstance(context).getDatabase();

get others column value on onItemSelected in Android

My Tbl_Driver have 3 columns _id,Driver_Code,Driver_Name
How do i able to get the Driver_Name when the Spinner OnItemSelected, because The Spinner will only show Driver_Code
public void DriverDatabaseConn(){
DataBaseHelper myDbHelper = new DataBaseHelper(this.getApplicationContext());
myDbHelper = new DataBaseHelper(this);
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
myDbHelper.openDataBase();
}catch(SQLException sqle){
throw sqle;
}
SQLiteDatabase db = myDbHelper.getReadableDatabase();
//SQLiteDatabase db = SQLiteDatabase.openDatabase("/data/data/com.example.abc2/databases/DB_BusData", null, 0);
Cursor c = db.rawQuery("SELECT * FROM Tbl_Driver", null);
//=====Add Additional=====
MatrixCursor extras = new MatrixCursor(new String[] { "_id", "Driver_Code" , "Driver_Name"});
extras.addRow(new String[] { "-1", "< Select Driver Code >","< Select Driver >" });
//extras.addRow(new String[] { "-2", "Empty Template","BB" });
Cursor[] cursors = { extras, c };
c = new MergeCursor(cursors);
//===========================
startManagingCursor(c);
//create an array to specify which fields we want to display
String[] from = new String[]{"Driver_Code"};
//create an array of the display item we want to bind our data to
int[] to = new int[]{android.R.id.text1};
//create simple cursor adapter
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_spinner_item, c, from, to );
adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
//get reference to our spinner
Spinner s = (Spinner) findViewById( R.id.DriverSpin);
s.setAdapter(adapter);
s.setOnItemSelectedListener(
new OnItemSelectedListener() {
public void onItemSelected(
AdapterView<?> parent, View view, int position, long id) {
Spinner s = (Spinner) findViewById( R.id.DriverSpin);
TextView textView = (TextView)s.getSelectedView();
String result = textView.getText().toString();
Log.d(null,"Spinner1: position=" + result + " id=" + id);
global.Driver_ID = id;
global.Driver_Code = result;
// at here how i can get the Driver_Name column's value at here?
}
public void onNothingSelected(AdapterView<?> parent) {
Log.d(null,"Spinner1: unselected");
}
});
//db.close();
//myDbHelper.close(); //cannot close, otherwise after logout the spinner will blank
}
DataBaseHelper.java
package com.example.abc2;
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.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHelper extends SQLiteOpenHelper{
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/com.example.abc2/databases/";
private static String DB_NAME = "DB_BusData";
private SQLiteDatabase myDataBase;
private final Context myContext;
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* #param context
*/
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
/**
* 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.
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 + DB_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(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_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);
}
#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) {
}
// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.
}
I have rewrite your DatabaseHelpe and a Test Activity:
public class DataBaseHelper {
private static final String DB_NAME = "DB_BusData";
public static final String TABLE_NAME = "Tbl_Driver";
private Context context;
private String path;
private SQLiteDatabase database;
private boolean isInitializing = false;
public DataBaseHelper(Context context) {
this.context = context;
this.path = context.getDatabasePath(DB_NAME).getAbsolutePath();
if (TextUtils.isEmpty(this.path)) {
throw new IllegalArgumentException("database can't be null");
}
}
public SQLiteDatabase getReadableDatabase() {
synchronized (this) {
checkAndCopyDatabase();
return getDatabaseLocked(false);
}
}
/**
* Attention:just support readable database until now
*
* #return
*/
public SQLiteDatabase getWriteableDatabase() {
synchronized (this) {
checkAndCopyDatabase();
return getDatabaseLocked(true);
}
}
private void checkAndCopyDatabase() {
File file = new File(this.path);
if (file.exists() && file.length() > 0) {
Log.d("TAG", "db already exist");
} else {
try {
InputStream is = context.getAssets().open(DB_NAME);
copyStreamToFile(is, new File(this.path));
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static final void copyStreamToFile(InputStream inputStream, File file) {
ensureDir(file);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
byte[] buffer = new byte[2048];
int read = 0;
while ((read = inputStream.read(buffer)) > 0) {
fos.write(buffer, 0, read);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
quietClose(inputStream);
quietClose(fos);
}
}
private static final void ensureDir(File file) {
if (file != null && (file = file.getParentFile()) != null && !file.exists()) {
file.mkdirs();
}
}
private static final void quietClose(final Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (final IOException e) {
}
}
}
private SQLiteDatabase getDatabaseLocked(boolean writeable) {
if (this.database != null) {
if (!this.database.isOpen()) {
database = null;
} else if (!writeable || !database.isReadOnly()) {
return database;
}
}
if (isInitializing) {
throw new IllegalArgumentException("getDatabase called recursively");
}
SQLiteDatabase db = this.database;
try {
isInitializing = true;
if (db != null && writeable && db.isReadOnly()) {
if (db.isOpen()) {
db.close();
}
db = null;
}
try {
db = SQLiteDatabase.openDatabase(this.path, null,
writeable ? SQLiteDatabase.OPEN_READWRITE : SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
e.printStackTrace();
}
this.database = db;
return db;
} finally {
isInitializing = false;
if (db != null && db != database) {
db.close();
}
}
}
public static class Driver implements BaseColumns {
long id;
String code;
String name;
static final String CODE_CLOMN_NAME = "Driver_Code";
static final String NAME_CLOMN_Name = "Driver_Name";
#Override
public String toString() {
return name;
}
}
public List<Driver> queryAllDriver() {
List<Driver> drivers = null;
SQLiteDatabase db = getReadableDatabase();
if (db != null) {
Cursor cursor = null;
try {
cursor = db.query(TABLE_NAME, null, null, null, null, null, null);
if(cursor != null && cursor.moveToFirst()) {
do {
final long id = cursor.getLong(cursor.getColumnIndex(Driver._ID));
final String code = cursor.getString(cursor.getColumnIndex(Driver.CODE_CLOMN_NAME));
final String name = cursor.getString(cursor.getColumnIndex(Driver.NAME_CLOMN_Name));
Driver driver = new Driver();
driver.id = id;
driver.code = code;
driver.name = name;
if(drivers == null)
drivers = new ArrayList<DataBaseHelper.Driver>();
drivers.add(driver);
} while(cursor.moveToNext());
}
} catch (SQLiteException e) {
e.printStackTrace();
} finally {
if(cursor != null)
cursor.close();
}
db.close();
}
return drivers;
}
}
The DB open and operation code is above, then I write a Test Activity:
public class MainActivity extends Activity implements OnItemSelectedListener {
private List<Driver> drivers;
private Spinner spinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner = (Spinner) findViewById(R.id.spinner);
spinner.setOnItemSelectedListener(this);
new DBTask().execute();
}
class DBTask extends AsyncTask<Void, Void, List<Driver>> {
#Override
protected List<Driver> doInBackground(Void... params) {
DataBaseHelper dbHelper = new DataBaseHelper(MainActivity.this);
return dbHelper.queryAllDriver();
}
#Override
protected void onPostExecute(List<Driver> result) {
bindSpinner(result);
}
}
private void bindSpinner(List<Driver> drivers) {
this.drivers = drivers != null ? drivers : new ArrayList<DataBaseHelper.Driver>(0);
ArrayAdapter<Driver> adapter = new ArrayAdapter<DataBaseHelper.Driver>(this,
android.R.layout.simple_spinner_item, this.drivers);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (this.spinner != null && position >= 0 && position < this.drivers.size()) {
Driver driver = drivers.get(position);
Toast.makeText(this, "selected: driver=" + driver.name + ", code=" + driver.code,
Toast.LENGTH_SHORT).show();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
Toast.makeText(this, "nothing selected", Toast.LENGTH_SHORT).show();
}
}
The Test Activity is works fine for me, I use the database that I simulated. I think you can't store spinner item in database, how many item in spinner? 10? 100 ? 1000?
You can move query data outside DataBaseHelper.java like this:
private List<Driver> queryAllDriver() {
List<Driver> drivers = null;
DataBaseHelper helper = new DataBaseHelper(this);
SQLiteDatabase db = helper.getReadableDatabase();
if (db != null) {
Cursor cursor = null;
try {
cursor = db.query(DataBaseHelper.TABLE_NAME, null, null, null, null, null, null);
if(cursor != null && cursor.moveToFirst()) {
do {
final long id = cursor.getLong(cursor.getColumnIndex(Driver._ID));
final String code = cursor.getString(cursor.getColumnIndex(Driver.CODE_CLOMN_NAME));
final String name = cursor.getString(cursor.getColumnIndex(Driver.NAME_CLOMN_Name));
Driver driver = new Driver();
driver.id = id;
driver.code = code;
driver.name = name;
if(drivers == null)
drivers = new ArrayList<DataBaseHelper.Driver>();
drivers.add(driver);
} while(cursor.moveToNext());
}
} catch (SQLiteException e) {
e.printStackTrace();
} finally {
if(cursor != null)
cursor.close();
}
db.close();
}
return drivers;
}

Categories