Computer programs have become more complex and connected to the world via “always-on” connections…. and due to the constant threat of new internet exploits, Operating systems are a frustrating, moving target.
As a result, certain things that worked on the last version of an operating system are banned in the next, and the churn is often miserable, especially if you’re a small company with limited resources. Simply keeping your app available on the Apple App Store requires regular maintenance, periodic updates, and frustrating amounts of your time.
I finally got my client’s PDF Reporting functionality restored in their iOS app and the solution was very simple, although it required trial and error. In fairness, the solution for iOS was much simpler than the Android solution that I had to figure out a few months back. If you need help with Android, fire me a comment and I’ll possibly update this blog.
On iOS, PDFs can easily be opened in the TWebBrowser component supplied by the FMX framework, assuming you have them up on an HTTPs server somewhere. However, my app downloads the PDFs over a different protocol and saves them locally before trying to open them, and when I put “file://” on the front of my path and pointed my TWebBrowser instance to the local file, all I got was a blank response.
The key to getting this working involved trial-and-error. In system.IOUtils, there is a TPath class with some class methods that are supposed to give you some platform-specific paths for documents and temporary files. I logged every possible special, sandboxed path exposed by TPath that I might be able to try. Some of them returned blank results, some of them return paths, but as far as I can tell, on iOS, only TPath.GetTempPath can be used for local files pointed to by TWebBrowser… the others are either blank or just don’t work.
For the sake of demonstration, here’s an excerpt from my log file showing the paths that were returned from TPath on iOS for my app.
- (blank don’t use)
TPath.GetSharedDocumentsPath=(blank)
- (blank don’t use)
TPath.GetSharedDownloadsPath=(blank)
- (doesn’t work)
TPath.GetCachePath=/var/mobile/Containers/Data/Application/DEF55A81-1475-43E8-BAF5-7695E4BDDDE2/Library/Caches
- (doesn’t work)
TPath.GetHomePath=/private/var/mobile/Containers/Data/Application/DEF55A81-1475-43E8-BAF5-7695E4BDDDE
- (works!)
TPath.GetTempPath=/private/var/mobile/Containers/Data/Application/DEF55A81-1475-43E8-BAF5-7695E4BDDDE2/tmp
To get your downloaded PDF to work inside your TWebBrowser on iOS.
- Download the file to TPath.GetTempPath. Your file name should look something like this:
/private/var/mobile/Containers/Data/Application/DEF55A81-1475-43E8-BAF5-7695E4BDDDE2/tmp/report.pdf
- Prefix the file name with file:// Your file name should now look something like this (note: 3 slashes):
file:///private/var/mobile/Containers/Data/Application/DEF55A81-1475-43E8-BAF5-7695E4BDDDE2/tmp/report.pdf
- WebBrowser.URL := myurl
Done!
To be fair, the Android version required maintenance too, and the Android solution was far more complex involving exposing a special URL to installed PDF reader apps. If you want advice on getting PDFs working in your Android app, please leave a comment, and maybe I’ll update this blog.
I miss the days when my computer had 640K of RAM and could be completely understood by a smart person! These days, things are bigger and crazier, and everyone is super paranoid about security, and malicious libraries. Hopefully, the latest iterations of these Operating Systems will remain stable enough to where I don’t have to bash my head against a wall for a week every year just to keep my app in the App Store.
Man, I feel you on the nostalgia for simpler times. Now every OS update is basically a minefield for developers. It’s like the more we advanced in tech, the more hurdles we gotta jump through, especially on mobile platforms. Security is crucial, no doubt, but it sure does throw a wrench in the works for devs. Makes me think twice about releasing anything on the App Store. Anyone else here find themselves spending more time maintaining and updating than actually developing new features?
Definitely. Maintenance is killer.
Absolutley, same here!