Query Data from Existing SQLite Database Android - java

I followed this tutorial: http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/ Created db with SQLite Database Browser, put db file in "assets" folder etc..
Here my db structure created using SQLite Database Browser with instructions in tutorial link;
Then i added this method to end of DataBaseHelper class;
public ArrayList<market> getMarkets() {
String table = "markets";
ArrayList<market> markets = new ArrayList<market>();
market mrkt = new market();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + table, null);
if(cursor.moveToFirst()) {
cursor.moveToNext();
do {
mrkt.market_id = cursor.getInt(cursor.getColumnIndex("marketid"));
mrkt.market_name = cursor.getString(cursor.getColumnIndex("name"));
mrkt.market_telno = cursor.getInt(cursor.getColumnIndex("telno"));
mrkt.market_location = cursor.getString(cursor.getColumnIndex("location"));
mrkt.market_hours = cursor.getString(cursor.getColumnIndex("hours"));
markets.add(mrkt);
}while(cursor.moveToNext());
}
cursor.close();
db.close();
return markets;
}
and i try to show first market's informations on textview with these lines in activity class:
myDbHelper = new DataBaseHelper(this);
markets = new ArrayList<market>();
myDbHelper.createDataBase();
myDbHelper.openDataBase();
markets = myDbHelper.getMarkets();
id.setText(markets.get(0).getMarket_id());
name.setText(markets.get(0).getMarket_name());
telno.setText(markets.get(0).getMarket_telno());
loc.setText(markets.get(0).getMarket_location());
hours.setText(markets.get(0).getMarket_hours());
However i got logcat error:
04-12 23:40:24.477: E/SQLiteLog(30698): (1) no such table: markets
i checked data/data file and there is not my db file
i followed tutorial line by line but i dont know why i can not create table or sqlite database properly ?
i tried .db, .sqlite3 extensions.. if i'm wrong then what should be my db file extension ?
please help..
(note: i have cyanogenmod 11.0 on my phone)

I am not sure what is the problem but this code:
if(cursor.moveToFirst()) {
cursor.moveToNext();
do {
mrkt.market_id = cursor.getInt(cursor.getColumnIndex("marketid"));
mrkt.market_name = cursor.getString(cursor.getColumnIndex("name"));
mrkt.market_telno = cursor.getInt(cursor.getColumnIndex("telno"));
mrkt.market_location = cursor.getString(cursor.getColumnIndex("location"));
mrkt.market_hours = cursor.getString(cursor.getColumnIndex("hours"));
markets.add(mrkt);
}while(cursor.moveToNext());
}
skips the first row of the query. With cursor.moveToFirst() you are already pointing to the first row in the table, but you do additional cursor.moveToNext() which skips the first row, and goes to the second.

You didn't define a table. I'm assuming as it wasn't in the tutorial. This is the line and it should be after the DATABASE_NAME and DATABASE_VERSION, and before the lines to identify the columns:
public static final String TABLE_NAME = "markets";
If you fixed it with other code, please let me know! I've been working on somet

Related

sqlite db not found on mobile device but works on emulator

