I am trying to attach a file to an SendIntent for Gmail, so that my users can email the file file to me upon request. I am targeting Android 35
I have declared a FileContentProvider in the Application element of my manifest
<provider
android:authorities="com.my_app.fileprovider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>
I have declared the file resource (res/xml/file_provider_paths.xml):
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="logs" path="/logs"/>
</paths>
I am constructing the Intent and handing it off as per:
final Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("mailto:"));
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{ "support@my_app.com"});
intent.putExtra(Intent.EXTRA_SUBJECT, "Some Subject");
intent.putExtra(Intent.EXTRA_TEXT, "Some content");
final File logsFolder = new File(context.getFilesDir(), "logs");
final File logsFile = new File(logsFolder, "Application.log")
final Uri contentUri = FileProvider.getUriForFile(context, "com.my_app.fileprovider", logFile);
Log.w(TAG, "Sending this log content: " + contentUri);
intent.putExtra(Intent.EXTRA_STREAM, contentUri));
intent.addFlags((Intent.FLAG_GRANT_READ_URI_PERMISSION));
startActivity(Intent.createChooser(intent, "Contact Us"));
This opens up a chooser in which Gmail is an option and upon choosing Gmail I get the prepared email with subject, content etc, but no attached file.
Looking at Logcat I see these errors (which appear after starting the ChooserIntent:
E Failed to find provider info for com.my_app.fileprovider
E ComposeActivity: Error adding attachment [CONTEXT android_log_tag="ComposeActivity" ]
hea: FileNotFoundException when openAssetFileDescriptor.
at gzz.e(PG:565)
at hsu.L(PG:182)
...
Caused by: java.io.FileNotFoundException: No content provider: content://com.my_app.fileprovider/logs/application.log
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:2029)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1858)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1773)
at lky.y(PG:10)
at gzz.e(PG:452)
...
I can resolve the content Uri using a ContentResolver within my app and see its and and file size. But Gmail doesn't seem to even be able to find my ContentResolver.
What am I doing wrong? What do I need to change so that GMail can resolve my file and attach it to the email?
Wrong intent action for attachments.
ACTION_SENDTO
(with mailto:
) is for composing an email without attachments. Most clients (incl. Gmail) ignore EXTRA_STREAM
with ACTION_SENDTO
. Use ACTION_SEND
.
You computed a contentUri
but attached a File
.
You must put the content://…
Uri
from FileProvider
in EXTRA_STREAM
, not the File
.
Authority mismatch.
Failed to find provider info for com.my_app.fileprovider
means the authority string in your code doesn’t match the provider declared in the installed app.
Avoid hard-coding: use ${applicationId}.fileprovider
in the manifest and context.getPackageName() + ".fileprovider"
in code.
Also note: package names can’t contain underscores; double-check your real applicationId.
paths
entry has a leading slash.
In file_provider_paths.xml
the path
must be relative (no leading /
). If your file is at context.getFilesDir()/logs/Application.log
, the path
should be logs/
.
Granting read permission.
Add FLAG_GRANT_READ_URI_PERMISSION
. (Optional but sometimes helpful: explicitly call grantUriPermission
for Gmail.)
<application ... >
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>
</application>
res/xml/file_provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- File will live at: context.getFilesDir()/logs/Application.log -->
<files-path name="logs" path="logs/" />
</paths>
Kotlin/Java (building the email)
val logsFolder = File(context.filesDir, "logs")
val logFile = File(logsFolder, "Application.log")
// Ensure it exists (and is within filesDir/logs)
require(logFile.exists()) { "Log file doesn't exist: ${logFile.absolutePath}" }
val authority = context.packageName + ".fileprovider"
val contentUri = FileProvider.getUriForFile(context, authority, logFile)
val email = Intent(Intent.ACTION_SEND).apply {
// A general type is fine; or detect based on your file
type = "text/plain" // or "application/octet-stream"
putExtra(Intent.EXTRA_EMAIL, arrayOf("support@my_app.com"))
putExtra(Intent.EXTRA_SUBJECT, "Some Subject")
putExtra(Intent.EXTRA_TEXT, "Some content")
putExtra(Intent.EXTRA_STREAM, contentUri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
// Optional: also set ClipData (helps some clients)
clipData = ClipData.newUri(context.contentResolver, "logs", contentUri)
}
// Optional: explicitly grant to Gmail (in case chooser picks Gmail)
try {
context.grantUriPermission(
"com.google.android.gm",
contentUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
} catch (_: Exception) { /* ignore if Gmail not installed */ }
startActivity(Intent.createChooser(email, "Contact Us"))