Synchronizing against unknown database schema in Android - android

I have an online (postgresql) database, and a local copy of the db in an Android app. The data in these is synchronized, so the app can function offline, but can download new data and upload results when it can. Data is transfered via http GET and POST requests.
I have no problem synchronizing the data for known tables, however, I would like it to be possible to create new tables/alter tables in the online database and have that change reflected in the Android db automatically i.e. without having to release a new version with the updated synchronization code. Is there an obvious/standard way to do this that I haven't found? Google searches I have performed just refer to database migrations for two of the same system or for known schema.

Is there an obvious/standard way to do this that I haven't found?
There's no "standard" way but there are ways to do it depending on your requirements and how your app works.
It's actually a broad question but solvable if you give it a bit of thought.
My app downloads data from a server on a daily basis. Part of the download process involves downloading a DB version file (just a plain text file) similar to the following...
db_version=12345
...the string representation of the previous version (if any) is saved in SharedPreferences as an int value.
If the version in the file is greater than the one in SharedPreferences, the downloader pulls some text files which contain SQL commands for creating, dropping, altering tables etc. Only after the changes have been successfully made does the downloader pull the actual data files and update the DB data (not forgetting to update the latest version in SharedPreferences).
If the version in the file is the same as in SharedPreferences then obviously the download simply does the normal daily data download and DB data update.

Related

Updating/Maintaining SQLite database after each App Release Xamarin Forms

This is my first time working on a Xamarin App and I am new to the app development world so I need some help figuring out this process.
Currently I run a php web service that generates some SQL files that I run in DB Browser and I get a database file which I then put into my Assets and Resources Folder. Using each platform's API I copy the database into a writable folder and use that to run my queries.
I followed this really helpful tutorial and it worked perfectly fine.
https://medium.com/#hameedkunkanoor/creating-a-sqlite-databse-and-storing-your-data-in-your-android-and-ios-application-in-xamarin-2ebaa79cdff0 .
After the "initial" setup I store a timestamp in a local table and and the next time the user opens the app I pass that timestamp and retrieve data that is older than that timestamp. The I update that timestamp and continue the process. That data is sent back in JSON format and make the updates to the tables.
My only concern is if a new version were to come out where I add a new table or a new column which is not present in the current version of my Database, how should I take care of those update Web Service calls? Is there a way of monitoring my DB version? I read somewhere where I could just ignore the new data that is not present already, like table or columns, but I'm not really sure how to do that.
I also saw that if I call CreateTable on my current tables I could potentially update them?
Also for future reference each time I develop a new app would I need to regenerate a new database file to store in the assets/resources folder? Is there a more automated process for this? Along with monitoring the version of my database?
Any Help/Tutorials/Suggestions would be greatly appreciated.
You have to remember that CreateTable it's already doing the columns update for you, because internally it calls a method called MigrateTable which you can see here for further clarification: https://github.com/praeclarum/sqlite-net/blob/master/src/SQLite.cs#L562.
However you could have to handle more advanced modification to your database, like adding triggers or something similar.
In that case i suggest you to perform modifications manually.
In Xamarin Forms i've ended up with this:
https://gist.github.com/matpag/b2545cc22c8e22449cd7eaf6b4910396
Could not be the best strategy ever but seems to work for me.
Summarizing :
You have to save the database version in an internal flag of the SQlite database called user_version accessible with PRAGMA keyword.
Every time you get the database connection, you have to perform a check and see if the current database version is the same as the app last database version.
If not you need to perform a database update and set the new current version.
Reference here.

How to alert users on new update to local database?

