Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android 10 - How can I assign the root path? #1458

Closed
FranGhe opened this issue Jul 10, 2022 · 7 comments
Closed

Android 10 - How can I assign the root path? #1458

FranGhe opened this issue Jul 10, 2022 · 7 comments
Labels

Comments

@FranGhe
Copy link

FranGhe commented Jul 10, 2022

Sorry in advance if my english is not so good.

As breautek wonderfully explain here #1354 (comment) , with Android 10 Platform (the mximum platform available at the moment on Cordova and the minimum platform required to publish on playstore) "XHR not CORS request" and "file://" not working if I don't set on my config.xml

<preference name="hostname" value="localhost" />
<preference name="AndroidInsecureFileModeEnabled" value="true" />

I'm pretty sure that this solution is useful... but temporary. I'm sure the PlayStore will impose a new restriction shortly and this solution will be in vain.

So I decided to not use them and carry on... I have solved my problem about XHR CORS request but I have no solution about how to set the root path... for example to assign it an image path

At the moment I get it as:

var urlRootMobile=cordova.file.applicationDirectory+'www/';
var img1 = urlRootMobile."/img/1.png";
var img2 = urlRootMobile."/img/2.png";
var img3 = urlRootMobile."/img/3.png";

Obviously don't work on my app because the path is : " file:///android_asset/www/img/1.png"

I tried to use "https://localhost/www"
I tried to use "https://localhost"
I tried to use "/"
But nothing...

I there some other command or trick ???

@FranGhe FranGhe changed the title Android how to assign the root path? Android 10 XHR Cors an file:// trouble Jul 10, 2022
@FranGhe FranGhe changed the title Android 10 XHR Cors an file:// trouble Android 10 - file:// trouble Jul 10, 2022
@FranGhe FranGhe changed the title Android 10 - file:// trouble Android 10 - How can I assign the root path? Jul 13, 2022
@breautek
Copy link
Contributor

Root paths aren't assignable in Android.

If you're using the filesystem strategy (e.g. <preference name="AndroidInsecureFileModeEnabled" value="true" />) then the root is file:///android_assets which is a special android folder that leads to the running process assets directory. Generally, cordova apps have a www folder for their web assets. By default your index.html file will be located at file:///android_assets/www/index.html

When using the filesystem strategy, / as root path will mean the literal android root folder, which is often unreadable or limited access to non-privileged applications.

If you're using the WebViewAssetLoader strategy (e.g. <preference name="AndroidInsecureFileModeEnabled" value="false" />), then the webview uses a system where as far as the webview is concerned, it is loading content from an http or https resource. By default, cordova is configured to use the domain https://localhost, but this is configurable via:

<preference name="scheme" value="https" />    <!-- scheme can only accept "http" or "https" on android -->
<preference name="hostname" value="localhost" />

The configured scheme/domain will point to your www folder, therefore assuming the default configuration, your index.html file will be at https://localhost/index.html

I'm pretty sure that this solution is useful... but temporary. I'm sure the PlayStore will impose a new restriction shortly and this solution will be in vain.

It's advised against using the AndroidInescureFileModeEnabled because Google has deprecated the setting in API 30, stating:

Don't enable this setting if you open files that may be created or altered by external sources. Enabling this setting allows malicious scripts loaded in a file:// context to launch cross-site scripting attacks, either accessing arbitrary local files including WebView cookies, app private data or even credentials used on arbitrary web sites.

While I agree that this shouldn't be your primary solution, it should be an option for the foreseeable future.

cordova.file.applicationDirectory

This is a filesystem constant that is the absolute path to your app's Application Directory. If you're using this path while using the WebViewAssetLoader system, you will get CORS error because you're requesting a file:// protocol url over a https origin.

Assuming you're using WebViewAssetLoader, If you have an image in <cordova-project>/www/img/image1.jpg for example, and you have your HTML documented loaded at <cordova-project>/www/index.html, then all you need to do is request "img/image1.jpg"

@FranGhe
Copy link
Author

FranGhe commented Jul 18, 2022

Thanks so much Norman... I have submit my App on PlayStore and at the moment it's approved... using AndroidInsecureFileModeEnabled as true.

I have to do it quickly (beforeGoogle conditions change) because I didn't want to lose months of work... but I want to be ready for next time and I want to use the WebViewAssetLoader strategy... so:

<preference name="scheme" value="https" />
<preference name="hostname" value="localhost" /> 
<preference name="AndroidInsecureFileModeEnabled" value="false" />

and the solution to assign an image
img/image1.jpg
is very easy to fix...

But at this point I have anoter problem... in many part of my project I use window.resolveLocalFileSystemURL to find folders and files... like this example:

