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
Related
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).
I created a rudimentary browser with help of a WebView.
When I visit a website (containing some text and a few images), the cache directory in /data/data/com.mayexample/cache/webViewCacheChromium gets filled with a few files called index, data_0, data_1, data_2, f_00001, f_00002 etc.
I was wondering, what's the format of these files, what do they contain? I thought about "so, a few of these files surely have to be the website's images then" and tried opening them in a file manager (open as image). But whatever file I pick, the process says "Failed loading!". Even if I rename some of them to .jpg, still I can't open anything.
I have read on the internet that this worked for some people though (look at Android WebView - Load Images from cache, it's exactly what I want to do), but I can't do anything with the cache's files.
Do you know a way to open webview cache files? Doesn't one file represent a corresponding cached image for example?
What I really want to achieve (once I understand the structure of the cache files) is to programmatically fetch images of the webview from it's cache, like the author of the link posted above (unfortunately this posting's answers don't help much)
Thanks!
The cached files might be one of the CSS, or JS/image/html types. On earlier Android releases, one cached file maps exactly one CSS or JS/image/html file.
As far as I know the Browser engine (actually the HTTP module) maintains such cached files in a URL-to-HashKey manner. So what you found (such as "4f42185de3a3a461_1") may be associated with any web resource files such as JS/CSS/images/HTML, etc.
I remember WebView used to store such URL-to-HashKey mapping data in sqlite3 tables in earlier Android versions.
The problem here is you have no idea about the mapping relations so you can hardly retrieve the file you want. A tricky way is to read the AOSP source code then you may be able to know how the generate the HashKey by an unique URL, or you can manipulate the sqlite3 tables, if there are still any on Android 4.4.
I was able to view files in the webViewCacheChromium folder using this tool designed for the Chrome desktop browser:
http://www.nirsoft.net/utils/chrome_cache_view.html
The contents are basically what you'd expect for web cache - images, javascript, css, html.
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 have 2 binary files that i would like to package with my apk. (/res/raw)
i need to copy these 2 files to /sdcard when the application is run
how can i do this?
We have the same issue ... the direction we are exploring is to have two separate installs - the first one is the app and the second one is the data-app. When the data-app installs it copies the binary files to the SD card. When we uninstall the data-app it frees up the internal storage.
We don't have this one completely licked yet, and would love to hear other input and maybe find someone to help us by writing a couple of skeletal sample applications for us.
There are so many people who are in this boat (based on my googling) that if this approach doesn't work I suggest we (or someone) set up a generic file delivery web server and generic file delivery Android service and make it available to developers for a very low cost.
You need to use the AssetManager.
That will give you can InputStream that you can copy to a FileOutputStream.
It all depends on what your goal is by doing this.
Are you trying to be nice to the user and conserve disk space on the device by moving files to the sdcard? Or do you merely want to ensure that these files are on the sd card?
If you just want to put the files on the sdcard then you should use the AssetManager as CaseyB mentioned
If you are trying to conserve phone memory then consider distributing the apk file without the 2 raw files, and then on first run download the files from a server that you have set up. This may cause a bit of a problem due to the time needed to download the files, but some users on devices with limited memory available on the device itself will be appreciative of it.
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.