I'd like to receive some advice from all of you.
What is the best way for me to alert users on an update to my app? My app is a very knowledge-based & it works like a dictionary, so there will always be updates to it.
The database I have used is by DB Browser for SQLite, and they are all local database where it is uploaded into the assets folder in Android Studio.
Currently, the limitations are that:
1) it's obviously not real-time because it's stored locally;
2) every update I make to the database structure, I am required to upload the new database into the assets folder again, followed by uninstalling the old app on my phone, then run the app to install in my phone again so that the new database is overwritten.
I have read (How can I regularly update a database of content on an Android app?) & some others, and it seemed like I have to have a server, a cloud-based database & live app in market, to solve the limitations?
Is there really no way for me to overcome the limitations if I want to stick to a local database? At the same time, I kinda wish to avoid setting up a server because I am not intending to make the app live on market, and also this is just a school project I am working on and as such, I have very limited skill sets & knowledge about it and would like to make it on a school-project-based level.
Thanks in advance.
One way to do it is to connect to your local DB through local network instead of assets folder. Therefore, you can update the information by querying the local DB.
As for syncing the information between DB and your application, you should create a trigger or watcher that notify your application when the DB is updated. Therefore, your application can know when to query the DB for the updates. Another way is to just query the database periodically.
Bonus: you could move your database to a cloud-based database. Usually there are several providers that provide free database hosting up to a certain size, which should be enough for your project.

Update local Android database

I'm currently in trouble with a SQLite database problem on Android.
My application have an local database which inside an apk file. When the application starts it will check for the new version, and download entirely new database if available (although between two database version, changes are very little). But the database is too large now. So it takes very long time when new database available. So any solution for this problem?
Basic idea
Here's how I'd do it. I'm assuming here that the client app doesn't make changes to the local database (except when it downloads a new version), so that there are only a few possible versions of the database in existence (one for every time you've made a change at the server end).
Add a column to every table called LastModified, with a default value of NOW(). That means that every time you add something to your master copy, it'll get an updated LastModified setting. You will have to make sure your updates (rather than inserts) change the LastModified field too.
Store somewhere in the database (a Settings table or something) a field that tracks the date that this version of the database was published on the server (call it PublishDate).
When the client wants to check for a new version, it sends its PublishDate to the server. The server then checks each table, and finds every row where LastModified comes after PublishDate. It sends SQL to the client to insert or update these rows on the client. It also sends the new PublishDate so that the client can update that in its local copy.
This deals with inserts and updates. It doesn't deal with deletions. It might be that they aren't an issue in your case; if they are:
Add either a separate table to log deletions, where you also track LastModified, so that you can tell the client which rows to delete; or preferably have a setup where you don't ever actually delete any rows, but just update them to be marked as "deleted".
Finally, this won't handle schema changes. Again, hopefully that isn't an issue in your case: hopefully you have a stable schema. But if you do need to add or drop tables or indexes or something, that will have to be done separately:
Create a SchemaChanges table on your master, and whenever you make structural changes, put the relevant details into the SchemaChanges table, along with a LastModified date, so that you can send this to the client on request too. If you're doing this, you'll want to send schema changes to the client first, because they might affect the meaning of other changes.
Now the nice thing about doing it this way is that you can pre-process everything on the server (because there are only a few versions in existence). For every old version, you can calculate the changes (based on the details above) that would take that old version up to the new version, and then store the resulting SQL on the server. If you do that, you avoid the need for generating the SQL on the fly: when the client sends the PublishDate, you just look up the SQL you've already calculated that transforms the version from that PublishDate to the latest version.
Alternative implementation
There is a nice and easy way of pushing the changes that the above scheme gives you, even with a slight simplification that doesn't require LastModified times, or indeed any changes to your existing structure. At the server end, where you already have the old version (because you have all the old versions) and the new version, you create an SQL dump of both databases, and then run diff over them to generate a patch file that you can send to the client app. The client app will use the same Java library to generate the SQL dump of the old version, and will then apply the diff patch to it to create a full SQL dump for the new version. At that point, it can drop the old database and create the new one from the SQL dump.
This will be very efficient if the changes aren't wholesale changes (in which case you might as well just push the new .db file).
It's fairly easy to do this by invoking the SQLite binary to create the dumps. You will need to modify the approach slightly for Android, according to this way of executing an external command.
You can use this Google library to calculate the diff patches at the server end and apply them at the client end.
Instead of getting an entire new database file, get the changes. Changes may be in the form of an SQL script. Let server generate the change script for every update, and then you can download the SQL scripts and run them on local database in sequence.
You need to create a timestamp on any changes you do to your database on your server.
When the app connects to your server, it sends the last timestamp downloaded so your server knows what is the new data to download.
Timestamps are not set on the device based on the real time, you need to download it as well to avoid timezone problems are different hour values.
You can use consecutive number versions if you prefer instead of timestamps
I have been working on a similar problem where I have to update local database every time there are any changes on server. The trick is to keep track of last updated time in local database in android and send that time to get just the updates from server in JSON format. Here, you will have to write server side code that takes input as last updated time and returns all the updates made to server side database in JSON format.
After getting the JSON data, you have to convert JSON data to SQL queries and insert or update in local database.
Have a look at this answer. And also look at Google IO 2014 code here.
I ended up using ContentProvider with schema and contract classes as explained here.
Then I created java object for every table in my database and used gson library to convert the incoming JSON updates to the java object. After that, you have to write inser/update/delete queries as given in documentation.
So basically, you have to create contract, database and provider classes for database handling. And java classes one for each table in your database and you have write code for fetching JSON updates from server, converting JSON string into java object and then insert/update/delete in database. Demo code is available in the Google IO 2014 app.
What isn't clear from your question is if you want
bidirectional sync (client and server can make data changes) or only
unidirectional sync (only server or client can make changes).
For me it sounds more like you want unidirectional sync from server to client. This is exactly what the Google I/O does with the conference data. You can found a detailed blog entry how this works here:
Conference Data Sync and GCM in the Google I/O App, just look at the chapter 'Downloading Conference Data Efficiently' which deals with manifest.json, sessions.json and speakers.json. If the data schema changes, just provide a new app which performs the schema change in the standard android way and make your json parsing routine in a way that it ignores additional fields. Just as addition:
a blogentry which provides Google I/O App Insights
The code itself on Github
If you want bidirectional sync then chiastic-security provided a good overview for the database operations. What is missing is the programmatically part of the solution:
a presentation was given at Google I/O 2010 by Virgil Dobjanschi: Developing Android REST client applications
The presentation lead to much questions since no code was presented, see for example this disscussion: Need sample Android REST Client project which implements Virgil Dobjanschi REST implementation pattern
A good picture from the architecture (SyncAdapter approach): here
and a very good blog entry about Write your own sync adapter
and you find some information in the Google blog entry (first link for the unidirectional sync)
and some code in this presentation - slide 31ff
Hope that helps.
Using greenDao you can perform such Migrations, Check it here. Good luck.
You can do this through Google Cloud Messaging API. It is a feature given to developers by Google which works on both Android and IOS devices. Google Cloud Messaging (GCM) is a service that helps developers send data between online servers and apps. Using this service you can send data to your application whenever new data is available instead of making new requests to the server in timely fashion.
A great tutorial for using GCM is this.
Hope it helps :)
Maybe you can use services for to change database version. Thus user can't notice that and User continue to use the application. When service finished it work, Application send a notification. Of course there are only approeach and advice.

