insert in database with multiple activities - android

I have a problem, I created database for all activities, and in each activity I should insert information to database, so for the first activity , the insert is done , for the second activity I update the row with new insertion to complete all information and so on, my problem is that I don't know how to refer to the last row, I mean what should I do that make the update for the second activity occurs to the last row that has been insert in the first activity, do you have any suggestions ???

Well you can just use the primary key. When you insert something into the database you get as a return value the primary key. You can add this to the Intent that opens the other Activity and that way refer back to the row you previously inserted.
Edit:
I don't know if you are working with and SQLiteDatabase Object or with a ContentProvider, but in any case the code would be pretty much the same. In this example I will work directly with an SQLiteDatabase Object, even though using ContentProviders is in most cases the better alternative.
In your first Activity:
// When you perform an insert you get the id of the row which was just inserted.
long id = sqliteDatabase.insert("some_table", null, contentValues);
// The id will be -1 if an error occured
if(id >= 0) {
...
}
...
// When you start your second Activity you can add the id to the Intent
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
// The String is a tag with which you can later retrieve the id from the Intent.
// Note that you should never hardcode String like that, use constants in your app.
intent.putExtra("rowId", id);
In the onCreate Method of your second Activity you can retrieve the id:
#Override
protected void onCreate (Bundle savedInstanceState) {
// Check if the Activity has been created for the first time
if(savedInstanceState == null) {
// Retrieve the Intent with which the Activity was started
Intent intent = getIntent();
long id = intent.getLongExtra ("rowId", -1);
// If id is valid proceed
if(id >= 0) {
Cursor cursor = sqliteDatabase.query("some_table", columns, "_id = ?",
new String[] { String.valueOf(id) }, null, null, null, null);
// Check if Cursor is valid and if yes read your data.
if(cursor != null) {
...
}
}
}
}

The best way to do this would be to add a column to your database which will hold the time the row was inserted. Then when you need the latest row, query for the one with the most current time. An example SQL string would be:
SELECT * FROM my_table WHERE 1 ORDER BY time_stamp LIMIT 1

Related

Should I use extra arraylist for efficient data operations while using Sqlite db with recyclerviews?

I hope straightforward questions.
1) I managed to get the data from Sqlite db and showing them on recyclerview. The question is for example when i click on the recyclerview items and do some operations (for example copying the content or updating) is it better to use an arraylist and get the data first when application loads then do the operations on this arraylist elements (then notifying db eventually)?
2) If there is no need for extra arraylist on onContextItemSelected() operations while clicking recyclerview item again, i ve some trouble in choosing the element and its values.
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.idshare :
//implicit intent
shareImplicitIntent();
return true;
......
for the shareImplicitIntent() method
private void shareImplicitIntent() {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
Cursor cursor=WordListOpenHelper.mReadableDB.rawQuery("SELECT * FROM
diary", null);
cursor.moveToPosition(XYZ);
Entry_Model entry_model= new Entry_Model();
entry_model.setmEntry(cursor.getString(cursor.getColumnIndex(WordListOpenHelper.KEY_ENTRY)));
String title = entry_model.getmEntry(); ......
basically using cursor and getting the title of the cursor at XYZ position.
But how can I choose that XYZ position ?
Working hours on it but couldnt find a clue. Please help me.Thanks a lot
To answer my question myself, shortly no, for example for getting input from the user and putting them in the arraylist then doing the database operations on the arraylist not very useful nor necessary. (Yet if your database is planned to hold only small amount of entries though you can use arraylist/linkedlists for fast CRUD manipulations on the recyclerview adapter).
For the second part of the question it s easy to copy the content of the clicked recyclerview element by creating setonclicklistener in the viewholder constructor of the viewholder innerclass, for example;
(note unlike in the example you dont have to use contentresolver if you dont plan to share the datas in the database with other applications)
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
int pos =getAdapterPosition();
String entry = "";
String[] mProjection =
{ Contract.WordList.KEY_ENTRY, // Contract class constant for the _ID column name };
Cursor cursor = mContext.getContentResolver().query(Uri.parse(
queryUri), mProjection, null, null, sortOrder);
if (cursor != null) {
if (cursor.moveToPosition(pos)) {
int indexEntry = cursor.getColumnIndex(Contract.WordList.KEY_ENTRY);
entry = cursor.getString(indexEntry);
}
}
Toast.makeText(v.getContext(), "copied entry is " + entry, Toast.LENGTH_LONG).show();
return false;
}
});

