Проблема:
При намерении успешно открывается окно выбора приложений, и когда я выбираю Gmail, экран создания сообщения открывается идеально. «Кому», «Тема», «Тело» и вложение PDF отображаются в пользовательском интерфейсе создания сообщения.
Однако, когда я нажимаю «Отправить», оно фактически не отправляется. Он просто попадает прямо в папку черновиков, а вложение PDF отсутствует. Остается только простой текст.
Что я пробовал (и не работало):
Чтобы это исправить, я попробовал следующее на основе лучших практик современного Android (API 30+):
- Использовал FileProvider для правильного обслуживания URI content:// вместо URI файла://.
- Добавлено Intent.FLAG_GRANT_READ_URI_PERMISSION к намерению.
- Добавлен Intent.setClipData(ClipData.newRawUri("PDF", uri)), который требуется некоторым современным приложениям для просмотра вложения.
- Попробовал использовать ShareCompat.IntentBuilder, чтобы убедиться, что намерение построено правильно.
- Проверено сохранение PDF-файла в нескольких местах: getCacheDir(), getExternalCacheDir() и getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).
- Добавлен fos.getFD().sync() в FileOutputStream, чтобы гарантировать, что PDF-файл будет полностью сброшен на физический диск до того, как сработает намерение.
- Добавлено для в манифесте для видимости пакета Android 11+.
- Создано уникальное имя файла с помощью System.currentTimeMillis() для каждого PDF-файла, чтобы гарантировать, что Gmail не кэширует старый/неработающий черновик.
Мой код:
Код: Выделить всё
`MainActivity.java`
public class MainActivity extends AppCompatActivity {
private static final String RECIPIENT = "mgauthier@duck.com";
private static final String SUBJECT = "Test Email";
private static final String BODY = "Test Email";
private static final String FILE_PROVIDER_AUTHORITY = "com.mike.email.fileprovider";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btnEmailPDF).setOnClickListener(v -> sendEmailWithPdf());
}
private void sendEmailWithPdf() {
File pdfFile = createPdf();
if (pdfFile == null || !pdfFile.exists()) return;
Uri contentUri = FileProvider.getUriForFile(this, FILE_PROVIDER_AUTHORITY, pdfFile);
Intent intent = ShareCompat.IntentBuilder.from(this)
.setType("application/pdf")
.setEmailTo(new String[]{RECIPIENT})
.setSubject(SUBJECT)
.setText(BODY)
.setStream(contentUri)
.getIntent();
// Granting permissions
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setClipData(ClipData.newRawUri("PDF Attachment", contentUri));
startActivity(Intent.createChooser(intent, "Send Email with PDF..."));
}
private File createPdf() {
PdfDocument document = new PdfDocument();
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(595, 842, 1).create();
PdfDocument.Page page = document.startPage(pageInfo);
Canvas canvas = page.getCanvas();
Paint paint = new Paint();
paint.setTextSize(18);
canvas.drawText("Hello, this is a test PDF document.", 50, 50, paint);
document.finishPage(page);
File baseDir = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
File directory = new File(baseDir, "EmailTests");
if (!directory.exists()) directory.mkdirs();
// Unique filename
File file = new File(directory, "EmailTest_" + System.currentTimeMillis() + ".pdf");
try (FileOutputStream fos = new FileOutputStream(file)) {
document.writeTo(fos);
fos.flush();
fos.getFD().sync(); // Ensure physical write
} catch (IOException e) {
return null;
} finally {
document.close();
}
return file;
}
}
`AndroidManifest.xml`
android:name="androidx.core.content.FileProvider"
android:authorities="com.mike.email.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
`res/xml/file_paths.xml`