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.
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 want to reduce my android apk file size, so I split some function source code and compile those code to a Jar file, it contain a dex file in the jar file. When android app need use those functions, the app download the jar file and load dex file from it.
But I found the Android Developer Program Policies said:
An app downloaded from Google Play may not modify, replace or update
its own APK binary code using any method other than Google Play's
update mechanism
My question is do I do this a violation?
Yes because you're basically updating your APK without the Google Play's update mechanism. If you truly wish to minimize the .apk file size, you can put your resources online and request them through a custom api.
For example: I developed an app which uses Google Earth marker and polygon coordinates, descriptions and other useful information that are stored on my webserver, online in a .kml file. Because I'm constantly updating the file with new markers and polygons, I don't want the user to download the .apk file with a huge filesize each time I update my resources. So that's why I stored my resources online which the user downloads while using my app and that keeps the .apk filesize to less than 3MB which is great for the people who download the app through the play store. Otherwise the filesize would have been 15MB+ with all the images and other resources with that keeps on growing by each minute.
Nonetheless, the user would have to download the resources one way or another but I do like your way of thinking though to keep the size of the .apk file low as possible.
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.
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.