SQLite SELECT query in Android external database - table error - java

I'm developing a data collection app using multiple relational data tables. I've created my database. And the code is working fine in case of the first table. If I try to run the same query for the second table, it shows the table doesn't exist, even though the table is in the database.
Database structure
public String getName(String Plant) {
c1 = db.rawQuery("select * from Area where PAd = '" + Plant + "'", new String[]{});
StringBuffer buffer = new StringBuffer();
while (c.moveToNext()) {
String plant = c.getString(0);
buffer.append("" + plant);
}
return buffer.toString();
}
Error Log:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.dbtest, PID: 28350
android.database.sqlite.SQLiteException: no such table: Area (code 1): , while compiling: select * from Area where PAd = 'Plant02'
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:890)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:501)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1392)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1331)
at com.example.dbtest.DatabaseAcess.getName(DatabaseAcess.java:46)
at com.example.dbtest.MainActivity$3.onClick(MainActivity.java:86)
at android.view.View.performClick(View.java:6305)
at android.view.View$PerformClick.run(View.java:24840)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6501)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Table structure of the second table
CREATE TABLE Area (
Name TEXT,
Address TEXT,
PAd TEXT
);
Table structure of the first table
CREATE TABLE Table1 (
Name TEXT,
Address TEXT
);
DatabaseOpenHelper code.
public class DatabaseOpenHelper extends SQLiteAssetHelper {
private static final String DATABASE_NAME = "MyExternalDatabase1.db";
public static final int DATABASE_VERSION = 1;
public DatabaseOpenHelper(Context context){
super(context,DATABASE_NAME,null,DATABASE_VERSION);
}
}
DatabaseAccess code.
public class DatabaseAcess {
private SQLiteOpenHelper openHelper;
private SQLiteDatabase db;
private static DatabaseAcess instance;
Cursor c = null;
Cursor c1 = null;
private DatabaseAcess(Context context){
this.openHelper = new DatabaseOpenHelper(context);
}
public static DatabaseAcess getInstance(Context context){
if(instance == null){
instance = new DatabaseAcess(context);
}
return instance;
}
public void open(){
this.db = openHelper.getWritableDatabase();
}
public void close(){
if(db!=null){
this.db.close();
}
}
public String getAddress(String name){
c= db.rawQuery("select Address from Table1 where Name = '" + name + "'", new String[]{});
StringBuffer buffer = new StringBuffer();
while (c.moveToNext()) {
String address = c.getString(0);
buffer.append("" + address);
}
return buffer.toString();
}
public String getName(String Plant) {
c1 = db.rawQuery("select Name from Area where PAd = '" + Plant + "'", null);
StringBuffer buffer = new StringBuffer();
while (c.moveToNext()) {
String plant = c.getString(0);
buffer.append(""+plant);
}
return buffer.toString();
}
}

Maybe this can help you
public String getName(String Plant) {
Cursor c = db.rawQuery("SELECT * FROM Area WHERE PAd='+Plant+'", null);
StringBuffer buffer = new StringBuffer();
while (c.moveToNext()) {
String plant = c.getString(0);
buffer.append(""+plant);
}
return buffer.toString();
}

