I am maintaining an existing BlackBerry application (implemented as a MIDlet). The application contains a number of data files that get bundled with the app as resources. Some of these data files need to be updated for a new version of the app. When the user goes to install a new version of the application (via URL of Jad file), it prompts them with the following message
"Persistent data exists for the application. Would you like to retain this data? "
If the user selects "Yes", it looks like the app continues to use the old resource files.
This is so surprising to me. First of all, am I losing my mind or will an upgrade really not overwrite existing resource files? Is there any way I can force it to?
Thanks,
Jeff
I think that message is only relevant to existing RMS records. Are you positive that your app is still using old resources? That sounds unbelievably strange (even for RIM). Anyway, this should be easy to verify if you change some image resource you're using in one of your screens or something.
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 have developed a hybrid mobile app that has been running on IOS, Android and Chrome reasonably well for over 5 years. My app uses an indexedDB database to maintain the state of the app and save it between restarts, however there are some cases where IOS can clear the indexedDB particularly if the client device is running low on memory.
I would like some help on how to maintain a parallel copy of the indexedDB using the native SQL database on the IOS device, in order to increase the resilience of my app, based on the hopeful expectation that IOS will not arbitrarily decide to clear an internal SQL database belonging to the app.
I understand how to communicate in both directions between Objective C and Javascript but I have not the foggiest idea in Objective C how to:
Create a SQL database in the app file system
Choose where to place the SQL database in the app file system
How to write a new key value pair to the database
Overwrite an existing key value pair in the database
Read back all key value pairs from the database (I expect there could be up to 1000 of these in practice) and pass these efficiently back to the javascript code.
Clear the database and start again.
Any pointers to useful resources on how to achieve this or better still coded examples would be most appreciated.
I would just like to add that I am not using Cordova or any other similar app development environment, so please do not suggest a SQLite plugin that is part of a bigger environment. I have got to where I am with a bespoke coding approach and I would like to keep it that way.
I have explored the idea of paralleling up each indexedDB save with a write to a file in the IOS App Documents Folder with the hope that this is less likely to be wiped than the Caches Folder.
Following each indexedDB setItem with a key-value-pair I pass a request to the objective-C IOS app code to create a text file in a sub folder created with the App Documents Folder, with the name 'key'.txt and the contents set to value.
Following each indexedDB removeItem, I pass a request to the objective-C IOS app code to delete the corresponding text file 'key'.txt.
Following each indexedDB clearAll, I delete the entire sub folder created above.
Now when the app starts up and discovers an empty localForage database, I pass a request to the objective-C IOS app code to test if the sub-folder with key-items is there or not.
If it is not, then this is a fresh install of the app and continue as normal for such a case.
if it is, then this is a case of the indexedDB database having been deleted.
In such case, I request the objective-C IOS app code to return the set of keys, by examining the contents of the folder created above and stripping off the .txt bit and in the case of the IOS Simulator ignoring the DS_Store file.
One by one I then request the contents of each key file and load them back into the previously empty localForage database and when this has been done I can continue as if it had not been deleted.
I found that it is necessary to use a zero duration timeout in the javascript before requesting each value to prevent call stack exceeded errors when restoring large databases.
This approach seems to work and I can test this any time by using the Safari Developer Resources tab actions to clear the database and then manually restarting the app. Using the same tab you can watch the indexedDB database being repopulated.
Due to the size of my database, I actually created a set of sub folders of different types of key, so that I could choose the order in which the database items were restored, especially as my app is often brought back to life in the background following a significant location change and in such cases there is an imposed maximum time limit on how long the app is given to do such a recovery. This refinement is of course optional and only needed for large databases.
The following notes are for anyone who wants to try this approach and assumes using Objective C in XCode 10.1
Use NSHomeDirectory() and stringByAppendingPathComponent #"Documents" to get the Documents folder.
Use stringByAppendingPathComponent to create a sub folder path for the keys sub folder.
Use fileExistsAtPath to check whether the keys sub folder exists already
Use createDirectoryAtPath if it does not.
When saving or changing items in indexedDB use the stringByAppendingPathComponent to create the key file name path e.g. Base.txt for a key of 'Base'.
Use fileHandleforWritingAtPath to get the fileHandle for a file
if fileHandle does not exist then need to create it using writeToFile to create the 'key' file
if fileHandle does exist then truncateFileAtOffseyt:0 (important) to clear it and then use writeData to create a new version of the 'key' file.
In both of the above specify UTF8 encoding.
When removing items from indexedDB do the same to get the key file path and then use removeItemAtPath.
The device can be cleared by removing the entire sub folder using removeItemAtPath.
The restore process uses contentsOfDirectoryAtPath to read the set of keys in the sub folder.
The restore process for each item uses stringWithContentsOfFile to read data files and return the contents enclosed in quotes using a call to stringByEvaluatingJavaScriptFromString
Hope this helps.
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 know there are similar questions on this subject but nothing that quite answers my query. I am aware that it is a bit of a newbie question!
I have an app on the AppStore which I will soon be looking to update. My binary contains a pre-loaded sqlite file with a list of data which the user starts off with. However, the user will extensively edit this information and it is crucial that that data is maintained through the update.
I am not changing the CoreData structure at all so won't be performing any migration but my concern is that when I upload the new binary the packaged sqlite file will overwrite the users existing data. I suspect that won't be the case but can anyone shed any light on it?
When updating an application the documents directory is untouched. Presumably your startup code checks to see if you have already copied the initial database from the bundle to the documents directory - this will work the same way after an upgrade.
You are testing this every time you run a new build on your device during development anyway - you've put a whole new version of the app bundle on there, and it doesn't kill all your data, does it? (does it???)
We built a PWA with Ionic 3, which is a multiple page application. We host this on a linux server with nginx and use Laravel as a backend
The situation
We have seen that a update to a PWA is not always instantly, our client requested that if we released a update this would happen instantly and automatically.
What we tried
File based caching:
Our first thought was to use the concept of (old fashioned?) cache busting, so when building the app we use a random hash string in the filename. This ended up causing a major issue: Some PWA’s seem to hold on to the old index.html. In our access log we can see that old files get requested. The result being people will see a white screen after the splash screen. The only way for them to fix it is to reinstall the PWA completely.
Url based caching:
We devised a new plan: instead of using random hash string in the filename we moved in to the folder name. The request path would look like this: ./build/98312uj91eh9u2e/vendor.js. With NGINX we remove the hash and serve the same file, so it will return the the file from this path: ./build/vendor.js. This caused another issue where files would be mismatched. So some user would have parts of the old version and parts of the news versions which caused a lot of random issues.
Hosting multiple versions hoping they would update:
This pretty much did nothing other than creating lot of confusion. because some PWA’s would never update some people would be stuck on a old version and not see the new features.
Our current idea
Instead of using a static html file we are thinking of using javascript to make an API call to the backend of the PWA. Which will return a string with the current version of the PWA. This version will be the random string contain within the file names. This way, regardless of index.html updates, the content well be dynamic and not cause issue before description issues.
So what is the question?
Is it a good idea to make use of the concept where we would use JavaScript for making an API call or would this cause other issues we have not thought about yet.