I have created an sqlite database consisting of a table and the database is populated with about 2000 rows.
I am able to query this table and everything is working fine when I do it via an emulator.
But when I test it on a mobile device, it is throwing following error:
android.database.sqlite.SQLiteException: no such table: person (code
1): , while compiling: SELECT name from person WHERE rowid = 292
When I tried it on a device, I was expecting my populated sqlite database to be automatically available on my device but based on above error, looks like that is not the case.
I did have a look through past issues and they do not match my issue.
I did not set my own path for the db storage location.
When I looked under Device File Explorer, the path for the database is
/data/data/com.somepackage.myappname/databases/person
I have tried uninstalling the application and reinstalling it again which doesn't make a difference.
My sdk setup details if relevant.
minSdkVersion 16
targetSdkVersion 27
Mobile device: Using Android version 8.0.0
Please advice how I can have the database automatically come with the app when installed (when I click run on Android Studio).
This is how I loaded the data into my database. This was ran only once and I have currently commented this code out.
try {
SQLiteDatabase database = this.openOrCreateDatabase("person", MODE_PRIVATE, null);
database.execSQL("DROP TABLE IF EXISTS person");
database.execSQL("CREATE TABLE IF NOT EXISTS person (name VARCHAR, name_size INT(8))");
BufferedReader br = new BufferedReader(new InputStreamReader(getAssets().open("person.txt")));
String line;
while ((line = br.readLine()) != null) {
String sql = "INSERT INTO person (name, name_size) VALUES ('" + line + "', " + line.length() + ")";
database.execSQL(sql);
}database.close();
}
catch (Exception e){
e.printStackTrace();
}
I initialise the database under onCreate method.
database = this.openOrCreateDatabase("person", MODE_PRIVATE, null);
When a button is clicked, the following method is executed.
The error occurs on the first line in this method.
private String retrieveNextPerson(int randomIndex){
//error on this raw query
Cursor cursor = database.rawQuery("SELECT name from person WHERE rowid = " + randomIndex, null);
int wordIndex = cursor.getColumnIndex("name");
cursor.moveToFirst();
return cursor.getString(wordIndex);
}
Assuming that you are not under the misconception that running the app on an emulator (or on any device) will alter the package so that the distribution will include the populated database
to distribute a pre-populated database involves
a) populating the database (generally using an SQLite management tool),
b) copying this (the file as that's the database) into the assets folder and then :-
c) retrieving this from the assets folder.
using SQLiteAssetHelper makes this easy, noting that with SQLiteAssethelper the DB file needs to exist in the databases folder (you'd very likely need to create this)).
then I suspect that you are prematurely invoking :-
database = this.openOrCreateDatabase("person", MODE_PRIVATE, null);
Doing so would create the person database without the person table and thus result in the failure that you have described.
You need to load the data before using the above line.
Alternately if you added the following code immediately after database = this.openOrCreateDatabase("person", MODE_PRIVATE, null);
Cursor csr = database.query("sqlite_master",null,"name='person'",null,null,null,null);
if (csr.getCount() < 1) {
database.execSQL("CREATE TABLE IF NOT EXISTS person (name VARCHAR, name_size INT(8))");
........ rest of the code that inserts data from the person.txt asset
}
The table would be created. However, it would be empty ( you could copy the data from the person.txt asset here )
Addition re comment :-
Thanks for reply. Not sure if you missed the part where I mentioned
the database creation is already done and that part has been commented
out. I invoked the db creation once and loaded it with data and the db
is just sitting in the app now (at least for the emulator). The
initialisation you mentioned should open an existing db with an
existing table thus I don't see why that would be premature.
The following is a pretty solid rework of your code that will cater for what I believe could be the most likely underlying issues:-
public class MainActivity extends AppCompatActivity {
public static final String DBNAME = "person";
public static final String TBNAME = "person";
public static final String COL_NAME = "name";
public static final String COL_NAME_SIZE = "name_size";
public static final String ASSET_FILENAME = "person.txt";
public static final String SQLITE_MASTER_TABLE = "sqlite_master";
public static final String COL_SQLITE_MATSER_NAME = "name";
static final int MIMINUM_ROWS_IN_PERSONTABLE = 1;
SQLiteDatabase db;
BufferedReader br;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPersonTable(); // Notes sets db either way
// FOR TESTING
long rows_in_person_table = DatabaseUtils.queryNumEntries(db,TBNAME);
Log.d(
"PERSON ROW COUNT",
"The number of rows in the " +
TBNAME +
" table is " +
String.valueOf(rows_in_person_table)
);
}
private void checkPersonTable() {
db = this.openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE,null);
// Database will now exist but it may or may not contain the person table so check sqlite_master
Cursor csr = db.query(
SQLITE_MASTER_TABLE,
new String[]{COL_SQLITE_MATSER_NAME},
COL_SQLITE_MATSER_NAME + "=?",
new String[]{TBNAME},
null,null,null
);
// Cursor will contain 1 row if the person table exists so check count
int person_table_count = csr.getCount();
csr.close();
// Before attemtping to create the Person table ensure that the assets file exists
// If not then throw a RunTime exception
if (person_table_count < 1) {
try {
if (!Arrays.asList(getResources().getAssets().list("")).contains(ASSET_FILENAME)) {
StringBuilder sb = new StringBuilder();
throw new RuntimeException("Asset file " +
ASSET_FILENAME +
" not found in the assets folder." +
" The following assets were found" +
sb
);
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (person_table_count < 1) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TBNAME +
"(" +
COL_NAME + " TEXT," +
COL_NAME_SIZE + " INTEGER" +
")"
);
loadPersonsFromAssets();
} else {
// <<<<<<<<<< NOTE Optional will load data from assets if miminum nuber of rows
// aren't in the person table
if (DatabaseUtils.queryNumEntries(db,TBNAME) < MIMINUM_ROWS_IN_PERSONTABLE) {
loadPersonsFromAssets();
}
}
}
// Load the person table from the Assets File
private void loadPersonsFromAssets() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(getAssets().open(ASSET_FILENAME)));
String line, sql;
int lines_read = 0;
db.beginTransaction();
while ((line = br.readLine()) != null) {
sql = "INSERT INTO " + TBNAME + " VALUES('" + line + "'," + String.valueOf(line.length()) + ")";
db.execSQL(sql);
lines_read++;
}
db.setTransactionSuccessful();
db.endTransaction();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Asset File " + ASSET_FILENAME + " not found in the assets folder.");
}
}
}
This will :-
only attempt to open the database once setting the the SQliteDatabase object when it does so.
will create the person database if it doesn't exist and then it will create the person table.
Even if the database exists it continues to check that the table exists and will create it if it doesn't.
An exception is if the asset file doesn't exist in the asset folder in which case a run-time exception will be raised (as if this is missing there is something drastically wrong as it should always exist as it's part of the package).
It will also populate the table when created or populate the table if there are two few rows (depending upon the value of MIMINUM_ROWS_IN_PERSONTABLE ).
Should the asset file person.txt not exist then you would get an exception similar to :-
06-10 03:58:43.503 3097-3097/personthing.so50777840 E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{personthing.so50777840/personthing.so50777840.MainActivity}: java.lang.RuntimeException: Asset file person.txt not found in the assets folder. The following assets were found
found asset file :- images
found asset file :- notperson.txt
found asset file :- sounds
found asset file :- webkit
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Asset file person.txt not found in the assets folder. The following assets were found
found asset file :- images
found asset file :- notperson.txt
found asset file :- sounds
found asset file :- webkit
at personthing.so50777840.MainActivity.checkPersonTable(MainActivity.java:83)
at personthing.so50777840.MainActivity.onCreate(MainActivity.java:39)
at android.app.Activity.performCreate(Activity.java:5008)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
... 11 more
Note as can be seen, person.txt has been "wrongly" named notperson.txt to force the error.
Note at this stage the database will exist (due to the openOrCreateDatabase) and it will contain two tables (sqlite_master and android_metadata) but not the person table e.g :-
However, creating the correct asset file person.txt (renaming notperson.txt to person.text) will then result in the table being created and loaded with data:-
e.g. if person.txt is :-
Then running the App will result in the log containing :-
06-10 04:39:04.277 3325-3325/? D/PERSON ROW COUNT: The number of rows in the person table is 11