SQLite database insert is somehow vanishing?

I'm having a very strange issue on my Android app wherein when I am inserting a value to a DB table, the first entry is disappearing somehow. However, any subsequent entries are appearing fine.
To be a little more specific, part of my application allows users to create a simple log where they enter some text and when they save it, it shows up on a list of log entries. However, when I try to insert the very first entry to an empty table, that entry is not being displayed, nor does the database indicate there is any data when I query for a count.
Interestingly enough, when I look at the return of the database insert call (SQLiteDatabase.insert()) I see a valid row number returned. In fact, when I look at any log entry I've saved to the database, the row number is correctly incrementing. As per the docs, my understanding is that if a non-negative number is returned, the insert was successful.
Here is the code that takes the result of the EditText from my AlertDialog, creates a new log entry, and calls the insert method:
newPainLogEntryDialog.setPositiveButton("Save",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//make new pain log entry
PainLog painLog = new PainLog();
painLog.setPainEntry(input.getText().toString());
painLog.setPainDateTime(Calendar.getInstance());
Database.init(PainLogTab.this.getActivity());
Database.createPainLog(painLog);
updatePainLogList();
//display success to user
Toast.makeText(PainLogTab.this.getActivity(),
"Log entry saved", Toast.LENGTH_SHORT).show();
}
});
The code for Database.createPainLog():
public static long createPainLog(PainLog painLog) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_PAINLOG_ENTRY, painLog.getPainEntry());
cv.put(COLUMN_PAINLOG_DATETIME, painLog.getPainDateTimeString());
return getDatabase().insert(PAINLOG_TABLE, null, cv);
}
And the last call before the Toast message is updatePainLogList(), which gets all the DB entries:
public void updatePainLogList(){
Database.init(PainLogTab.this.getActivity());
final List<PainLog> painLogs = Database.getAllPainLogs();
painLogListAdapter.setPainLogs(painLogs);
Log.d(getClass().getSimpleName(), "number of painLogs found: " + painLogs.size());
getActivity().runOnUiThread(new Runnable() {
public void run() {
// reload content
PainLogTab.this.painLogListAdapter.notifyDataSetChanged();
if(painLogs.size() > 0){
getView().findViewById(android.R.id.empty).setVisibility(View.INVISIBLE);
}else{
getView().findViewById(android.R.id.empty).setVisibility(View.VISIBLE);
}
}
});
}
And for completion sake, the body of the getAll() and its accompanying method getCursor():
public static Cursor getPainLogCursor() {
String[] columns = new String[] {
COLUMN_PAINLOG_ID,
COLUMN_PAINLOG_ENTRY,
COLUMN_PAINLOG_DATETIME
};
return getDatabase().query(PAINLOG_TABLE, columns, null, null, null, null,
null);
}
public static List<PainLog> getAllPainLogs() {
List<PainLog> painLogs = new ArrayList<PainLog>();
Cursor cursor = Database.getPainLogCursor();
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
PainLog painLog = new PainLog();
painLog.setId(cursor.getInt(IDX_PAINLOG_ID));
painLog.setPainEntry(cursor.getString(IDX_PAINLOG_ENTRY));
painLog.setPainDateTime(cursor.getString(IDX_PAINLOG_DATETIME));
painLogs.add(painLog);
}
}
cursor.close();
return painLogs;
}
Now with some code I can explain what debugging steps I have taken thus far. As mentioned above, when I look at the return of the DB insert, I get a positive, non-zero number. However, when I try to print the number of logs in the immediately following update method (no deletes or anything get called en route), it displays 0, and indeed if I follow the Cursor I find that it never enters the loop which adds logs to the list which is displayed, also indicating it is not picking up the entry.
I have tried to set the DB insert in a transaction so that I can manually commit, but this does not help either. What makes this more interesting to me is that I have similar functionality elsewhere in my app where I save user preferences and display them in a list, and this does not suffer from the same problem...I have compared against this code and couldn't find any differences that would cause it.
To sum it up, my question is two-fold: why is only my first insert on an empty table showing up as not there, while all following ones are fine?; why am I getting a valid return from the database insert and yet immediately following the insert when I query for that data it is missing?
Thanks in advance for any help you can provide :)
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
This skips the first row in cursor. moveToFirst() moves to the first row and moveToNext() moves to the next one, skipping the first one.
You can replace this with just while (cursor.moveToNext()). When you get your cursor from a query, it is placed at index -1 first i.e. at the row before the first one.
if (cursor.moveToFirst()) {
while (cursor.moveToNext()) {
This would be the best solution for it....

App crashes between onPause and onResume Listview issue

I have a listview activity which populates data through an sqlite database; however, whenever I enter onPause and then go into onResume my app crashes and I receive this error: "java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#418106a8". Would anyone know how to stop this? Is there a method I have to call in onPause?
#Override
protected void onResume() {
super.onResume();
uGraduateListAdapter = new ArrayAdapter<String>(ListOfAlarms.this, android.R.layout.simple_list_item_1, populateList());
listOfAlarms.setAdapter(uGraduateListAdapter);
Log.i(TAG, "Resume was called");
}
#Override
protected void onPause() {
super.onPause();
Log.i(TAG, "Pause was called");
sqliteDatabase.close();
}
public List<String> populateList(){
// We have to return a List which contains only String values. Lets create a List first
List<String> uGraduateNamesList = new ArrayList<String>();
// First we need to make contact with the database we have created using the DbHelper class
AndroidOpenDbHelper openHelperClass = new AndroidOpenDbHelper(this);
// Then we need to get a readable database
sqliteDatabase = openHelperClass.getReadableDatabase();
// We need a a guy to read the database query. Cursor interface will do it for us
//(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
cursor = sqliteDatabase.query(AndroidOpenDbHelper.TABLE_NAME_ALARM, null, null, null, null, null, null);
// Above given query, read all the columns and fields of the table
startManagingCursor(cursor);
// Cursor object read all the fields. So we make sure to check it will not miss any by looping through a while loop
while (cursor.moveToNext()) {
// In one loop, cursor read one undergraduate all details
// Assume, we also need to see all the details of each and every undergraduate
// What we have to do is in each loop, read all the values, pass them to the POJO class
//and create a ArrayList of undergraduates
String alarmName = cursor.getString(cursor.getColumnIndex(AndroidOpenDbHelper.COLUMN_NAME_ALARM_NAME));
// String ugUniId = cursor.getString(cursor.getColumnIndex(AndroidOpenDbHelper.COLUMN_NAME_UNDERGRADUATE_UNI_ID));
String alarmTotalTime = cursor.getString(cursor.getColumnIndex(AndroidOpenDbHelper.COLLUMN_ALARM_TOTALTIME));
// Finish reading one raw, now we have to pass them to the POJO
TestAlarm ugPojoClass = new TestAlarm();
ugPojoClass.setTitle(alarmName);
ugPojoClass.setTotalTime(alarmTotalTime);
// Lets pass that POJO to our ArrayList which contains undergraduates as type
pojoArrayList.add(ugPojoClass);
// But we need a List of String to display in the ListView also.
//That is why we create "uGraduateNamesList"
uGraduateNamesList.add(alarmName);
}
// If you don't close the database, you will get an error
sqliteDatabase.close();
return uGraduateNamesList;
}
You are using deprecated methods (startManagingCursor()), which is dangerous.
How I see what happens: when you close your database (twice actually: in populateList() and onPause()), your cursors to this database become invalid. But since you called startManagingCursor(), your Activity retains your cursors and tries to call requery() on them when restarting, which throws the error.
Try not calling startManagingCursor() at all, just cursor.close() when you're done with it. Or you can migrate to newer LoaderManager altogether.

using Buttons to retrieve data from database

I have connected a database in my Android Application. Now I have created a button and when it is clicked, that should get the next data from the table of database. I have cursor and he moveToFirst() and moveToNext() methods in my code. also I have set onclick listener to my button. but in output when I click the button, its is not fetching the next data from database
heres the part of code where I have tried to set on click listener for button
c=myDbHelper.query(myDbHelper.DB_PATH +"/MainTable",null, null, null, null,null, null);
c.moveToFirst();
myques=(TextView)findViewById(R.id.question);
myrg=(RadioGroup)findViewById(R.id.rg1);
myc1=(RadioButton)findViewById(R.id.radio0);
myc2=(RadioButton)findViewById(R.id.radio1);
myc3=(RadioButton)findViewById(R.id.radio2);
myc4=(RadioButton)findViewById(R.id.radio3);
NxtQues=(Button)findViewById(R.id.button1);
myques.setText(c.getString(1));
myc1.setText(c.getString(2));
myc2.setText(c.getString(3));
myc3.setText(c.getString(4));
myc4.setText(c.getString(5));
NxtQues.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View V)
{
c.moveToNext();
}
});
what changes should I make in this code to set on click listener in a proper way.
So in your code is a few problems. At first here:
c = myDbHelper.query(myDbHelper.DB_PATH +"/MainTable", ...);
As first parameter of query() method is "raw" tablename so you can't assign there full path of your database(if it isn't real tablename...), it's wrong. Just assign MainTable like this:
c = myDbHelper.query("MainTable", null, null, null, null, null, null);
Then your logic about fetching data from database is not good at all. You assigned values to your widgets only once and no more. They never be refreshed, you need to call as many times setText() method as you want to update widget's content. Actually you don't update them.
You need to change your logic to:
#Override
public void onClick(View V) {
if (c.moveToNext()) {
myques.setText(c.getString(1));
myc1.setText(c.getString(2));
myc2.setText(c.getString(3));
myc3.setText(c.getString(4));
myc4.setText(c.getString(5));
}
}
Recommendation:
When you are using "getters" methods of Cursor, i recommend you to use column names to get columns indexes:
myques.setText(c.getString(c.getColumnIndex("columnName")));

