在Android的Nougat +世界中,Google正在对content://
Uris执行file://
Uris。这对app-private文件有意义,但不适用于系统范围或公共文件。我有一个文件管理器应用程序,自然需要在用户的手机上与各种查看器应用程序共享文件。这种情况不符合content://
协议的基本原理,即临时授予我应用程序文件访问其他应用程序的权限。文件/sdcard/Downloads/kittens.png
对我的文件管理器不是私有的,因此我的应用程序将kittens.png(公共文件)标记为私有并因此通过content://
共享给查看器应用程序似乎是不合适的。毕竟,设计文件管理器仅仅是组织者和用户文件与其首选应用程序之间的便捷链接。
由于file://
协议在这些日子里非常不受欢迎,我尝试使用content://
协议,结果不一致。某些应用会响应content://
Uri并处理该文件,而其他应用则不会。但是,我测试的每个查看器应用都会正确响应file://
协议,然后才能处理该文件。一个很好的例子是VLC和jetAudio,我最喜欢的媒体播放器。 VLC将播放通过content://
和file://
的音频,而jetAudio仅播放file://
传递的音频。
我需要能够使用安装任何未知的查看器应用程序来分享用户手机上的几乎所有文件,就像文件管理员应该能够做到的那样。某些查看器应用程序(可能较旧的目标不是24+)不能正确显示在content://
上共享的文件 - 这会导致我的文件管理器无法使用。其他文件管理器应用可以通过定位较低的SDK或取消对file://
的限制来避免此问题,但我不确定这是否是一个好的,面向未来的选项。 解决此问题的正确方法(又称安全和持久)是什么?
按内容分享
这就是我尝试与content://
共享的方式,但是对于某些查看器应用程序(例如jetAudio)来说,这是失败的。
C#(我使用Xamarin):
Intent viewFile = new Intent(Intent.ActionView);
fileIntent.SetDataAndType(FileProvider.GetUriForFile(Application.Context, Application.Context.PackageName + ".provider", new Java.IO.File(fileFullpath)), fileMIME);
fileIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.GrantReadUriPermission | ActivityFlags.GrantWriteUriPermission);
...
StartActivity(viewFile);
在清单:
中<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
XML / provider_paths :
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
按文件分享
我希望将目标SDK保留在25.这样,我可以使用StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
或类似的东西来共享file://
的文件。这适用于几乎所有的查看器应用程序,但显然是一种解决方法,而不是解决方案。如果可能的话,我想避免这种情况,因为我不确定这种方法在Android版本的未来版本中会被允许多长时间。
超级用户援助
如果有一个bash实用程序或本机代码可以更好地解决这个问题,我绝对是开放的。