To make a long story short, we have released an app that has hundreds of images stored in the application bundle. The file structure for the images is something like:
/var/mobile/Applications/.../ApplicationName.app/Images 1.0/0001.png
/var/mobile/Applications/.../ApplicationName.app/Images 1.0/0002.png
We want to release an update to the app that replaces all of these images with our 2.0 assets:
/var/mobile/Applications/.../ApplicationName.app/Images 2.0/0001.png
/var/mobile/Applications/.../ApplicationName.app/Images 2.0/0002.png
The tricky part is that the new images are not a strict one-to-one replacement of the old images — we have added a few and removed a few. Unfortunately, it appears that you are unable to remove file from the app bundle and the update itself does nothing to change them either.
The primary reason we want to remove the old resources is that they take up quite a bit of space on disk. It doesn't seem good to have these old, unused files hanging around.
Related
I've recently transitioned my iOS Unity app to use asset bundles as on demand resources. This all works great! The only problem is that when the application first starts up and all the ODRs are preloaded it just starts to download them from the apple servers. I need to know before preloading them if they require downloading and if so, how big of a download. I need this info to show a prompt for the user to let them know that additional data needs to be downloaded and maybe turn on their wifi etc.
If you are using WWW class then there is this WWW.LoadFromCacheOrDownload, this function takes in a version parameter which you can probably use for checking on versions.
If you are using UnityWebRequest, then maybe you can use the meta files which get generated with asset bundle and then download it and read version or a hash (You will probably have to google a little bit on this what to use) to actually look if you have a version change and do you need to download new version or not.
If none of the above suits you then the hard coded way would be to setup a list of your asset bundles with your versions on a webserver and download it to match it with your local version everytime you start the app.
I hope this atleast helps you look in the correct direction.
I've managed to do this myself in the end. My current setup is the following:
I have a bunch of assetbundles marked as On Demand Resources.
When I build the assetbundles I save a file containing the CRC and file sizes of all these bundles and I save it in StreamingAssets to always have it available
Whenever the app starts up, I try to load the assetbundles from PersistentDataPath against their latest CRC (at first launch there will be no bundles there)
If any bundles are missing or have invalid CRC, show a prompt to the user that x MB of data needs to be downloaded (taken from the file made at build time)
After the ODR resources are downloaded, I reencrypt the assetbundle from res:// (the only way I could access it) and move it to PersistentDataPath
Whenever a new updated comes it, it should contain new CRCs for the changed bundles and the process should restart
It seems to work quite well. The only real issues that I have is that I currently don't know how to delete the downloaded ODR data, and there could be a version mismatch if a user installs the app and defers downloading the extra data, and only opts to do so when an updated version of the app (with different bundle CRCs) is available on the server but they still stay on the older version. This would probabily load the new bundles but will fail the CRC checks for them...
I am making an iOS app that uses assets to store audio files. I setup TestFlight to do testing. I discovered I had a bad audio file, so replaced it and deployed a new build. The changed file did not show up after the update in TestFlight. This appears to be because assets are stored as user data and app updates preserve user data. I had to delete the app and reinstall it to get the changed asset to appear.
So I'm assuming any update to an app that modifies an existing asset must include code to detect the update and then overwrite the asset with a new version.
or else the asset must be renamed, though this will leave the original asset taking up memory. I have not been able to find any discussion on this topic.
Can an asset be overwritten? if so how?
Am I missing something here?
Update: I have submitted an issue on the GitHub flutter/flutter project
Another Update:
I was asked to present the problem with out third party packages. This led me to look deeper into just_audio which is what I am using. After eventually finding the place where assets are loaded, it turns out it defaults to always caching audio files in the app's temp directory which persists across app reloads and updates. You must make an explicit function call to clear the cache in the event of changed assets. It would have been nice if this was mentioned in the documentation.
Anyway, problem solved, and I feel kinda dumb for not suspecting just_audio was the source of the issue.
Strangely I can't find a lot of information on this.
I am making an application that downloads images, they are downloaded and saved into my apps /Documents/ folder. To avoid an initial huge download I want to ship the app with ~100 images already "downloaded" into the folder.
How can I do this?
They have to go into your Resources bundle. You can then copy them into Documents on first launch. Yes, this means they take twice the space; if you can compress the ones in Resources effectively, I would.
An ideal answer is to have your loading routine be willing to look in both Documents and your Resources bundle and merge the results. I don't believe any built-in controllers will do this for you, however.
My app have too much dynamic app resources like images, html+css and xml or json files..that can be updated, So I cannot put these resources in app bundle it will not get updated once on app store i need to have it updated there...secondly i also cannot put these resources on server where I can request the content from server every time i need it...
So my question is that is good to store data locally in document directory??? how does apple app review team will react to it? I have heard that there is an iCloud problem while putting data in document directory is it right?
So where to store data of iOS application locally on device?
Thanks in Advance.... Looking for some good solid answer!
This kind of data should be copied to ~/Library/Application Support. See the File System Programming Guide for full details on where everything goes and how it will be treated.
You may want to consider having the initial assets you are referring to be resident in your application bundle. And then when you have updated versions, save them in your Documents directory (or any legal path you want).
The reason for this is for failover, in case there is a problem, it allows you to revert back. When you are dynamically loading content, you have to factor in you can encounter various problems during a download such as corrupt data or even a dependency not being downloaded yet.
FWIW, I implemented this for a game that supported dynamic loading of content. The bundle had the original assets. There was a temp download directory. When data was validated, it was moved to a locale where it was consumable. On app start, the first step was to just copy the data from the bundle to the consumable directory. While it seems perhaps wasteful and several steps, it worked surprising well and most would not even know this sort of thing was happening.
I have a simple app that downloads some data from a webservice and displays it in tableviews. In order to allow offline access, the app caches this data in the cache directory on the device itself. I keep a list of all of the cached files for reference, and save that to the cache directory as well. So after all of the downloads are complete I have the following files:
XMLFileList
XML1
XML2
...
I launched this app a couple weeks ago, and have since had to release a few minor updates as necessary to fix some minor bugs. It seems, however, that when a user updates the app on their device, they no longer see the downloaded resources. I have managed to get this to happen on a development device, by updating through the app store, then loading a debug build, and determined the following problem
It would seem that it is not displaying the data in the downloaded files because they no longer exist. It is also not re-downloading the files because they show up in the saved list. This provides a rather interesting question: why did the cached XML files get deleted, but not the master list?
What exactly is going on behind the scenes during an app update that I could account for, or reproduce to ensure this does not continue happening?
If you're putting files into /Library/Caches (or whatever it is), then there is no guarantee that those files will be there the next time you run your app. Anything you put into /Documents, however, will be there. And in fact, anything in /Documents will also be backed up to iCloud (unless you set the bit newly available in iOS 5.0.1 that lets you opt-out files in /Documents from being backed up.)
Anyway, the point is that you should read Apple's docs on what files you should put where. (I searched around for the correct reference unsuccessfully; I've seen it before though.) It boils down to this: Anything that is user generated should go in /Documents, anything that can be re-fetched from a server should go in /Library/Caches and may be purged by the OS.
Cache directory contents are not guaranteed to be preserved. But I don't see any documented guarantee that the entire directory will be cleared all at once. (Maybe only the biggest and/or oldest contents or some such?)