26

Porting a web app to phoneGap on iOS, we have asset (and ajax) URLs that are absolute paths, e.g.:

<img src="/img/logo.png">

We have the img directory packaged under PhoneGap's www directory. The image will not load with the absolute path, but only with a relative path, e.g.:

<img src="img/logo.png">

Could someone please explain how the URL is being prefixed or translated in this context? I.e.:

<img src="/www/img/logo.png">

does not work either. So what is the URL base used by PhoneGap on iOS?

We've also tried, e.g.:

<img src="file://img/logo.png">
<img src="file:///img/logo.png">

but no go.

We would like to avoid changing the URLs to relative for the port, as absolute path URLs are used throughout the CSS, Ajax code, are set by Sprockets with the Rails backend, etc. How can we just get PhoneGap/UIWebView on iOS to load the assets using the absolute path URLs as written?

I see this question is asked a lot in various forms here on StackOverflow, but I've yet to see a correct answer.

tribalvibes
  • 2,097
  • 3
  • 25
  • 30
  • 5
    Assuming it's a single-page app (as is generally recommended for PhoneGap/Cordova), any reason you can't just use in your index.html and call it a day? – Trott Nov 14 '13 at 06:11

4 Answers4

17

One can get the path to the application in JavaScript by:

cordova.file.applicationDirectory

Since I'm on Android, it says: "file:///android_asset/" ...for example:

var img_path = cordova.file.applicationDirectory + 'www/img/logo.png';

Like this all resources would be found when cross-building for various platforms.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • 1
    The Cordova JS layer is all the same, no matter which platform. Please complain at the "Genius Bar" concerning your iOS issues, not exactly my fault. – Martin Zeitler Jan 16 '15 at 01:12
  • 1
    It is a bug in Cordova, at least on 3.7 on iOS, as I explain in my answer here http://stackoverflow.com/questions/27905969/load-assets-from-www-folder-on-ios-8-with-cordova-3-7-file Btw I was not complaining, just stating. – Paranoid Android Jan 16 '15 at 15:30
  • the current version is v4.0.0... maybe consider upgrading? could imagine that the objective C part not exposes it properly to the JS part. sorry for ranting. – Martin Zeitler Jan 17 '15 at 05:06
  • I am on the latest release. Cordova versioning is confusing, as CLI 4.1.2 resolves to 3.7 on iOS and 3.6.4 on Android. A good post about it is http://devgirl.org/2014/11/07/cordovaphonegap-version-confusion/ – Paranoid Android Jan 18 '15 at 10:51
  • This works for me with iOS 8, believe it is the correct answer. – Eric_WVGG Feb 27 '15 at 16:03
  • 7
    Works and needs the File plugin: https://www.npmjs.com/package/cordova-plugin-file – Vince Sep 23 '15 at 21:54
  • 4
    For starters, please mention that it needs https://www.npmjs.com/package/cordova-plugin-file – Paulo Coghi Dec 13 '15 at 10:17
8

Did some testing and maybe a bit of JavaScript hackery can make it a bit more manageable. This will change all <a> and <img> tags with URL starting with / to be relative to the current file.

Put this into a file and include it with a <script> tag or inject it with stringByEvaluatingJavaScriptFromString:

document.addEventListener("DOMContentLoaded", function() {
  var dummy = document.createElement("a");
  dummy.setAttribute("href", ".");
  var baseURL = dummy.href;
  var absRE = /^\/(.*)$/;

  var images = document.getElementsByTagName("img");
  for (var i =  0; i < images.length; i++) {
    var img = images[i];
    var groups = absRE.exec(img.getAttribute("src"));
    if (groups == null) {
      continue;
    }

    img.src = baseURL + groups[1];
  }

  var links = document.getElementsByTagName("a");
  for (var i =  0; i < links.length; i++) {
    var link = links[i];
    var groups = absRE.exec(link.getAttribute("href"));
    if (groups == null) {
      continue;
    }

    link.href = baseURL + groups[1];
  }
});
Mattias Wadman
  • 11,172
  • 2
  • 42
  • 57
  • hmm, well a nice approach but not sure the timing on that will work since it needs to modify the paths of all the other includes on the main page. maybe better to hack PG to just delete the leading '/'... looking into that. – tribalvibes Jan 31 '12 at 20:20
  • Yeah that might be a problem. But note that PhoneGap on iOS is more or less just a `UIWebView` too so you will end up with the same problems. I think you must rewrite the HTML code dynamically (template system?) and or also intercept link clicks somehow... i haven't figure out how. Let me know of your progress. – Mattias Wadman Jan 31 '12 at 21:23
  • 2
    At this stage since it's only our own well-formed HTML, a simple sed script in the build pipeline did the trick, e.g. sed -e /href="\//href="/ – tribalvibes Feb 04 '12 at 01:48
  • 1
    The idea to use **sed** was awesome. Much more reliable than something at runtime. But instead of **sed** I made a cordova hook and used node with the [replace package](https://www.npmjs.com/package/replace). – JoshuaDavid Jul 19 '15 at 06:26
3

When checking the absolute path through your iPhone/iPad you would see something like this:

<img src="file:///var/mobile/Applications/7D6D107B-D9DC-479B-9E22-4847F0CA0C40/YourApplication.app/www/logo.png" />

And it will be different on Android or Windows devices so I don't think it's actually a good idea to reference assets using absolute paths in this case.

As an alternative you could consider using the base64 strings in your CSS files:

div#overview
{
    background-image: url('data:image/jpeg;base64, <IMAGE_DATA>');
    background-repeat: no-repeat;
}
MonkeyCoder
  • 2,600
  • 2
  • 28
  • 30
  • 2
    thanks. is there a PG API to cough up the current absolute path to the doc root? we do use data urls for some images but it's not a universal solution. – tribalvibes Jan 31 '12 at 20:19
  • 1
    `PhoneGap` has an exposed API for file manipulations, but I didn't have a chance to use it yet: http://docs.phonegap.com/en/1.0.0/phonegap_file_file.md.html#File – MonkeyCoder Jan 31 '12 at 20:22
  • using @mattias's approach I see we could get the original absolute path from the DOM and go from there. – tribalvibes Jan 31 '12 at 20:26
0

In ionic 5 / angular 12 I have
this.file.applicationDirectory+'/www/assets/pdf/my.pdf'
and it works for my app with https://ionicframework.com/docs/native/file https://ionicframework.com/docs/native/document-viewer.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54