来自File Provider Uri的Android 7.0 Notification Sound无法播放 [英] Android 7.0 Notification Sound from File Provider Uri not playing
问题描述
我正在更改我的应用程序代码以支持Android 7,但在我的NotificationCompat.Builder.setSound(Uri)中传递来自FileProvider的Uri,通知不会播放任何声音,在Android 6中使用Uri.fromFile()工作正常。
I'm changing my app code for supporting Android 7, but in my NotificationCompat.Builder.setSound(Uri) passing the Uri from FileProvider the Notification don't play any sound, in Android 6 using the Uri.fromFile() worked properly.
mp3文件位于:
/ Animeflv / cache /.sounds /
/Animeflv/cache/.sounds/
这是我的通知代码:
knf.animeflv.RequestBackground
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)
This is my 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中:
In AndroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="knf.animeflv.RequestsBackground"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
provider_paths.xml:
provider_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="_.sounds" path="Animeflv/cache/.sounds/"/>
</paths>
推荐答案
以下内容来自我刚刚发布的博客文章,转载于此,因为,嘿,为什么不呢?
The following is from a blog post that I just published, reproduced here because, hey, why not?
您可以在通知上放置自定义铃声
,通过
setSound()
等方法在 NotificationCompat.Builder
上。这需要一个 Uri
和
导致Android 7.0出现问题,正如
报告的那样几个人关于
Stack Overflow 。
You can put a custom ringtone on a Notification
, via methods like
setSound()
on NotificationCompat.Builder
. This requires a Uri
, and
that causes problems on Android 7.0, as is reported by
a few people on
Stack Overflow.
如果您使用文件:
Uri
值,如果您的 targetSdkVersion
为24,则它们不再适用于Android 7.0
或更高,因为声音 Uri
被检查
是否符合禁止文件:
Uri
值。
If you were using file:
Uri
values, they no longer work on Android 7.0
if your targetSdkVersion
is 24 or higher, as the sound Uri
is checked
for compliance with the ban on file:
Uri
values.
但是,如果您尝试内容:
Uri
来自,例如, FileProvider
,你的
声音将无法播放...因为Android没有读取权限
内容。
However, if you try a content:
Uri
from, say, FileProvider
, your
sound will not be played... because Android does not have read access to that
content.
以下是解决此问题的一些方法。
Here are some options for addressing this.
手术刀: grantUriPermissions()
The Scalpel: grantUriPermissions()
您始终可以通过 grantUriPermissions()
,$ b $向其他应用授予内容权限ba方法上下文
。挑战在于知道谁 b b b授予权限。
You can always grant permissions for content to other apps via grantUriPermissions()
,
a method available on Context
. The challenge is in knowing who to
grant the permissions to.
什么适用于Nexus 6P(Android 6.0 ...仍然......)和Nexus 9(Android 7.0)是:
What works on a Nexus 6P (Android 6.0... still...) and a Nexus 9 (Android 7.0) is:
grantUriPermission("com.android.systemui", sound,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
(其中声音
是 Uri
您使用 setSound()
)
是否这是将支持所有设备和所有Android操作系统版本,
我不能说。
Whether this will hold up for all devices and all Android OS versions, I cannot say.
断头台:没有更多用户文件
android.resource
因为方案适用于 Uri
的值setSound()
。
而不是允许用户从文件中选择他们自己的铃声,
你只允许他们选择你在应用中输出
作为原始资源的几个铃声之一。但是,如果这代表了app
功能的损失,那么您的用户可能会感到不满意。
android.resource
as a scheme works fine for Uri
values for setSound()
.
Instead of allowing users to choose their own ringtone from a file,
you only allow them to choose one of several ringtones that you ship
as raw resources in your app. If this represents a loss of app
functionality, though, your users may be unimpressed.
Ax:使用自定义 ContentProvider
The Axe: Use a Custom ContentProvider
FileProvider
在导出时无法使用&mdash ;它在
启动时崩溃了。但是,对于这种情况,唯一的内容:
Uri
这将是
工作没有其他问题是一个提供者是导出
而
没有读访问权限(或者恰好需要一些权限
com.android.systemui
或等价物碰巧持有)。
FileProvider
cannot be used when it is exported — it crashes on
startup. However, for this case, the only content:
Uri
that will
work without other issues is one where the provider is exported
and
has no read access permissions (or happens to require some permission that
com.android.systemui
or the equivalent happens to hold).
最后,我会将此选项添加到
我的 StreamProvider
,因为
部分是只读 提供商功能。
Eventually, I'll add options for this to
my StreamProvider
, as
part of some "read only" provider functionality.
但是,您可以为此推出自己的提供商。
But, you could roll your own provider for this.
电锯:禁止禁令
以下代码段会阻止与
相关的所有 StrictMode
检查VM行为(即主应用程序线程行为以外的东西),
包括禁止文件:
Uri
值:
The following code snippet blocks all StrictMode
checks related to
VM behavior (i.e., stuff other than main application thread behavior),
including the ban on file:
Uri
values:
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
或者,您可以配置自己的 VmPolicy
无论你想要什么
规则,只需不用调用 detectFileUriExposure()
。
Alternatively, you could configure your own VmPolicy
with whatever
rules you want, just without calling detectFileUriExposure()
.
这允许你使用 file:
Uri
值在任何地方。谷歌禁止文件有很好的
原因: Uri
,所以试图避免
禁令可能会在长期内咬你不幸的身体部位。
This allows you to use file:
Uri
values anywhere. There are good
reasons why Google is banning the file:
Uri
, and so trying to avoid
the ban may bite you in unfortunate body parts in the long term.
The Nuke:使用较低的 targetSdkVersion
The Nuke: Use a Lower targetSdkVersion
这也取消了对文件的禁令:
Uri
值以及24+的 targetSdkVersion
选择加入的所有其他
行为。值得注意的是,这将是
导致您的应用显示可能无法使用分屏 Toast
如果用户输入分屏多功能-window模式。
This also removes the ban on file:
Uri
values, along with all other
behavior that a targetSdkVersion
of 24+ opts into. Of note, this will
cause your app to display a "may not work with split-screen" Toast
if the user enters split-screen multi-window mode.
真正的解决方案:Android中的修复
NotificationManager
应该为我们调用 grantUriPermissions()
,或者应该有其他方式让我们来使用我们用于自定义
的
听起来。 Uri
关联
FLAG_GRANT_READ_URI_PERMISSION
通知
敬请期待进一步的发展。
The NotificationManager
should be calling grantUriPermissions()
for us, or there should be some other way for us to associate
FLAG_GRANT_READ_URI_PERMISSION
with the Uri
that we use for custom
Notification
sounds.
Stay tuned for further developments.
这篇关于来自File Provider Uri的Android 7.0 Notification Sound无法播放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!