pwlin / cordova-plugin-file-opener2

A File Opener Plugin for Cordova
MIT License
314 stars 587 forks source link

Can't edit opened files #164

Open falkyr opened 7 years ago

falkyr commented 7 years ago

Hi!,

Recently I've been working in an app that needs to edit an excel sheet. I use this plugin to open the sheet with a third party app.

The fact is the sheet opens right in the external app but it does in read only mode, so if I want to save changes I have to create a copy instead overwrite directly the file.

The funny thing is that I can overwrite the original in read only mode if going into the file folder and save there with same name.

Also if I open file directly out of my app I can edit and save normally.

Any idea?

Thanks in advance.

hydrococcous commented 6 years ago

I have exactly the same problem. Any solutions?

beffjarker commented 6 years ago

I have a similar, possibly related issue. I can open a PDF file, and I can edit it. But when I close Adobe Reader, it says "Document saved", however, it isn't actually saved. If it is, it's in a different location than the original file that was opened. After it says "Document Saved", if I open the file again, it is empty with all of my changes missing. Is it copying the PDF to a temp location when it opens it, or does it open it directly at the given path?

godoyrw commented 6 years ago

Using this might solve the problem.

<platform name="android">
       <preference name="AndroidPersistentFileLocation" value="Compatibility" />
</platform>
<platform name="ios">
       <preference name="iosPersistentFileLocation" value="Compatibility" />
</platform>
godoyrw commented 6 years ago

Or try this way! Using -> cordova.file.applicationDirectory | cordova.file.externalDataDirectory


    window.resolveLocalFileSystemURL(cordova.file.externalDataDirectory, function(dirEntry) {
        fileEntry.copyTo(dirEntry, 'file.pdf', function(newFileEntry) {
            cordova.plugins.fileOpener2.open(newFileEntry.nativeURL,'application/pdf',
            { 
                error : function(e) { 
                    console.log('Error status: ' + e.status + ' - Error message: ' + e.message);
                },
                success : function () {
                    console.log('file opened successfully');                
                }
            }
            );
        });
    });
});
beffjarker commented 6 years ago

Thanks for your suggestions!

I tried your first one, and it didn't change anything. I didn't try your second suggestion because I'm not sure where "fileEntry" is coming from.

Here's what I currently have:

const filePath = `${window.cordova.file.externalRootDirectory}${PEDS_DIR}/${fileName}`;
  window.cordova.plugins.fileOpener2.open(
    filePath,
    'application/pdf',
    {
      error: function(e) {
        logError('openPedsPdf: Error: ', e);
      },
      success: function() {
        logInfo(`openPedsPdf: ${filePath} opened`);
      }
    }
  );

I have found that Reader is actually saving the files, but with a '-n' at the end of the file (n being a number how many times I've edited and saved the file), and it's saving them in the Adobe Reader Downloads folder instead of where it's opening it from.

I've installed the same APK on another tablet (both Samsung S2s) and it edits the files in place as expected.

The only difference between the two tablets is one of them is Android 5.1.1 and the one that doesn't work is 6.0.1.

Another native application on the 6.0.1 tablet can open PDF files with Adobe Reader and edit them just fine as well.

I'm at a loss here. :(

godoyrw commented 6 years ago

Let's try this! Replace your code with this one! 👍 👍 👍

window.resolveLocalFileSystemURL('${window.cordova.file.externalRootDirectory}${PEDS_DIR}/${fileName}', function(dirEntry) {
        fileEntry.copyTo('${window.cordova.file.externalRootDirectory}${PEDS_DIR}/', '${fileName}', function(newFileEntry) {
            window.cordova.plugins.fileOpener2.open(newFileEntry.nativeURL,'application/pdf',
            { 
                error : function(e) { 
                    logError('openPedsPdf: Error: ', e);
                },
                success : function () {
                    logInfo('openPedsPdf: ${fileName} opened');             
                }
            }
            );
        });
    });
});
beffjarker commented 6 years ago

Would love to try this out, but I'm still not sure where "fileEntry" is defined in your example. What is that referring to? Should that be "dirEntry" instead?

beffjarker commented 6 years ago

so I've changed the code a bit and I seem to have made some progress, but I keep getting a code: 9 on copyTo.

According to this https://github.com/apache/cordova-plugin-file it means Invalid Modification. I don't have a clue what that actually means...

Here's how I have it now:

