MakinTosH
MakinTosH

Reputation: 642

Android Intent to Gmail not attaching file by FileProvider "Unable to attach file"

When attaching file to Gmail I briefly see the file in attachments and then get Toast saying "Unable to attach file" and then it's gone. It works fine with Drive, Discord and other apps.. Also the file stays in attachments on emulator but when I send it, the mail is send without attachments. I have a simple .csv file and attach it via FileProvider.

Tried writing to internal storage, didn't help.

val fileLocation = File(requireContext().getExternalFilesDir("data"), "data.csv")

            // Saving the file into device
            val streamOut =
                FileOutputStream(fileLocation)
            streamOut.write(myString.toByteArray())
            streamOut.close()

            // Exporting

            val contentUri = FileProvider.getUriForFile(
                requireContext(),
                "mypackage.fileprovider",
                fileLocation
            )

            val fileIntent = Intent(Intent.ACTION_SEND)
                .setType("text/csv")
                .putExtra(Intent.EXTRA_SUBJECT, "Data")
                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                .putExtra(Intent.EXTRA_STREAM, contentUri)

            val chooser = Intent.createChooser(
                fileIntent,
                requireContext().resources.getText(R.string.send_to)
            )

            chooser.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

            val resInfoList: List<ResolveInfo> = requireActivity().packageManager
                .queryIntentActivities(chooser, PackageManager.MATCH_DEFAULT_ONLY)

            for (resolveInfo in resInfoList) {
                val packageName = resolveInfo.activityInfo.packageName
                requireActivity().grantUriPermission(
                    packageName,
                    contentUri,
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
                )
            }

            requireActivity().startActivity(
                chooser
            )

provider_paths

<paths>
    <external-files-path
        name="data"
        path="." />
</paths>

Manifest

<provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="mypackage.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">

            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

Upvotes: 3

Views: 2181

Answers (2)

MakinTosH
MakinTosH

Reputation: 642

Solved it by changing file_paths.xml according to this template:

<?xml version="1.0" encoding="utf-8"?>
<paths>
  <external-path
    name="external"
    path="." />
  <external-files-path
    name="external_files"
    path="." />
  <cache-path
    name="cache"
    path="." />
  <external-cache-path
    name="external_cache"
    path="." />
<files-path
    name="files"
    path="." />
</paths>

Upvotes: 4

SvdTweel
SvdTweel

Reputation: 302

Can you try to update your file_paths.xml to use a specific path with the external-path and try if it works?

See my working solution below. It uses multiple attachments but it works with the Gmail app:

java class

private void prepareEmail(File report, List<Expense> openExpenses) {
    Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
    intent.setType("message/rfc822");
    intent.putExtra(Intent.EXTRA_EMAIL, new String[]{preferences.getEmailReceiver()});
    intent.putExtra(Intent.EXTRA_SUBJECT, preferences.getEmailSubject());
    intent.putExtra(Intent.EXTRA_TEXT, preferences.getEmailBody());

    ArrayList<Uri> uris = new ArrayList<>();
    uris.add(FileProvider.getUriForFile(getApplicationContext(), "my.package", report));
    for (Expense expense : openExpenses) {
        if (expense.getType() == ExpenseType.EXPENSE.getValue()) {
            File file = new File(expense.getReceipt());
            uris.add(FileProvider.getUriForFile(getApplicationContext(), "my.package", file));
        }
    }
    intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
    startActivity(Intent.createChooser(intent, getResources().getString(R.string.report_report_send)));
}

file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/my.package/files/Pictures" />
    <external-path name="my_pdfs" path="Android/data/my.package/files/Documents" />
    <external-path name="my_reports" path="Android/data/my.package/files" />
    <files-path name="files" path="." />
</paths>

manifest

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="my.package"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

Upvotes: 1

Related Questions