Playing sound on the alarm channel on android
Asked Answered
A

2

7

I have done a lot of googling but other's solutions are not working for me.

My goal is to play a sound on demand on the alarm channel.
(So the sound volume is adjusted by the alarm volume setting)

from this thread I build the following code

mediaPlayerScan = MediaPlayer.create(getContext(), R.raw.scan_beep);

if (Build.VERSION.SDK_INT >= 21) {
  mediaPlayerScan.setAudioAttributes(new AudioAttributes.Builder()
          .setUsage(AudioAttributes.USAGE_ALARM)
          .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
          .build());
} else {
  mediaPlayerScan.setAudioStreamType(AudioManager.STREAM_ALARM);
}

It still plays on the music channel. (IE volume is adjusted in music setting not alarm)

My intuition is that i'm missing a permission or something, but I haven't found such a permission.

I'm testing on a Google Pixel 1

Thanks,
Nathan

Edit:

Thanks to @jeffery-blattman the following code works for me

mediaPlayerScan = new MediaPlayer();
try {
  mediaPlayerScan.setDataSource(getContext(),
          Uri.parse(getString(R.string.res_path) + R.raw.scan_beep));

  if (Build.VERSION.SDK_INT >= 21) {
    mediaPlayerScan.setAudioAttributes(new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_ALARM)
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .build());
  } else {
    mediaPlayerScan.setAudioStreamType(AudioManager.STREAM_ALARM);
  }
  mediaPlayerScan.prepare();
} catch (IOException e) {
  e.printStackTrace();
}
Aeneous answered 15/6, 2018 at 19:37 Comment(1)
This might have a problem on the main thread - where is the call to mediaPlayerScan.start()? I posted an answer below with all the details. Your way of doing setDataSource is also good, but please show us what R.string.res_path looks like!Perren
A
6

The problem is that create() puts the MediaPlayer in a state where it won't accept the attributes (it calls prepare() for you). You need to use the more verbose mechanism of creating the player.

  final MediaPlayer mediaPlayer = new MediaPlayer();
  mediaPlayer.setDataSource(...);

  AudioAttributes attrs = new AudioAttributes.Builder().setUsage(usage).build();
  mediaPlayer.setAudioAttributes(attrs);

  new AsyncTask<Void,Void,Boolean>() {
    @Override
    protected Boolean doInBackground(Void... voids) {
      try {
        mediaPlayer.prepare();
        return true;
      } catch (IOException e) {
        e.printStackTrace();
      }
      return false;
    }

    @Override
    protected void onPostExecute(Boolean prepared) {
      if (prepared) {
          mediaPlayer.start();
      }
    }
  }.execute();
Astraddle answered 15/6, 2018 at 19:43 Comment(1)
whats usage hereNicknack
P
3

I upvoted Jeffrey Blattman's answer above, but here is the full code that shows how to use setDataSource with an audio file that you put into your app resources (raw). Also a couple of other things I picked up in my travels...

static public void playAlarmSound () {
    final MediaPlayer mediaPlayer = new MediaPlayer();
    new AsyncTask<Void, Void, Boolean>() {
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                    @Override
                    public void onCompletion(MediaPlayer mp) {
                        mediaPlayer.reset();
                        mediaPlayer.release();
                    }
                });
                mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        mediaPlayer.start();
                    }
                });
                AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(R.raw.nameofyourresource);
                if (afd == null) return false;
                mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
                afd.close();

                if (Build.VERSION.SDK_INT >= 21) {
                    mediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
                            .setUsage(AudioAttributes.USAGE_ALARM)
                            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                            .build());
                } else {
                    mediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
                }
                mediaPlayer.setVolume(1.0f, 1.0f);
                mediaPlayer.prepare();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }

    }.execute();
}
Perren answered 20/11, 2018 at 9:38 Comment(1)
Credit to Chris Zou for the AFD portion: his answer is here: https://mcmap.net/q/393852/-setting-data-source-to-an-raw-id-in-mediaplayerPerren

© 2022 - 2024 — McMap. All rights reserved.