I don't know where are my mistakes. I am trying to store the lyrics.db file in my DB_PATH when the database doesn't exist and my checkDatabase method returns false, or my DB is obsolete.
However, I get the following :-
E/SQLiteLog: (14) cannot open file at line 36356 of [605907e73a]
(14) os_unix.c:36356: (2) open(/data/user/0/id.ac.umn.project_uts_mobile_16862/filesid.ac.umn.project_uts_mobile_16862/databases/lyrics.db) -
(1) Process ts_mobile_16862 : Pid (12455) Uid (10196) Euid (10196) Gid (10196) Egid (10196)
(1) osStat failed "/data/user/0/id.ac.umn.project_uts_mobile_16862/filesid.ac.umn.project_uts_mobile_16862/databases/lyrics.db" due to error (2)
(1) osStat failed "/data/user/0/id.ac.umn.project_uts_mobile_16862/filesid.ac.umn.project_uts_mobile_16862/databases" due to error (2)
(1) osStat failed "/data/user/0/id.ac.umn.project_uts_mobile_16862/filesid.ac.umn.project_uts_mobile_16862" due to error (2)
(1) Stat of /data/user/0/id.ac.umn.project_uts_mobile_16862 : st_mode(40700) st_uid(10196) st_gid(10196) st_ino(265643)
(1) Stat of /data/user/0 : st_mode(40771) st_uid(1000) st_gid(1000) st_ino(262147)
(1) Stat of /data/user : st_mode(40711) st_uid(1000) st_gid(1000) st_ino(196619)
(1) Stat of /data : st_mode(40771) st_uid(1000) st_gid(1000) st_ino(2)
E/SQLiteDatabase: Failed to open database '/data/user/0/id.ac.umn.project_uts_mobile_16862/filesid.ac.umn.project_uts_mobile_16862/databases/lyrics.db'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 1294): Could not open database
#################################################################
Error Code : 1294 (SQLITE_CANTOPEN_ENOENT)
Caused By : Specified directory or database file does not exist.
(unknown error (code 1294): Could not open database)
#################################################################
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:272)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:213)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:701)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:272)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:239)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:1276)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:1231)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:915)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:864)
at id.ac.umn.project_uts_mobile_16862.DbHelper.checkDatabase(DbHelper.java:50)
at id.ac.umn.project_uts_mobile_16862.DbHelper.createDB(DbHelper.java:85)
at id.ac.umn.project_uts_mobile_16862.show_lyrics.onCreate(show_lyrics.java:22)
at android.app.Activity.performCreate(Activity.java:7258)
at android.app.Activity.performCreate(Activity.java:7249)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1222)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2927)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3059)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1724)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:7000)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
it's my code for load the DB
public class DbHelper extends SQLiteOpenHelper {
private static String DB_PATH = "";
private static String DB_NAME = "lyrics.db";
private SQLiteDatabase vDatabase;
private Context vContext = null;
public DbHelper(Context context) {
super(context, DB_NAME, null, 1);
if( Build.VERSION.SDK_INT >= 17)
DB_PATH = context.getFilesDir().getPath()+context.getPackageName()+"/databases/";
else
DB_PATH = context.getApplicationInfo().dataDir+"/databases/";
this.vContext = context;
}
#Override
public synchronized void close() {
if( vDatabase != null ) {
vDatabase.close();
}
super.close();
}
private boolean checkDatabase() {
SQLiteDatabase dbTemp = null;
try{
String path = DB_PATH + DB_NAME;
dbTemp = SQLiteDatabase.openDatabase(path, null, OPEN_READWRITE);
} catch ( SQLiteException e) { }
if (dbTemp != null ) {
dbTemp.close();
}
return dbTemp != null;
}
public void copyDB() throws SQLiteException{
try {
InputStream myInput = vContext.getAssets().open(DB_NAME);
String outputFileName = DB_PATH + DB_NAME;
Log.d("LIFECYCLE", outputFileName);
OutputStream myOutput = new FileOutputStream(outputFileName);
byte[] buffer = new byte[1024];
int length;
while( (length=myInput.read(buffer)) > 0 ){
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
} catch ( IOException e) {
e.printStackTrace();
}
}
public void openDB() {
String path = DB_PATH + DB_NAME;
vDatabase = SQLiteDatabase.openDatabase(path, null, OPEN_READWRITE);
}
public void createDB() {
boolean dbExist = checkDatabase();
if ( dbExist ){
}
else {
this.getReadableDatabase();
copyDB();
}
}
public List<Lyric> getAllSong(){
List<Lyric> temp = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor;
try{
cursor = db.rawQuery( "SELECT * FROM lyrics" , null);
if( cursor == null) return null;
cursor.moveToFirst();
do {
Lyric lyric = new Lyric(
cursor.getString(cursor.getColumnIndex("index")),
cursor.getString(cursor.getColumnIndex("song")),
cursor.getString(cursor.getColumnIndex("year")),
cursor.getString(cursor.getColumnIndex("artist")),
cursor.getString(cursor.getColumnIndex("genre")),
cursor.getString(cursor.getColumnIndex("lyrics"))
);
temp.add(lyric);
} while (cursor.moveToNext());
cursor.close();
} catch ( Exception e){ }
db.close();
return temp;
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
I've already trying to debug this code for almost 15 hours, and even don't get a single clue, where are my mistakes.
how to check, if that path exist? and how to make directory / path if it didn't exist?
Step by Step guide.
1. Create the database using an appropriate SQLite management tool with the table lyrics populated with the required data. Ensuring the database is saved.
In this case NaviCat was used and the following SQL was used to create and populate the lyrics table.
:-
CREATE TABLE IF NOT EXISTS lyrics (
id INTEGER PRIMARY KEY,
song TEXT,
year TEXT,
artist TEXT,
genre TEXT,
lyrics TEXT
);
INSERT INTO lyrics (song, year, artist, genre, lyrics) VALUES
('song1','1970','Fred','Rock','Rock rock rock'),
('song2','1980','Mary','Pop','Pop pop pop'),
('song3','1960','Sue','Folk','Folk folk folk');
Note index is a keyword so is not a valid column name unless it is enclosed, so id has been used instead of index.
2. The file was saved as lyrics.db and copied into the assets folder of the project.
3. DbHelper.java (various modifications)
public class DbHelper extends SQLiteOpenHelper {
private static String DB_NAME = "lyrics.db";
private SQLiteDatabase vDatabase;
private Context vContext;
public DbHelper(Context context) {
super(context, DB_NAME, null, 1);
this.vContext = context;
// Copy the DB if need be when instantiating the DbHelper
if (!checkDataBase()) {
copyDB();
}
vDatabase = this.getWritableDatabase(); //Get the database when instantiating
}
/**
* No need for build version check as getDataBasePath works for all versions
* No need for open and close of Database, just open it once for the lifetime (more efficient)
*/
/**
* 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() {
/**
* Does not open the database instead checks to see if the file exists
* also creates the databases directory if it does not exists
* (the real reason why the database is opened, which appears to result in issues)
*/
File db = new File(vContext.getDatabasePath(DB_NAME).getPath()); //Get the file name of the database
Log.d("DBPATH","DB Path is " + db.getPath());
if (db.exists()) return true; // If it exists then return doing nothing
// Get the parent (directory in which the database file would be)
File dbdir = db.getParentFile();
// If the directory does not exist then make the directory (and higher level directories)
if (!dbdir.exists()) {
db.getParentFile().mkdirs();
dbdir.mkdirs();
}
return false;
}
public void copyDB() throws SQLiteException{
try {
InputStream myInput = vContext.getAssets().open(DB_NAME);
String outputFileName = vContext.getDatabasePath(DB_NAME).getPath(); //<<<<<<<<<< changed
Log.d("LIFECYCLE", outputFileName);
OutputStream myOutput = new FileOutputStream(outputFileName);
byte[] buffer = new byte[1024];
int length;
while( (length=myInput.read(buffer)) > 0 ){
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
} catch ( IOException e) {
e.printStackTrace();
}
}
public List<Lyric> getAllSong(){
List<Lyric> temp = new ArrayList<>();
Cursor cursor = vDatabase.query("lyrics",null,null,null,null,null,null);
//Cursor cursor = db.rawQuery( "SELECT * FROM lyrics" , null); // used query method generally preferred to rawQuery
//if( cursor == null) return null; // Cursor will not be null may be empty
//cursor.moveToFirst(); // changed to use simpler loop
while (cursor.moveToNext()) {
Lyric lyric = new Lyric(
//cursor.getString(cursor.getColumnIndex("index")), //<<<<<<< changed due to column name change
cursor.getString(cursor.getColumnIndex("id")),
cursor.getString(cursor.getColumnIndex("song")),
cursor.getString(cursor.getColumnIndex("year")),
cursor.getString(cursor.getColumnIndex("artist")),
cursor.getString(cursor.getColumnIndex("genre")),
cursor.getString(cursor.getColumnIndex("lyrics"))
);
temp.add(lyric);
}
cursor.close();
//db.close(); // inefficient to keep on opening and closing db
return temp;
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
Check the comments re modifications
4. Uninstall the existing App or delete the App's data (IMPORTANT)
5. Test it.
The following is an activity that will test the above.
public class MainActivity extends AppCompatActivity {
DbHelper vDBHlpr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vDBHlpr = new DbHelper(this);
List<Lyric> mylyricslist = vDBHlpr.getAllSong();
for (Lyric l: mylyricslist) {
Log.d("LYRICFROMDB","Song is " + l.getSong() + " Year is " + l.getYear() + " Artist is " + l.getArtist() + " Genre is " + l.getGenre() + " Lyrics are " + l.getLyrics());
}
}
}
The log should include (first run) :-
03-17 19:42:11.067 16057-16057/? D/DBPATH: DB Path is /data/data/com.example.so55199382lyrics/databases/lyrics.db
03-17 19:42:11.067 16057-16057/? D/LIFECYCLE: /data/data/com.example.so55199382lyrics/databases/lyrics.db
03-17 19:42:11.086 16057-16057/? D/LYRICFROMDB: Song is song1 Year is 1970 Artist is Fred Genre is Rock Lyrics are Rock rock rock
03-17 19:42:11.086 16057-16057/? D/LYRICFROMDB: Song is song2 Year is 1980 Artist is Mary Genre is Pop Lyrics are Pop pop pop
03-17 19:42:11.086 16057-16057/? D/LYRICFROMDB: Song is song3 Year is 1960 Artist is Sue Genre is Folk Lyrics are Folk folk folk
or for subsequent runs :-
03-17 19:49:11.275 16136-16136/? D/DBPATH: DB Path is /data/data/com.example.so55199382lyrics/databases/lyrics.db
03-17 19:49:11.279 16136-16136/? D/LYRICFROMDB: Song is song1 Year is 1970 Artist is Fred Genre is Rock Lyrics are Rock rock rock
03-17 19:49:11.279 16136-16136/? D/LYRICFROMDB: Song is song2 Year is 1980 Artist is Mary Genre is Pop Lyrics are Pop pop pop
03-17 19:49:11.279 16136-16136/? D/LYRICFROMDB: Song is song3 Year is 1960 Artist is Sue Genre is Folk Lyrics are Folk folk folk
Note run twice so you check both the copy process and handling of the existing db.
The above was tested on emulators running Android Lollipop and Pie
I've already trying to debug this code for almost 15 hours, and even
don't get a single clue, where are my mistakes.
Your issue is that the databases directory doesn't exist when you try opening the database in the checkDatabase method.
The clue is here :-
Error Code : 1294 (SQLITE_CANTOPEN_ENOENT)
Caused By : Specified directory or database file does not exist.
(unknown error (code 1294): Could not open database)
The path is typically data/data/your_package/databases/your_database_file
data/data will exist as it's part of android.
The package sub-directory will exist as part of installing the package.
The databases directory does not initially exist, using a sub-class of SQLiteOpenHelper will, when creating the database, create the databases folder and hence why you see attempts to open the database via such a helper, simply to create the databases directory. However, this can be problematic as from Android Pie on SQLite WAL mode is used by default, which unless the -shm and -wal files are deleted before the copy of the database, result in an empty database being created (-wal/-shm files do not belong/correlate to the copied database so database file is deleted/emptied).
I'd suggest that rather than trying to open the database that you check to see if the File exists and if not to then check if the File's parentfile exists (the databases directory) and if that doesn't exist to use the mkdirs method to create the directory.
The following is an example method that does all the above checking :-
/**
* 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() {
/**
* Does not open the database instead checks to see if the file exists
* also creates the databases directory if it does not exists
* (the real reason why the database is opened, which appears to result in issues)
*/
File db = new File(myContext.getDatabasePath(DB_NAME).getPath()); //Get the file name of the database
Log.d("DBPATH","DB Path is " + db.getPath());
if (db.exists()) return true; // If it exists then return doing nothing
// Get the parent (directory in which the database file would be)
File dbdir = db.getParentFile();
// If the directory does not exist then make the directory (and higher level directories)
if (!dbdir.exists()) {
db.getParentFile().mkdirs();
dbdir.mkdirs();
}
return false;
}
Note the above uses the recommended getDatabasePath so there is no need to hard code anything other than the database name (you may wish to adopt this throughout your code).
Related
I don't know what is the problem of my database, my app keep stopping after i added the data base code.
Please can you help with to fix that.
I have tried many times to figure it out but still not getting anywhere.
This is my data base code :
public class databaseOpenHelper extends SQLiteOpenHelper{
// Country table name
private static final String TABLE_NAME= "contacts";
// Country Table Columns names
private static final String KEY_ID = "id";
private static final String NAME = "Name";
private static final String PHONENO = "PhoneNo";
public databaseOpenHelper(Context context){
super(context,"Login.db",null,1);
}
#Override
public void onCreate(SQLiteDatabase myDB) {
myDB.execSQL("create Table users(username Text primary key,password Text)");
// create the table for the first time
String CREATE_COUNTRY_TABLE = "CREATE TABLE " + TABLE_NAME + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + NAME + " TEXT,"
+ PHONENO + " TEXT" + ")";
myDB.execSQL(CREATE_COUNTRY_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase myDB, int i, int i1) {
myDB.execSQL("drop Table if exists users");
}
public Boolean isertData(String username,String password){
SQLiteDatabase myDB = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("username",username);
contentValues.put("password",password);
long result = myDB.insert("users",null,contentValues);
if(result == -1){
return false;
}
else {
return true;
}
}
public Boolean checkusername(String username){
SQLiteDatabase myDB = this.getWritableDatabase();
Cursor cursor = myDB.rawQuery("select * from users where username = ?",new String[] {username});
if (cursor.getCount()>0){
return true;
}
else {
return false;
}
}
public Boolean checkusernamePassword(String username,String password){
SQLiteDatabase myDB = this.getWritableDatabase();
Cursor cursor = myDB.rawQuery("select * from users where username = ? and password = ?",new String[] {username,password});
if (cursor.getCount()>0){
return true;
}
else{
return false;
}
}
// method to add the contact
public void addcontact(ContactModel contact){
SQLiteDatabase db=this.getWritableDatabase();
ContentValues c=new ContentValues();
c.put(NAME,contact.getName());
c.put(PHONENO,contact.getPhoneNo());
db.insert(TABLE_NAME,null,c);
db.close();
}
// method to retrieve all the contacts in List
public List<ContactModel> getAllContacts(){
List<ContactModel> list=new ArrayList<>();
String query="SELECT * FROM "+TABLE_NAME;
SQLiteDatabase db=this.getReadableDatabase();
Cursor c=db.rawQuery(query,null);
if(c.moveToFirst()) {
do {
list.add(new ContactModel(c.getInt(0),c.getString(1),c.getString(2)));
} while (c.moveToNext());
}
return list;
}
// get the count of data, this will allow user
// to not add more that five contacts in database
public int count(){
int count=0;
String query="SELECT COUNT(*) FROM "+TABLE_NAME;
SQLiteDatabase db = this.getReadableDatabase();
Cursor c=db.rawQuery(query,null);
if(c.getCount()>0){
c.moveToFirst();
count=c.getInt(0);
}
c.close();
return count;
}
// Deleting single country
public void deleteContact(ContactModel contact) {
SQLiteDatabase db = this.getWritableDatabase();
int i=db.delete(TABLE_NAME,KEY_ID + " = ?",
new String[] { String.valueOf(contact.getId()) });
db.close();
}
}
And this is my logcat :
FATAL EXCEPTION: main
Process: com.example.localisation, PID: 11700
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.localisation/com.example.localisation.phone}: android.database.sqlite.SQLiteException: no such table: contacts (code 1 SQLITE_ERROR): , while compiling: SELECT * FROM contacts
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3635)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3792)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: android.database.sqlite.SQLiteException: no such table: contacts (code 1 SQLITE_ERROR): , while compiling: SELECT * FROM contacts
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1047)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:654)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:590)
at android.database.sqlite.SQLiteProgram.(SQLiteProgram.java:62)
at android.database.sqlite.SQLiteQuery.(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:46)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1546)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1485)
at com.example.localisation.databaseOpenHelper.getAllContacts(databaseOpenHelper.java:108)
at com.example.localisation.phone.onCreate(phone.java:81)
at android.app.Activity.performCreate(Activity.java:8051)
at android.app.Activity.performCreate(Activity.java:8031)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3608)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3792)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
The failure is saying that there is not a table called contacts as per
Caused by: android.database.sqlite.SQLiteException: no such table: contacts (code 1 SQLITE_ERROR): , while compiling: SELECT * FROM contacts
Running your code and then using the errant getAllContacts method, as indicated in the log by:-
at com.example.localisation.databaseOpenHelper.getAllContacts(databaseOpenHelper.java:108)
Works.
As such it is highly likely that you have added the contacts cable after previously running the App and that this has created the database. The database persists and thus will still exist from on run to the other. As such the onCreate method will not be called, as it is only called once when the database is created.
The easy fix is to uninstall the App and rerun. However, this will delete any existing data.
If you need to keep any data then you should a) increase the version number and then b) add code to the onUpgrade method to create the new table (same code).
For example:-
a)
public databaseOpenHelper(Context context){
super(context,"Login.db",null,2 /*<<<<<<<<<< CHANGED */);
}
b)
#Override
public void onUpgrade(SQLiteDatabase myDB, int i, int i1) {
//myDB.execSQL("drop Table if exists users");
if (i1 == 2) {
String CREATE_COUNTRY_TABLE = "CREATE TABLE " + TABLE_NAME + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + NAME + " TEXT,"
+ PHONENO + " TEXT" + ")";
myDB.execSQL(CREATE_COUNTRY_TABLE);
}
}
You can the see that the contacts table has been created by using App Inspection e.g.
according to the error code you uploaded i noticed this SELECT * FROM contacts which means that you don't have table named contacts in you sqlite database so i recommend you, for testing you should use sqlite browser to create database and add data to it and then use it in your android studio project. if you get any problem fearther don't hesitate to ask it in comments thanks.
It worked by using the hard coded path. Is my path wrong? This is my code for getting the path
public class DatabaseAssets extends SQLiteOpenHelper {
private static String dbName = "questions.db";
Context context;
File dbFile;
public DatabaseAssets(Context context) {
super(context, "questions.db", null, 1);
this.context = context;
File DB_PATH = context.getDatabasePath(dbName);
String db = DB_PATH.getAbsolutePath();
dbFile= new File(db + "questions.db");
}
This is my getWritableDatabase and getReadableDatabase code.
#Override
public synchronized SQLiteDatabase getWritableDatabase() {
if(!dbFile.exists()){
SQLiteDatabase db = super.getWritableDatabase();
copyDataBase(db.getPath());
}
return super.getWritableDatabase();
}
#Override
public synchronized SQLiteDatabase getReadableDatabase() {
if(!dbFile.exists()){
SQLiteDatabase db = super.getReadableDatabase();
copyDataBase(db.getPath());
}
return super.getReadableDatabase();
}
This is my copy code, but I don't think this is the problem.
private void copyDataBase(String dbPath){
try{
InputStream assestDB = context.getAssets().open("databases/"+"questions.db");
OutputStream appDB = new FileOutputStream(dbPath,false);
byte[] buffer = new byte[1024];
int length;
while ((length = assestDB.read(buffer)) > 0) {
appDB.write(buffer, 0, length);
}
appDB.flush();
appDB.close();
assestDB.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
I believe that your issue is because you are using SQLiteDatabase db = super.getReadableDatabase(); or getWritableDatabase (doesn't matter which) and also that you are appending the database name to the database name (and thus the path will be data/data/<the_package_name>/databases/questions.dbquestions.db instead of data/data/<the_package_name>/databases/questions.db) :-
You could fix the path name issue using either :-
public DatabaseAssets(Context context) {
super(context, "questions.db", null, 1);
this.context = context;
File DB_PATH = context.getDatabasePath(dbName);
String db = DB_PATH.getAbsolutePath();
//dbFile = new File(db + "questions.db");
// path will be data/data/<the_package_name>/database/questions.dbquestions.db
dbFile = new File(db);
}
or :-
public DatabaseAssets(Context context) {
super(context,dbName,null,1);
this.context = context;
dbFile = context.getDatabasePath(dbName);
}
In regard to the first mentioned issue, getting a writable or readable database has been used historically to circumvent an issue in that the copy of the asset would fail (due to the databases directory not existing when an App is installed). What this does is create a database which is then overridden JUST to create the databases directory.
With later versions of Android the default mode is now WAL (Write-Ahead Logging), it used to be Journal. With WAL changes to the database are written to the WAL file. Copying the asset will only copy the database not the WAL file. The database open detects an issue (the WAL part does not tally with the database) and the overly kind Android API creates a new empty database rather than failing.
To avoid this issue you can create the missing directory (which is actually more efficient anyway). So instead of :-
if(!dbFile.exists()){
SQLiteDatabase db = super.getWritableDatabase();
copyDataBase(db.getPath());
}
Use :-
if(!dbFile.exists()){
if (!dbFile.getParentFile().exists) {
dbfile.mkdirs()
}
copyDataBase(dbFile.getPath());
}
I build an app that does some calculations in MainActivity.java and stores the results in SQLite database. When the user presses a button, opens the GraphActivity.java with the corresponding GraphView. Maybe it is because I don't have so much experience with SQLite databases yet but I can't get the Graph's X-axis to show the date each result was stored.
So, given that the Insert method and and the Graph take place in separate activities, how can I get the stored dates to show as X-axis in the GraphActivity?
I followed the YouTube tutorial for GraphView date & SQLite but it has the storing and the Graph in the same activity. (https://www.youtube.com/watch?v=lSgK6-cKjmA&list=PLFh8wpMiEi88ojfNpavGpMB0dtP4mvEqa&index=16)
I tried to send the date variable with Intent EXTRAS but it forces you to the GraphActivity when the Save button is pressed.
Then I tried getting the time in the GraphActivity, which works but shows the date in X-axis as continuous "1-1-1970" for every result.
I used format to show the current date with timestamp but still it doesn't show the date each result was stored, just the current date for all.
MainActivity.java: Insert method for the Results and Date
public void insertData() {
try {
(...)
// Gets the time & date the results are stored
String timeStamp = new SimpleDateFormat("d M yy hh:mm").format(Calendar.getInstance().getTime());
// Create a ContentValues object where column names are the keys,
// and container attributes from the MainActivity are the values.
ContentValues values = new ContentValues();
values.put(DexameniEntry.COLUMN_CONTAINER_NAME, "TODO");
values.put(DexameniEntry.COLUMN_a, X1aInput);
values.put(DexameniEntry.COLUMN_DATE, timeStamp);
values.put(DexameniEntry.COLUMN_b, X1bInput);
values.put(DexameniEntry.COLUMN_c, X1cInput);
values.put(DexameniEntry.COLUMN_d, dX1StringDouble);
values.put(DexameniEntry.COLUMN_e, eX1StringDouble);
values.put(DexameniEntry.COLUMN_percent, percentX1fromDoubletoString);
(...)
} catch (NumberFormatException e) {
} catch (NullPointerException e) {
}
}
GraphActivity.java : Setting the GraphView
public class GraphActivity extends AppCompatActivity {
(...)
SimpleDateFormat sdf = new SimpleDateFormat("EEE d M yyyy h mm", Locale.US);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.graph_activity);
GraphView bigGraphX1 = findViewById(R.id.bigGraph);
mDbHelper = new ResultsDbHelper(this);
sqLiteDatabase = mDbHelper.getWritableDatabase();
bigGraphX1.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter() {
#Override
public String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return
sdf.format(new Date((long)value));
}else {
return super.formatLabel(value, isValueX);
}
}
});
(...)
EDIT
The DbHelper.class (named ResultsDbHelper)
public class ResultsDbHelper extends SQLiteOpenHelper {
public static final String LOG_TAG = ResultsDbHelper.class.getSimpleName();
// Name of the database in a String type constant (to be referenced later)
private static final String DATABASE_NAME = "containerResults.db";
// Database version in a Integer type constant for updating the database
private static final int DATABASE_VERSION = 1;
// Constructor: Constructs a new instance of ResultsDbHelper.
// * #param is the context of the app
public ResultsDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Modify the onCreate method to have the table created on startup of the app
#Override
public void onCreate(SQLiteDatabase db) {
// Define the schema of the table: which columns will be created by the onCreate method.
// The whole schema creation is put in a String variable (CREATE_RESULTS_TABLE) for easy reference
String CREATE_RESULTS_TABLE = "CREATE TABLE " + DexameniEntry.TABLE_NAME + " ("
+ DexameniEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ DexameniEntry.COLUMN_CONTAINER_NAME + " TEXT NOT NULL, "
+ DexameniEntry.COLUMN_DATE + " TEXT NOT NULL, "
+ DexameniEntry.COLUMN_a + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_b + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_c + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_d + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_e + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_percent + " REAL NOT NULL);";
// Execute the SQL Statement (Create the table)
db.execSQL(CREATE_RESULTS_TABLE);
}
/**
* This is called when the database needs to be upgraded.
*/
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
final String LOG_TAG = ("Upgrading the database from version " + oldVersion + " to " + newVersion);
// on upgrade drop older tables
db.execSQL("DROP TABLE IF EXISTS " + DexameniEntry.TABLE_NAME);
// Recreate tables
onCreate(db);
}
}
I expect the X-axis to display the date each result was stored, so that all the values to show as LineSeries in the GraphView. But I can't seem to get the dates from the database to the Graph so the date is always the same for all, and the LineSeries is not coherent.
EDIT: Before posting the question I had began also looking for a way to put in the GraphActivity a database reference of the DATE column, inside the FormatLabel method. For example
#Override
public String formatLabel(double value, boolean isValueX) {
if (isValueX) {
return
sdf.format(new Date(**put here the DATE column variable so that the X-axis is populated the column's data**);
}else {
return super.formatLabel(value, isValueX);
}
I couldn't do this either because I don't know how to write this code...
EDIT: Picture of the issue
I don't know what else to do to solve this, can you please help me?
EDIT 2: GraphActivity after changes (It seems like the graph still isn't populated by the db data.Maybe problem with Saving the data in the db?idk..)
You are trying to do too much in the MainActivity and you are perhaps having issues with the date as it appears from your comments that they/it is 0.
Basically you probably want to pass the criteria for generating the graph (e.g. a date range for the graph) and then extract the data from the database via methods coded in the Databasehelper (ResultsHelper).
Instead of getting the current time when adding data and storing it in the database in D M Y format. You could simply matters (e.g. extracting data according to a date range) by storing the date in a sortable format and for manipulating/formatting dates in a format that is SQLite friendly primarily YYYY-MM-DD HH:MM:SS (although you could simply store the timestamp).
As such I'd suggest some relatively simple changes.
Change the date column definition to be :-
+ DexameniEntry.COLUMN_DATE + " TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, " //<<<<<<<<<< LET SQLITE GET THE DATE TIME
This allows SQLite to store the current date and time if you simply don't provide a value, which is done by commenting out/deleting the line :- //values.put(DexameniEntry.COLUMN_DATE, timeStamp); //<<<<<<<<<< Use default
Move the insertData method into ResultHeper (it can then be used elsewhere)
Add a method to the ResultHelper to extract the data into a Cursor, including the dynamic generation of columns.
dynamic columns are additional columns generated on the fly telling SQLite to do things.
e.g. say you wanted to add 2 columns a and b, you can say SELECT *, a + b AS my_addition FROM the_table; and the result will include all columns AND the column my_addition.
Pass the basic/minimum selection criteria for extracting the data for the graph from the MainActivity to the GraphActivity and then extract the actual data in the graphActivity.
Note Changed to populate Graph with date labels.
Working Example
The following code, based up your code and the above points, is a working example (it doesn't populate the graph but gets the data).
DexameniEntry.java
public class DexameniEntry {
public static final String[] WEEKDAYS_LONG = new String[]{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
public static final String[] WEEKDAYS_SHORT = new String[]{"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
public static final String _ID = BaseColumns._ID;
public static final String TABLE_NAME = "container_results";
public static final String COLUMN_CONTAINER_NAME = "container_name";
public static final String COLUMN_DATE = "container_date";
public static final String COLUMN_a = "container_value_a";
public static final String COLUMN_b = "container_value_b";
public static final String COLUMN_c = "container_value_c";
public static final String COLUMN_d = "container_value_d";
public static final String COLUMN_e = "container_value_e";
public static final String COLUMN_percent = "container_percent";
public static final String EXTRACT_COLUMN_DATELABEL = "date_label";
public static final String EXTRACT_COLUMN_GRAPHDATELABEL = "graph_date_label";
public static final String INTENTKEY_GRAPHVALUE = "ik_graph_value";
}
This is made up primarily with guess work (column and table names). However note the following two constants (the WEEKDAYS_?? constants could be used)
EXTRACT_COLUMN_DATELABEL (dynamically generated column name) and
EXTRACT_COLUMN_GRAPHDATELABEL (dynamically generated unix timestamp)
INTENTKEY_GRAPHVALUE (used to pass intent value)
ResultHelper
public class ResultsDbHelper extends SQLiteOpenHelper {
public static final String LOG_TAG = ResultsDbHelper.class.getSimpleName();
// Date format that suits SQLite i.e. YYYY-MM-DD HH:MM:SS
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); // Not used but could be useful
// Name of the database in a String type constant (to be referenced later)
private static final String DATABASE_NAME = "containerResults.db";
// Database version in a Integer type constant for updating the database
private static final int DATABASE_VERSION = 1;
SQLiteDatabase mDB;
// Constructor: Constructs a new instance of ResultsDbHelper.
// * #param is the context of the app
public ResultsDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mDB = this.getWritableDatabase(); // Sets mDB (also forces open of DB)
}
// Modify the onCreate method to have the table created on startup of the app
#Override
public void onCreate(SQLiteDatabase db) {
// Define the schema of the table: which columns will be created by the onCreate method.
// The whole schema creation is put in a String variable (CREATE_RESULTS_TABLE) for easy reference
String CREATE_RESULTS_TABLE = "CREATE TABLE " + DexameniEntry.TABLE_NAME + " ("
+ DexameniEntry._ID + " INTEGER PRIMARY KEY, " //<<<<<<<<<< AUTOINCREMENT NOT REQD AS IS INEFFICIENT
+ DexameniEntry.COLUMN_CONTAINER_NAME + " TEXT NOT NULL, "
+ DexameniEntry.COLUMN_DATE + " TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, " //<<<<<<<<<< LET SQLITE GET THE DATE TIME
+ DexameniEntry.COLUMN_a + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_b + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_c + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_d + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_e + " REAL NOT NULL, "
+ DexameniEntry.COLUMN_percent + " REAL NOT NULL);";
// Execute the SQL Statement (Create the table)
db.execSQL(CREATE_RESULTS_TABLE);
}
/**
* This is called when the database needs to be upgraded.
*/
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
final String LOG_TAG = ("Upgrading the database from version " + oldVersion + " to " + newVersion);
// on upgrade drop older tables
db.execSQL("DROP TABLE IF EXISTS " + DexameniEntry.TABLE_NAME);
// Recreate tables
onCreate(db);
}
public void insertData(String name,
Double X1aInput,
Double X1bInput,
Double X1cInput,
Double X1dInput,
Double X1eInput,
Double percent) {
String timeStamp = "";
try {
// Gets the time & date the results are stored
//timeStamp = new SimpleDateFormat("d M yy hh:mm").format(Calendar.getInstance().getTime());
timeStamp = sdf.format(Calendar.getInstance().getTime());
} catch (NumberFormatException e) {
} catch (NullPointerException e) {
}
// Create a ContentValues object where column names are the keys,
// and container attributes from the MainActivity are the values.
ContentValues values = new ContentValues();
values.put(DexameniEntry.COLUMN_CONTAINER_NAME, name);
values.put(DexameniEntry.COLUMN_a, X1aInput);
//values.put(DexameniEntry.COLUMN_DATE, timeStamp); //<<<<<<<<<< Use default
values.put(DexameniEntry.COLUMN_b, X1bInput);
values.put(DexameniEntry.COLUMN_c, X1cInput);
values.put(DexameniEntry.COLUMN_d, X1dInput);
values.put(DexameniEntry.COLUMN_e, X1eInput);
values.put(DexameniEntry.COLUMN_percent, percent);
mDB.insert(DexameniEntry.TABLE_NAME,null,values);
}
public Cursor getAllResults() {
String formatted_date = "strftime('%d %m %Y'," +
DexameniEntry.COLUMN_DATE + ") AS " + DexameniEntry.EXTRACT_COLUMN_DATELABEL;
String unixtype_date = "julianday(" + DexameniEntry.COLUMN_DATE + ") * 86400 * 1000 AS " +DexameniEntry.EXTRACT_COLUMN_GRAPHDATELABEL;
String[] columns = new String[]{"*",formatted_date,unixtype_date};
return mDB.query(DexameniEntry.TABLE_NAME,columns,null,null,null,null,DexameniEntry.COLUMN_DATE + " ASC");
}
}
The date column has been changed to have a special DEFAULT value of CURRENT_TIMESTAMP
The insertData method has been moved here from MainActivity and now requires parameters passed to it (see it being used in MainActivity)
The getAllResults has been added (see GrapActivty for where getAllreults is used)
note that the resultant Cursor has all columns from the table PLUS two extra (dynamically generated) columns that will have the date in DD MM YYYY format (the date column will have the date in YYYY-DD-MM HH:MM:SS format (example output later)) and the other as a unix timestamp. (julianday(the_column) * 86400 * 1000 AS the_column_name )
MainActivity.java
MainActivity loads some data (only the first time it is run) and has a button that when clicked will start GraphActivity.
public class MainActivity extends AppCompatActivity {
Button mShowGraph;
Context mContext;
ResultsDbHelper mDBHlpr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
mShowGraph = this.findViewById(R.id.show_graph);
setupShowGraphButton();
//Instantiate the DatabaseHelper
mDBHlpr = new ResultsDbHelper(this);
// Add some data if none exists
if (DatabaseUtils.queryNumEntries(mDBHlpr.getWritableDatabase(),DexameniEntry.TABLE_NAME) < 1) {
mDBHlpr.insertData("C1", 10.12, 11.12, 12.12, 13.12, 14.12, 25D);
mDBHlpr.insertData("C2", 20.12, 21.12, 22.12, 23.12, 24.12, 35D);
mDBHlpr.insertData("C3", 31.12, 32.12, 33.12, 34.12, 35.12, 25D);
}
}
// Setup the Buttons on click listener to start the GraphActivity
private void setupShowGraphButton() {
mShowGraph.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(mContext,GraphActivity.class);
i.putExtra(DexameniEntry.INTENTKEY_GRAPHVALUE,100);
startActivity(i);
}
});
}
}
GraphActivity
Although this display the Graph it doesn't load any data, rather the dates are extracted from the Database and written to the log.
public class GraphActivity extends AppCompatActivity {
Context mContext;
Button mDone;
GraphView mBigGraphX1;
ResultsDbHelper mDBHlpr;
Cursor mResults;
LineGraphSeries<DataPoint> mLGS;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_graph);
mContext = this;
mDone = this.findViewById(R.id.done);
setupDoneButton();
mDBHlpr = new ResultsDbHelper(this);
mResults = mDBHlpr.getAllResults();
mBigGraphX1 = this.findViewById(R.id.graphview);
demoDatesFromDB();
doTheGraphLineStuff();
}
private void setupDoneButton() {
mDone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
#Override
protected void onDestroy() {
mResults.close(); //<<<<<<<<<< Should always close cursor when done
super.onDestroy();
}
private void demoDatesFromDB() {
StringBuilder sb = new StringBuilder("Data From Table ").append(DexameniEntry.TABLE_NAME).append(" as per :-");
while (mResults.moveToNext()) {
String date_asperdb = mResults.getString(mResults.getColumnIndex(DexameniEntry.COLUMN_DATE));
String date_formatted = mResults.getString(mResults.getColumnIndex(DexameniEntry.EXTRACT_COLUMN_DATELABEL));
long unix_date = mResults.getLong(mResults.getColumnIndex(DexameniEntry.EXTRACT_COLUMN_GRAPHDATELABEL));
sb.append("\n\tResults for row ");
sb.append(String.valueOf(mResults.getPosition() + 1));
sb.append(" Date as per DB is ").append(date_asperdb);
sb.append(" Formatted Date is ").append(date_formatted);
sb.append(" Unix Date is ").append(unix_date);
}
Log.d("DEMODATEINFO",sb.toString());
}
private void doTheGraphLineStuff() {
long one_day = 1000 * 60 * 60 * 24;
mResults = mDBHlpr.getAllResults();
int rowcount = mResults.getCount();
long[] extracted_dates = new long[rowcount];
DataPoint[] dataPoints = new DataPoint[rowcount];
while (mResults.moveToNext()) {
/**
* NOTE as all 3 rows are added within milliseconds this adds on a day
*/
extracted_dates[mResults.getPosition()] = mResults.getLong(
mResults.getColumnIndex(
DexameniEntry.EXTRACT_COLUMN_GRAPHDATELABEL
))
+ (one_day * ((long)mResults.getPosition() + 1L) //<<<< Frig the data show it is one day more than the previous
);
dataPoints[mResults.getPosition()] = new DataPoint(
extracted_dates[mResults.getPosition()],
mResults.getDouble(mResults.getColumnIndex(DexameniEntry.COLUMN_a))
);
}
mLGS = new LineGraphSeries<>(dataPoints);
mBigGraphX1.addSeries(mLGS);
mBigGraphX1.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(mContext));
mBigGraphX1.getGridLabelRenderer().setNumHorizontalLabels(rowcount);
mBigGraphX1.getViewport().setMinX(extracted_dates[0]);
mBigGraphX1.getViewport().setMaxX(extracted_dates[rowcount - 1]);
mBigGraphX1.getViewport().setXAxisBoundsManual(true);
mBigGraphX1.getGridLabelRenderer().setHumanRounding(false);
}
Result
The following is output to the Log :-
2019-01-12 09:01:07.194 3073-3073/so54140390.so54140390graph D/DEMODATEINFO: Data From Table container_results as per :-
Results for row 1 Date as per DB is 2019-01-11 21:02:06 Formatted Date is 11 01 2019
Results for row 2 Date as per DB is 2019-01-11 21:02:06 Formatted Date is 11 01 2019
Results for row 3 Date as per DB is 2019-01-11 21:02:06 Formatted Date is 11 01 2019
So it's just a matter of perhaps changing or adding the formats to suit.
- The bible for this is SQL As Understood By SQLite- Date And Time Functions
The Graph from the above :-
This question already has answers here:
Android Cursor Index out of Bound Exception
(3 answers)
Closed 6 years ago.
I'm trying to retrieve data from sqlite data base but but when I call the nameData() logcat shows the exception:
android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
I don't understand why, any clues?
process:
public class SearchContactByName2 extends AppCompatActivity {
String dbString="",dbString2="";
SQLiteDatabase db;
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.searchcontactbynamelayout2_main);
TextView textView=(TextView)findViewById(R.id.textViewShowName);
TextView textView2=(TextView)findViewById(R.id.textView2ShowNumber);
SearchContactByName objOfSearchContactByName=new SearchContactByName();
ContactDatabase onbOfContactDatabase=new ContactDatabase(getBaseContext());
Cursor allcontact2= onbOfContactDatabase.nameData(objOfSearchContactByName.getNameForSearchTypeString);
allcontact2.moveToFirst();
do{
dbString+=allcontact2.getString(allcontact2.getColumnIndex("name"));
dbString2+=allcontact2.getString(allcontact2.getColumnIndex("phone"));
dbString+="\n";
dbString2+="\n";
textView.setText(dbString);
textView2.setText(dbString2);
}while(allcontact2.moveToNext());
Toast.makeText(getBaseContext(), "data", Toast.LENGTH_LONG).show();
}
}
database part:
public class ContactDatabase extends SQLiteOpenHelper {
SQLiteDatabase db;
public static final String DATABASE_NAME="totalContact.db";
public static final String TABLE_NAME="mecontact";
public static final String NAME="name";
public static final String PHONE="phone";
public ContactDatabase(Context context) {
super(context, DATABASE_NAME, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL("create table mecontact" +
"(id integer primary key autoincrement, name text, phone text)");
}catch(android.database.SQLException e){
System.out.println("table create nhi ho rha");
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS mecontact");
onCreate(db);
}
public void insertContact(String nam,String mob){
db=this.getWritableDatabase();
ContentValues contentValues=new ContentValues();
contentValues.put(NAME,nam);
contentValues.put(PHONE,mob);
db.insert(TABLE_NAME, null, contentValues);
db.close();
}
public Cursor showData(){
db=this.getWritableDatabase();
Cursor res = db.rawQuery("SELECT * FROM mecontact", null);
return res;
}
public Cursor nameData(String dataName){
db=this.getWritableDatabase();
Cursor res = db.rawQuery("SELECT * FROM mecontact WHERE name = '"+dataName+"'", null);
return res;
}
}
try below code
if(allcontact2.moveToFirst()){
do{
dbString+=allcontact2.getString(allcontact2.getColumnIndex("name"));
dbString2+=allcontact2.getString(allcontact2.getColumnIndex("phone"));
dbString+="\n";
dbString2+="\n";
textView.setText(dbString);
textView2.setText(dbString2);
}while(allcontact2.moveToNext());}
Toast.makeText(getBaseContext(), " no data", Toast.LENGTH_LONG).show();
actually your database has no data
Cursor allcontact2= onbOfContactDatabase.nameData(objOfSearchContactByName.getNameForSearchTypeString);
if(allcontact2.size() > 0){
while(allcontact2.moveToNext()){
dbString+=allcontact2.getString(allcontact2.getColumnIndex("name"));
dbString2+=allcontact2.getString(allcontact2.getColumnIndex("phone"));
dbString+="\n";
dbString2+="\n";
textView.setText(dbString);
textView2.setText(dbString2);
}
Toast.makeText(getBaseContext(), "data", Toast.LENGTH_LONG).show();
}
Along with the answer by sush change nameData method to,
public Cursor nameData(String dataName){
db=this.getReadableDatabase();
//String dataname might contain special characters like a quote
//retreive the cursor this way
Cursor res=db.query("mecontact",new String[]{columnsYouwantToSelect},"name =?",new String[]{dataName},null,null,null);
//if you want to select all the columns in the table replace
//the second parameter with null
return res;
}
Not really answering your question, but more advice on how to prevent trouble in the future. I would suggest you change your oncreate code to this and declare your ID value in the top like you did for the others. This will make sure the database is created correctly and that in the future if changes happen you can easily get values without making typing errors. Code like this is safer to use than pure queries.
db.execSQL("CREATE TABLE "
+ TABLE_NAME
+ " (" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ NAME + " TEXT,"
+ PHONE + " TEXT);" );
How can I create a DB table and fill it up with some data onto application startup?I have a init_sql.sql file with create table and insert statements but only CREATE TABLE is executed so I have my table but it is empty.
init_sql.sql
CREATE TABLE IF NOT EXISTS Event (
id INTEGER PRIMARY KEY NOT NULL,
time TEXT NOT NULL,
name TEXT NOT NULL,
description TEXT NOT NULL,
additional_info TEXT,
stage CHAR(50)
);
INSERT INTO Event (name, time, description, stage)
VALUES ('13:30 - 14:30', 'koncert Blue tone Band',
'Mladá, energická jazzfunková kapela Blue tone Band Vás pobaví a rozhýbe zaručeně každého absolventa!', 'mainStage');
I verified that this file is correct by issuing sqlite3 myDb.db < init_sql.sql, this creates the table and inserts data.
My SQLHelper looks like this
public class SQLiteHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "alumni.db";
private Context context;
public SQLiteHelper(Context context) {
super(context, DB_NAME, null, 6);
this.context = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
InputStream stream = context.getResources().openRawResource(R.raw.init_sql);
try {
String sqlString = convertStreamToString(stream);
db.execSQL(sqlString);
} catch (IOException ex) {
//TODO
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS Event;");
onCreate(db);
}
And I am using it inside my DAO class like new SQLiteHelper(context).getWritableDatabase();
So any ideas what could I've been doing wrong?
execSql executes a single SQL command.
When you want to execute multiple commands, you have to execute them separately.
A better idea might be to ship the precreated database with the app.
(In that case, consider using SQLiteAssetHelper.)