For my internship I'm working on an Android application, and trying to get a local database running to set up for offline referal as well as preventing new BasicAuth requests and a required database pull every time the user returns to a certain activity. To achieve this, I'm trying to set up a SQLite database, but things are not really working out.
I'm currently using this tutorial to try and set up the database. For my application specifically I edited the MySQLiteHelper and TicketsDataSource classes.
MySQLiteHelper:
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class MySQLiteHelper extends SQLiteOpenHelper {
public static final String TABLE_TICKETS = "tickets";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_TICKET_ID = "ticketId";
public static final String COLUMN_TICKET_TITLE = "ticketTitle";
public static final String COLUMN_PROJECT_NAME = "projectName";
public static final String COLUMN_CLIENT_NAME = "clientName";
public static final String COLUMN_TICKET_DESCRIPTION = "ticketDescription";
private static final String DATABASE_NAME = "commments.db";
private static final int DATABASE_VERSION = 1;
// Database creation SQL statement
private static final String DATABASE_CREATE = "create table "
+ TABLE_TICKETS
+ "("
+ COLUMN_ID + " integer primary key autoincrement, "
+ COLUMN_TICKET_ID + " text not null, "
+ COLUMN_TICKET_TITLE+ " text not null, "
+ COLUMN_PROJECT_NAME+ " text not null, "
+ COLUMN_CLIENT_NAME+ " text not null, "
+ COLUMN_TICKET_DESCRIPTION+ " text not null);";
public MySQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(MySQLiteHelper.class.getName(),
"Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_TICKETS);
onCreate(db);
}
}
TicketsDataSource:
import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
public class TicketsDataSource {
// Database fields
private SQLiteDatabase database;
private MySQLiteHelper dbHelper;
private String[] allColumns = { MySQLiteHelper.COLUMN_ID,
MySQLiteHelper.COLUMN_TICKET_ID, MySQLiteHelper.COLUMN_TICKET_TITLE, MySQLiteHelper.COLUMN_PROJECT_NAME,
MySQLiteHelper.COLUMN_CLIENT_NAME, MySQLiteHelper.COLUMN_TICKET_DESCRIPTION};
public TicketsDataSource(Context context) {
dbHelper = new MySQLiteHelper(context);
}
public void open() throws SQLException {
database = dbHelper.getWritableDatabase();
}
public void close() {
dbHelper.close();
}
public Ticket createTicket(String ticket) {
ContentValues values = new ContentValues();
values.put(MySQLiteHelper.COLUMN_TICKET_DESCRIPTION, ticket);
long insertId = database.insert(MySQLiteHelper.TABLE_TICKETS, null,
values);
Cursor cursor = database.query(MySQLiteHelper.TABLE_TICKETS,
allColumns, MySQLiteHelper.COLUMN_ID + " = " + insertId, null,
null, null, null);
cursor.moveToFirst();
Ticket newTicket = cursorToTicket(cursor);
cursor.close();
return newTicket;
}
public void deleteTicket(Ticket ticket) {
long id = ticket.getId();
System.out.println("Ticket deleted with id: " + id);
database.delete(MySQLiteHelper.TABLE_TICKETS, MySQLiteHelper.COLUMN_ID
+ " = " + id, null);
}
public List<Ticket> getAllTickets() {
List<Ticket> tickets = new ArrayList<Ticket>();
Cursor cursor = database.query(MySQLiteHelper.TABLE_TICKETS,
allColumns, null, null, null, null, null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Ticket ticket = cursorToTicket(cursor);
tickets.add(ticket);
cursor.moveToNext();
}
// make sure to close the cursor
cursor.close();
return tickets;
}
private Ticket cursorToTicket(Cursor cursor) {
Ticket ticket = new Ticket();
ticket.setId(cursor.getLong(0));
ticket.setTicketId(cursor.getLong(1));
ticket.setTicketTitle(cursor.getString(2));
ticket.setClientName(cursor.getString(3));
ticket.setProjectName(cursor.getString(4));
ticket.setTicketDescription(cursor.getString(5));
return ticket;
}
}
In my activity, I then call the TicketsDataSource class by first defining it:
private TicketsDataSource datasource;
And then calling it from an if-statement that checks if the server has been called succesfully already:
else {
datasource = new TicketsDataSource(this);
datasource.open();
}
Unfortunately, when I switch to the DDMS view, I can't see any database being created after I run the application multiple times. In fact, I can't even see any other folders within the main "data" folder in the DDMS view. I'm not getting any error messages (except for an 'eglSurfaceAttrib not implemented', which seems to be irrelevant after some searching on google) at this moment, but when I place a system print in the onCreate function of the MySQLiteHelper class, it does not print anything in the log (it does appear in the else-statement). I'm not sure if my Java-code is faulty, or if there's something wrong with my general setup.
Thanks in advance for your help,
Dennis
You'll only be able to see files/folders in the /data folder if you're
a: using the emulator, or
b: using a rooted phone. Those are protected folders and can't be viewed by mere mortals.
The real test of what you've written is this - can you write to and read from the database?
The best android db troubleshooting solution for me was to add this method to my SQliteHelper class which will copy your sqlite db to the sd card on the device your testing on. You can then open it up using any number of sqlite manager desktop apps and verify your tables and data. You don't need to root the phone this way. While developing, I stick calls to this method where i need to get a snapshot of the db:
public static void backup() {
try {
File sd = Environment.getExternalStorageDirectory();
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath = "//data//com.example//databases//" + DATABASE_NAME;
String backupDBPath = DATABASE_VERSION + DATABASE_NAME;
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, "//Download//" + 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) {
Log.e(TAG, e.getMessage());
}
}
you need to add external storage permissions to your manifest.
Related
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);
}
}
When I run my android app I keep getting the error (1) no such table userTable, as far as I am aware I am creating the table in
TABLE_CREATE = "create table userTable("
+ USER + " text not null, " + PWD + " text not null, );";
I have two other databases in this project and the are working fine, any help is welcome.
package com.weightpro.db;
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.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class usrPwdDB {
public static final String USER = "userName";
public static final String PWD = "password";
public static final String TABLE_NAME = "userTable";
public static final String DATA_BASE_NAME = "userdatabase";
public static final String KEY_ROWID = "_id";
public static final int DB_VERSION = 2;
private static final String TABLE_CREATE = "create table userTable("
+ USER + " text not null, " + PWD + " text not null, );";
DBHelper WDBHelper;
Context mContext;
SQLiteDatabase db;
public usrPwdDB(Context mContext) {
this.mContext = mContext;
WDBHelper = new DBHelper(mContext);
}
private static class DBHelper extends SQLiteOpenHelper
{
public DBHelper(Context context) {
super(context,DATA_BASE_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
try{
db.execSQL(TABLE_CREATE);
}
catch(SQLException e)
{
e.printStackTrace();
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS userTable");
onCreate(db);
}
}
public usrPwdDB open()
{
db = WDBHelper.getWritableDatabase();
return this;
}
public void close(){
WDBHelper.close();
}
public long insertInfo(String userName, String password){
ContentValues content = new ContentValues();
content.put(USER, userName);
content.put(PWD, password);
return db.insertOrThrow(TABLE_NAME, null, content);
}
public boolean getUserNameAndPassword(String userName, String Password) throws SQLException {
Cursor mCursor =
db.query(true, TABLE_NAME, new String[] {USER,
PWD},USER+"='"+userName+"' AND password='"+Password+"'", null,
null, null, null, null);
if (mCursor.getCount() > 0)
{
return true;
}
return false;}
public Cursor returnData(){
return db.query(TABLE_NAME, new String[] {USER, PWD},null,null,null,null,null);
}
}
remove the last comma , from the create table syntax,
private static final String TABLE_CREATE =
"create table userTable("
+ USER + " text not null, "
+ PWD + " text not null, );"; // remove this comma after not null
The correct syntax should be
private static final String TABLE_CREATE =
"create table userTable("
+ USER + " text not null, "
+ PWD + " text not null );";
You go wrong over here
+ USER + " text not null, " + PWD + " text not null, );"; //remove , from last text not null
correct SQL command with below
private static final String TABLE_CREATE = "create table userTable("
+ USER + " text not null, " + PWD + " text not null);" ;
private static final String TABLE_CREATE = "create table userTable("
+ USER + " text not null, " + PWD + " text not null,);" ;
remove "," after "text not null" and also remove ";"(semicolon) in the string, that is not needed i think,
then clear data or uninstall application then execute again
even though the creation of table failed i think next time onCreate() in SQLiteOpenHelper only executes once, so you will need to clear data of application
if you are using separate class for separate table and using same DB name, then all the tables in the first using class will be ok, and others will not be created since for a single database onCreate() function works only one, even if there is separate classes each with onCreate(),
onCreate() function creates a file in DB location of android file system when first called onCreate(), if the onCreate called again it check for the existence of DBNAME file in DB location and avoid creating if its exit, I think this is logic behind it...
so keep one onCreate() function for a single DB file and create all tables in that function
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.
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.
This is my Database class
public class ProgramDbAdapter{
public static final String KEY_ROWID = "_id";
public static final String KEY_PROGRAM_TITLE = "ProgramTitle";
public static final String KEY_PROGRAM_DATE = "ProgramDate";
public static final String KEY_PROGRAM_TIME = "ProgramTime";
public static final String KEY_PROGRAM_CHANNEL = "ProgramChannel";
private static final String DATABASE_CREATE =
"CREATE TABLE " + DATABASE_TABLE + " (" + "_id integer primary key autoincrement, "
+ "ProgramTitle text, " + "ProgramDate varchar(20), "
+ "ProgramTime varchar(20), " + "ProgramChannel text)";
private static final String DATABASE_UPGRADE = "DROP TABLE IF EXISTS " + DATABASE_TABLE;
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(DATABASE_UPGRADE);
onCreate(db);
}
}
public ProgramDbAdapter open() throws SQLException{
mDbHelper = new DatabaseHelper(mcontext);
mDb = mDbHelper.getWritableDatabase();
return this;
}
public long CreateData(String ProgramTitle, String ProgramDate, String ProgramTime, String ProgramChannel){
ContentValues initialvalues = new ContentValues();
initialvalues.put(KEY_PROGRAM_TITLE, ProgramTitle);
initialvalues.put(KEY_PROGRAM_DATE, ProgramDate);
initialvalues.put(KEY_PROGRAM_TIME, ProgramTime);
initialvalues.put(KEY_PROGRAM_CHANNEL, ProgramChannel);
return mDb.insert(DATABASE_TABLE, null, initialvalues);
}
}
This is my main class
public class Program extends ExpandableListActivity{
public void onCreate(Bundle savedInstanceState) {
mDbHelper = new ProgramDbAdapter(this);
mDbHelper.open();
mDbHelper.CreateData("a","a","a","a");
}
}
when i call open() and createdata function, the logcat tell me no such table:Program. where is the problem is?
There is no varchar type in sqlite, see here. Use text instead.
I don't see where 'DATABASE_TABLE' is coming from.
Also, you should use the "rawQuery()", "query()"-Methods or a "SQLiteStatement" to bind parameters into your SQL-Statement.
And last but not least, SQLite doesn't know any 'varchar'. Check here for all Data types: Link
varchar is translated to text ...
from vladimir link:
If the declared type of the column
contains any of the strings "CHAR",
"CLOB", or "TEXT" then that column has
TEXT affinity. Notice that the type
VARCHAR contains the string "CHAR" and
is thus assigned TEXT affinity.
problem is that u created db in first run and there was different Create statment ...
delete app data from android settings or change DATABASE_VERSION