从资产文件夹设置通知声音

24

我将声音文件附加到资产文件夹中以便在通知中播放声音,但无法从资产文件夹中播放声音。

我有一个设置页面,用户可以在其中为通知设置声音,并且还可以播放声音。这部分已经完成。我能够使用媒体播放器从资产文件夹中播放声音。我可以在创建通知时使用相同的逻辑,但当用户单击通知时可能会出现问题,因为媒体播放器仍在播放声音。

我尝试过

notification.sound = Uri.parse("file:///android_asset/Sound/Long/AlarmClock.mp3");

也尝试过这样

notification.sound = Uri.parse("android_asset/Sound/Long/AlarmClock.mp3");

但我的问题仍未解决。

是否有其他将通知声音设置为资产目录中的方式?

Logcat

01-10 09:57:01.509: ERROR/PlayerDriver(31): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
01-10 09:57:01.509: ERROR/MediaPlayer(52): error (1, -4)
01-10 09:57:01.519: WARN/NotificationService(52): error loading sound for android_asset/Sound/Long/audio.mp3
01-10 09:57:01.519: WARN/NotificationService(52): java.io.IOException: Prepare failed.: status=0x1
01-10 09:57:01.519: WARN/NotificationService(52):     at android.media.MediaPlayer.prepare(Native Method)
01-10 09:57:01.519: WARN/NotificationService(52):     at android.media.AsyncPlayer.startSound(AsyncPlayer.java:64)
01-10 09:57:01.519: WARN/NotificationService(52):     at android.media.AsyncPlayer.access$200(AsyncPlayer.java:33)
01-10 09:57:01.519: WARN/NotificationService(52):     at android.media.AsyncPlayer$Thread.run(AsyncPlayer.java:99)
01-10 09:57:01.519: WARN/PlayerDriver(31): PVMFInfoErrorHandlingComplete

还有其他想法吗?请给我提示。

6个回答

39

将您的MP3文件放入res->raw文件夹,尝试从raw文件夹中提取声音文件。

Uri path = Uri.parse("android.resource://com.androidbook.samplevideo/" + R.raw.myvideo);

或者

Uri path = Uri.parse("android.resource://com.androidbook.samplevideo/raw/myvideo");

是的,创建内容提供程序以访问内部文件是一个很好的想法。 - Dharmendra
3
注意,我发现声音必须是 .mp3 格式才能正常工作,不是像其他声音文件一样的 .ogg 格式。并且,就像上面 rajpara 展示的那样,似乎也需要不包括扩展名。因此,我项目中 myproject/res/raw 文件夹中的 push.mp3 声音文件可以这样工作:android.resource://com.mycompany.myapp/raw/push - leontx
请告诉我如何编写代码将此Uri设置为铃声、通知和闹钟。我没有找到相关的内容。 - Zia Ur Rahman
2
如果资源ID发生更改,则引用R.raw.myvideo的第一种方法将停止工作,因为通知渠道永远不允许您更改声音/路径。请参阅此帖子:https://dev59.com/H7Lma4cB1Zd3GeqPUAGG#54796493 - Steve Strates
1
无法强调得足够多:如果您正在使用此方案生成用于与“NotificationChannel”一起使用的声音URI,请注意资源ID可能会在构建之间更改。而且,由于您无法编辑与给定“NotificationChannel”关联的URI(一旦已建立),因此这将导致您的应用程序通知声音在更新后随机中断。请改用此模式;避免使用整数资源ID。 - greeble31

8

这对我来说非常有效。我在另一篇帖子上找到了它。

notification.sound = Uri.parse("android.resource://my.package.name/raw/notification");

您的Uri表明您正在访问资源文件夹,而不是从资产中访问。您正在引用资源内行文件夹中的文件。 - Dharmendra
确实,将声音文件放入行文件夹并引用该文件是很好的做法。 - Dharmendra

4

资产是该应用程序的私有资源,我认为您将无法将其设置为铃声,您需要一个可由媒体进程访问的公共文件才能设置铃声。您将不得不将文件复制到SD卡上才能将其设置为铃声。


是的,我认为你是对的。要访问私有资源,我将不得不使用内容提供程序。 - Dharmendra
问题与铃声无关。 - greeble31

0

我无法直接访问通知中的资产音频文件。

所以,我按照以下步骤进行操作,这样我就能在通知中播放音频了:

  1. 我将那些文件复制到数据目录中。
  2. 尽管数据目录对于通知声音来说是不可访问的,但我创建了一个自定义内容提供者(Content Provider),以共享现在在数据文件夹中的资源文件。
  3. 现在,在创建通知时,我将文件的Uri设置为通知声音。

通过以上步骤,我能够将自定义声音设置为通知声音。


0

从您的资产文件夹加载某些内容的正确路径是file:///android_assets/relative_path_to_your_file。请注意这里有三个斜杠。虽然我没有尝试过以这种方式设置通知声音,但我已经成功地在WebView中使用了这种方法多次,并且希望它能以同样的方式工作。


好的,让我试着用三个斜杠。 - Dharmendra

0

ContentProvider 是最好的选择。 我认为没有必要像 @Dharmendra 建议的那样将文件复制到数据目录中。 你可以直接通过 ContentProvider 访问资产文件夹。

public AssetFileDescriptor openAssetFile(Uri uri, String mode)
        throws FileNotFoundException {
    String filePart = Sound.getSoundFileName(uri);

    try {
        return getContext().getResources().getAssets().openFd(filePart + ".ogg");
    }catch(IOException e) {
        Log.d(TAG, "fail " + e.getMessage());

    }
    return null;
}

我该如何从这个AssetFileDescriptor中获取铃声呢? - wutzebaer
@wutzebaer,你可以给NotificationCompat.Builder一个声音的URI,以便在通知中播放。 在你的内容提供程序中,openAssetFile会使用此URI并返回AssetFileDescriptor以供通知播放。 http://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html - Chiatar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接