var urlDateFiles=cordova.file.applicationDirectory+'www/img/icons";
 window.resolveLocalFileSystemURL(
     urlDateFiles, 
     function(fileEntry) {
         ...
     }, 
    function (error){ 
        ...
    }
);

In this case if I set the urlDateFiles as "img/icons" the functions goes to error... if I use cordova.file.applicationDirectory+'www/img/icons" that work fine...

Do you have a suggestion about it? Is it better to mantain this solution or do you have to suggest me another one?

@breautek
Copy link
Contributor

I would advise to only use the cordova.file constants in conjunction with the cordova file plugin apis. They will always reference file paths through the file protocol. So they may work with AndroidInsecureFileModeEnabled turned on, but you will run into problems when it's turned off.

I would recommend working towards making your app compatible with AndroidInsecureFileModeEnabled turned off. Any file you bundle with your app by placing into the www folder will be available using relative pathing, and it will work cross-platform.

If you're creating dynamic content and writing files during runtime, using the file plugin, then it is ok to continue using the file plugin and it's constants to read that data or to resolve filesystem urls, but trying to use these paths with the webview will not work when AndroidInsecureFileModeEnabled is turned off.

@FranGhe
Copy link
Author

FranGhe commented Jul 21, 2022

Excuse my english...

... yes my target is write code with AndroidInsecureFileModeEnabled turned off and following your suggestions I see the finish line about to set the right path to an image ... but not to read the file stored in some folder.

For example... I want to read the files stored inside img folder (www/img/icons)... for this need I use (now) window.resolveLocalFileSystemURL... but it doesen't work if I set img/icons as urlFolderImage... I have to set cordova.file.applicationDirectory+'www/img/icons';

var urlFolderImage=cordova.file.applicationDirectory+'www/img/icons'; // work
var urlFolderImage='img/icons'; // not work

window.resolveLocalFileSystemURL(
  urlFolderImage,       // THE PROBLEM IS HERE
    function(data) {
      var dataReader = data.createReader();
        dataReader.readEntries( function(entries) {
          if (entries){
            for (var i=0; i<entries.length; i++) {
              if (entries[i].isFile === true && entries[i].name.match(/(.png)/)){
                // OLD SOLUTION (WRONG)
                    //var pathImg = cordova.file.applicationDirectory+'www/img/icons/'+entries[i].name; 

                //RIGHT SOLUTION
                    var pathImg = entries[i].fullPath.replace("/www/","")       
                    // pathImg will be "img/icons/[nameFile.png]"

                $(".img_"+i).attr("src",pathImg ); 
              }
            }
          }
        });
      }, 
      function(err) {
        alert("Error");
      }
    );

So as you can see your suggestion to use "img/icons/..." work fine to set the pathImg ... the problem is that window.resolveLocalFileSystemURL don't accept img/icons as urlFolderImage, but it need to use cordova.file.applicationDirectory+'www/img/icons'

So the question is...

  1. I'm obligated to use window.resolveLocalFileSystemURL and cordova.file.applicationDirectory ?
  2. resolveLocalFileSystemURL will be (or already is) an obsolete method?
  3. There is another way to read file in folders that accept the absolute path as img/icons?

@breautek
Copy link
Contributor

My suggestion about using the relative paths applies when you're using the DOM apis, such as pathing used in HTML or CSS (e.g. <img src="img/icons/Myicon.png" />)

If you're using the cordova file plugin APIs including resolveLocalFileSystemURL to read files then it's acceptable and recommended to use the file constants at this point, like cordova.file.applicationDirectory.

Understand that there are two different systems here. The standard webview APIs cannot use the file:// protocol, but the native code that cordova plugins interfaces with does, which is why if you inspect the actual value of cordova.file.applicationDirectory, you'll still see a file:// url.

@FranGhe
Copy link
Author

FranGhe commented Jul 22, 2022

Yes sure... but I like to convert all in only one system using the standard web view APis.

Is there a way to read files with this method?
I tried to find it to a long time... but without success.

Thanks for your support

@breautek
Copy link
Contributor

Yes sure... but I like to convert all in only one system using the standard web view APis.

Not really sure if this is what you're looking for but the latest version of the file plugin (v7.0.0) has a new API to convert the cdvfile:/ protocol (a protocol intended to have a common url across platform to a URL that the webview asset loader can consume. I don't think it's a well documented feature, but it the PR that describes it can be found at apache/cordova-plugin-file#513

So if you have a FileEntry object (given to by a resolveFileSystemURI call for example), then you can call fileEntry.toURL()

The URL given by toURL will be a http(s):// url when using the webview asset loader, which means you can use it with the standard webview apis. So if you have a file:// url, this could be a way to translate them into an URL usable by the standard webview APIs.

But there is still no way to assign a root path like you were originally seeking out, but I think the above might be something useful to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants