couldn't attach file send email android 11

Viewed 8872

I am developing an application that sends processing reports via email. When completing the processing data in the application, the user sends an email containing the processing data. However, I am facing a problem on Android 11. When attaching the report to the email, regardless of the email application, a message appears: the file could not be attached. I've been researching a little and saw that it may be related to the permission to access the internal storage of the device on devices with version of android 11. I would like me to help you send email with file attached on android 11.

My code: Manifest

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:networkSecurityConfig="@xml/network_security_config"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    android:requestLegacyExternalStorage="true"
    tools:ignore="AllowBackup"
    tools:targetApi="n">

    <activity.....
     <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
  </application>

My xml:

enter image description here

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

Save file .pdf

val mDocProc = Document()
            val file =
                File(
                    Environment.getExternalStorageDirectory()
                        .toString() + "/" + "Relatório diário" + date + ".pdf"
                )
            if (file.exists()) {
                file.delete()
            }
            //pdf file path
            mFilePathDaily =
                Environment.getExternalStorageDirectory()
                    .toString() + "/" + "Relatório diário " + date + ".pdf"

Class send email:

val report = File(mFilePathDaily)
            val uri = FileProvider.getUriForFile(
                activity.requireContext(),
                activity.requireContext().applicationContext.packageName + ".provider",
                report
            )

            val i = Intent(Intent.ACTION_SENDTO)
            i.data = Uri.parse("mailto:")
            i.putExtra(Intent.EXTRA_EMAIL, arrayOf("testesdissertacao@gmail.com"))
            i.putExtra(Intent.EXTRA_SUBJECT, EMAIL_SUBJECT)
            i.putExtra(Intent.EXTRA_TEXT, "Segue em anexo o relatório de Benchmark")
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            i.putExtra(Intent.EXTRA_STREAM, uri)
            //i.type = "image/png"
            activity.requireContext().startActivity(Intent.createChooser(i, null))
            progressDialog.dismiss()

Now the problem is that you can't find the report to attach to the email. I noticed that the report was saved inside that other folder in the emulator, and not in the root folder. I think that is why you are not finding the file to attach to the email.

enter image description here

enter image description here

Do not attach the file to the email

enter image description here

4 Answers

I have attached the image successfully in email i will give you a code

convert your URI to file

 private void Share(File savepath) {
       
 if (savePath != null) {

            Uri uri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", savePath);

            Intent i = new Intent(Intent.ACTION_SEND);
            i.putExtra(Intent.EXTRA_EMAIL, new String[]{"fake@fake.edu"});
            i.putExtra(Intent.EXTRA_SUBJECT,"On The Job");
            //Log.d("URI@!@#!#!@##!", Uri.fromFile(pic).toString() + "   " + pic.exists());
            i.putExtra(Intent.EXTRA_TEXT,"All Detail of Email are here in message");
            i.putExtra(Intent.EXTRA_STREAM,uri);
            i.setType("image/png");
            context.startActivity(Intent.createChooser(i,"Share you on the jobing"));

        }

how to add provider in XML path first, you have to create an XML resource folder then create an XML resource file after pasting this code

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

then also add-in manifest

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

file provider in xml

decalre in manifest

I was able to send an email with pdf attachment using the code below. screenshot Crucial was granting READ_URI_PERMISSION and WRITE_URI_PERMISSION, using ACTION_SEND instead of ACTION_SENDTO and the Uri being linked to a pdf file in one of the standard directories such as Download or Documents. I did not need to convert Uri to File.:

  //obtaining the uri to the pdf report when creating it
  Uri pathToPdf = null;
  int EmailRequestCode = 200;
  ContentResolver contentresolver = getContentResolver();
  ContentValues contentvalues = new ContentValues();
  contentvalues.put(MediaStore.MediaColumns.DISPLAY_NAME, pdfFileName);
  contentvalues.put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf");
  contentvalues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + File.separator +"Reports");
  pathToPdf = contentresolver.insert(MediaStore.Files.getContentUri("external"), contentvalues);

  //... writing data to the pdf

  //getting email addresses to include in the email
  String[] mailto = listMailAddressTO.toArray(new String[2]);
  String[] mailCC = listMailAddressCC.toArray(new String[2]);

  Intent emailIntent = new Intent(Intent.ACTION_SEND);
  emailIntent.setType("application/pdf");
  emailIntent.putExtra(Intent.EXTRA_EMAIL, mailto);
  emailIntent.putExtra(Intent.EXTRA_CC, mailCC);
  emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
  emailIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  emailIntent.putExtra(Intent.EXTRA_SUBJECT, "UllageReport (Pdf)");                                
  emailIntent.putExtra(Intent.EXTRA_TEXT, "UllageReport");
  emailIntent.putExtra(Intent.EXTRA_STREAM, pathToPdf);
  try{
      if (emailIntent.resolveActivity(getPackageManager()) != null) {
          startActivityForResult(emailIntent, EmailRequestCode);
      }
  }
  catch(android.content.ActivityNotFoundException e){
       Toast.makeText(UllageReportPdf.this, "No email client available", Toast.LENGTH_SHORT).show();
  }

The solution for me was I had to replace res/xml/file_paths.xml with:

<?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>

You should use only the lines you need to make it work.

Related