On file size
You need to deal with the vast array of issues that come from the sheer size of images - whether compressed or not, images range from hundreds of KBs and up - which is tens to hundreds times larger than the typical amount of data your frontend/backend handles per operation.
Therefore, the first strategy is to focus on reducing the image size. Don't bother with techniques that only improve a few percents - to make things improve, you need an order of magnitude better compression.
The best file-size-reduction approach is to scale down the image - as much as you can without making your users angry.
If you use JPEG or WebP (or some other lossy formats) you can try use different quality level. Sometimes the best trade-off is obtained from a combination of scaling down and adjusting quality level. Don't limit your scale-down factors to powers-of-two.
The second best image compression approach depends on the type of image content. You will need to learn about the basics of compressed image formats, and be creative applying those basics.
In one very simple approach, large areas of uniform color is simply cropped away from the image, and replaced with a background color - to be painted by the app - using the same RGB hex.
On versioning
The backend database needs to be able to serve a checksum, timestamp (last modified time) or file version number that serves to inform the app whether they have the most up-to-date file.
On keeping the user from boredom
You might need to show small, fast-to-download thumbnails (which are scaled down versions of the image) just in case your app users are quick-tempered. Make sure these thumbnails are properly cached by the backend - loading the thumbnails from disk adds to the latency, which defeats the purpose.
On backend image processing
It looks like the prevailing advice on Programmers.StackExchange is to keep a queue of image processing operations to be performed; the queue to be executed by an out-of-process ImageMagick worker process; results are added back to another "finished queue" to be handled by the backend.
If you're going to sync against your master SQL database you will always have the same problem: how do you resolve conflicting changes?
CouchDB doesn't help you there. It explicitly does not handle conflicts and leaves it up the user to handle them (by picking sides). Other solutions also can't really help you, because to resolve a conflict you must understand the meaning of the data that is in a conflicting state. In other words, there is no generic "perfect" solution to this problem.
My advice would be to develop some solution yourself using that upload changes to a queue strategy you described. Performance likely won't be your biggest issue, but conflict resolution will be. Choose one of several strategies for handling that queue:
- Optimistic concurrency control
Keep track of the timestamp when a client took data out of the system, and when uploading a new version of that data check that no changes occurred. If changes did occur, either use strategy 3 or allow the user to force or discard.
- Locking
Allow the user to explicitly do a "check out" and "check in" operation. Some basic things to take into account: other users need to be able to see who has a lock, and take that lock away from them. Only the user with a lock may check in changes performed on data held under that lock. Look at how subversion (and clients like tortoisesvn) handles locks, it's sane, as far as such things go.
- Merging
This is a variation on strategy 1, except that when you detect conflicts you perform a merge. You can implement this using multiple strategies. Last one wins, first one wins, explicit user choice (possibly showing them the delta). You can reduce the risk of conflicts by tracking the data at a finer-grained level (per-field instead of per-form).
Best Answer
Note: Sync adapters run asynchronously, so you should use them with the expectation that they transfer data regularly and efficiently, but not instantaneously. If you need to do real-time data transfer, you should do it in an AsyncTask or an IntentService. - source.
Basically, if you need real time transfer use IntentService (the first option), else SyncAdapter. I prefer an IntentService though because it feels more customizable, but a more trivial approach would be to use a SyncAdapter.