Java 意图.行动\发送目标API级别24+
当我试图发送一个带有意图的文件时,会出现android.os.StrictMode.onFileUriExposed异常。我的理解是,这是因为我的目标是24>,不再支持file://了,应该使用content://了 首先我想说,我看到过类似的问题,我也看到过博客帖子 但问题是,所有帖子在拍照时都引用了URI,在我的例子中,文件是使用URI成功保存的,现在我想使用如下意图发送图像:Java 意图.行动\发送目标API级别24+,java,android,Java,Android,当我试图发送一个带有意图的文件时,会出现android.os.StrictMode.onFileUriExposed异常。我的理解是,这是因为我的目标是24>,不再支持file://了,应该使用content://了 首先我想说,我看到过类似的问题,我也看到过博客帖子 但问题是,所有帖子在拍照时都引用了URI,在我的例子中,文件是使用URI成功保存的,现在我想使用如下意图发送图像: shareBtn.setOnClickListener(new View.OnClickListener() {
shareBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri screenshotUri = Uri.parse("file://" + directoryToStore + "/" + filename);
//the Uri above - file:///storage/emulated/0/Android/data/myPackageName/files/SavedImages/test.jpeg
sharingIntent.setType("image/jpeg");
sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
startActivity(Intent.createChooser(sharingIntent, "Share image using"));
}
});
通过执行上述操作,我只会在运行19>的某些设备上发生崩溃。在我的三星J7Pro安卓7.0 API 24上测试,我没有崩溃
我看到一些答案说我可以使用:
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
但这不是首选的方式
所以,我的问题是。以24>为目标时,我应该如何处理发送文件的问题。我是否应该执行if/else语句来检查版本,如if Build.version.SDK_INT>=19{,然后对运行的设备使用普通Uri从应用程序共享文件的正确方式是内容提供商,特别是 将文件提供程序添加到AnroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.MyFileProvider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/shared_paths"/>
</provider>
编辑:将图元类型从更改为。
重要提示:更改路径属性以满足您的需要
最后更改代码如下:
shareBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri screenshotUri = FileProvider.getUriForFile(context, context.getPackageName() + ".MyFileProvider", new File(directoryToStore, filename))
//the Uri above - file:///storage/emulated/0/Android/data/myPackageName/files/SavedImages/test.jpeg
sharingIntent.setType("image/jpeg");
sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent chooserIntent = Intent.createChooser(sharingIntent, "Share image using");
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(chooserIntent);
}
});
如果您将文件保存在内存中的公共媒体文件夹中,即用于图像/存储/模拟/0/DCIM/my.package.name/SavedImages/myImage.jpg,您还可以通过图像的it-s内容媒体uri共享该文件content://media/external/images/media/4711. 这样,您不需要自己的文件提供程序,但该文件可供所有人使用 如果应用程序的私有数据目录中有lcoal文件提供程序,则该文件只能通过应用程序使用,如果卸载应用程序,该文件将被删除 contentprovider的用途是,您可以将任何uri中的内容作为inputStream读取,即格式uri=。。。,file:///storage/emulated/0/...,ftp:…,content:…只要有此服务的提供商
使用api 25,Google强制执行该文件:…uri-s不再被允许你能检查你的日志猫,看看你得到了什么错误/堆栈跟踪吗?@ArsenyLevin我没有得到任何错误,当我按下共享按钮时,我只得到ViewPostiInputStage进程指针1,然后我得到选择器,在那里我可以选择与之共享图像的应用程序。@ArsenyLevin我已经记录了Uri contentUri=FileProvider.getUriForFilegetApplication,getApplication.getPackageName+.MyFileProvider,newFile;它返回共享文件而不是SaveDimages更改xml为:@ArsenyLevin我仍然得到与上面编辑相同的Toast。Uri现在返回content://my.packahe.name.MyFileProvider/SavedImages/test.jpegThank谢谢你的回答,我想保持文件的私密性,我想在卸载应用程序后将其删除。我只希望我的应用程序能够访问文件,除非我想在y应用程序中共享文件。对于私密性文件,你需要contentprovider或DocumentProvider OK谢谢。我的最低SDK是16,我是否应该选择Ck如果SDK为19<,然后使用file://?以旧方式执行,这取决于接收映像的客户端应用程序。有些可以处理file://有些可以处理content://还有一些可以同时处理两者。使用和来分析intent和contentprovider。my可以同时处理两者,并且很快将获得一个配置设置wther以公开file://或content://where默认为content://and 事情只会变得更复杂1.谢谢你抽出时间回答我的问题。
shareBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri screenshotUri = FileProvider.getUriForFile(context, context.getPackageName() + ".MyFileProvider", new File(directoryToStore, filename))
//the Uri above - file:///storage/emulated/0/Android/data/myPackageName/files/SavedImages/test.jpeg
sharingIntent.setType("image/jpeg");
sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent chooserIntent = Intent.createChooser(sharingIntent, "Share image using");
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(chooserIntent);
}
});