3

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>
MakinTosH
  • 623
  • 7
  • 12
  • I'm a java developer, but have you declared READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE perms? – River_B Jun 28 '20 at 07:00
  • No, as I'm using FileProvider these permissions are not needed as per documentation. I tried using internal storage and the issue stays the same.. Maybe Gmail need those permissions, I'll try it. – MakinTosH Jun 28 '20 at 07:05
  • `No, as I'm using FileProvider these permissions are not needed `. They are not needed indeed. But that has nothing to do with using a file provider. The reasen is that they are not needed for getExternalFilesDir. – blackapps Jun 28 '20 at 08:08
  • `.setType("text/csv")` Try to set a different type. – blackapps Jun 28 '20 at 08:11

2 Answers2

4

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>
MakinTosH
  • 623
  • 7
  • 12
1

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>
SvdTweel
  • 172
  • 1
  • 2
  • 11