4

この引数に関するすべての回答を読みましたが、写真を受け取るアプリケーションのエラーが常に表示されます。 すべてのアプリケーションで、私にとってうまくいっ
た唯一の方法はこれでした(SDカードファイルがすべてのアプリケーションに公開されているため、機能します):

final File tmpFile = new File(context.getExternalCacheDir(), "exported.jpg");
Uri tmpFileUri = Uri.fromFile(tmpFile);

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setDataAndType(tmpFileUri, "image/jpeg");
shareIntent.putExtra(Intent.EXTRA_STREAM, tmpFileUri);
context.startActivity(Intent.createChooser(shareIntent, context.getString(R.string.share_image)));



現在、プライベート フォルダーにあるファイルを共有する方法に行き詰まっています。Googleドキュメントで提供されているコードを使用しました:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.test.myapp.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true" >
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>
...
...
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="internal_files" path="/"/>
    <cache-path name="internal_cache" path="/" />
</paths>


これは を使用してファイルを共有するためのコードですが、FileProviderwhats up 以外のアプリケーションでは機能しません。

final File tmpFile = new File(context.getCacheDir(), "exported.jpg");
Uri tmpFileUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", tmpFile);
//Remove the uri permission because we overwrite the file
context.revokeUriPermission(tmpFileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

saveBitmapToPath(bitmap, tmpFile);
bitmap.recycle();

Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setDataAndType(tmpFileUri, "image/jpeg");
shareIntent.putExtra(Intent.EXTRA_STREAM, tmpFileUri);
//Grant again the permissions
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
context.startActivity(Intent.createChooser(shareIntent, context.getString(R.string.share_image)));

次のように、他のアプリケーションでエラーが発生し続けるのはなぜですか:
java.lang.SecurityException: Permission Denial: content://com.test.myapp.fileprovider/internal_cache/exported.jpg (pid=675, uid=10052) requires null
または
IllegalArgumentException: Failed to find configuration root that contains content://com.test.myapp.fileprovider/internal_cache/exported.jpg

4

1 に答える 1

6

最後に受信アプリのソースコードを見てみると、解決策が得られました。
これは、私が共有する完全で機能するコードです。
私は誰かを助けることを願っています:

<!-- AndroidManifest.xml -->
<provider
    android:name="com.test.myapp.fileprovider.FileProvider"
    android:authorities="com.test.myapp.fileprovider"
    android:exported="true"
    tools:ignore="ExportedContentProvider" />


//EntryPoint
private void mySharer() {
    ArrayList<Uri> streamUris = new ArrayList<Uri>();
    for (int i = 0; i < 10; i++) {
        File tmpFile = new File(getContext().getCacheDir(), "tmp" + i + ".jpg");
        Uri tmp = FileProvider.getUriForFile("com.test.myapp.fileprovider", tmpFile);
        streamUris.add(tmp);
    }
}

//Share Intent creator
public final void shareUris(ArrayList<Uri> streamUris) {
    if (!streamUris.isEmpty()) {
        Intent shareIntent = new Intent();
        shareIntent.putExtra(ShareCompat.EXTRA_CALLING_PACKAGE, getPackageName());
        shareIntent.putExtra(ShareCompat.EXTRA_CALLING_ACTIVITY, getComponentName());
        shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        shareIntent.setType("image/jpeg");

        if (streamUris.size() == 1) {
            shareIntent.setAction(Intent.ACTION_SEND);
            shareIntent.putExtra(Intent.EXTRA_STREAM, streamUris.get(0));
        } else {
            shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
            shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, streamUris);
        }

        //For multiple images copy all images in the baseDir and use startActivityForResult
        startActivityForResult(Intent.createChooser(shareIntent, getString(R.string.share_image)), 500);
    }
}

//onResult you can delete all temp images/files with specified extensions
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case 500:
            getContentResolver().delete(FileProvider.getUriForFile(getPackageName() + ".fileprovider", null), FileProvider.WHERE_EXTENSION, new String[]{"jpg"});
            break;
        default:
            break;
    }
}

/**
 * This class extends the ContentProvider
 */
abstract class AbstractFileProvider extends ContentProvider {

    private final static String OPENABLE_PROJECTION_DATA = "_data";
    private final static String[] OPENABLE_PROJECTION = { OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE, OPENABLE_PROJECTION_DATA };

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        if (projection == null) {
            projection = OPENABLE_PROJECTION;
        }

        final MatrixCursor cursor = new MatrixCursor(projection, 1);
        MatrixCursor.RowBuilder b = cursor.newRow();

        for (String col : projection) {
            if (OpenableColumns.DISPLAY_NAME.equals(col)) {
                b.add(getFileName(uri));
            } else if (OpenableColumns.SIZE.equals(col)) {
                b.add(getDataLength(uri));
            } else if (OPENABLE_PROJECTION_DATA.equals(col)) {
                b.add(getFileName(uri));
            } else {
                b.add(null);
            }
        }

        return cursor;
    }

    @Override
    public String getType(Uri uri) {
        return URLConnection.guessContentTypeFromName(uri.toString());
    }

    protected String getFileName(Uri uri) {
        return uri.getLastPathSegment();
    }

    protected long getDataLength(Uri uri) {
        return AssetFileDescriptor.UNKNOWN_LENGTH;
    }

    @Override
    public Uri insert(Uri uri, ContentValues initialValues) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public int delete(Uri uri, String where, String[] whereArgs) {
        throw new RuntimeException("Operation not supported");
    }
}

/**
 * This class extends the AbstractFileProvider
 */
public class FileProvider extends AbstractFileProvider {

    public static final String CONTENT_URI = "content://";
    private File baseDir;

    @Override
    public boolean onCreate() {
        baseDir = getContext().getCacheDir();

        if (baseDir != null && baseDir.exists()) {
            return true;
        }

        Log.e("FileProvider", "Can't access cache directory");
        return false;
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        File f = new File(baseDir, uri.getPath());

        if (f.exists()) {
            return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
        }

        throw new FileNotFoundException(uri.getPath());
    }

    @Override
    protected long getDataLength(Uri uri) {
        File f = new File(baseDir, uri.getPath());

        return f.length();
    }

    public static Uri getUriForFile(String authority, File file) {
        return Uri.parse(CONTENT_URI + authority + "/" + file.getName());
    }
}



-------------編集: 05/11/16--------------
複数の画像のサポートが追加されました:

  1. baseDirフォルダ内のすべての画像をコピー
  2. メソッドdelete()FileProvider
  3. 使用するstartActivityForResult
  4. 聞くonActivityResult
  5. すべての一時画像を削除できるようになりました

電子メールの添付ファイルの場合、ファイルを削除する前に電子メールが送信されるのを待つ必要があります。そうしないと、空の添付ファイルが送信されます

于 2014-07-24T03:40:40.790 に答える