HowTo: Provide notification to Android app whenever SQLite table updates - android

I am in process of developing an Android tablet app using sqllite 3.7.4 which would
perform following:
Fetches information from the UI
Performs some logic and store related information to the sqlite database
The stored information has to be send immediately OR at schedule
interval (ex. at 5:00 on xyz date) over the network
Currently, we have developed a dispacher mechanism (thread ), which constantly polls the database for new information inserted in the database. The thread fetches the information and send to the network module.
But, I feel this is not the correct approach as
Polling every time is a overhead. There can be times when there is nothing to execute
It is not real time , because we poll after every 5 seconds
So
Is there a way to send a trigger to my network module as soon as information is updated in database?
Or any better way to achieve this task?
Thanks in advance.

This question is about one year ago, but i think this is a common problem. This is how i handled the Database changes:
In my Adapter ( SQL ADAPTER) i have methods for updating / deleting or inserting data into the Database obviously. Like this method:
public long addProduct(String code, String name ... String gid, String gdate) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_CODE, code);
initialValues.put(KEY_NAME, name);
...
initialValues.put(KEY_CHECK, this.checkfalse);
initialValues.put(KEY_GID, gid);
---------
Intent i = new Intent("data_inserted");
i.putExtra("date", date);
sendBroadcast(i);
---------
return mDb.insert(SQLITE_TABLE, null, initialValues);
}
After the change happened it will send an broadcast intent. To fetch this first register your Broadcast Receiver in your onCreate Method (uploaderClass or whatever). This will look like this:
registerReceiver(Updated, new IntentFilter("data_inserted"));
And this Method to handle the following actions!
private final BroadcastReceiver Updated= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
doSomething(); // Data was inserted upload it
}
};
EDIT :
To fetch only new items from database, I sign new products. I have a colum "info" which can contain Strings like "upload", "update" or "delete". Then i fetch all Items from the database which contain these special strings and upload them. After that i set them to null or an empty String. Whatever you wish. Hope i explained it not to complicated :)

You can create your own database listener whenever something is updated to the database it will fetch the information and send to the network. I think will clear some idea for implementing this thing.

Now we can use Room to achieve this.
database.getInvalidationTracker().addObserver(new InvalidationTracker.Observer(tableToObserve) {
#Override
public void onInvalidated(#NonNull Set<String> tables) {
}
});
database is an instance of RoomDatabase, which is the base class for all Room databases. All classes that are annotated with "#Database" (which is the way to use the Room Libary) must extend this class.
In the creator method of InvalidationTracker.Observer, you can pass in an array of String (or in the form of varargs) to indicate the tables you'd like to observe, if any update happen to those tables, the callback method onInvalidated is invoked.
Some links to refer to:
https://developer.android.com/reference/android/arch/persistence/room/InvalidationTracker.html#addObserver(android.arch.persistence.room.InvalidationTracker.Observer)

hope so this will help you
private Handler h;
// in create time
h = new Handler();
// call where you want
h.postDelayed(myRunnable2, 1000); // after 1000 millisecond this function call automatically
// this function
private Runnable myRunnable2 = new Runnable() {
public void run() {
// do some thing
h.postDelayed(myRunnable2, 1000);
}
};

Related

Inserting into a many to many relation in room

I am currently building an android app, that uses a small database which consists of two entity-data-classes (Card and CardDeck) and a third one representing a many to many relationsship between the former two by mapping there long id primary keys together (CardInCardDeckRelation).
Now I want to insert a new Deck into my database, which works just fine, but if I want to insert some CardInCardDeckRelation-objects afterwards by using the id returned from the insertCardDeck()-method it fails because the insertion calls on the relationship-table occur before the insertion of the cardDeck object is finished so I am always getting the wrong cardDeck-id.
I think I am going into the right direction by using a Async-task to insert my CardDeck however I don't know to proceed from there since I can only pass one set of Arguments to my async-task object, so I can't pass my Relationshipobjects to be inserted in say for example a onPostExecute-method in the Async-task-class.
This my insert-method in my Repository-class:
public void insertCardDeckAsync(CardDeck cardDeck){
new insertAsyncTaskDao(mCardDeckDao).execute(cardDeck);
}
private static class insertAsyncTaskDao extends AsyncTask<CardDeck, Void, Void> {
private CardDeckDao mAsyncTaskDao;
insertAsyncTaskDao(CardDeckDao dao){
mAsyncTaskDao = dao;
}
#Override
protected Void doInBackground(final CardDeck... params){
mAsyncTaskDao.insertCardDeck(params[0]);
return null;
}
#Override
protected void onPostExecute(Void v){
//maybe insert Relationship object here?
}
}
I would be very thankful if someone could provide a way to properly insert an entity object and some many-to-many relationsship objects afterwards, using the id generated by the former insert.
So after some testing i figured out my error:I was initially using an Executor which I defined somewhere else in my App to handle database operations, so I don't have to create a private inner class extending AsyncTask for every database operation in my Repository class.For some reason though my usage of Executor does seem to block the particular thread when executing database-queries so:
mExecutors.diskIO().execute(new Runnable(){
//insert new Deck
//insert Many-to-Many relationsship-object
}
would execute both operations immediately after one another, thus causing a SQL-ForeignConstraint-related error, because it tries to insert the realtion objects before the actual deck object is inserted.
The solution to this is to just use a AsyncTask instead, handling all the database operation in the right order in the doInBackground-method:
#Override
protected Void doInBackground(final CardDeck... params){
// insert new deck object into database
insertionId = mAsyncTaskDao.insertCardDeck(params[0]);
// create relations-array
CardInCardDeckRelation[] relations = new CardInCardDeckRelation[STANDARD_CARDS.length];
// insert standard-card objects into array
for(int i = 0; i < STANDARD_CARDS.length; i++){
relations[i] = new CardInCardDeckRelation(insertionId,
mAsyncCardDao.getStandardCardByName(STANDARD_CARDS[i]),
i);
}
// insert created array into database
mRelationDao.insertMultiple(relations);
Log.d(LOG_TAG, "Deck inserted");
return null;
}
If anyone needs further explanation I can provide the whole AsyncTask class.

Receiving notification once all read operations are successfully performed

I have a question about some functionalities of Firestore. I am trying to occupy an array of data obtained through multiple read operations from the Firestore database. Is there a way for me to be notified when all the data are successfully read and stored in my array? This is particularly an issue because read operations are not finished in the order that they are called. Here are some code that illustrates my problem:
/* My array to insert the data read from the Firestore database */
String[] my_array = new String[3];
/* A method that will be called to initialize our array */
private void initArray(String doc_one, String doc_two, String doc_three) {
initSingleIndex(0, doc_one);
initSingleIndex(1, doc_two);
initSingleIndex(2, doc_three);
}
private void initSingleIndex(final int index, String doc_id) {
/* We perform our read operation here */
question_ref.document(doc_id).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
my_array[index] = documentSnapshot.getString("some_field");
}
});
}
My current implementation is to keep a global counter, which will be used to keep track of how many read operations were successfully carried out. I am also wondering whether the onSuccess() callbacks can be fired concurrently, since this will then lead to data corruption (i.e. the classic problem of incrementing values concurrently).
Any help or suggestion will be appreciated.

