AsyncTask to check if user input is in database? - android

I have a problem with synchronizing results from AsyncTask when needed to check if input is vaild.
My application asks user to type in some promotion code into EditText. I want to label promotion code as valid if promotion code is in database. If promotion code entered is not in database, it is labeled as invalid.
This is code for button listener
// Listens for Add button presses
addButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String promo_code = (String) PromotCodeEditText.getText().toString();
// Start AsyncTask that will store true or false in checkCodeInDatabase variable
// depending if PromoCode is in database. We use checkCodeInDatabase in else if check below.
new CheckCodeDatabase().execute(promo_code);
// Check if Promo Code that user typed is in database
// checkCodeInDatabase is false if course is not in database
if (!checkCodeInDatabase) {
// Display No code in database alert dialog
showMsgDialog(getString(R.string.noCodeDBTitle),
getString(R.string.noCodeDBMessage));
courseCodeEditText.setText("");
} else {
// Add promo code user typed in EditText
addCode(promo_code);
}
}
});
My idea is that when user presses ADD button, to add promo code, I start AsyncTask which performs a query on database. AsyncTask stores true or false in static variable checkCodeInDatabase.
Here's code for AsyncTask:
private class CheckCodeDatabase extends AsyncTask<String, Object, Boolean> {
DataBaseHelper myDbHelper = new DataBaseHelper(MainActivity.this);
#Override
protected Boolean doInBackground(String... params)
{
try {
myDbHelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
try {
myDbHelper.openDataBase();
} catch (SQLException sqle) {
throw sqle;
}
// This returns true or false if params[0], which is a promo code,
// is in in PromoCodes table in database.
return myDbHelper.checkCourseInDatabase(params[0]);
}
#Override
protected void onPostExecute(Boolean result) {
// Store true or false in checkCodeInDatabase which is a static variable.
// This variable will be used to check if code is valid in add button listener.
checkCodeInDatabase = result;
myDbHelper.close();
}
Problem:
Problem is that AsyncTask does not store value into checkCodeInDatabase variable on time. Meaning, if statement which is performed in add button listener, value of checkCodeInDatabase is the old value because AsyncTask does not have enough time to perform database query and update checkCodeInDatabase variable before if statement is executed in add button listener.
So, how to make add button listener wait for AsyncTask to update checkCodeInDatabase and then perform if check.
Thanks in advance!
p.s. I'm new to android development. I read in some book on Android development that any queries on database should be performed in AsyncTasks, to avoid unresponsive app. Maybe it's impossible to achieve what I want with AsyncTasks. Any suggestions are welcome.

You should delegate the whole
if (!checkCodeInDatabase) {
// Display No code in database alert dialog
showMsgDialog(getString(R.string.noCodeDBTitle),
getString(R.string.noCodeDBMessage));
courseCodeEditText.setText("");
} else {
// Add promo code user typed in EditText
addCode(promo_code);
}
block into you AsyncTask's onPostExecute.
Doing that you are sure that you have fetched the result AND that you are running on the ui thread.

Related

How to stop execution of piece of code in android until data is retrieved from Firebase?

I am trying to perform some task based on the data retrieved from Firebase.
for (inti=0;i<dateList.size();i++)
{
attendanceDateRef= attendanceRef.child(dateList.get(i));
attendanceClassRef= attendanceDateRef.child(ViewAttendanceSelectClassActivity.selectedClass);
attendanceClassRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshotdataSnapshot) {
for (DataSnapshotdsp : dataSnapshot.getChildren())
{
attendanceList.add(dsp.getValue(String.class));
Log.e("attendanceListValues",dsp.getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseErrordatabaseError) {
}
});
}
intindex=1;
for (inti=1;i<=attendanceList.size();i++)
{
if(i%4==0)
{
fullDateRangeList.add(dateList.get(index));
index++;
}
else
{
fullDateRangeList.add(dateList.get(index));
}
}
Log.e("fullDateRangeList",String.valueOf(fullDateRangeList.size()));
Log.e("attendanceList",String.valueOf(attendanceList.size()));
above code is written on the OnClick event of a Button , when I click on the Button following output is generated on logcat:
fullDateRangeList:0
attendanceList:0
attendanceListValues:Value1
attendanceListValues:Value2
attendanceListValues:Value3
attendanceListValues:Value4
.
.
.
attendanceListValues:ValueN
from the above output it looks like second loop is executing before data is retrieved from Firebase and that is why size of fullDateRange and attendanceList is 0.
is there any way i can prevent second loop from executing until data is stored in attendanceList?
You cannot stop that method or make it wait until you get the all the data from your database. This is the behaviour of an asynchronous method. You need to change the logic of your code a little bit by declaring and using that data only inside the onDataChange() method, otherwise it will be always empty.
Also there is another approach. If you want, you can dive into the asynchronous world and use my answer from this post.

How do I delete a single call log entry from my android call register programmatically

I need to delete a single call entry from the call register when the user clicks on clear this call.
I managed to delete all call entries of a number while user clicks on clear all calls for this number.
How can I clear a single entry from the call register?
i assume you have a details of that call entry which you want to delete then try like this
try {
int idOfRowToDelete; // I assume you have this id;
getContentResolver().delete(Uri.withAppendedPath(CallLog.Calls.CONTENT_URI, String.valueOf(idOfRowToDelete)), "", null);
}
catch (Exception ex) {
System.out.print("Exception here ");
}

SyncDatabaseHelper not found with github.com/ntoskrnl/DataSync

I am working on a small app in which I want to have an SQLite DB to work locally but have it synced with parse.com.
I am trying to follow the example at https://github.com/ntoskrnl/DataSync but I am having problems with this statement:
// obtain our DatabaseHelper object
SyncDatabaseHelper dbHelper = OpenHelperManager.getHelper(context, DatabaseHelper.class);
// create and initialize SyncHelper object
SyncHelper syncHelper = new SyncHelper(dbHelper);
syncHelper.setUserId(ParseUser.getCurrentUser().getObjectId());
syncHelper.setLastSyncDate(new Date(lastSyncDate));
SyncDatabaseHelper does not seem to be a known class.
There was a mistake in the README file. Thank you for mentioning, I updated it.
As njzk2 pointed out, it is better to open an issue on GitHub.
First of all, the database operations shouldn't be performed on the UI thread. You should do all your work with DB in background thread (such as AsyncTask or Bolts task).
Secondly, you there is no need in additional updatedAt field in your entity-class. SyncEntity that you extend already has the field syncDate mapped to the updatedAt of ParseObject. Also, you cannot directly change updatedAt in your ParseObject, so the library uses reflection for this.
Just use syncDate instead of updatedAt. When you create new category or update existing one, you should set or update syncDate field of your entity - just as you did with updatedAt in your code.
Here is how I use the library in one of my projects:
ProgressDialog pDialog = null;
public void sync() {
// show progress dialog
pDialog = new ProgressDialog(getActivity());
pDialog.setIndeterminate(true);
pDialog.setMessage("Synchronizing session data...");
pDialog.setCancelable(false);
pDialog.show();
// get last sync date from preferences
final Date lastSyncDate = new Date(mPrefHelper.getLong(
Constants.APP_LAST_SYNC_TIMESTAMP, 0L));
// Prepare SyncHelper
final SyncHelper syncHelper = new SyncHelper(HelperFactory.getHelper());
syncHelper.setUserId(ParseUser.getCurrentUser().getObjectId());
syncHelper.setLastSyncDate(lastSyncDate);
Task.callInBackground(
new Callable<Long>() {
#Override
public Long call() throws Exception {
// save sync timestamp
long sync = System.currentTimeMillis();
syncHelper.synObjects(CardioSessionEntity.class, true, new SyncCallback());
return sync;
}
}
).continueWith(
new Continuation<Long, Object>() {
#Override
public Object then(Task<Long> task) throws Exception {
if (task.isFaulted()) {
Log.w(TAG, "Sync failed with exception", task.getError());
if (getActivity() != null) {
Toast.makeText(getActivity(), "Sync failed.",
Toast.LENGTH_SHORT).show();
}
} else if (task.isCompleted()) {
// save new sync timestamp to Preferences
mPrefHelper.putLong(Constants.APP_LAST_SYNC_TIMESTAMP, task.getResult());
}
// refresh UI and hide progress dialog
refreshSessionList();
if (pDialog != null) {
pDialog.dismiss();
}
pDialog = null;
return null;
}
},
Task.UI_THREAD_EXECUTOR);
}
I store last sync timestamp in Android preferences and use Bolts task to do synchronization in background. The synchronisation is performed by calling syncHelper.syncObjects(). I provide the entity-class, a userAware flag and SyncCallback object (can be null).
In the app, I have Sync button. Every time user clicks on it, I call the method sync() shown above. For each updated object the corresponding methods of SyncCallback are called.
For your particular case, I assume you don't need userId, so you can call
// Do this in the background
// save sync timestamp
long sync = System.currentTimeMillis();
// sync Category.class
syncHelper.synObjects(Category.class);
// return sync timestamp to save it in the later
return sync;
Call it from within AsyncTask.doInBackground() whenever you want to perform synchronization.
The syncDate is optional. If you don't provide lastSyncDate, the library will request all objects from the server.
Because the library doesn't support (and is not aware of) the relationships between your database entities, if you synchronize multiple entity-classes, you must handle save operations using SyncCallback. Its methods onSaveLocally() and onSaveRemotely() will be invoked just before persist/update (in local DB) or save (to parse.com).

Android not waiting for DB response before finishing statement

I have an interesting problem that I've never run into in programming before. I have an onClickListener that does a lot of username and password checks (makes sure the username is proper length, not taken, etc). I'm using MobDB, and I was using a conditional statement that would return a row if the username already existed. The problem is that the Listener skips the DB and goes to the final check that, if everything works, posts a new username and password to my DB. How can I make it wait for a response from the DB before skipping to the last check?
Here is the relevant code:
usernamecheck3 = true;
MobDB.getInstance().execute(APP_KEY, null, rd, null, false, new MobDBResponseListener() {
#Override public void mobDBSuccessResponse() {
usernamecheck3 = false;
Log.e("mobdbSuccess:", "success");
}
#Override public void mobDBResponse(Vector<HashMap<String, Object[]>> row) {
}
#Override public void mobDBResponse(String jsonObj) {
/*Log.e("mobdbSuccess:", "jsonObj");
Log.e("mobdbSuccess:", jsonObj);
JSONObject mainObject;
try {
mainObject = new JSONObject(jsonObj);
// need to parse the json object.
} catch (JSONException e1) {
e1.printStackTrace();
} */
}
#Override public void mobDBFileResponse(String fileName, byte[] fileData) {
//get file name with extension and file byte array
}
#Override public void mobDBErrorResponse(Integer errValue, String errMsg) {
usernamecheck3 = false;
Log.e("doesnt", "work");
}
});
if(usernamecheck3 == false){
Toast.makeText(getApplicationContext(), "Username is taken, please choose another", Toast.LENGTH_SHORT).show();
}
Basically the check always returns true, and then logcat will say mobdbSuccess: success, which should have set the Bool to false.
Thanks.
MobDBResponseListener is executing on a different thread. What happens here is that the processing is split, while a thread is doing the query, the main thread on which you added the listener, skips right ahead to the validation. Your best bet is to place the validation inside the MobDBResponseListener, on the mobDBResponse method.
Try to debug your code and calls, the Listener may be using an async task. If so, you may do anything you please from the response method, as it will be executing in the main thread again. Otherwise, you should look at solutions that handle threaded execution like Handlers

