Unable to share file using chooser intent and FileProvider

Jon.0578Jon.0578 USUniversity ✭✭

Hi I am currently having an issue when trying to share a file using a FileProvider.

In all but one test instance, the file is not available to the application selected from the chooser intent. Running the test, that was enable to attach the pdf document to an email, is now also failing.

Further to this, if Gmail is selected as the share destination and an email sent, the body of the email has appended to it, this is not in the value that is added to the intent with the ExtraText flag.

I have checked the file that is being tested, and it is a valid PDF file.

From stepping through the code I am able to see that the file is in the files/pdf directory on the device.

The canonical file path is:
/data/data/com.myapp.identity/files/pdf/testdocument.pdf.

The absolute file path is :
/data/user/0/com.myapp.identity/files/pdf/testdocument.pdf

The following is the contents of the providers file

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="...">
    <files-path name="pdfshare" path="./pdf" />
</paths>

The following is the method used for sharing the file.

public Task Show(string title, string message, string filePath)
{
    //  Create a Java file instance, to be used by the file provider and check that the file exists
    var pdfFile = new Java.IO.File(filePath);
    if (!pdfFile.Exists())
    {
        //  The file that is being shared does not exist so throw an exception
        throw new Exception("Unable to share file; File does not exist at specified path");
    }

    //  Get a URI for the file from the file provider to enable sharing
    var pdfUri = FileProvider.GetUriForFile(CrossCurrentActivity.Current.Activity, AUTHORITY, pdfFile);
    //  Get the mime type for the URI
    var mimeType = CrossCurrentActivity.Current.Activity.ContentResolver.GetType(pdfUri);
    //  Create the intent for the chooser with the required permissions
    var intent = new Intent();
    intent.SetAction(Intent.ActionSend);
    intent.AddFlags(ActivityFlags.GrantReadUriPermission);
    //  Add the PDF to the intent and set the mime type for the data
    intent.PutExtra(Intent.ExtraStream, pdfUri);
    intent.SetType(mimeType);
    //  Add the additional details to the intent, incase email is selected
    intent.PutExtra(Intent.ExtraSubject, title ?? SHARE_SUBJECT);
    intent.PutExtra(Intent.ExtraText, message ?? DEFAULT_TEXT);
    // Create and display the native chooser for the user to select an app from
    var chooserIntent = Intent.CreateChooser(intent, "Select App to share file");
    chooserIntent.SetFlags(ActivityFlags.ClearTop  | ActivityFlags.NewTask);
    CrossCurrentActivity.Current.Activity.StartActivity(chooserIntent);

    return Task.FromResult(true);
}

I am currently unable to determine why this code is failing to enable the file to be accessed by the selected application.

I also get the same result if I use ShareCompat.

Can anyone help?

Thank you.

Best Answer

  • Jon.0578Jon.0578 US ✭✭
    edited January 28 Accepted Answer

    I have resolved this issue.

    The code I had implemented to share the files was working correctly.

    What I was not aware of was that another developer was deleting all files when the application was transitioning to the background.

    Obviously when the user selects an application to share the file, the current application will be suspended (activating the delete process).

    Refactoring the clean-up process has resolved the issue.

Answers

  • jezhjezh Member, Xamarin Team Xamurai

    Could you please post a basic demo so that we can test it?

  • Jon.0578Jon.0578 USUniversity ✭✭

    Thank you for you reply. I will endeavour to provide a functional demo as soon as I have time.

  • Jon.0578Jon.0578 USUniversity ✭✭

    I have finally found the time to be able to create the test project.

    However, when testing the test project I found that the sharing functionality was behaving as expected.

    This has confused me even more, as the code has been copied out of the solution that has the issue and into the test project.

    There are only a few things that are different between the two solution
    1. Namespaces.
    2. Android Package identity.
    3. Libraries in use.

    If the issue where due to namespaces, then I should have got build or runtime errors.

    I am at real loss as to why I am seeing this behaviour.

    I can see that Logcat is out putting a File not Found exception from Gmail.

    The file does exist, otherwise an exception would be raised and the chooser not displayed.

        //  Create a Java file instance, to be used by the file provider and check that the file exists
        var pdfFile = new Java.IO.File(filePath);
        if (!pdfFile.Exists())
        {
            //  The file that is being shared does not exist so throw an exception
            throw new Exception("Unable to share file; File does not exist at specified path");
        }
    

    The configuration of the FileProvider is the same in both solutions, with the only difference being the Android package Id. However, it must be this that is failing.

  • Jon.0578Jon.0578 USUniversity ✭✭
    edited January 28 Accepted Answer

    I have resolved this issue.

    The code I had implemented to share the files was working correctly.

    What I was not aware of was that another developer was deleting all files when the application was transitioning to the background.

    Obviously when the user selects an application to share the file, the current application will be suspended (activating the delete process).

    Refactoring the clean-up process has resolved the issue.

Sign In or Register to comment.