I'm looking to packing a large sqlite database with an android app, about 200-300MB. From what I've read, my options are putting it in the assets folder, and coping it out at runtime, resulting in duplicate data, or downloading the database from the web at runtime. I don't want to create a webserver for this app, so I was thinking of creating a seperate app that just installs the database to get around the data duplication problem.
All of those are pretty crummy, and I was wondering if there is a better solution?
First, I don't think you are allowed to put a 200-300MB database in your assets folder and distribute it as a single apk, since the hard limit for an apk file size is (as per google's documentation) 50 MB and I doubt that your db will compress that far.. Google introduced the "APK expansion files" for packaging large files with your apk. You can read all about those here: http://developer.android.com/google/play/expansion-files.html
I think (but I have no experience with expansion files myself) that this will not fix the issue you mentioned about having to deal with duplicate data because of the requirement to copy out your database file, but at least this will help you in the sense that you won't have to host your database file on your own webserver. I quickly scanned the documentation on the link I gave above and it clearly states that you should NOT throw away the expansion files when you are done with them, so no help on that part.
Of course, for the "setting up your own webserver part": I wouldn't even bother setting up my own webserver. There are plenty of parties out there that provide you some file hosting service. Probably you will have to pay for the bandwidth, but hey.. if people download your db file a lot, that also means that your app is doing well ;-)
I test of apk expansion files. I created a test app with a 100 MB sqlite database, uploaded the apk and database to the play store. I then downloaded the app onto the phone, the database was downloaded at the same time. The database was automatically renamed and placed in the publicly accessible directory:
/storage/sdcard0/Android/obb/com.example.app/main.1.com.example.app.obb
The app was able to open the database without any problems, but required external read and write permissions. The new and original database are bit for bit, the same. This appears to be the best solution for my use case.
A few issues, the new android developer console does not support uploading expansion files, so the old one needs to be used. Google only allows 2 expansion files, so that may be an issue for some use cases. Google say that you must not rename or delete the file, and that your app must be able to download the file from Google itself if it wasn't automatically installed.
Related
I am developing an Android app in Java using OSMDroid to deliver offline maps in Mapnik tile format in a .zip file.
My question is about how to deliver these maps to users who download the app from the Play Store.
I don't know the exact size of my finished tileset but it will be a .zip file of about 100MB.
In protyping I am including a smaller tileset in my project's /assets folder, and on first run copying it to the user's external storage directory using the getExternalStoragePublicDirectory(Environment.MEDIA_SHARED) folder and replacing /shared with /osmdroid (on my phone it is /storage/emulated/0/osmdroid) and creating the directory if necessary. It's a bit of a hack but it works.
The problems with this are that the tileset (about 100MB) remains attached to the application while a copy is created in external storage. Which is kinda wasteful of space. I may also encounter problems with the APK being too big.
I thought of allowing the user to download the .zip file from an FTP server after they're finished installing the app (prompting them that it's a biggish download and to use WiFi if possible). I haven't looked at the technicalities in detail but this strikes me as being fairly straightforward to implement. However, I can't find any descriptions of people using this method.
So, my questions are:
Is there a standard or recommended way of delivering Mapnik tiles to users in live for offline use?
If so, what is it? (preferably with links to examples if possible)
Thank you to everybody in advance for your help!
In the end I downloaded the zip from an FTP server. This has been tested with a group of test users in a real-life environment and it seems to work well.
The zip file is downloaded to the directory returned by the method getExternalFilesDir. This returns the app's data storage directory which gives the advantage over a hard-coded path that when the app is uninstalled the zip files are also deleted.
I am currently developing an offline app with OSMDroid and I'm starting to ask myself some questions about the storage space the app is going to take.
Previously we had the MBTiles and the database stored at the root of the internal memory and we installed it apart from the app, but we judged it insecure and inconveniant.
Now, the files are compiled with the app and are installed on start-up in the private folder of the app itself.
Here's my question, does it mean that technically both files are duplicated because there is one version compiled in the app and one in the internal memory, thus taking more storage space?
Is there a better solution for this?
After multiple attempts to find a standard way to not duplicate the resources files, I found that I will have to use expansion files.
According to https://developer.android.com/google/play/expansion-files.html, APK files may not exceed 100MB, after that limit you have to use expansion files that will be downloaded with the installer from the play store.
Expansion files are already in a reachable location for OSMdroid so no need to copy them in the app's private folder.
However since my app might be for a restricted-public only and installation will be done manually, I thought of building a separate app that will install the app + expansion files to give less hassle to my clients.
My expansion file is 200 Mb. I can't see it viable to pull files out of it in realtime (too slow for my purposes). So, I'm extracting all of them to regular files in other folder.
Now, I want to save some space on the card for my beloved user by avoiding app data duplication.
I have an idea to delete the actual expansion file and replace it with a zero size dummy, to fool Google Play and prevent it from downloading 200Mb again. Would that trick work?
I can't test for that as my app is not published yet.
I have no idea what kind of data they look at in order to redownload the expansion file, but if you don't want to use it as intended I think you'll have an easier time hosting your files and downloading them through your own download mechanism.
I making an application with phonegap/cordova where I need to keep a lot of files up to date. Some files (mainly images) will need to be erased in time, and some new ones will get downloaded. The thing is, in Android, to manipulate those files, it seems I need to have them on the sdcard; so I copy the files the app starts with from my assets folder to the sdcard. It just seems like a waste of memory space.
Do you know if is there anyway I can start with the app having those files the app starts with already inside the sdcard? or at least somewhere I can delete them later?
Thank you.
Files that are delivered to the device as part of your APK will be stored in a form that cannot be modified by your application (other than by updating to a new version of the apk).
If you copy the files out of the APK into the private internal storage area or the external storage area, those copies can be modified, but the originals inside the apk will remain.
The most efficient solution may be to not put these files in your apk, but have your app instead download them separately on the first run, using whatever mechanism you wanted to use to change them in the future.
(Some people object to this feeling that such files are less secure against unauthorized use, but as the contents of an .apk are trivial to extract this is not a strong argument. Needing to maintain a server to download from is a slightly more substantial objection.)
You do not need to store the files on the SD Card. Each app has its own internal storage that is not accessible by any other apps. For more information see the official docs: http://developer.android.com/guide/topics/data/data-storage.html
My app requires a lot of image resources, so I've had to package them into an expansion file. I've got this working fine when I manually copy the expansion file to my emulator's shared storage. What's unclear to me is the whole download process.
In Google's (often frustrating) documentation, it says:
On most devices, Google Play downloads the expansion file(s) at the same time it downloads the APK, so your application has everything it needs when the user opens it for the first time. In some cases, however, your application must download the files from Google Play when your application starts.
My app will be free with a single expansion file. Can I actually rely on the expansion file being downloaded with the app? Or must I implement the downloader service to ensure that the expansion file is downloaded when the app starts?
What are the circumstances under which the expansion file would not be downloaded with the apk? I suppose that the user might erase or remove the shared storage volume onto which the expansion file was originally copied, so that might be a case I'd have to worry about.
Tell me I can be lazy! Come on! And then someone link to this question on a blog post lamenting the laziness of app developers. OK, OK, I won't get all defensive. I just want to understand the mechanics here, and yes I would rather avoid the extra headaches of implementing the downloader service. I'm not a full-time Android developer, and I've got other things to do!
Thanks
The play store will attempt to download the expansion files but network connections fail or time out etc
You should check the files are available when your app starts and manually download them if they are not.
If you don't allow for this eventuality then some users will be unable to use your app unless it will work without the expansion pack.