I think by the external database, you meant a database which you want to be loaded from your asset directory. Here you need to copy the database in your application internal storage first to make this accessible from your code. So I would like to suggest you do the following when you run the application for the first time.
public static final String DB_PATH = "/data/data/" + "com.your.package.name" + "/databases/";
private void copyFromAssetsAndCreateDatabase() {
InputStream yourDatabaseFromAsset;
try {
yourDatabaseFromAsset = getApplicationContext().getAssets().open("MyExternalDatabase1");
File dir = new File(DataHelper.DB_PATH);
if (!dir.exists()) dir.mkdir();
File f = new File(DataHelper.DB_PATH + "MyExternalDatabase1" + ".sqlite");
if (!f.exists()) {
f.createNewFile();
}
OutputStream mOutput = new FileOutputStream(f);
byte[] mBuffer = new byte[1024];
int mLength;
while ((mLength = yourDatabaseFromAsset.read(mBuffer)) > 0)
mOutput.write(mBuffer, 0, mLength);
mOutput.flush();
mOutput.close();
mInputEnglish.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Now when the database is copied from your external folder to your internal storage where the databases are located usually, it should find the database without any error. I do not know about the first database though. I think it was created in your application using the CREATE TABLE statement.
Hope that helps.

One possible reason is that you created only first table at first time. After that you append code for second table. Note database is already created and will not call onCreate() again. You should upgrade database version and create second table in onUpgrade().
I made same mistakes before.

Related

How to access database on Android app without root

I'm developing a small app with a database of 100 elements. I import the database but only in one emulator (of 3 witch I have) runs correctly. I found that it runs without problems because the "Songs.db" database exists in data/data/myapppackage/databases/ folder witch I can't have access without rooting the device.
I search through internet for different approaches and solutions to this problem but nothing is working. I am new to android programming and for this kind of problem there isn't any tutorial.
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "Songs.db";
public static final String TABLE_NAME = "songs_table";
public static final String COL_1 = "ID";
public static final String COL_2 = "TITLE";
public DatabaseHelper (Context context) {
super( context, DATABASE_NAME, null, 1 );
SQLiteDatabase db = this.getWritableDatabase();
}
public Cursor getData(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery( "select TITLE from songs_table where ID="+id+"", null );
return res;
}
}
and on PlayerTurn class
myDb = new DatabaseHelper( this );
Cursor rs = db.getData( b );
rs.moveToFirst();
tit = rs.getString( rs.getColumnIndex( db.COL_2 ) );
The error message I get most of the times is android.database.sqlite.SQLiteException: no such table: songs_table (code 1):
Can anyone help me? I spend almost 15 hours about that...
You can copy the DB into SD card, From SD card you can always access the DB
Try this code:
try {
File sd = Environment.getExternalStorageDirectory();
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath = "data/"+sPackageName+"/databases/"+sDBName;
String backupDBPath = "/.appname-external-data-cache/"+sDBName; //"{database name}";
File dir = new File(sd,backupDBPath.replace(sDBName,""));
if(dir.mkdir()) {
}
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
} catch (Exception e) {
}

How to update an existing SQLite db table data with new android app update?

I recently launched an app on the android app store that contained a SQLite database.
I am now attempting to release an update of the app, and want to add more data into the existing database, however have come a bit unstuck. I have read answers on SO that outline making changes to the database itself, however I want my tables and columns to stay the same, only add new data in.
The data that i want to add to the database is pulled from CSV files in the Raw file, and originally loaded into the database when the user registers for the app.
I have a feeling I am going to need to implement the onUpgrade method, however should I be adding the new data from the CSV files in at that point as well? Is it a matter of simple updating the database version and using the onUpgrade to load the new data?
I am fairly new to SQLite DB, so any help would be hugely appreciated.
CourseDBHelper Code
public class CourseDBHelper extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "CourseDB";
// Create two table names
private static final String TABLE_COURSES = "courses";
// Universities Table Columns names
private static final String COURSE_NAME = "Course_name";
private static final String UNI_NAME = "Uni_name";
private static final String COURSE_DURATION = "Duration";
private static final String COURSE_STUDY_MODE = "Study_mode";
private static final String COURSE_QUALIFICATION = "Qualification";
private static final String COURSE_ENTRY_STANDARDS = "Entry_standards";
private static final String COURSE_GRADUATE_PROSPECTS = "Graduate_prospects";
private static final String COURSE_STUDENT_SATISFACTION = "Student_satisfaction";
private String CREATE_COURSES_TABLE = "CREATE TABLE courses" +
"(" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"Course_name TEXT NOT NULL," +
"Uni_name TEXT NOT NULL," +
"Duration TEXT NOT NULL," +
"Study_mode TEXT NOT NULL," +
"Qualification TEXT NOT NULL," +
"Entry_standards TEXT NOT NULL," +
"Graduate_prospects TEXT NOT NULL," +
"Student_satisfaction TEXT NOT NULL" +
");";
private static final String[] COLUMNS = {
COURSE_NAME,
UNI_NAME,
COURSE_DURATION,
COURSE_STUDY_MODE,
COURSE_QUALIFICATION,
COURSE_ENTRY_STANDARDS,
COURSE_GRADUATE_PROSPECTS,
COURSE_STUDENT_SATISFACTION
};
public CourseDBHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// TODO: REMOVED NOT NULL FROM EVERY COLUMN FOR TEST PURPOSES, WILL NEED TO BE READDED
#Override
public void onCreate(SQLiteDatabase db)
{
db.execSQL(CREATE_COURSES_TABLE);
}
public void deleteAll()
{
SQLiteDatabase db = this.getWritableDatabase();
db.delete("courses", null, null);
db.execSQL("delete from " + "courses");
db.close();
}
// Getting one course by course name and uni name
public Course getCourse(String courseName, String uniName) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(TABLE_COURSES, COLUMNS, " Course_name = ? AND Uni_name = ?",
new String[]{courseName, uniName},
null,
null,
null,
null);
if (cursor != null)
cursor.moveToFirst();
Course course = new Course();
/*
System.out.println(cursor.getString(0));
System.out.println(cursor.getString(1));
System.out.println(cursor.getString(2));
System.out.println(cursor.getString(3));
System.out.println(cursor.getString(4));
System.out.println(cursor.getString(5));
System.out.println(cursor.getString(6));
*/
course.setCourseName(cursor.getString(0));
course.setUniversity(cursor.getString(1));
course.setCourseDuration(cursor.getString(2));
course.setStudyMode(cursor.getString(3));
course.setQualification(cursor.getString(4));
course.setEntryStandards(cursor.getString(5));
course.setGradProspects(cursor.getString(6));
course.setStudentSatisfaction(cursor.getString(7));
return course;
}
public void addCourse(Course course)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COURSE_NAME, course.getCourseName());
values.put(UNI_NAME, course.getUniversity());
values.put(COURSE_DURATION, course.getCourseDuration());
values.put(COURSE_STUDY_MODE, course.getStudyMode());
values.put(COURSE_QUALIFICATION, course.getQualification());
values.put(COURSE_ENTRY_STANDARDS, course.getEntryStandards());
values.put(COURSE_GRADUATE_PROSPECTS, course.getGradProspects());
values.put(COURSE_STUDENT_SATISFACTION, course.getStudentSatisfaction());
db.insert(TABLE_COURSES,
null, //nullColumnHack
values);
db.close();
}
public ArrayList<Course> getAllCourses()
{
ArrayList<Course> courses = new ArrayList<>();
// 1. build the query
String query = "SELECT * FROM " + TABLE_COURSES;
// 2. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
// 3. go over each row, build course and add it to list
Course course;
if(cursor.moveToFirst()){
cursor.moveToNext();
do{
course = new Course();
course.setCourseName(cursor.getString(1));
course.setUniversity(cursor.getString(2));
course.setCourseDuration(cursor.getString(3));
course.setStudyMode(cursor.getString(4));
course.setQualification(cursor.getString(5));
course.setEntryStandards(cursor.getString(6));
course.setGradProspects(cursor.getString(7));
course.setStudentSatisfaction(cursor.getString(8));
// Add course to courses list
courses.add(course);
} while(cursor.moveToNext());
}
// return courses
return courses;
}
public int getDBCount()
{
SQLiteDatabase db = this.getWritableDatabase();
String count = "SELECT count(*) FROM courses";
Cursor mcursor = db.rawQuery(count, null);
mcursor.moveToFirst();
int icount = mcursor.getInt(0);
return icount;
}
public void deleteCourse(Course course) {
// 1. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
// 2. delete
db.delete("courses", //table name
"Course_name = ? AND Uni_name = ?", // selections
new String[] { course.getCourseName(), course.getUniversity() }); //selections args
// 3. close
db.close();
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
Method that loads data from CSV file to SQlite DB
public void populateCourseDatabase(int id) {
// NOW POPULATE THE COURSE DATABASE FILE
inputStream = getResources().openRawResource(R.raw.coursesone);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String word;
String cvsSplitBy = ",";
try{
while((word = reader.readLine()) != null){
Log.d(TAG, "constructing Course object from: " + word);
String[] segment = word.split(cvsSplitBy);
Course course = new Course();
course.setCourseName(segment[0]);
course.setUniversity(segment[1]);
course.setCourseDuration(segment[2]);
course.setStudyMode(segment[3]);
course.setQualification(segment[4]);
course.setEntryStandards(segment[5]);
course.setGradProspects(segment[6]);
course.setStudentSatisfaction(segment[7]);
myCourseDBHelper.addCourse(course);
progressBar.setProgress(count);
count = count + 1;
System.out.println("Sucessfully added: " + course.toString());
}
}
catch(IOException e1){
e1.printStackTrace();
System.out.println("SOMETHING WENT WRONG");
}
}
SQLiteOpenHelper onCreate() and onUpgrade() callbacks are invoked when the database is actually opened, for example by a call to getWritableDatabase().onCreate() is only run when the database file did not exist and was just created. onUpgrade() is only called when the database file exists but the stored version number is lower than requested in constructor.Increment the database version so that onUpgrade() is invoked.
Example pseudo code below
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch(oldVersion) {
case 1:
//upgrade logic from version 1 to 2
case 2:
//upgrade logic from version 2 to 3
case 3:
//upgrade logic from version 3 to 4
break;
default:
throw new IllegalStateException(
"onUpgrade() with unknown oldVersion " + oldVersion);
}
}

