使用 ContentProvider 将文件附加到电子邮件不起作用

Attaching file to email using ContentProvider isn't working

我想附加一个我在运行时生成的文件。

运行时流程:

  1. 创建意图
  2. cacheDir
  3. 下创建一个文件
  4. 将文件添加为 content:// 额外的意图
  5. 启动选择器和 select Gmail
  6. 期待 openFile() 被调用并允许访问
  7. 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 类型)。