const filePath = `${window.cordova.file.externalDataDirectory}${PEDS_DIR}/${fileName}`;
  window.resolveLocalFileSystemURL(filePath, function(fileEntry) {
    window.resolveLocalFileSystemURL(`${window.cordova.file.externalDataDirectory}${PEDS_DIR}/`, function(dirEntry) {
      fileEntry.copyTo(dirEntry, `${fileName}`, function(newFileEntry) {
        window.cordova.plugins.fileOpener2.open(newFileEntry.nativeURL,
          'application/pdf',
          {
            error: function(e) {
              logError('openPedsPdf: Error: ', e);
            },
            success: function() {
              logInfo('openPedsPdf: ${fileName} opened');
            }
          }
        );
      }, function(e) {
        logError('openPedsPdf: Error: ', e);
      });
    }, function(e) {
      logError('openPedsPdf: Error: ', e);
    });
  });
godoyrw commented 6 years ago

1 - About invalid modification, I think it can be here; check this redundancy this:

window.resolveLocalFileSystemURL(filePath, function(fileEntry) {
window.resolveLocalFileSystemURL(`${window.cordova.file.externalDataDirectory}${PEDS_DIR}/`, function(dirEntry) {

2- Put/Verify this in your config.xml Android:

<preference name="AndroidPersistentFileLocation" value="Internal" />
<preference name="AndroidPersistentFileLocation" value="Compatibility" />

IOS:

<preference name="iosPersistentFileLocation" value="Library" />
<preference name="iosPersistentFileLocation" value="Compatibility" />

3 - See this docs: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

beffjarker commented 6 years ago

1- I'm not sure I follow you here. I think I get the idea. We're trying to copy the file from the same directory it's already in, to the same directory. I am not sure why that would be an issue unless it might be permission related. Maybe that's why it's throwing an error - because it's trying to copy the file on top of itself? 2- We're only on Android here, so I don't need to worry about iOS. Default is Internal for Android, I have tried Compatibility mode for Android, but there was no difference in functionality for this test case.

godoyrw commented 6 years ago

yes it was to copy to the same directory just to test if the PERMISSION WAS THE PROBLEM, NOT TO KEEP THAT CODE. Also, it was for you to put a new name, not the same, I put your variable so you understood what each thing was!

OR THE DIRECTORY YOU ARE SAVING IS THAT IS WITH PERMISSION PROBLEM, try in another directory the way you did before!

I tried to help you, sorry if it was not enough! 👍

beffjarker commented 6 years ago

Thanks for all the help, I definitely appreciate it. It seems like an OS issue. We've tried on about 5 different tablets now, and it always works on 5.1.1, but not on 6.x or 7.x. :(

I think at this point, we are going to try and look for another library...

Thanks again for the help!

beffjarker commented 6 years ago

For anyone else coming across this problem. It seems to us that this is a plugin problem with Android versions post Lollipop. Every other version afterwords has this problem. Not sure what the root cause is. File Opener Devs, I hope you can fix the issue, or let me know a workaround or something I'm doing wrong.

For now we ended up going with InAppBrowser and it works perfectly across all versions of the OS.

rastafan commented 5 years ago

Maybe Pull Request #255 can solve this issue? We had the same problem and this was the solution we found.

shnist commented 5 years ago

Release v2.2.1 includes @rastafan's fix, so perhaps the issue is resolved now.

sukramAxians commented 5 years ago

Issue still exists. We use https://github.com/Evolution-36/cordova-plugin-file-opener2 for now. Changes by Evolution-36 Works for us.

hydrococcous commented 4 years ago

It seems Microsoft itself is the Problem: https://github.com/cryptomator/cryptomator-android/issues/150#issuecomment-514401775

I change the FileOpener2.java from:

intent = new Intent(Intent.ACTION_VIEW);
Context context = cordova.getActivity().getApplicationContext();
Uri path = FileProvider.getUriForFile(context, cordova.getActivity().getPackageName() + ".opener.provider", file);
intent.setDataAndType(path, contentType);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NO_HISTORY);

to:


import android.os.StrictMode;
import android.webkit.MimeTypeMap;

...

intent = new Intent(Intent.ACTION_EDIT);
Context context = cordova.getActivity().getApplicationContext();
Uri path;
path = Uri.fromFile(file);
intent.setDataAndType(path, contentType);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_ACTIVITY_NO_HISTORY);

Hope it helps.

whodeee commented 3 years ago

I am having this same issue with iOS. Any suggestions for that?

Lucasrsv1 commented 2 years ago

I faced this issue today when trying to download and edit files on my app. After opening the file it cannot be edited, unless I change the FileOpener2.java file replacing intent = new Intent(Intent.ACTION_VIEW); with intent = new Intent(Intent.ACTION_EDIT);.

Doing this changes the opening dialog showing only apps that can edit the file. I think that the right solution would be to add a new parameter to the showOpenWithDialog function that would determine if the file is being opened to be edit or just visualized.

shnist commented 1 year ago

@Lucasrsv1 seems to be correct here. The application currently doesn't support the ability to edit files because the intent passed through is Intent.ACTION_VIEW. A potential enhancement would be to create a new method that would allow the user to open and edit.