I am writing an app that needs to fetch the latest changes to android's native calendar since the last time I performed such a "sync" operation.
I am also accessing other content such as the contacts. Here I can reliably check whether the VERSION column of a RawContact changes over time, however I fail to find similar options for calendar events.
Registering a ContentObserver only triggers once something changes, but does not yield the rows that changed. I thought about querying the Calendar.Events ContentProvider for any rows that have the DIRTY column set to 1, however I would be at the mercy of Google's sync adapter, which might potentially be called more quickly (?) than my query is being processed.
Likewise when no network connection is present on the android device, the dirty columns will remain 1, which yields unsuitable results for my use-case.
Is there a better way to listen for changes to the native android calendar which returns correct results, even when no network connection is present?
Apparently, there is no simple way to do this.
Here is how I worked around this issue:
I am keeping a local cache database for contacts that I found the last time I queried the database. Whenever a change occurs (notified by a call to ContentObserver::onChange()) I compare the entries in my cache database to those of CalendarContract.Contacts using a CursorJoiner.
Ids that exist in both cursors need to be compared for changes. To do so I generated a hash for every content, which i stored alongside the contact Id in my cache db.
IDs only provided by the ContentProvider represent new contacts since the last "sync", while IDs only contained in the cache DB are deleted contacts.
Once the differences are obtained, the cache database needs to be updated accordingly.
Related
I'm working on a Mobile App, where the main feature has the user do a lot of CRUD (Create, Read, Update and Delete) tasks within it.
The main storage of data for the App is a local sqlite database, but the user has the option to register an account and use Cloud database to backup their data.
This App needs to be able to work both offline and online. And the user should be able to use multiple devices containing the same data.
Currently in all of my sql tables I have 3 extra columns that keep track of which entries in the database is synced: createdAt(datetime), updatedAt(datetime) and synced(boolean).
With this I am able to keep track of which entries are the most recent, and update either the local or the cloud database accordingly.
I'm using Cloud Firestore as the Cloud, and using its' Offline capabilities is not a viable option in my case.
My Question is; Which solution would be the best when keeping track of deleted entries until the App is able to sync with the cloud?
One idea for a solution for this is to have an table that contains all the ID's of deleted entries together with which table it belongs, and then when the App is able to sync; remove these entries on both the local database(on all devices) and the cloud database.
The problem I have with this solution is that, this 'deletion' table quickly will become huge, and removing entries from this table would be a problem, because of the need of all the user's devices to be up-to-date before deletion and in a scenario where the user has abandoned one of his devices, this would mean that the device would never sync, resulting in the entries not being remove from the 'deletion' table.
What would your suggestion be for a robust way of tracking deleted entries?
I don't think there's a solution that satisfies both these objectives:
Don't keep deleted items in the database forever
Make sure deletions are synchronized between all devices forever
So you will have to decide which one to give up on. Your idea satisfies 2 but not 1. A solution that would satisfy 1 but not 2 is to delete the deletion records after a period of time, maybe six months. A variation on that would be when a record is deleted, rather than actually deleting it just mark it as deleted (as well as the date when it was deleted), and if applicable remove any large pieces of data from the record. After whatever grace period you decide, the record can be actually deleted. The down side is that if a mothballed device is brought back out, it could restore previously deleted records.
I've read a lot about regarding offline cache strategies but unfortunately I found nothing that can fulfils my requirements.
Let's say that I have a list of Order in my local database that need to be synced back with the server if one of them is modified. The Order can have multiple statuses like: New, Started, Paused and Completed. The status changes must be synced sequentially with the server because the order is also important.
Creating the table with "isModified" column is not good for me because i need to sync every status change one by one sequentially, not just the last one.
What are the best strategies to store all status changes when the device is offline? I am thinking about duplicating the Order table or creating a new one for the sync data because there can be also other objects not just Orders.
Any advice would be much appreciated.
If the order of modifications is relevant, you should store each modification in some kind of ordered data structure, e.g. another local table.
Use Firebase Database for offline database. It synchronises automatically when an internet connection is active.
Add the line below in your Application class:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
I have a remote database that can change at any time. I need to find a way to keep my sqlite database update with all the changes in the better and optimised way possible.
I thought having a single timestamp per table and send only the updated table to the client would be one solution, or maybe having one timestamp per row and sending only the updated row to the client..
But
- how can i manage deleted items, for example?
- how can i manage the technical update on Android?
Basically, in a few words, at some point in the app, i need to download the changes with an API and update the local db.
Does anyone have some ideas?
Thanks
Since it seems this is a one-way only sync, I would:
Make each table on the server DB have a UUID column and a last
updated date/time column.
Create a REST call that will request updated data. Ideally, it would
take the time the client was updated. This date should come from the
server during the update call.
The server would scan each table searching for rows that have a date > than the date passed. Serialize the data and return it as JSON along with the server date/time for the next request.
Now tracking deletes is a bit more work. You can either:
Never delete data and only mark the rows as deleted, this is the easiest, but depending on your data may end up with lots of rows in the DB.
Delete the data and then track the deleted rows in another table. These can be deleted after some time and if/when all clients have been updated.
Have a second update call that will push down all the UUID values and time stamps for each row. The client could then figure out which rows need to be deleted.
Though it's the most complex, I'd probably opt for option 3, as I don't like old data hanging around. The direction I would go would also depend on how many clients will be syncing with the DB.
I've decided to follow another approach:
I've created an api that parse the Mysql db into an SQLITE db on the SERVER side. There is a "last_update_timestap" that will be updated every time that something will be changed.
Another api call, gives in the header an extra field containing that timestamp.
On the client side there is a Sync process that do the follow when needed:
Api call retrieving just the HEADER, getting the last update timestamp and checking if an update is needed;
If is needed download the database from the other api
Write the database into a temporary file and copy that temporary file at the position and with the same name of the real database
Use the database
Thanks everyone for the help but this turned out to be the suitable approach for my project structure.
Well, I'm building a app in both iOS and Android and both app needs to be syncronized with the cloud DB MySQL. Both the apps works offline so I need all the insert and update functionality. Delete is probably not going to be used but still I'd like to know.
Well, what I'm looking here is the solution or ideas or algo that's needs to done to achieve this.
I have kept CreatedOn and LastSync as timestamp column on each table.
Now the problem is should I always keep checking all the rows and all the columns everytime?
What I think is I should keep ModifiedOn column on all the tables and check that with LastSync for every device id. What do you guys suggest?
Maybe it's not the answer you are waiting for, but on the project I'm working on, we are using Azure Mobile Services. There is an Android and iOS SDK where they implemented synchronization between offline database and Azure (just like in Git you can call push and pull methods).
There are some limitations (TableStorage is a limited MSSQL storage), but you should check it out.
I know it's about two years overdue , but I've been doing the same thing (Android App that syncs with web api and postgresql)
What I do up to now (still researching if it's the best way, which is how I found this question) is that I keep a last_update field with a timestamp on when the data was last_updated and an altered field with a boolean on whether the data was altered (by a user action on the device)
So when I perform the sync:
I first copy the database to a backup (in case there is a problem)
I send all the rows that are marked as altered (the server handles conflicts)
then delete them
after that I find the max(last_update) value,
I subtract one minute from it
Then request all rows that have been updated after that value,(this will also also include the data I have sent because there is no way , unless there is a problem, that a row is set to altered with a last_update before the last non altered row)
It may cause some duplicate data being transfered (especially if you make A LOT of changes frequently) but in my case it's a rare phenomenon
I just had a little confusion about how a sync provider utilizes delete. After reading http://developer.android.com/guide/topics/providers/content-provider-creating.html#Delete, I implemented my own custom content provider, and I've written the server side implementation so that all the rows with the deleted flag set are deleted on the server, but when do the rows get deleted off the device? I wrote the rest of the application so that only rows without the delete flag are ever used, but are rows that are deleted simply left there and never deleted?
If anyone is curious, I simply ended up writing my ContentProvider such that it does not query for rows with the deleted flag set unless specifically queried for. This includes the other REST methods. I don't know if this is the correct way to do it, but it works.