I am very new to Android development.
Suppose my application has a few static HTML files that I expect will need frequent updates. Suppose I do not want to publish a new version of my application every time a file changes, but I do want to keep these files up-to-date.
What I imagine I could do, is to write a piece of code within the app to go to a known URL and check for updates every few days. If the updated resources bundle is available, the code will download and unpack it, replacing old files, so that the user will see the most resent content.
Questions I have:
- is such approach a good/bad idea? In other words, are their specific disadvantages to doing update in such manner or is it a commoin practice?
- how can I implement something like that? Service? Is there an existing sample piece of code that I could reuse?
Thanks!
If the updated resources bundle is available, the code will download and unpack it, replacing old files, so that the user will see the most resent content.
This is fine, except for the "replacing old files" part. Resources are read-only and cannot be modified at runtime. However, you can adjust your code that uses these files to look for your downloaded-and-cached updated files first and use those, falling back to the resources if updates are not available.
how can I implement something like that?
If your app involves other data synchronization, and you are using something like SyncManager for that, just include these files as part of the synchronization work.
Otherwise, use AlarmManager to arrange to get control every so often to check for updates. You will probably need to use WakefulBroadcastReceiver or my WakefulIntentService to do the actual downloading, as the device will want to fall asleep right away otherwise, if the user is not using the device right then. Use HttpUrlConnection or your favorite HTTP wrapper library to download the files to getFilesDir() or getCacheDir().
Related
I have an android app that is able to open a certain file type via a VIEW intent.
After a file is opened using my app for the first time, I would like the app to "remember" the file so that the user can choose to open it again from a list of "recent" files inside the app...
My question is: what is the best way to implement this kind of "remembering" - should I:
Automatically copy any files passed to my app into my app's own storage area, and then list "recent/old" files there?
Or, should I record a list of files that my app has been passed previously, and access them via the same path later if necessary? If that is recommended, is there any guarantee that I will be able to access them again later? (I guess not!)
Option 1. seems like more work and doubles the storage space needed for all files passed to my app, but will guarantee the files will be accessible in future. Option 2. is easy if the files are always readable by my app in future, and are not renamed/deleted for some reason - it seems there's no guarantee of that though...
If it helps, I expect most files passed to my app to come from "Downloads" via the user's browser, but some might come from email/other apps etc.
Thanks
I would go with Option #3: drop the proposed feature.
As DeeV pointed out in a now-deleted answer, Option #1 is not a great solution for a "recent files" list. It would be the right option for other verbs than "remember", such as "import".
Option #2 will not work much of the time. Your app needs to support the content scheme, in addition to (or even instead of) the file scheme. By default, you will only have rights to access the content at a content Uri until your process terminates (at best). You may be able to takePersistableUriPermission() to get durable access, but that will not work much of the time — it depends upon whether the other app is granting you such access. Hence, you might have a Uri that you can remember, but remembering will do you little good.
I've got an Android app written in Kivy (Python), which stores local files that should survive an app update (adb install -r).
If the files are stored in a subdirectory of the current directory ("data/data/app_name/files"), I see that they are deleted after update.
However after some experiments I could "solve" this by storing the files in the "data/data/app_name/shared_prefs" directory, which seems to be persistent after updates. By the way, I didn't check but maybe the "data/data/app_name/databases" also is.
Is there a cleaner way of doing things ?
I need to test if I can create a new folder not called shared_prefs nor databases under "data/data/app_name", and if it is persistent.
(this seems kind of a hack because those directories have another dedicated purpose, even though my app is not using them for this dedicated purpose right now)
(NB: I don't want to keep the files outside the app private directory)
There is not a simple way (as in a build hook or similar) right now, but it's something we've specifically discussed in the last few days as the current situation has become a direct problem. I'm not sure what the resolution was, but there will probably be a change in python-for-android to fix it fairly soon.
If you want to keep up to date with this, ask on the kivy mailing list or irc. In particular, knapper_tech was making these changes.
I'm just wondering how the following scenario can be solved:
I want to write a very simple app for my daughter. The app displays 4 colored fields on the activity and through speech output says something like "tap green". She should then tap the green field to get positive feedback. So far, so easy.
I then thought it might be nice if the app would also "grow" as she grows older. Maybe later I want to have a game mode where I display animals, numbers, vehicles, etc., so it would be nice if I could have something like "Shape sets" - basically a set of images along with a description of what the app should say for each image. Also easy enough - all you need is a set of images and an XML file describing the images.
BUT
I'd like to be able to install these "Shape sets" as additional APKs later on, so that I don't have to modify the app every time. I'd like to install the APKs, so that the contents are added to a specific sub folder on the SD card, into which my app looks to enumerate available "Shape sets".
If I ever published the app to the Play Store, other people should also be able to download the "Shape sets" I create (no need for user contributions, though).
Is that possible? If so, what would I have to do to have the Android OS "copy" the contents of an APK to a specific folder (lets say "/TapGame/Shape Sets/Animals") on the SD card? Or is there even another way of achieving what I want that I didn't think of?
The term "plugin architecture" just came to my mind as I wrote the question. Searching using that term I found this question: Extend my android app in different APK
It seems to provide a solution to my problem - I'll investigate this further, but please feel free to suggest other possible solutions!
Is that possible?
Um, sure.
If so, what would I have to do to have the Android OS "copy" the contents of an APK to a specific folder (lets say "/TapGame/Shape Sets/Animals") on the SD card?
Android won't do any of that. You have to do that. You would have to detect that a "shape set" APK was installed (either watching for package-installed broadcasts, scanning all installed apps for ones that seem to be a "shape set", etc.). Then you would have to arrange to copy whatever you wanted to wherever you wanted it, either by:
Asking the "shape set" app to do it (e.g., send a command to some IntentService), or
Using createPackageContext() and trying to do the copying from your main app
Or is there even another way of achieving what I want that I didn't think of?
Um, just use ZIP files that your app downloads itself from a well-known location. That corresponds to Dave Smith's final paragraph of his answer on the question you just linked to in your edit.
Or, just update the main app. I'm not quite certain what effort you think that you are saving otherwise.
Or, just keep the content online, using a Web service to indicate the available "shape sets" and downloading them as needed (with optional caching).
Fascinating question. If you really want to go for plug-ins then OSGi would probably be the way to go, but it's a lot of work to get to know and to use and seems like overkill in this case.
I don't know how your shapes are defined, but they are probably each defined in a separate file-set, providing the shape (maybe a png or jpg?) as well as the audio-file that will be used as a command for this shape. If the folder in which these file-sets are stored is fixed (TapGame/Shape Sets/...) the app could scan the folder each startup and the views could be generated accordingly (in this case, the activity cannot be build entirely in the XML-File, but must be partially done programmatically).
The Plugin-Aps would be rather easy. They are an apk which includes the file sets (jpg and mp3 or whatever). Started once they deposit all these files into the specified folder (they probably check before if these files exist) and then the apk can shut down again and be uninstalled.
on the next startup the Tap Game App would find the new symbols and include them into the game.
This seems rather straight forward to me. Another way would be to actually store the shapes and audio files on the internet and with each start of the App check if the number of shapes and audio-files has changed and create local copies of new ones. This would mean no downloads of apks... probably a more usual approach to the issue.
I am very interested to hear what you make of it, seems like a different approach then the norm, which is always cool to see.
Has anyone tried using market apk expansion downloader library (available as an add-on) for downloading large files on android <= 2.2? The source code is a bit difficult to understand and I was not able to figure out how it can be used for downloading any large files in general. Are there any alternatives for downloading large files on lower android devices(apart from writing my own DownloadService which I wouldn't prefer doing if there is something already available).
I have not tried to use it but the docs do state the the expansion downloader library is compatibile with API Level 4, taken from the docs:
Note: By default, the Downloader Library requires API level 4, but the
APK Expansion Zip Library requires API level 5.
I completely agree that the source code is difficult to follow, however it was designed in such a way to be fault tolerant to network issues.
I think you can take the sample and roll with that, however I found it was very difficult to test.
We ended up going with our own in the end (using an Arbitrary server) to host the downloads.
I do not believe there are any alternatives, however the downloader library does have a few gems. For instance the Expansion Zip Library can be used independently of the Downloader Library and is a great way to read content directly from the zip.
The only challenge would be writing your own downloader service and performing a CRC check.
Seems like API 4 or >
The expansion API is used for "permanent" file extensions to your application, they don't want you to move them or delete them or even unpack them etc. but use them in place, it's unclear what would happen if you did but I suspect a lot of odd side effects.
You also don't have direct control of when this file is downloaded, it has to be associated in the market and then it happens automatically unless for some reason it "fails" in which case when your app starts you are expect to initiate the process manually and then you need to use the Download Libary, else it's automagic as my 3 year old says.
From your post you may be looking for a way to get large files (more than one) and do what you want with them, if so this is not a good method to do that since every time you add a new file via the market it would tell your users you have an updated version and overwrite the older file (though you can use the patch extension to avoid that if you are updating the original but that only moves it back one step)
All of that is here what expansions files are for and how to use them
If you just want a method to get large files using your own server take a look at the support package and specifically the loader and loader manager. They also say they are making source code to the extension library downloader and zip file manager available but I haven't bothered to check that yet.
I have some configuration I want to save it in my Android application and read it whenever I need , for instance, the server URL that it should try to access like that.
Is there any similar mechanism like web.config in ASP.NET available in Android?
A central configuration file that can be set up manually and then read by the application? Any help would be appreciated!
We use a .properties file in assets folder. It works out very well for us as we support multiple carriers with this, write to it (in case some values, sent from server, need to change. This is done at app start time, thus making our code configurable from server).
You can throw things like that into your strings.xml file. But, since you can't actually modify these values in real-time (since it's a distributed application rather than running on a server), throwing it into a constants class is quite acceptable.
Use Shared Preferences.
Here's a link Shared Preferences
You can use sq lite database files for it. You have a native API to read and write those and on top of that a command line tool.
If you want to create an XML file instead, then it's no different than any other xml file (unless you are thinking about the Shared Preferences, which use an xml format to save the data, but I believe it's not the best API for your application).
I was stumped on this too, but came across Managed Configurations in the Android documentation.
Managed configurations, previously known as application restrictions, allow the enterprise administrator to remotely specify settings for apps. This capability is particularly useful for enterprise-approved apps deployed to a managed profile.
It allows you to set a default value in case you rather not getting into the enterprise admistration business but leaves that option open for the future.
There is a caveat. This only works if your app is registered for EMM. Otherwise you will retrieve an empty map of restrictions.