android onUpgrade moving some records from old db to new db

What I'm trying to achieve is that my application will ship with an existing sqlite database exported from my web panel with some records(news, products, categories etc.) and later on it will insert some records of its own into it(lets say it'll insert notifications it receives) and it will be copied to the databases folder, up to here there is no problem but my concern is when a user upgrades their application through market I want to replace the new database with the old one but keep those application generated records(notifications it has received) and insert them into the new one. Here's my code so far: (please enhance if necessary)
public class Helper_Db extends SQLiteOpenHelper{
public static final String DB_NAME = "Test.sqlite";
public static final int DB_VERSION = 3;
private static String DB_PATH = "";
private SQLiteDatabase _db;
private final Context _ctx;
public Helper_Db(Context context) {
super(context, null, null, 1);
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
_ctx = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
try
{
copyDatabase();
Log.e("DATABASE", "Database created");
}
catch(IOException io)
{
Log.e("DATABASE", io.toString());
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//take out the notifications from old db
//insert them into the new db
//delete the old db
//copy the new db
}
private void copyDatabase() throws IOException
{
InputStream input = _ctx.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream output = new FileOutputStream(outFileName);
byte [] buffer = new byte [1024];
int length;
while((length = input.read(buffer)) > 0)
{
output.write(buffer, 0, length);
}
output.flush();
output.close();
input.close();
}
public boolean openDatabase() throws SQLException
{
String path = DB_PATH + DB_NAME;
_db = SQLiteDatabase.openDatabase(path, null,
SQLiteDatabase.CREATE_IF_NECESSARY);
return _db != null;
}
#Override
public void close()
{
if(_db != null)
{
_db.close();
}
super.close();
}
}
Thanks in advance.
I do something similar. I have default content in a database that I ship with the app that changes sometimes. However, I have a routine for synchronizing databases for syncing between users and with backups, and each time I upgrade the DB, I just take the included DB and sync it with the existing user's DB.
That may be too much for your needs, but this brings me to how I know whether data is user data or not which seems like is the real problem here. You need to determine what data is user data. Then all you need to do is copy that data.
So, my recommendation is to create an integer column in each database table called something like "IncludedContent" and set that to 1 on all data that you include in your shipped database and set the default value to 0 which is what all user content will have. Then all you have to so is attach the databases using the Attach command something like this:
db.execSQL("ATTACH DATABASE ? AS Old_DB", new String[]{fullPathToOldDB});
and then do an insert like this to copy only user content:
db.execSQL("INSERT INTO New_DB.TABLE SELECT * FROM Old_DB.TABLE WHERE IncludedContent = 0");

Populating SQLite Database

I am not very much familiar with android sqlite database. I only have rough idea of populating sqlite database. I have followed some tutorials but they tells different things.
I have an android project and one of its' packeges is a .db
This package consists of 5 different classes. They are:
DataAdapter.java
DataBaseHelper.java
DBAdapter.java
LoadDBActivity.java
SelectDBAdapter.java
I know SelectDBAdapter class is used to select data from the database. My database is in asset folder which is in .jpeg format.I can open it from sqliteBrowser.
Actually, what I want to know is why should we use these different classes ? and what's the purpose of each and every class ?
I am really sorry, I cannot post codes since this projects belongs to another person (my friend).
I would be much obliged if anyone could be so kind enough to explain the meaning of using these different classes and why should we use such a senario ?
From my development experience , I always prefer to add a prepared sqlite database file in the /res/raw folder.You create/manage sqlite database using Sqlite Manager addon of Firefox , it's a great tool. This method is really great because
firstly I don't need to write a bunch of codes for creating/managing database.
Most importantly , some applications needs to read from a pre-populated database. I don't need to care about what the app requires and whether database is empty or filled already. It serves all purpose. I just need to write some methods that runs the required simple sqls.
Here is my own customised DatabaseHelper class. To use this class you'll need to follow some instructions.
If sqlite database size is more than 1MB then split the file into chunks , I prefer 512KB chunks and place them into /res/raw directory.
Edit the package name and your db file names in the following class.
package your.packagee.name;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import android.widget.Toast;
public class DataBaseHelper extends SQLiteOpenHelper {
private static final String pkg = "your package name";
private static String DB_PATH = "/data/data/" + pkg + "/databases/";
private static String DB_NAME = "yourDBFile.sqlite";
int[] dbfiles = { R.raw.chunk1 , R.raw.chunk2 ..... };
private SQLiteDatabase myDataBase;
private final Context myContext;
public DataBaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
public void createDataBase() {
boolean dbExist = checkDataBase();
if (dbExist) {
// do nothing - database already exist
} else {
this.getReadableDatabase();
try {
CopyDataBase();
} catch (IOException e) {
Toast.makeText(myContext, e.getMessage(), Toast.LENGTH_SHORT)
.show();
Log.d("Create DB", e.getMessage());
}
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.NO_LOCALIZED_COLLATORS);
} catch (SQLiteException e) {
Toast.makeText(myContext, e.getMessage(), Toast.LENGTH_SHORT)
.show();
Log.d("Check DB", e.getMessage());
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
private void CopyDataBase() throws IOException {
InputStream databaseInput = null;
Resources resources = myContext.getResources();
String outFileName = DB_PATH + DB_NAME;
OutputStream databaseOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[512];
int length;
for (int i = 0; i < dbfiles.length; i++) {
databaseInput = resources.openRawResource(dbfiles[i]);
while ((length = databaseInput.read(buffer)) > 0) {
databaseOutput.write(buffer, 0, length);
databaseOutput.flush();
}
databaseInput.close();
}
databaseOutput.flush();
databaseOutput.close();
}
public void openDataBase() throws SQLException {
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.NO_LOCALIZED_COLLATORS);
}
#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) {
}
public boolean deleteItem (String ID){
String query = "delete from item where id='" + ID + "'" ;
Log.d("Query : ", query);
try{
myDataBase.execSQL(query);
return true ;
} catch (Exception e){
Log.d("Exception", e.toString());
return false ;
}
}
public Cursor getSearchFromID(String id) {
return myDataBase.rawQuery("select * from item where id = \"" + id + "\"", null);
}
public boolean addSave(String type, String data , String time) {
String query = "insert into item (type, data , timestamp) values ('" + type
+ "', '" + data + "', '" + time + "')";
try {
myDataBase.execSQL(query);
return true ;
} catch (Exception e) {
return false ;
}
}
}
Here's some methods written as a sample , how to use it.
Usage is simple. When your application starts , that means in your Launcher activity use this code to initialize your database
DataBaseHelper helper = new DataBaseHelper(this);
helper.createDataBase();
helper.openDataBase();
helper.close();
Then just use the methods written in DatabaseHelper class. A sample will be like this
String id = "1";
DataBaseHelper helper = new DataBaseHelper(this);
helper.openDataBase();
Cursor c = helper.getSearchFromID(id);
if(c.getCount() > 0){
c.moveToFirst();
while(!c.isAfterLast()){
// extract your data from cursor
c.MoveToNext();
}
}
Hope it will solve your all problems about sqlite database in Android. At least it solved for me. Thank you.
There are various way in populating a database. What I do is I create an insert(ObjectType objectName) in the DBAdapter Class. That being said, I create an object class and for this example, I'm going to use Authorized Personnel
public class AuthorizedPersonnelClass {
private String _id;
private String Last_Name;
private String Middle_Name;
private String First_Name;
private String Store_ID;
private String Status;
private String New_Personnel;
//of course insert your 2 constructors and getter setter methods here
}
In my DBAdapter, I'll create the insert(AuthorizedPersonnelClass authorizedPersonnel) method to handle the data insertions:
public long addPersonnel(AuthorizedPersonnelClass authorizedPersonnel){
ContentValues values = new ContentValues();
values.put(AUTHORIZEDPERSONNEL_ID, authorizedPersonnel.get_id());
values.put(L_NAME_AUTHORIZED_PERSONNEL, authorizedPersonnel.getLast_Name());
values.put(M_NAME_AUTHORIZED_PERSONNEL, authorizedPersonnel.getMiddle_Name());
values.put(F_NAME_AUTHORIZED_PERSONNEL, authorizedPersonnel.getFirst_Name());
values.put(STATUS, authorizedPersonnel.getStatus());
values.put(STORE_ID, authorizedPersonnel.getStore_ID());
values.put(NEW, authorizedPersonnel.getNew_Personnel());
return this.mDB.insert(TABLE_AUTHORIZED_PERSONNEL, null, values);
}
And from there, let's say I want to populate entries in my onCreate() function or in a button call, I'll just do as such:
//instantiate a global variable for the DBAdapter
DBAdapter db = new DBAdapter(this);
//then if you want to insert
db.insert(new AuthorizedPersonnelClass( /*insert variables here*/ ));
Of course these values may be hard coded or user input (just use EditTexts and extract the Strings and use them there).
Here, I used the ContentValues example because it's easier for beginners to use as opposed to doing a rawQuery Insert statement which may get confusing.