SQLite and Activity updates

I have a neat, working SQLite database on Android that records species observations. I am then using JSON (successfully) to verify observations entered against a set of parameters on a remote database. On verification, a flag in the database is updated to say that this process has been done. But, when I view my main activity (Text, the values for observations with flags after verification don't update.
My activity order is:
Main activity (obs = 0 from database)
Obs Entry activity
Main activity (obs = 1 with flag A from db)
Data management activity, verify button
Verify done activity, main button
Main activity (obs = 1 with flag A from db)
If I exit, or leave it for a while, then come back in to Main activity, the database is being polled correctly and obs = 1 with flag B from db.
So I know my database is right and the SQL is correct too. Could it be that I'm declaring my buttons at the wrong point for the Activity to correctly resume()?
My code:
final Button verifySightingsButton = (Button) findViewById(R.id.uploadprocess);
if (verifies == 0) {
verifySightingsButton.setTextColor(getResources().getColor(R.color.red));
} else {
verifySightingsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// do stuff
}
});
}
where 'verifies' is the number of flag A records. The button is being called with the onCreate() method. Would it make any difference if I instantiated it as a class variable?
Thanks in advance - bugging me senseless!
UPDATE: This is the code (actually using XML, not JSON which is used for other queries) that handles the verification and update of flag:
// Get details for an observation within loop
ArrayList d = (ArrayList) allVerifyRows.get(i);
// Build the URL to verify the data
String aURL = buildVerifyURL(d);
// Parse the XML
aValid = ParseVerificationXML.verifyXMLdata(aURL);
db.open();
Long bouCode = new Long((String) speciesList.get((String) d.get(3)));
boolean insert = db.updateNote(
((Long) d.get(0)).longValue(),
((Long) d.get(1)).longValue(),
// and some other variables being updated
db.close();
and the code to check the database for records that are and are not verified:
NotesDbAdapter db = new NotesDbAdapter(this);
db.open();
Cursor c = db.fetchAllNotes();
species = new ArrayList<String>();
while (c.moveToNext()) {
String str1 = c.getString(2); // Date
species.add(str1);
}
c.close();
Cursor v = db.performNullCountForVerification();
if (v.moveToFirst()) {
stillToVerify = v.getInt(0); // Non-Verified records
readyForUpload = stillToVerify;
}
v.close();
stillToVerify = species.size() - stillToVerify;
db.close();
You might use the onResume method of your main activity to update the shown values. The onResume method is called every time the activity appears on the screen in contrast to onCreate, which is only called when the activity gets created.

Categories

Resources