Android saving and retrieving an object from a database

I've created an object that I need to save so the user can access the information in it later. I was using other questions, and tutorials to put it into a JSONobject, and then turn that into a string. After that, I would insert it into a table...
JSONObject json = new JSONObject();
json.put("run", run);
String runString = json.toString();
SQLiteDatabase database = openOrCreateDatabase("your runs",MODE_PRIVATE,null);
database.execSQL("CREATE TABLE IF NOT EXISTS Runs(Run BLOB);");
database.execSQL("INSERT INTO Runs VALUES('"+runString+"');");
To retrieve it I use this code...
cursor = database.rawQuery("Select * from Runs",null);
cursor.moveToFirst();
runArray = new Run[cursor.getCount()];
while(cursor.moveToNext()){
try {
object = new JSONObject(String.valueOf(cursor.getBlob(0)));
run = (Run) object.opt("run");
runArray[count] = run;
count ++;
} catch (JSONException e) {
e.printStackTrace();
}
}
This seems to work, but when I try to get a Run from the runArray, and get the name of the run it causes a null pointer exception. The runArray has a length of one, which should be correct because I only created one Run. Is this the proper way to retrieve the Runs, or should I be going about this a different way?
I figured it out. Instead of trying to put the Run object into the table. I just put all of the values from Run into the table. In the other activity that retrieved the values, I took the values and created a new Run with them.
Here's the code that inserts the values...
SQLiteDatabase database = openOrCreateDatabase("your runs",MODE_PRIVATE,null);
database.execSQL("CREATE TABLE IF NOT EXISTS Runs(name VARCHAR, units VARCHAR, runtime VARCHAR, date VARCHAR, pace FLOAT, avgSpeed FLOAT, distance FLOAT, laps BLOB, speeds BLOB, distances BLOB);");
database.execSQL("INSERT INTO Runs VALUES('"+run.getName()+"','"+run.getUnits()+"','"+run.getRunTime()+"','"+run.getDate()+"','"+run.getPace()+"','"+run.getAvgSpeed()+"','"+run.getDistance()+"','"+Arrays.toString(run.getLaps())+"','"+Arrays.toString(run.getSpeeds())+"','"+Arrays.toString(run.getDistances())+"');");
And here's the code that retrieves it...
database = openOrCreateDatabase("your runs",MODE_PRIVATE,null);
cursor = database.rawQuery("Select * from Runs",null);
cursor.moveToFirst();
runArray = new Run[cursor.getCount()];
count = 0;
while(!cursor.isAfterLast()){
run = new Run();
run.setName(cursor.getString(0));
run.setUnits(cursor.getString(1));
run.setRunTime(cursor.getString(2));
run.setDate(cursor.getString(3));
run.setPace(cursor.getFloat(4));
run.setAvgSpeed(cursor.getFloat(5));
run.setDistance(cursor.getFloat(6));
run.setLaps(toArray(new String(cursor.getBlob(7))));
run.setSpeeds(toFloatArray(new String(cursor.getBlob(8))));
run.setDistances(toFloatArray(new String(cursor.getBlob(9))));
runArray[count] = run;
count++;
cursor.moveToNext();
}
I'm not sure if this is the best way, but it works for now. I can improve it later.

