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.
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 currently have a local SQLite database that will update periodically from a server.
Initially, the local database will be empty. The app will fetch entire server database as json, and insert all the new rows locally.
After some time the app will fetch the entire server database as json again, and insert any new rows, or update any existing rows that have changed.
Now, the issue is if the server's database has removed an item (row). The app will never be aware of these removed items, and it will exist forever locally.
What's the best way to handle this?
A few ideas:
Add a "is deleted" flag on each item. This would allow the app to remove any items, but this seems like it would be harder to maintain, and a lot of changes for each table. Although it would allow you to undelete items as well.
Same idea as the flag, just modify as existing field and return it. For example, return a negative id ( id = 150 -> id = -150 ). This wouldn't require any database changes, but is confusing to anyone who doesn't know what's happening.
Modify the result to return a list of "deleted" items. This wouldn't be too much work, but doesn't seem like a good solution either.
Is there any standard pattern to follow for this?
Thanks.
You can use Realm instead of SQLite for better experience, And When the app is fetching the data from server clear all data in the realm and insert new records, It will not save the removed item.
Thank you.
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.
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.
I'm new to android. I want to ask about SQLite database lifecycle. Basicaly, I want to include the insert data method and viewing data method in the main class (which basicaly called 1st when we open the app). Then I'm going to make some update to the database in another activity. What I want to ask is, when I'm going to open the app for the next time, which data that will be showed? Is it the 1st data that I inserted with insert method OR the updated one?
I don't understand exactly your question. So I hope this will answer it. There are 4 operations, you should implement: create, read, update, delete. For example when you have a contact table with id, name, phone number then you can create (John, 012345). If you then call the read method with id 1, you will get (John, 012345). But if you update this before you read it, you obviously get the updated item - the database didn't delete anything when you close the activity. I highly recommend you to create a new class to handle those crud-operations, because you will get crazy, when you wanna change the update operation and must search it in every single line from your app. I also recommend you to read this blog. It saved me a lot of time:
http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/
As far as I understand your question,
my answer is -> You should see the updated data, because Db is same throughout the app.
The data that will be shown is the updated one , because SQL operations are immediate. It is very unlikely that onUpdate() will not update the database until and unless it encounters any error. you can see that itself using a CursorLoader attached with your cursor after running a query command. This can be done in an activity just displaying the contents of the database.
For database operations, It is beneficial to use Content Providers cause then you can extend your apps to widgets, share data with other apps etc.