Android application force closing on device

On the Emulator the app runs fine. On the device the moment im trying to copy my database over the application's database and execute a query the app force closes. Any idea why this could be happening? Do i have to request any kind of permissions or something in manifest for it to run?
Database.Java
public class Database extends SQLiteOpenHelper{
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/gr.BHC.www/databases/";
//Name of the Database to be created.
private static String DB_NAME = "BHCLibrary3.sqlite";
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 Database(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{
//First we check if the database already exists, Method declared later
boolean dbExist = checkDataBase();
if(dbExist){
//do nothing - database already exists
}else{
//By calling this method an empty database will be created into the default system path
//of your application so we are going to be able to overwrite that database with our database.
this.getReadableDatabase();
try {
copyDataBase(); //Method declared later
} 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;
boolean checkdb = false;
try{
String myPath = DB_PATH + DB_NAME;
File dbfile = new File(myPath);
//checkdb = SQLiteDatabase.openDatabase(myPath,null,SQLiteDatabase.OPEN_READWRITE);
checkdb = dbfile.exists();
}
catch(SQLiteException e){
System.out.println("Database doesn't exist");
}
return checkdb;
}
/**
* 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 transferring byte stream.
* */
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();
}
//Opening the Database
public void openDataBase() throws SQLException{
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
//Finally overriding a few methods as required
#Override
public synchronized void close() {
if(myDataBase != null)
myDataBase.close();
super.close();
}
#Override
public void onCreate(SQLiteDatabase db) {
//First we check if the database already exists, Method declared later
boolean dbExist = checkDataBase();
if(dbExist){
//do nothing - database already exists
}else{
//By calling this method an empty database will be created into the default system path
//of your application so we are going to be able to overwrite that database with our database.
this.getReadableDatabase();
try {
copyDataBase(); //Method declared later
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
And Results.java (The activity i run my query)
public class SearchResults extends ListActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.searchresults);
Database myDbHelper = new Database(null);
myDbHelper = new Database(this);
}
// Get the intent, verify the action and get the query
Intent intent = getIntent();
String query = intent.getStringExtra(SearchManager.QUERY);
SQLiteDatabase myDb = myDbHelper.getReadableDatabase();
//Executing our query against the server using rawQuery and getting the cursor
String select="SELECT DISTINCT b._ISBN as _id, b.BookTitle, b.Edition, b.Year, b.Pages, b.Rating, c.Category, p.Publisher, w.LastName" +
" FROM" +
" Books b" +
" JOIN Categories_Books cb ON cb._Books_ISBN = _id" +
" JOIN Categories c ON c._CategoryID = cb._Categories_CategoryID" +
" JOIN Publishers p ON p._PublisherID = b.PublisherID" +
" JOIN Writers_Books wb ON wb._Books_ISBN = _id" +
" JOIN Writers w ON w._WriterID = wb._Writers_WriterID" +
" WHERE b.BookTitle LIKE '%" + query +"%'" +
" OR c.Category LIKE '%" + query +"%'" +
" OR p.Publisher LIKE '%" + query +"%'" +
" OR w.LastName LIKE '%" + query +"%'" +
" OR _id LIKE '%" + query +"%'" +
" GROUP BY b.BookTitle";
Cursor c = myDb.rawQuery(select, null);
startManagingCursor(c);
// the desired columns to be bound
String[] columns = new String[] { "Books.BookTitle", "Publishers.Publisher" };
// the XML defined views which the data will be bound to
int[] to = new int[] { R.id.ISBN_entry, R.id.Title_entry };
//Getting results into our listview
try
{
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, R.layout.listlayout, c, columns, to);
this.setListAdapter(mAdapter);
}
catch( Exception e)
{
}
}
}
Help would be appreciated.
EDIT: The error im getting is : java.lang.runtimeexception: Unable to start activity Componentinfo(gr.BHC.www/gr.BHC.www.SearchResults} and then various exceptions saying table books etc dont exist.
EDIT2: I saw the exception im getting usually related with content providers but i still cant figure out why i'd get that.
I think I solved the problem. I made some changes on your codes and now it is working. Here are the codes:
SearchResults.java
public class SearchResults extends ListActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.searchresults);
DbManager myDbHelper = new DbManager(null);
myDbHelper = new DbManager(this);
// Get the intent, verify the action and get the query
myDbHelper.createNewDatabase();
try {
myDbHelper.open();
Log.d("Search Results", "database opened");
} catch (SQLException sqle) {
throw sqle;
}
Intent intent = getIntent();
String query = intent.getStringExtra(SearchManager.QUERY);
// Executing our query against the server using rawQuery and getting the
// cursor
String select = "SELECT DISTINCT b._ISBN as _id, b.BookTitle, b.Edition, b.Year, b.Pages, b.Rating, c.Category, p.Publisher, w.LastName"
+ " FROM"
+ " Books b"
+ " JOIN Categories_Books cb ON cb._Books_ISBN = _id"
+ " JOIN Categories c ON c._CategoryID = cb._Categories_CategoryID"
+ " JOIN Publishers p ON p._PublisherID = b.PublisherID"
+ " JOIN Writers_Books wb ON wb._Books_ISBN = _id"
+ " JOIN Writers w ON w._WriterID = wb._Writers_WriterID"
+ " WHERE b.BookTitle LIKE '%"
+ query
+ "%'"
+ " OR c.Category LIKE '%"
+ query
+ "%'"
+ " OR p.Publisher LIKE '%"
+ query
+ "%'"
+ " OR w.LastName LIKE '%"
+ query
+ "%'"
+ " OR _id LIKE '%"
+ query
+ "%'"
+ " GROUP BY b.BookTitle";
Cursor c = myDbHelper.rawQ(select);
startManagingCursor(c);
// the desired columns to be bound
String[] columns = new String[] { "Books.BookTitle",
"Publishers.Publisher" };
// the XML defined views which the data will be bound to
int[] to = new int[] { R.id.ISBN_entry, R.id.Title_entry };
// Getting results into our listview
try {
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this,
R.layout.listlayout, c, columns, to);
this.setListAdapter(mAdapter);
} catch (Exception e) {
}
}
}
And your new database helper, DbManager:
DbManager.java
public class DbManager extends SQLiteOpenHelper {
private static final String DB_NAME = "BHCLibrary3.sqlite";
private static final String DB_PATH = "/data/data/gr.BHC.www/databases/";
private static final Integer DB_VERSION = 1;
private static final String TAG = "DbManager";
private final Context context;
private SQLiteDatabase db;
private DbManager dbManager;
public DbManager(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.context = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE 'notes' (_id integer primary key autoincrement, title text not null);");
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
public DbManager open() {
dbManager = new DbManager(context);
db = dbManager.getWritableDatabase();
return this;
}
public void createNewDatabase() {
InputStream assetsDB = null;
try {
assetsDB = context.getAssets().open(DB_NAME);
OutputStream dbOut = new FileOutputStream(DB_PATH + DB_NAME);
byte[] buffer = new byte[1024];
int length;
while ((length = assetsDB.read(buffer)) > 0) {
dbOut.write(buffer, 0, length);
}
dbOut.flush();
dbOut.close();
assetsDB.close();
Log.i(TAG, "New database created...");
} catch (IOException e) {
Log.e(TAG, "Could not create new database...");
e.printStackTrace();
}
}
public Cursor rawQ(String select) {
return db.rawQuery(select, null);
}
}
Looks like the size of your database exceeds one MB. In that case you need to store it in the assets folder as .jpg and then copy it over. This is because Android places a restriction on the size of the text assets.

Categories