我已经阅读了关于这个论点的所有答案,但我总是收到收到我的照片的应用程序的错误。
对我来说工作的唯一方法是适用于所有应用,这是(它的工作因为SD卡文件对所有应用程序都是公开的):< / p>
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>
这是使用FileProvider
共享文件的代码,但不适用于任何应用程序,除了最新内容:
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
答案 0 :(得分:5)
最后查看接收应用的源代码,我得到了解决方案 这是我分享的完整,有效的代码 我希望能帮助别人:
<!-- 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 --------------
添加了对多个图像的支持:
baseDir
文件夹delete()
FileProvider
方法
startActivityForResult
onActivityResult
对于电子邮件附件,您必须等待删除文件之前发送电子邮件,否则您将发送空附件