I have an app that downloads a single html file and various images and sometime, mp4 videos.
After an initial download, repeat downloads are done every 15 minutes by a background service.
The service checks if there are any new files and if any files have been modified (in this case, it is typically the html file that would be modified and some new images will be downloaded)
I have a webview that is displaying the html file and after the background service successfully downloads some new assets, the webview get refreshed.
However, whilst the service is downloading, the app would be using the files, displaying them in the webview (the videos are handled with a videoview, using a javascript bridge, which flips the two views around)
So, to my question.
After seeing some possible issues with the current app, I want the background service to download the assets to a temporary folder, instead of the main folder used (I use a sub-folder created in Downloads)
Then, once the downloads are complete, I would "stop" the webview, copy the files form "tmp" to the real folder, and restart the webview.
Logic sounds OK, but I am worried about speed. The files to copy could weight in at 100mb potentially (maybe more, hopefully less, due to bandwidth issues obv.) so how fast could Android copy those over?
Ideally the transition needs to happen in under a couple of seconds.
Can anyone advise on this?
Is there possibly a better way to handle this situation?
Put the temporary directory below the main data directory, then use an atomic rename(2) call to move the new file into place. (This only works atomically when the source and destination directories are within the same filesystem, hence the recommendation about tempfile placement. You can also put them as FILENAME.EXTENSION.new into the same directory then rename them. Be wary of tempfile races, as usual, when designing filenames; use something like mkstemp(3) to create them if you can.)
Could you point the WebView at the "temporary" directory instead, and then in the background delete the original directory? (then you'd always use the "temporary" directory going forward).
Related
I need to copy all files from assets folder to android cache to load this data faster. The main reason is loading it once during the start of the app. In the whole app lifecycle, I could access needed files from the cache which would be probably faster. I was searching on the Internet but found nothing. How to do that?
One Android "cache directory" is obtained by calling getCacheDir() on some Context, such as an IntentService or JobIntentService. Copying a bunch of content out of assets into files on the filesystem will take some time, and so a Service with a background thread may be appropriate. Doing the actual copying is a matter of:
Getting an InputStream on the desired asset from AssetManager
Getting a FileOutputStream on where you want to write the content to, such as a file inside of getCacheDir()
Using standard Java I/O to copy the bytes
However, please understand that "cache" is not some magic pixie dust that you spread over an app to make it faster. For example, getCacheDir() is not faster than getFilesDir(), or getExternalCacheDir(), or getExtenalFilesDir(), because they all point to the same hardware (on most devices). Files on the filesystem may be faster to access than are assets, since assets are stored in the APK and require a bit of work to read them out of the APK. So, this may help a bit.
However, since you have not used method tracing, or Log statements, or anything to determine where your time is being spent, it is entirely possible that you will go through this work and get no net improvement. For example, my main book is published as an APK, among other formats. That book has 200+ chapters, all stored as HTML in assets. I do not find that loading that HTML is especially slow. It is possible that using files rather than assets will help you more than it might help me, due to the nature of what you are doing in those pages.
But it is also possible that your performance issues come from:
JavaScript doing too much work
Forgetting that you have a bunch of things that you are downloading from the network, because the URLs to them are buried somewhere (e.g., images referenced in CSS files), and it takes a while for those images to download
Something else that you are doing in your app, while simultaneously you are trying to load this Web content, and so you are overloading the CPU of the device
And so on
I'm writing an android application, which user can download some image files from server. There image files will be stored in android mobile.
Now I want to put some of image files inside the apk file, that user can start the application quickly after installing. I found I can put them into assets directory, but the directory is read only. When user download other image files, I need to store them into another directory.
So there will be two directories to store the image files, but they are the same type.
Is there any good solution for this case?
Check out http://developer.android.com/guide/topics/data/data-storage.html#filesInternal for a listing of different places you can put data on Android.
You should put downloaded image files into one of three places, depending on your needs.
If the images are meant to be viewable by the user (e.g. downloaded photos), put them on the external storage. If they are meant to be user-interface elements or other crucial (but not user-facing) images, put them on internal storage. If they are meant to be cached for quick access but downloaded if necessary (e.g. temporary images like those found on a website), put them in the internal cache directory (Context.getCacheDir()).
If you don't have a lot of assets, you can copy them to the target location when your program first runs (e.g. check for the existence of a certain file, and create that file when you are done setting up). Then you only have to check one place (unless it's the cache dir, in which case you can't guarantee that the files will stick around forever).
If you have a lot of asset files, I would use a two-stage lookup: consult your downloaded image directory first (so you can override builtin assets, for example), then consult your assets directory. This is also flexible enough to allow you to make use of multiple storage locations should you find the need.
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
I've got a link for a media file on the web that my application usually plays using a MediaPlayer. I want the user to be able to download the file and save it on his device.
How can I download the file and save it on a predefined folder on his device.
I'm actually asking for two things
1) How to download a file
2) How to save a file to the device's memory.
You may want to do HTTP GET to get a file, start looking at HttpClient class and example, to save, data storage.
You've asked a very general question, so the best I can do is give you a general answer. To actually download the file itself, you'll probably want to use an HttpURLConnection. Make sure not to do this on the main thread UI thread as it will cause your app to freeze. You'll want to do it on separate thread using something like an AsyncTask. To actually have the user kick off the download, you'll probably want to put some sort of button in your UI that allows them to first select a folder and then once a folder is selected, you launch your AsycnTask. Android doesn't really have a builtin file manager, but you can could integrate with the OpenIntents file manager.
This is a bit unorthodox but I'm trying to figure out if there's a way to access files stored in the src tree of my applications apk in Android. I'm trying to use i-Jetty (Jetty implementation for Android) and rather than use it as a separate application and manually download my war file, I'd rather just bake i-jetty in.
However, in order to use (easily) standard html/jsp I need to be able to give it a document root, preferably within my application's apk file. I know Android specifically works to prevent you from accessing (freely) the stuff on the actual system so this may not be possible, but I'm thinking it might be possible to access something within the apk. One option to work around this would be to have all of the files stored in the res directory and then copy them to the sdcard on startup but this wouldn't allow me to automatically remove the files on uninstall.
To give you an idea of what I've tried, currently, the html files are stored in org.webtext.android
Context rootContext = new Context(server_, "/", Context.SESSIONS);
rootContext.setResourceBase("org/webtext/webapp");
Returns a 404 error.
final URL url = this.getClassLoader().getResource("org/webtext/webapp");
Context html = new WebAppContext(url.toExternalForm(), "/");
Blows up with a NullPointerException because no URL is returned from the getResource call.
Any thoughts would be greatly appreciated!
Thanks,
Chris
Edit In case anybody finds this looking for a similar answer, I never found a great answer. I used a slight hack on what was suggested below. I created a war file with only html/jsp content (servlets I added to the server manually and was able to keep in the in the src tree) and stored it in the assets folder. When the app starts, I copy the war file to the sdcard. When the app closes, I delete the copy. Of course, if the app is killed rather than gracefully exiting, I don't get the chance to delete it, but that's not a huge deal.
You might consider creating a subclass of Context that supports loading files out of the assets/ directory using AssetManager.