为什么两种构建资源URI的方式在Android中给出不同的结果?

Why do two ways of building resource URI give different results in Android?

我正在尝试播放通知中的声音,所以我有这样的代码

Notification notification = new NotificationCompat.Builder(context)
        .setSound(uri)
        // ... more builder options
        .build();

我尝试了两种不同的构建 uri 的方法。第一个是

Uri uri = Uri.parse(String.format("android.resource://%s/%d",
                                  context.getPackageName(),
                                  resourceId));

第二个是

Uri uri = new Uri.Builder().scheme("android.resource")
                           .path("//")
                           .appendPath(context.getPackageName())
                           .appendPath(Integer.toString(resourceId))
                           .build();

如果我打印由这些技术中的每一种生成的 uris,我会得到一个相同的字符串:

android.resource://com.example.notification/2130968576

但是,当我使用第一种技术时会播放声音,而当我使用第二种技术时不会播放。这是为什么?

我在 Android 4.3 和 Android 4.4 上使用 v4 支持库观察到了这种行为。

您必须在您的 uri 中设置正确的权限,而不是在前面加上 //:

Uri uri = new Uri.Builder().scheme("android.resource")
                       .authority(context.getPackageName())
                       .path(Integer.toString(resourceId))
                       .build();

我承认这很令人困惑,因为这两种方法 return 相同的字符串并且比较相等,但这就是为我修复它的原因。