Check box refresh not working when Activity not reloaded - Android

I have created an activity that refresh quotes when the user clicks a button. Within the same activity there is a check box which the users can click if they like the quote.
Everything works perfectly apart from the check box. When the user clicks they like the quote, I want that check box checked. This only happens when the user moves away from the activity and returns at a later stage.
However when the user stays within the activity and returns to the quote, the old state is shown instead of the users preference.
The check box is configured from the values even in the database, if the value is 1, the check box should be ticked, if not, check box should be clear.
The code is shown below:
When the user clicks the next button, the following code is executed:
Button nextGenerateButton = (Button) findViewById(R.id.btn_next_quotes);
nextGenerateButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
String nextQuote = myDbHelper.getnextQuote();
setQuoteDisplay(nextQuote);
btn_favorite.setChecked(myDbHelper.getFavouriteCheckBoxValue());
}
});
The button retrieves the next quote and the getFavouriteCheckBoxValue() confirms whether the favourite column is marked in the database and either returns a true of false which sets the check box value.
public boolean getFavouriteCheckBoxValue()
{
int laballedFavourite = cursor.getInt(0);
if(laballedFavourite == 0)
{
return false;
}
else
{
return true;
}
}
if the user likes the quote, the code executes the addFavourite() which updates the table where the favourite column will be modified on one.
btn_favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if(isChecked == true)
{
myDbHelper.addFavourite();
}
if(isChecked == false)
{
myDbHelper.removeFavourite();
}
}
});
public void addFavourite()
{
ContentValues vals = new ContentValues();
vals.put("favouriteQuote", 1);
db.update(TABLE_NAME, vals, "columnId = " + cursor.getInt(1), null);
}
Again this only works perfectly when I resume the quote activity and not when I am currently live in the quote activity.
Hope this makes sense.
Any help would be greatly appreciated.
You need to refresh your checkbox to see the changement because you made a changement in you db but not on the UI. You need to observe the db and refresh the checkbox after a modification.
Refreshing cursor solved the problem.

Categories

Resources