SQLite Java Android no such table, program crashes

I'm trying to make database for my program and I'm having a lot of dumb problems...
It's fragment of main activity:
Database db = new Database(this,editText.getText().toString());
String text = db.printRow();
textView.setText(text);
Now database class:
String nickname="EmptyNick";
public Database(Context context, String name) {
super(context, "database.db", null, 1);
nickname = name;
}
public void onCreate(SQLiteDatabase db) {
if(!nickname.equals("EmptyNick")) {
db.execSQL("create table player(id integer primary key autoincrement,nick text);");
Users user = new Users();
user.setNick("Mariusz");
addPlayer(user);
}
else {
//not important
}
}
private void addPlayer(Users user) {
SQLiteDatabase db = getWritableDatabase();
ContentValues values = new ContentValues();
values.put("nick",user.getNick());
db.insertOrThrow("player",null,values);
}
public String printRow() {
String string=null;
if(!nickname.equals("EmptyNick")) {
String[] collumns = {"id","nick"};
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query("player",collumns,null,null,null,null,null);
cursor.moveToFirst();
while (cursor.moveToNext()) {
string += cursor.getString(1);
}
}
else {
//not important
}
return string;
}
Errors:
no such table: player
Caused by: java.lang.reflect.InvocationTargetException
Caused by: android.database.sqlite.SQLiteException: no such table: player (code 1): , while compiling: SELECT id, nick FROM player
I really can't see what's wrong. Error says there is no table 'player', but it is. On the beggining of onCreate methon in line:
db.execSQL("create table player(id integer primary key autoincrement,nick text);");
Can somebody help me? If I make Toast instead of text.setText(...) it shows me empty field, so yes, it can't create specific row. I understand the error, but do not from where and why it comes.
The table you try to use does not exist. In such cases it is generally a good idea to check the database you are using and check whether the table exists. In this particular case it seems that you create the table if a condition is met. The condition is that your nickname's value differs from the default value. However, it does not differ. Make sure that you use a table if and only if it exists and you have the correct condition for creating the table.
I don't really understand your problem. If there is an error, it will throw an ANR message, how can you print the toast and it shows the empty? and the Toast showed empty because you add only one record of data to your table, then in your printRow(), you called cursor.moveToFirst, then you call while(cursor.moveToNext()) which will move your cursor to second row and it will return false since you only have 1 record.

