Offline not working in mobile Safari with cache manifest - iphone

I'm working on a mobile site for the iphone. I've added a cache manifest and loaded it with a list of resources needed for offline capability. The manifest file has the correct content type. If you view the response header for the file, the content type is text/cache-manifest. The manifest file is here:
http://hoodisgood.clientsit.es/cache.manifest
The site is viewable here (you'll need to take a look on your iphone (or simulator) or on Safari with user agent set to the iphone.
http://hoodisgood.clientsit.es/
After viewing the site and bookmarking it to the home screen, I set my iphone to airplane mode and when I try to view the site, I can't. I get an alert that it can't open because it's not connected to the internet. I've specified all the files I need for offline operation in the cache manifest file.
Also, correct me if I'm wrong, but with a cache manifest, shouldn't the browser read from the cached source even when the device is online? When I view the site, photos I haven't seen are loaded from the server, as it should be. When I close and reopen, previously viewed images are still loading from the server.
Am I doing something wrong? I checked and re-checked, everything seems to be correct, just not sure why it's not working.
Thanks.

I did notice that your tag did not reference the manifest.
<html manifest="cache.manifest">
Additionally, you need to ensure that the manifest file uses the "text/cache-manifest" mime type.
Also make sure that the manifest has UTF-8 encoding, and not some encoding that the browser has a hard time understanding.
Also I can recommend that you load the site in Chrome. If you check the developer log in Chrome, Chrome will write very helpfull error messages that will guide you to where the problem lies.

I did notice that your tag did not reference the manifest.
<html manifest="cache.manifest">
Additionally, you need to ensure that the manifest file uses the "text/cache-manifest" mime type.

I had a similar problem:
Try referencing absolute paths in your manifest file. This did the trick for me and I as well was using a sub domain.
Also enable your developer console in Safari and add the following JS
function logEvent(event) {
console.log(event.type);
}
window.applicationCache.addEventListener('checking', logEvent, false);
window.applicationCache.addEventListener('noupdate', logEvent, false);
window.applicationCache.addEventListener('downloading', logEvent, false);
window.applicationCache.addEventListener('cached', logEvent, false);
window.applicationCache.addEventListener('updateready', logEvent, false);
window.applicationCache.addEventListener('obsolete', logEvent, false);
window.applicationCache.addEventListener('error', logEvent, false);
Like this you can check what happens in regards to your cache manifest in the browser and learn if an error occurs.

Related

IONIC 4: How to call iOs file resource from custom script within app

Here is the situation:
Ionic 4: (cli-5.2.7)
XCode 10.3
We have a custom eReader that lives in our assets folder.
When we want to download an eBook from our server and read it, we download the file and save it using the Native File plugin.
When we start up the reader, we send it the container in which we want the reader to be created and built, and an internal url to the file resource we want to read.
After window.Ionic.WebView.convertFileSrc, the file ref looks like:
ionic://localhost/_app_file_/var/mobile/Containers/Data/Application/[APP-ID]/Library/NoCloud/[BOOK-ID]/vol-001-chapter-006.xhtml
The reader will then build the iframe and send a simple XMHttpRequest to the provided url, then place the resulting html into the iframe.
The problem is that it only works on first load of the eBook from our server
I can see the file being downloaded, and written to its own folder in the apps file system (File.dataDirectory).
When I debug the XMLHttpRequest in our eReader.js, I can see the call being made to the resource and the HTML returning to the request, which is then rendered on the page.
BUT, if I close the app, reopen it, and try to access the already-downloaded book, the XMLHttpRequest in our eReader.js returns nothing.
I can verify that the file exists at the resource location after a reload, but the XMLHttpRequest acts like it cannot find anything at the provided location.
AND, this is only on iOs. Android works as intended.
My questions is, what am I missing? Is this something to do with the iOs permissions or persistence?
Any help would be appreciated.

Invalidating an HTML5 cache (manifest) completely?

I have an iPhone web-app, and I want to know how to force a cache refresh.
My cache manifest is this:
CACHE MANIFEST
index.html
file1.css
file1.js
index.html is the meat of the application, so I put that in the cache. At this point, I seem to be boned, as I can't figure out how to get iPhone to invalidate the cache. Even going to Settings > Safari > Clear Cache doesn't work, although I'd like to be able to control this programatically. Removing index.html from the manifest and re-adding it seems to work, but I would have to know that all my clients had a clean hit of the updated manifest.
How do I cache index.html and still have it updated when it changes?
Off the top of my head, any change to the manifest will do the trick - and manifests can contain comments starting with #. Just add a random comment and it'll work.
It's a useful property, when I worked on an HTML5 application in a git repository I used to have the manifest automatically regenerated with a comment containing the HEAD hash after each commit so that the changes always propagate to the users.
There seems to be a bug in WebKit Browsers preventing them to reload the website on manifest changes, see this link
Have no clue for a workaround except when I call the index.html directly.
No chance for a iPad/iPhone-WebApp pinned to do the job...
Yes, you can use JavaScript to force Safari to reload cached resource files.
According to Apple, modifying the cache manifest file will cause Safari to reload any changed resource files. But those reloaded files won't be used by the browser until the user visits the site a second time. That delay can a pain, especially during development.
To force Safari to reload the cache contents immediately, Apple says you can use this JavaScript to manipulate the applicationCache object:
function updateSite(event) {
window.applicationCache.swapCache();
}
window.applicationCache.addEventListener('updateready', updateSite, false);

iPhone Safari offline-cache manifest not working correctly

I'm working on a mobile site for the iphone. I've added a cache manifest and loaded it with a list of resources needed for offline capability. The manifest file has the correct content type. You can view the manifest file in the header of this page:
http://www.rvddps.com/apps/sixshot/booking.html
I had a bunch of links to pages but due to my user level i'm only allowed to post one link. You can see the manifest file there and the source code of the page i'm trying to cache.
I've set the correct MIME type on the server, but the cache only seems to work occasionally.. not all the time. I've tried following apples' official caching guidelines as well.
Can anyone point out where i'm going wrong?
Thanks
Daniel
I looked at the manifest file and found 'Â' characters in some of the blank lines. What text editor are you using? Make sure you use the proper encoding and line ending types.

iPhone application cache and XMLHttpRequest

I have a WebApp that I've been try to make work offline. The WebApp is too big, even minified, to simply use the application cache (things download but I eventually get a window.applicationCache error). I'm trying to use XMLHttpRequest to get the larger scripts and main html and keep them in localStorage and just keep a small loader script in the application cache. The problem I'm seeing is that the XMLHttpRequest returns a network error when the loader script is being served locally. When the the cache is downloading no error is returned and it works fine. When I turn off the application cache the loader works fine, but of course then I need the network to get the loader.
I tried setRequestHeader("Cache-Control", "no-cache") but that didn't help.
Anybody have a clue?
What does your network: section in your manifest look like?
I found that if I weren't allowing wildcard network traffic it wouldn't load with XMLHttpRequest. So changing it to:
Network:
*
did the trick for us.
I think I found a solution. It would probably work for others.
I split the loader into two separate HTML files: one that uses XMLHttpRequest to get all the required files and put them in localStorage (the loader) and another that simply reads the files from localStorage and writes them into the document (the booter) with appropriate wrappers (e.g. ). The booter has a manifest file to keep it in the application cache. The loader does not. The user first invokes the booter. If the booter finds files already in localStorage it does it's thing. Otherwise, it uses location.replace() to invoke the loader. The loader loads the files from the server using XMLHttpRequest and puts them in localStorage, and then re-invokes the booter using location.replace(). This seems to not cause an network error.
In order to run offline, the user must invoke the booter in the iPhone Safari browser (which invokes the loader, which re-ivokes the booter) which boots the WebApp. In Safari, the user must then add the WebApp (the booter link) to their Home Screen (using the "+" button at the bottom). When offline the user can get to the app from the Home Screen icon. It takes a few seconds to re-render, but it's fully functional after that. It's the same delay when online. Invoking the link from the iPhone Safari browser will not work offline, though it will work online.
The booter monitors the application cache's "updateready" event so that when online and the when iPhone detects a change in the booter's manifest file and downloads a new booter, it will swap the new cache (window.applicationCache.swapCache()) and invoke the loader using location.replace() again. I also add an alert() to let the user know something funky is going on. So changing the manifest file (I mean making some bytes different, not just tweaking the modify time) will cause clients to get new files when online.
Interestingly, I noticed that localStorage set up in Safari is not available to the same page served from invoking the Home Screen icon, even though the cookies transfer! So the first time the booter is invoked from the icon it will reload the files even though they were previously loaded in Safari. Also, I had to explicitly prevent the loader from being cached as it was not reloading from the server when the rest of the files were updated.
You are correct. Ultimately it was the network section in the manifest.
I thought the site where the application was loaded from was included automatically and you didn't need to mess with it, but it's not true. You need to put the site in the network section.

iPhone WebApp cache

I've made a simple Web Application for the iPhone, it's just 6 pages each with an image on it and I use the Cube transition to switch between them, all static content.
I need this to work on an iPod Touch offline, i.e. visit it once, disconnect from WiFi, and then be able to browse the static site.
I'm trying to do this using the HTML5 manifest feature, but I'm clearly doing it wrong?
My Manifest file:
CACHE MANIFEST
index.html
main.css
main.js
Images/Appointments_Page.png
Images/backgroundStripes.png
Images/button.png
Images/button1.png
Images/button1_clicked.png
Images/button2.png
Images/button2_clicked.png
Images/button3.png
Images/button3_clicked.png
Images/button_clicked.png
Images/CloseIcon.png
Images/CloseIcon_pressed.png
Images/Efficacy_Page.png
Images/EfficacyGraph_Page.png
Images/Graph_Icon.png
Images/GraphIcon.png
Images/GraphIcon_pressed.png
Images/Home_Page.png
Images/Tolerability_Page.png
Images/TolerabilityTable_Page.png
Images/WebClipIcon.png
Parts/ButtonHandler.js
Parts/PushButton.js
Parts/setup.js
Parts/StackLayout.js
Parts/Transitions.css
Parts/Transitions.js
Parts/utilities.js
top of my HTML file
<!DOCTYPE HTML>
<html manifest="cache-manifest">
Hey I figured it out, leaving answer here in case it helps anyone else.
The problem I was having was that our server (IIS6) was refusing to serve my manifest file.
I had to add the MIME type ".manifest" using "text/cache-manifest".
Since then it's been caching fine, all 40+ files ranging from 1kb to 200kb.
Hope this helps.
I also wrote some tips on using the Manifest at: http://wecreategames.com/blog/?p=210
Other things to note: You need to reload the app TWICE to get the manifest's new contents, and you need to change the actual content of the manifest to force reloading the containing pages (I do this by changing a comment #v.03 to #v.04, or something similar).
As a note: Apple suggests:
"The HTML file that declares the manifest file ..... is automatically included in the application cache. You do not need to add it to the manifest file."
(https://developer.apple.com/library/content/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/OfflineApplicationCache/OfflineApplicationCache.html#//apple_ref/doc/uid/TP40007256-CH7-SW2)
So it would work with leaving "index.html" out of the manifest list.