Android 7.0 来自文件提供程序 Uri 的通知声音未播放
Android 7.0 Notification Sound from File Provider Uri not playing
我正在更改我的应用程序代码以支持 Android 7,但是在我的 NotificationCompat.Builder.setSound(Uri) 从 FileProvider 传递 Uri 时,通知不播放任何声音,在 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
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:
<?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>
以下内容来自a blog post,我刚刚发表,转载于此,因为,嘿,为什么不呢?
您可以通过以下方法将自定义铃声放在 Notification
上
setSound()
在 NotificationCompat.Builder
上。这需要 Uri
,并且
这会导致 Android 7.0 出现问题,据报道
a few people 上
Stack Overflow.
如果您使用的是 file:
Uri
值,它们不再适用于 Android 7.0
如果您的 targetSdkVersion
是 24 或更高,因为声音 Uri
被选中
遵守 the ban on file:
Uri
values.
但是,如果您尝试 content:
Uri
来自 FileProvider
,您的
不会播放声音...因为 Android 没有读取权限
内容。
这里有一些解决这个问题的方法。
手术刀:grantUriPermissions()
您始终可以通过 grantUriPermissions()
向其他应用授予内容权限,
Context
上可用的方法。挑战在于了解谁
授予权限。
适用于 Nexus 6P(Android 6.0...仍然...)和 Nexus 9(Android7.0)的是:
grantUriPermission("com.android.systemui", sound,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
(其中 sound
是您与 setSound()
一起使用的 Uri
)
这是否适用于所有设备和所有 Android OS 版本,
我不能说。
The Guillotine:没有更多的用户文件
android.resource
作为一种方案适用于 setSound()
的 Uri
值。
不再允许用户从文件中选择自己的铃声,
您只允许他们选择您提供的几种铃声之一
作为您应用中的原始资源。如果这表示应用丢失
功能,但是,您的用户可能不为所动。
斧头:使用自定义 ContentProvider
FileProvider
导出时无法使用 - 它会崩溃
启动。但是,对于这种情况,唯一的 content:
Uri
没有其他问题的工作是提供者 exported
和
没有读取访问权限(或恰好需要一些权限
com.android.systemui
或等价物正好成立)。
最后,我会为此添加选项
my StreamProvider
, 作为
"read only" 提供程序功能的一部分。
但是,您可以为此推出自己的提供商。
The Chainsaw: Ban the Ban
以下代码片段阻止所有 StrictMode
检查相关
VM 行为(即主应用程序线程行为以外的东西),
包括对 file:
Uri
值的禁令:
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
或者,您可以配置自己的 VmPolicy
您想要的规则,无需调用 detectFileUriExposure()
.
这允许您在任何地方使用 file:
Uri
值。有好的
Google 禁止 file:
Uri
并试图避免的原因
从长远来看,该禁令可能会在不幸的 body 部分咬到你。
The Nuke:使用较低的 targetSdkVersion
这也删除了对 file:
Uri
值以及所有其他值的禁令
24 岁以上的 targetSdkVersion
选择加入的行为。值得注意的是,这将
让您的应用显示 "may not work with split-screen" Toast
如果用户进入 split-screen multi-window 模式。
真正的解决方案:Android
中的修复
NotificationManager
应该调用 grantUriPermissions()
对我们来说,或者应该有一些其他的方式让我们联系
FLAG_GRANT_READ_URI_PERMISSION
和我们用于自定义的 Uri
Notification
声音。
Stay tuned for further developments.
我正在更改我的应用程序代码以支持 Android 7,但是在我的 NotificationCompat.Builder.setSound(Uri) 从 FileProvider 传递 Uri 时,通知不播放任何声音,在 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
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:
<?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>
以下内容来自a blog post,我刚刚发表,转载于此,因为,嘿,为什么不呢?
您可以通过以下方法将自定义铃声放在 Notification
上
setSound()
在 NotificationCompat.Builder
上。这需要 Uri
,并且
这会导致 Android 7.0 出现问题,据报道
a few people 上
Stack Overflow.
如果您使用的是 file:
Uri
值,它们不再适用于 Android 7.0
如果您的 targetSdkVersion
是 24 或更高,因为声音 Uri
被选中
遵守 the ban on file:
Uri
values.
但是,如果您尝试 content:
Uri
来自 FileProvider
,您的
不会播放声音...因为 Android 没有读取权限
内容。
这里有一些解决这个问题的方法。
手术刀:grantUriPermissions()
您始终可以通过 grantUriPermissions()
向其他应用授予内容权限,
Context
上可用的方法。挑战在于了解谁
授予权限。
适用于 Nexus 6P(Android 6.0...仍然...)和 Nexus 9(Android7.0)的是:
grantUriPermission("com.android.systemui", sound,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
(其中 sound
是您与 setSound()
一起使用的 Uri
)
这是否适用于所有设备和所有 Android OS 版本, 我不能说。
The Guillotine:没有更多的用户文件
android.resource
作为一种方案适用于 setSound()
的 Uri
值。
不再允许用户从文件中选择自己的铃声,
您只允许他们选择您提供的几种铃声之一
作为您应用中的原始资源。如果这表示应用丢失
功能,但是,您的用户可能不为所动。
斧头:使用自定义 ContentProvider
FileProvider
导出时无法使用 - 它会崩溃
启动。但是,对于这种情况,唯一的 content:
Uri
没有其他问题的工作是提供者 exported
和
没有读取访问权限(或恰好需要一些权限
com.android.systemui
或等价物正好成立)。
最后,我会为此添加选项
my StreamProvider
, 作为
"read only" 提供程序功能的一部分。
但是,您可以为此推出自己的提供商。
The Chainsaw: Ban the Ban
以下代码片段阻止所有 StrictMode
检查相关
VM 行为(即主应用程序线程行为以外的东西),
包括对 file:
Uri
值的禁令:
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
或者,您可以配置自己的 VmPolicy
您想要的规则,无需调用 detectFileUriExposure()
.
这允许您在任何地方使用 file:
Uri
值。有好的
Google 禁止 file:
Uri
并试图避免的原因
从长远来看,该禁令可能会在不幸的 body 部分咬到你。
The Nuke:使用较低的 targetSdkVersion
这也删除了对 file:
Uri
值以及所有其他值的禁令
24 岁以上的 targetSdkVersion
选择加入的行为。值得注意的是,这将
让您的应用显示 "may not work with split-screen" Toast
如果用户进入 split-screen multi-window 模式。
真正的解决方案:Android
中的修复NotificationManager
应该调用 grantUriPermissions()
对我们来说,或者应该有一些其他的方式让我们联系
FLAG_GRANT_READ_URI_PERMISSION
和我们用于自定义的 Uri
Notification
声音。
Stay tuned for further developments.