来自File Provider Uri的Android 7.0 Notification Sound无法播放
我正在更改我的应用程序代码以支持Android 7,但是在我的NotificationCompat.Builder.setSound(Uri)中,从FileProvider传递Uri,Notification不播放任何声音,在Android 6中使用Uri.fromFile()正常工作。
mp3文件位于:
/Animeflv/cache/.sounds/
这是我的通知代码:
knf.animeflv.RequestBackground
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_not_r) .setContentTitle(NotTit) .setContentText(mess); ... mBuilder.setVibrate(new long[]{100, 200, 100, 500}); mBuilder.setSound(UtilSound.getSoundUri(not)); //int
这是我的UtilSound.getSoundUri(int)
public static Uri getSoundUri(int not) { switch (not) { case 0: return RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); default: try { File file=new File(Environment.getExternalStorageDirectory()+"/Animeflv/cache/.sounds",getSoundsFileName(not)); if (file.exists()) { file.setReadable(true,false); if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){ return FileProvider.getUriForFile(context, "knf.animeflv.RequestsBackground",file); }else { return Uri.fromFile(file); } }else { Log.d("Sound Uri","Not found"); return getSoundUri(0); } }catch (Exception e){ e.printStackTrace(); return getSoundUri(0); } } }
在AndroidManifest.xml中:
provider_paths.xml:
以下是我刚刚发表的一篇博文 ,转载于此,因为,嘿,为什么不呢?
您可以通过Notification
上的setSound()
等方法在NotificationCompat.Builder
上添加自定义铃声。 这需要一个Uri
,这会导致Android 7.0出现问题,正如Stack Overflow上的一些人所报告的那样。
如果您使用的是file:
Uri
值,如果您的targetSdkVersion
为24或更高,它们将不再适用于Android 7.0,因为检查声音Uri
是否符合禁止file:
Uri
值 。
但是,如果您尝试content:
来自FileProvider
Uri
,您的声音将无法播放…因为Android没有对该内容的读取权限。
以下是解决此问题的一些选项。
手术刀: grantUriPermissions()
您始终可以通过grantUriPermissions()
Context
提供的方法grantUriPermissions()
内容权限授予其他应用程序。 挑战在于知道授予谁的权限。
适用于Nexus 6P(Android 6.0 ……仍然……)和Nexus 9(Android 7.0)的是:
grantUriPermission("com.android.systemui", sound, Intent.FLAG_GRANT_READ_URI_PERMISSION);
( sound
是你使用setSound()
的Uri
)
这是否能够支持所有设备和所有Android OS版本,我不能说。
断头台:没有更多的用户文件
android.resource
作为一个方案适用于setSound()
Uri
值。 您只允许用户从应用程序中选择作为原始资源提供的多个铃声之一,而不是允许用户从文件中选择自己的铃声。 但是,如果这代表了应用function的丢失,那么您的用户可能会感到不满意。
Ax:使用自定义ContentProvider
FileProvider
时无法使用FileProvider
– 它在启动时崩溃。 但是,对于这种情况,唯一的content:
Uri
将在没有其他问题的情况下工作,其中提供者被exported
并且没有读取访问权限(或者恰好需要com.android.systemui
或等效的一些权限) 。
最后,我将向我的StreamProvider
添加选项,作为一些“只读”提供程序function的一部分。
但是,您可以为此推出自己的提供商。
电锯:禁止禁令
以下代码片段阻止与VM行为相关的所有StrictMode
检查(即主应用程序线程行为以外的其他内容),包括禁止file:
Uri
值:
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
或者,您可以使用您想要的任何规则配置自己的VmPolicy
,而无需调用detectFileUriExposure()
。
这允许您在任何地方使用file:
Uri
值。 谷歌禁止使用该file:
有很好的理由file:
Uri
,所以试图避免禁令可能会让你长期处于不幸的身体部位。
Nuke:使用较低的targetSdkVersion
这也删除了file:
禁令file:
Uri
值,以及24+的targetSdkVersion
选择进入的所有其他行为。 值得注意的是,如果用户进入分屏多窗口模式,这将导致您的应用程序显示“可能无法使用分屏” Toast
。
真正的解决方案:Android中的修复
NotificationManager
应该为我们调用grantUriPermissions()
,或者我们应该有其他方式将FLAG_GRANT_READ_URI_PERMISSION
与我们用于自定义Notification
声音的Uri
相关联。 请继续关注进一步的发展 。