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.
Related
I have a weird sqlite problem, partly Flutter partly Android... I have a database that I create in Flutter. When I insert a new row and I save it, I want to retrieve it in Android and send the values to a broadcast receiver. I am using this query: "SELECT * FROM " + TABLE_NAME + " ORDER BY " + COLUMN_ID + " DESC LIMIT 1"; This works great when creating the first row, but after that my broadcast receiver only ever receives the value of the last but one row, not the last row.
This is my code on the Java side, to get the details from the sqlite database and send them to the receiver:
public void getScheduleFromFlutter() {
String setting = "";
DatabaseHandler db = new DatabaseHandler(this);
Cursor cursor = db.getValues();
if (cursor.moveToFirst())
setting = cursor.getString(cursor.getColumnIndex(COLUMN_SETTING));
Intent intent = new Intent(this, Schedules.class);
intent.putExtra("SETTING", setting);
sendBroadcast(intent);
cursor.close();
db.close();
}
Any ideas?
You might have some issues in the query to retrieve the last row.
However if you re inserting values in table with Sqflite.
When inserting a value:
// Insert the Dog into the correct table. You might also specify the
// `conflictAlgorithm` to use in case the same dog is inserted twice.
//
// In this case, replace any previous data.
await db.insert(
'dogs',
dog.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
The method insert returns a future with the ID of new column.
// INSERT helper
Future<int> insert(String table, Map<String, dynamic> values,
{String nullColumnHack, ConflictAlgorithm conflictAlgorithm});
You can then send this ID instead or query the table with this ID to get the entry you need.
So I've been trying to convert content of a SQLite Database to Objects in an ArrayList. To do that, I've tried to iterate through the Table like written in the code below. But this doesn't return each mark of the specified subject once, but iterates through the table about 70-80 times. I think I know the problem, being that the c.moveToNext moves to the next column of the row and not the next row, but I don't know the solution to this.
public ArrayList<Marks> toMarksList(String subject){
ArrayList<Marks> marksArrayList = new ArrayList<Marks>();
SQLiteDatabase db = getWritableDatabase();
String query = "SELECT * FROM " + TABLE_MARKS + " WHERE " + COLUMN_SUBJECT + "=\"" + subject + "\";";
Cursor c = db.rawQuery(query, null);
c.moveToFirst();
while(!c.isAfterLast()){
if(c.getColumnIndex("subject")!=0){
String dbName = c.getString(c.getColumnIndex("name"));
Double dbValue = c.getDouble(c.getColumnIndex("value"));
Double dbWeight = c.getDouble(c.getColumnIndex("weight"));
marksArrayList.add(new Marks(subject, dbName, dbValue, dbWeight));
}
c.moveToNext();
}
db.close();
return marksArrayList;
}
This code seems to be seriously broken, because it also gets the wrong name for the third entry in the database, but onnly in the first half of the while loops. How do I make it so the cursor is at one row, reads the needed entries of that row and then continues to the next row?
EDIT: Turns out I'm completely stupid and kept adding new entries to the list every time I launched the app.
But this doesn't return each mark of the specified subject once, but iterates through the table about 70-80 times.
I don't see evidence of iterating over the table multiple times.
If that's what you're observing somehow,
it's not in the posted code, but somewhere in the caller of this method.
In any case, I suggest improving the main loop in there, like this:
Cursor c = db.rawQuery(query, null);
while (c.moveToNext()) {
String dbName = c.getString(c.getColumnIndex("name"));
Double dbValue = c.getDouble(c.getColumnIndex("value"));
Double dbWeight = c.getDouble(c.getColumnIndex("weight"));
marksArrayList.add(new Marks(subject, dbName, dbValue, dbWeight));
}
db.close();
See the edit, I just kept adding Data to the Database, which I noticed when the length of the ArrayList kept going up.
Let me just dig a hole and disappear in it.
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
I'm developing my firs app for android right now, I am using multiple tables to get and insert data. during the development and found myself fetching data from the table with has only two columns STATS(_id, stat_name). What my problem is? I have an activity with 10 buttons, and every button correlates with one stat_name. When users presses one of the buttons application is "going" to STATS table to get correct _id and then is inputting this _id to another table GAME_STATS(_id, PlayerId (fk), GameId(fk), StatsId(fk)(andmore)) on STATS._id = GAME_STATS.StatsId and I basicly have to do similar operation for PlayerId.
Right now, I'm doing it this way:
public String getStatId(String statName){
String statId = "Error";
Cursor c = mDb.query(STAT_TABLE, new String[] {AbstractDbAdapter.STAT_ID, AbstractDbAdapter.STAT_NAME}, AbstractDbAdapter.STAT_NAME+ " = " +statName, null, null, null, null);
int count = c.getCount();
if(count == 1){
c.moveToFirst();
statId = c.getString(c.getColumnIndex(AbstractDbAdapter.STAT_ID));
}
c.close();
mDb.close();
Log.d("FootballApp","StatId =" +statId);
return statId;
}
What my problem is, that I know that there SHOULD be only one value returned, and I still have to use Cursor, to do so. Also, in my opinion, it looks way to complicated and time consuming wo write all that code just to get one id from one table. I have 9 tables in my application, and I will have to write similar method every time I need _id from different table when I have, for example, only name.
Can someone tell me if there is easier way to do all that? Please :)
thanks! :)
I think it doesn't get much simpler than that. However you can make the method more generic so you can reuse the code:
public String getFromDb(String tableName, String select, String selectBy, String selectName){
String selection = "Error";
Cursor c = mDb.query(tableName, new String[] {select}, selectBy + "=" + selectName, null, null, null, null);
if(c.getCount() == 1){
c.moveToFirst();
selection = c.getString(c.getColumnIndex(select));
}
c.close();
mDb.close();
Log.d("FootballApp", select + "=" + selection);
return id;
}
Example usage:
int statID = getFromDb(STAT_TABLE, AbstractDbAdapter.STAT_ID, AbstractDbAdapter.STAT_NAME, statName);
That is about as simple as it gets, but Cursor.moveToFirst() returns false if the cursor is empty so you can cut out the c.getCount() call and just say if(c.moveToFirst()) instead. That will save you a little bit of typing :)
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());
}