我正在寻找一种方法,以正确共享(而不是打开)内部文件与外部应用程序使用安卓支持库的FileProvider。
按照文档上的示例,
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.android.supportv4.my_files"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/my_paths" />
</provider>
并使用ShareCompat将文件共享到其他应用程序,如下所示:
ShareCompat.IntentBuilder.from(activity)
.setStream(uri) // uri from FileProvider
.setType("text/html")
.getIntent()
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
不起作用,因为FLAG_GRANT_READ_URI_PERMISSION只授予在意图的data
上指定的Uri的权限,而不是EXTRA_STREAM
extra的值(由setStream
设置)。
我试图通过将提供程序的android:exported
设置为true
来折衷安全性,但FileProvider
在内部检查自身是否已导出,如果是,它将抛出异常。
发布于 2015-10-05 21:54:31
这个解决方案适用于我从OS4.4开始的版本。为了让它在所有设备上都能工作,我为旧设备添加了一个变通方法。这确保始终使用最安全的解决方案。
Manifest.xml:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.package.name.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
file_paths.xml:
<paths>
<files-path name="app_directory" path="directory/"/>
</paths>
Java:
public static void sendFile(Context context) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
String dirpath = context.getFilesDir() + File.separator + "directory";
File file = new File(dirpath + File.separator + "file.txt");
Uri uri = FileProvider.getUriForFile(context, "com.package.name.fileprovider", file);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Workaround for Android bug.
// grantUriPermission also needed for KITKAT,
// see https://code.google.com/p/android/issues/detail?id=76683
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, attachmentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
if (intent.resolveActivity(context.getPackageManager()) != null) {
context.startActivity(intent);
}
}
public static void revokeFileReadPermission(Context context) {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
String dirpath = context.getFilesDir() + File.separator + "directory";
File file = new File(dirpath + File.separator + "file.txt");
Uri uri = FileProvider.getUriForFile(context, "com.package.name.fileprovider", file);
context.revokeUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
在片段或活动的onResume和onDestroy()方法中使用revokeFileReadPermission()撤消权限。
发布于 2013-09-03 12:01:10
正如Phil在他对原始问题的评论中所说的那样,这是独一无二的,在google中没有其他信息,我想我也应该分享我的结果:
在我的应用程序中,FileProvider开箱即用来使用共享意图来共享文件。除了设置FileProvider之外,不需要任何特殊的配置或代码。在我的manifest.xml中,我放置了:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.my.apps.package.files"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/my_paths" />
</provider>
在my_paths.xml中,我有:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="files" path="." />
</paths>
在我的代码中,我有:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("application/xml");
Uri uri = FileProvider.getUriForFile(this, "com.my.apps.package.files", fileToShare);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.share_file)));
而且,我可以毫不费力地将存储在我的应用程序私有存储中的文件与Gmail和google drive等应用程序共享。
发布于 2014-01-20 06:37:09
据我所知,这只能在较新版本的Android上运行,所以你可能不得不想出一种不同的方法来实现它。这个解决方案适用于我的4.4版本,但不适用于4.0或2.3.3版本,所以对于一个本应在任何Android设备上运行的应用程序来说,这不是一个有用的分享内容的方式。
在manifest.xml中:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.myapp.SharingActivity"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
请仔细注意您如何指定权限。您必须指定您将从中创建URI并启动共享意图的活动,在本例中,该活动称为SharingActivity。这一要求在谷歌的文档中并不明显!
file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="just_a_name" path=""/>
</paths>
请注意指定路径的方式。以上内容默认为私有内部存储的根目录。
在SharingActivity.java中:
Uri contentUri = FileProvider.getUriForFile(getActivity(),
"com.mydomain.myapp.SharingActivity", myFile);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("image/jpeg");
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "Share with"));
在本例中,我们共享了一张JPEG图像。
最后,最好确保您已经正确地保存了该文件,并且可以使用以下内容访问它:
File myFile = getActivity().getFileStreamPath("mySavedImage.jpeg");
if(myFile != null){
Log.d(TAG, "File found, file description: "+myFile.toString());
}else{
Log.w(TAG, "File not found!");
}
https://stackoverflow.com/questions/18249007
复制相似问题