来自File Provider Uri的Android 7.0 Notification Sound无法播放 [英] Android 7.0 Notification Sound from File Provider Uri not playing

查看:194
本文介绍了来自File Provider Uri的Android 7.0 Notification Sound无法播放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在更改我的应用程序代码以支持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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