使用 ContentProvider 将文件附加到电子邮件不起作用
Attaching file to email using ContentProvider isn't working
我想附加一个我在运行时生成的文件。
运行时流程:
- 创建意图
- 在
cacheDir
下创建一个文件
- 将文件添加为
content://
额外的意图
- 启动选择器和 select Gmail
- 期待
openFile()
被调用并允许访问
- Gmail 打开时没有附件
然而,openFile()
没有被调用。
相关代码如下:
创建意图并添加额外内容:
public static void contact(Activity activity, String message) {
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("text/plain");
String version = Version.appVersion(activity);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{activity.getString(R.string.contact_email)});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, activity.getString(R.string.app_name)+" ("+version+")");
emailIntent.putExtra(Intent.EXTRA_TEXT, message);
addInfoAttachment(emailIntent, activity);
String title = activity.getString(R.string.string_select_email_app);
activity.startActivity(Intent.createChooser(emailIntent, title));
}
创建缓存文件:
public static void createCachedFile(Context context, String fileName,
String content) throws IOException
{
File cacheFile = new File(context.getCacheDir() + File.separator
+ fileName);
cacheFile.delete();
cacheFile.createNewFile();
FileOutputStream fos = new FileOutputStream(cacheFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
PrintWriter pw = new PrintWriter(osw);
pw.println(content);
pw.flush();
pw.close();
}
将文件添加到意图:
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + AUTHORITY + File.separator + REPORT_INFO_FILE_NAME));
覆盖 ContentProvider
:(未调用)
public class LogFileProvider extends ContentProvider {
private static final String TAG = "LogFileProvider";
public static final String AUTHORITY = "com.domain.appName.LogFileProvider";
private UriMatcher uriMatcher;
@Override
public boolean onCreate() {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "*", 1);
return true;
}
@Override
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
Log.v(TAG, "openFile Called with uri: '" + uri + "'." + uri.getLastPathSegment());
// Check incoming Uri against the matcher
switch (uriMatcher.match(uri)) {
// If it returns 1 - then it matches the Uri defined in onCreate
case 1:
String fileLocation = getContext().getCacheDir() + File.separator
+ uri.getLastPathSegment();
return ParcelFileDescriptor.open(new File(
fileLocation), ParcelFileDescriptor.MODE_READ_ONLY);
default:
Log.v(TAG, "Unsupported uri: '" + uri + "'.");
throw new FileNotFoundException("Unsupported uri: "
+ uri.toString());
}
}
// //////////////////////////////////////////////////////////////
// Not supported / used / required for this example
// //////////////////////////////////////////////////////////////
@Override
public int update(@NonNull Uri uri, ContentValues contentvalues, String s,
String[] as) {
return 0;
}
@Override
public int delete(@NonNull Uri uri, String s, String[] as) {
return 0;
}
@Override
public Uri insert(@NonNull Uri uri, ContentValues contentvalues) {
return null;
}
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String s, String[] as1,
String s1) {
return null;
}
}
清单中:
<provider
android:name=".LogFileProvider"
android:authorities="com.domain.appName.LogFileProvider"
android:enabled="true"
android:exported="false"
android:grantUriPermissions="true"/>
您需要将 FLAG_GRANT_READ_URI_PERMISSION
添加到 Intent
。目前,收件人无权访问该内容。
您可以考虑使用 FileProvider
而不是自己的。一些客户会期望提供者做的比您拥有的更多(例如,响应 query()
以获得 OpenableColumns
,响应 getType()
并使用实际的 MIME 类型)。
我想附加一个我在运行时生成的文件。
运行时流程:
- 创建意图
- 在
cacheDir
下创建一个文件
- 将文件添加为
content://
额外的意图 - 启动选择器和 select Gmail
- 期待
openFile()
被调用并允许访问 - Gmail 打开时没有附件
然而,openFile()
没有被调用。
相关代码如下:
创建意图并添加额外内容:
public static void contact(Activity activity, String message) {
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("text/plain");
String version = Version.appVersion(activity);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{activity.getString(R.string.contact_email)});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, activity.getString(R.string.app_name)+" ("+version+")");
emailIntent.putExtra(Intent.EXTRA_TEXT, message);
addInfoAttachment(emailIntent, activity);
String title = activity.getString(R.string.string_select_email_app);
activity.startActivity(Intent.createChooser(emailIntent, title));
}
创建缓存文件:
public static void createCachedFile(Context context, String fileName,
String content) throws IOException
{
File cacheFile = new File(context.getCacheDir() + File.separator
+ fileName);
cacheFile.delete();
cacheFile.createNewFile();
FileOutputStream fos = new FileOutputStream(cacheFile);
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
PrintWriter pw = new PrintWriter(osw);
pw.println(content);
pw.flush();
pw.close();
}
将文件添加到意图:
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + AUTHORITY + File.separator + REPORT_INFO_FILE_NAME));
覆盖 ContentProvider
:(未调用)
public class LogFileProvider extends ContentProvider {
private static final String TAG = "LogFileProvider";
public static final String AUTHORITY = "com.domain.appName.LogFileProvider";
private UriMatcher uriMatcher;
@Override
public boolean onCreate() {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "*", 1);
return true;
}
@Override
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
Log.v(TAG, "openFile Called with uri: '" + uri + "'." + uri.getLastPathSegment());
// Check incoming Uri against the matcher
switch (uriMatcher.match(uri)) {
// If it returns 1 - then it matches the Uri defined in onCreate
case 1:
String fileLocation = getContext().getCacheDir() + File.separator
+ uri.getLastPathSegment();
return ParcelFileDescriptor.open(new File(
fileLocation), ParcelFileDescriptor.MODE_READ_ONLY);
default:
Log.v(TAG, "Unsupported uri: '" + uri + "'.");
throw new FileNotFoundException("Unsupported uri: "
+ uri.toString());
}
}
// //////////////////////////////////////////////////////////////
// Not supported / used / required for this example
// //////////////////////////////////////////////////////////////
@Override
public int update(@NonNull Uri uri, ContentValues contentvalues, String s,
String[] as) {
return 0;
}
@Override
public int delete(@NonNull Uri uri, String s, String[] as) {
return 0;
}
@Override
public Uri insert(@NonNull Uri uri, ContentValues contentvalues) {
return null;
}
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String s, String[] as1,
String s1) {
return null;
}
}
清单中:
<provider
android:name=".LogFileProvider"
android:authorities="com.domain.appName.LogFileProvider"
android:enabled="true"
android:exported="false"
android:grantUriPermissions="true"/>
您需要将 FLAG_GRANT_READ_URI_PERMISSION
添加到 Intent
。目前,收件人无权访问该内容。
您可以考虑使用 FileProvider
而不是自己的。一些客户会期望提供者做的比您拥有的更多(例如,响应 query()
以获得 OpenableColumns
,响应 getType()
并使用实际的 MIME 类型)。