Get notified when data changed in database

I'd like to know how can I be notified when data change in my database.
Is there a solution to this or not?
The fact is I know how to push and get data in it but I don't know how to be notified when a modification happens
If the responsibility changing the data in your database is your app, you should create a database layer and then create some callback to notify your app your data has an Insert, update or delete operation.
If you use sqlite like local database:
First approach, using the android SDK content provider, the content observer class. Create a content observer that monitors some table in your local sqlite.
http://www.grokkingandroid.com/use-contentobserver-to-listen-to-changes/
If you use a ORM, there are callbacks in the ORM to notify changes. For example GreenDao using AsyncSession:
AsyncSession asyncSession = App.getInstance().daoSession.startAsyncSession();
asyncSession.setListener( new AsyncOperationListener() {
#Override
public void onAsyncOperationCompleted(AsyncOperation operation) {
// do whats needed
}
});
asyncSession.insert(MyObject);
If you use Realm.IO, there is a callback from the realm transaction to notify is an update is done.
Realm realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
MyObject myobject = new MyObject();
myobject.setId(UUID.randomUUID().toString());
myobject.setName("My object name test");
realm.copyToRealm(myobject);
}
}, new Realm.Transaction.Callback() {
#Override
public void onSuccess() {
//realm already update
Log.e("lh", "this callback i can use to notify. after save " + realm.allObjects(MyObject.class).size());
realm.close();
}
});
Changues in the backend.
If the changes are in the backend. A possible solution is send a push notification and start to do a background service in the app.
In this URL you have a PHP script to do a push notification to google cloud.
https://gist.github.com/prime31/5675017
You must attach the google cloud push notification receiver in you android app and create a specific service that will do an HTTP request to download the new data if you expose your database with a REST endpoint.
the most simple way is to keep a row in database and update its value when data is changed.

Make AsyncAppData in Kinvey serial

I want to get a data from a kinvey Collection, put it in a db and then modify it locally.I want to be sure that all data is gotten from collection before any modification. My problem is that, getting collection is done via AsyncAppData which runs in background,which makes my task impossible.
A sample code is shown
//getting data
ArrayList<String> runfunc = new ArrayList<String>();
final AsyncAppData<EventEntityWhy> myevents4 = mKinveyClient.appData("WhyWorldTemp", EventEntityWhy.class);
myevents4.get(new KinveyListCallback<EventEntityWhy>() {
#Override
public void onSuccess(EventEntityWhy[]){
for (EventEntityWhy x1 : result) {
String temp1 = (String) x1.get("whyindex");
runfunc.add(temp1)
}
}
}
//then processing will start
//runfunc array will be processed here
That's not how asynchronous programming works, and Kinvey has no plans to change that paradigm. The proper way to build your code is by processing your data inside the onSuccess callback rather than on the mainthread.
What you could do is set an event flag inside the callback, and then you create a waiter at your "//then processing will start" point that waits for that flag.

UI responesive in Android

I create an app that like dictionary app. When the user types in an Edittext, I call an AsyncTask to compute and update the result to the screen (I put the UI update code in onPostExecute() method ). However, when you type little fast, the eddittext become not responesive (a little latency). I think this promblem occurs because many AsyncTasks are running (each AsynTask for an input letter). So, I think I need to stop the first task before calling new task. Am I right? What should I do in this situation?
You don't need to implement the filter method in an async task. I call filter method on data when first letter has been written in editbox and save the result in an temporary array, then when another letter has been written, I call filter method on the temporary data which technically has less information than the original data. By doing this, the dimmension of data set decreases as you type in editbox. Also, you can use this method to store previous data set so when you press backspace, you don't have to call filter method again, you just go to previous saved temporary data set. For me, it works fine and I don't have to use async task because it is efficient
I suggest you another approach: use only one thread. The searching thread should wait for searching data > do search > and sleep until new data. E.g.:
private static class SearchThread extends Thread{
private Object monitor = new Object();
private String value;
public void search(String value){
this.value = value;
synchronized (monitor){monitor.notify();}
}
#Override
public void run() {
while(true){
try {System.out.println("Wait for search data."); synchronized (monitor){monitor.wait(); }
} catch (InterruptedException e) {e.printStackTrace();}
System.out.println("Searching for " + value);
}
}
}

Categories

Resources