Android updating a database

I there a way I can set up my app so that things like the database and images can be optionally downloaded/updated when when I make changes to the data, without updating the app. i.e. a kind of syncing with the new data?
I would have the database and images on my server and the user can update or not without having an icon on their phone saying there are updates available.
As far as I know, Android databases are just sqlite.db files. You should be able to have a button in your app that downloads a new sqlite.db file from your server. Have it replace the file that is already on the device and you should be good to go!
If you have a localized database you can modify, add to, and delete as needed based on server response. Create a robust enough Database Helper and you can use it to make the database whatever is needed, in a run time environment.

Sync an external database with SQLIte database on application start

I have an SQLite database for my Android app that stores a copy of some data from another database on a server. When the user opens the app, I want to sync the local copy to the external master. The user may have been on the related website and inserted/updated/deleted data.
If it was just insert/update, timestamps could be used, but as they could delete data, I'm not sure how to go about checking for deleted rows.
So, what's the best way to tell what's changed and update the local copy?
I'd add a table to audit the deletes (containing key fields of the deleted records) and transfer that on sync, and after a successful sync clear the table down.
Hm, we are working on iOS project, which will sync it's database with server if server will respond what it have newer version.
Our server incrementally stores performed SQL and on request if compounds all those changes to specific date and gziped sends to the application, where my Objective-C wrapper execute SQL statement from downloaded file.
May be same approach will be good for you too.

Categories

Resources