SQLite Cursor getColumnIndex() returning -16 even when column exists

I'm storing a number of objects for my app in an SQLite Database. The class for these objects has a constructor that takes a Cursor object, passed in from the Database class. Example:
public MyClass(Cursor cursor) {
this.id = cursor.getString(cursor.getColumnIndex(MyDatabase.KEY_ROWID));
this.nickname = cursor.getString(cursor.getColumnIndex(MyDatabase.KEY_NICKNAME));
...and so on.
However I've noticed that at random times I've been getting a crash when getColumnIndex for the ID column returns -16. (And if I comment out that line, whichever the first column I try to access is, it will also return -16). I've added some extra logging around it but it hasn't helped as it seems like the columns are fine:
public MyClass(Cursor cursor) {
Log.i("TEST", Column names are: " + Arrays.toString(cursor.getColumnNames()));
Log.i("TEST", Making object, id column index is " + cursor.getColumnIndex(MyDatabase.KEY_ROWID));
Which prints:
Column names are: [_id, nickname...]
Making object, id column index is -16
So it sees like everything should be fine, anyone got any clue why everything could be getting so messed up while reading from the Cursor?
EDIT: Here's how I'm getting the cursor, this is a method in the database class:
public MyObject getMyObject(String id) {
MyObject objectFound = null;
String[] whereArgs = { id };
Cursor cursor = db.query(true, getTableName(), null, WHERE_EQUALS, whereArgs, null, null, null, null);
if(cursor.moveToFirst()) {
//Should only return 1 entry from DB
while(cursor.isAfterLast() == false) {
objectFound = new MyObject(cursor);
cursor.moveToNext();
}
}
cursor.close();
return objectFound;
}

Get data from Sqlite database one at a time with Android

I am building an application where the user can save some information into an sqlite database. What I now want to do is be able to get the data from the sqlite database and store each row in its own string.
Note
There is only one column in the database.
So, algoritm is not difficult, just create Cursor and in loop you will be retrieving data from it and then save them to List for example.
So try this snippet of code:
final String SELECT_QUERY = "Select column from Table";
List<String> data = new ArrayList<String>();
String member = null;
Cursor c = db.rawQuery(SELECT_QUERY, null);
if (c.getCount() > 0 && c.moveToFirst()) {
do {
member = new String(c.getString(0));
data.add(member);
}
while (c.moveToNext());
}

Categories

Resources