I'm developing a Voip-Application and i have an edge case where i want to play two raw files at the same time.
When i have an incoming call from my application i am creating a new Mediaplayer and play a custom ringtone. When i get shortly after also an incoming GSM-call i create a new mediaplayer and play a knocking sound to give the user feedback that there is also a GSM-Call incoming. At the same time i want the custom ringtone to continue playing.
private fun setAudioAttributesForFile(audioUsage: Int): AudioAttributes {
return AudioAttributes.Builder()
.setUsage(audioUsage)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
}
private fun startRingtone(fileToPlay: Int): MediaPlayer {
return MediaPlayer().apply {
reset()
if (fileToPlay == R.raw.ring {
setAudioAttributes(setAudioAttributesForFile(AudioAttributes.USAGE_NOTIFICATION_RINGTONE))
} else {
setAudioAttributes(setAudioAttributesForFile(AudioAttributes.USAGE_MEDIA))
}
isLooping = true
Main.get().resources.openRawResourceFd(fileToPlay).use {
setDataSource(
it.fileDescriptor,
it.startOffset,
it.length
)
}
setOnPreparedListener { start() }
prepareAsync()
}
}
The problem that i have with this code is that as soon as the knocking sound is playing the ringtone gets muted by the system and as soon as the knocking sound is stopping the ringtone continues.
What i also tried:
Using only
AudioAttributes.USAGE_NOTIFICATION_RINGTONE. As soon as the knocking sound starts to play both mediaPlayers are getting muted.
If i leave the setAudioAttributes() call away and replace these four lines to
if (fileToPlay == R.raw.ring) {
setAudioAttributesForFile(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
} else {
setAudioAttributesForFile(AudioAttributes.USAGE_MEDIA)
}
then i can play those two files at the same time. The problem then is that the ringtone file is not shown as a ringtone instead it is only shown as a media file. So when i increase and decrease the volume of the ringtone the flag does not show that it is a ringtone.
Is there a way to play one sound as a Ringtone and another sound over it as a normal Media Sound?
Thanks in advance. Any help is appreciated.
Use sound pool if you want to play both sounds at the same time.
Related
When my character crosses a finish line, I play a "win" sound. I have an AudioSource object to which I simply call PlayOneShot and pass it my AudioClip as:
public void PlayWon() {
if (GameData.Data.Settings.SoundsOn) {
AudioSource audio = GetComponent<AudioSource>();
audio.Stop();
audio.PlayOneShot(WinSound);
}
}
My settings for the AudioSource are this:
and the object where this is attached to is loaded in a Loader scene which is never destroyed. I ensure this by calling:
DontDestroyOnLoad(this);
on Awake.
My sound plays fine on iOS, iPhone and iPads. But when testing on my Samsung Galaxy Tab S, the sound plays and then pauses whilst the interstitial advert is displayed and then when dismissed, the sound carries on. I am using Chartboost and Admob and use the basic invoke:
if (Chartboost.hasInterstitial(CBLocation.LevelComplete)) {
Debug.Log("Showing CB Ad");
Chartboost.showInterstitial(CBLocation.LevelComplete);
}
else if (_admobInterstitial.IsLoaded()) {
Debug.Log("Showing Admob Ad");
_admobInterstitial.Show();
}
else {
Debug.Log("Neither cached, trying CB again");
Chartboost.cacheInterstitial(CBLocation.LevelComplete);
Chartboost.showInterstitial(CBLocation.LevelComplete);
}
Any ideas why my sounds cut out on this device? I don't have another Android device to test it on but I'm assuming it's an Android related problem. The sound cuts out on both Chartboost and Admob.
Thanks
You can use a coroutine for playing the sound. When the coroutine is finished, you can show ads.
private IEnumerator PlaySoundAndShowAd()
{
//play sound
yield return new WaitForSeconds(1.0f)
//show ads or do something.
}
I'm developing an android application. If we have the package name of an application, could we know whether an application is playing music or recording the voice or not? I have no idea how to do that. If someone has done it, could you please help me or give me the information about it?
Thank your for your help,
public class AudioManager {
/**
* Checks whether any music is active.
*
* #return true if any music tracks are active.
*/
public boolean isMusicActive() {
return AudioSystem.isStreamActive(STREAM_MUSIC, 0);
}
}
AudioManager is what you are looking for. You can check this response: https://stackoverflow.com/a/16252044/3743245 Also the official documentation: AudioManager
And a small example of how to use it:
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
// Request audio focus for playback
int result = am.requestAudioFocus(focusChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC,
// Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// other app had stopped playing song now , so you can do your stuffs now .
}
Them you add the focusChangeListener listed in the link I've left you.
I'm developing a game. I need a button to turn on and off game sounds.
In my app, I play background music which I want to be muted upon clicking a button. Here's my code:
AudioManager aManager = (AudioManager)getSystemService(AUDIO_SERVICE);
if (aManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) {
aManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
} else {
aManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
When I debug, the conditions are right but nothing happens! The sound is never turned off!
Check for method "isVolumeFixed()". If true, your device can't have it's sound changed. Some devices have a policy about that.
I have an app with an integrated music player. I don't want the music to be interrupted by incoming calls.
I use following function for that:
public static void updateDoNotDisturbMode(boolean enabled, boolean checkPrefs)
{
...
AudioManager audioManager = ((AudioManager) MainApp.get().getSystemService(Context.AUDIO_SERVICE));
NotificationManager notificationManager = (NotificationManager) MainApp.get().getSystemService(Context.NOTIFICATION_SERVICE);
// audioManager.setMode(AudioManager.MODE_IN_CALL);
if (!enabled)
{
audioManager.setStreamSolo(AudioManager.STREAM_MUSIC, false);
audioManager.setStreamMute(AudioManager.STREAM_VOICE_CALL, false);
audioManager.setStreamMute(AudioManager.STREAM_RING, false);
audioManager.setStreamMute(AudioManager.STREAM_NOTIFICATION, false);
...
}
else
{
audioManager.setStreamSolo(AudioManager.STREAM_MUSIC, true);
audioManager.setStreamMute(AudioManager.STREAM_VOICE_CALL, true);
audioManager.setStreamMute(AudioManager.STREAM_RING, true);
audioManager.setStreamMute(AudioManager.STREAM_NOTIFICATION, true);
...
}
}
what works
silent phone if no headphones are connected
internal music player does play on without interruption if someone calls
so without headphones connected, everything works perfectly fine
what does not work
if headphones are connected, the standard beep sound is interrupting my music player and is played in the headphones
How can I avoid that incoming calls are interrupting my music player even if headphones are connected?
TARGET SDK
Only 4.2 and upwarts... (including 5)
What do you mean integrated music player? Can you change code of music app?
A player stops playing because it listens to PhoneStateChanges - void onCallEvent(int state, String number);
If you can change code of the player you should check is mute mode on within this method - if yes then do not stop playback.
If you can't change the code of player - you can use advanced player with preferences of audio focus. For example poweramp has such option. Set Settings/Audio/Audio Focus/Pause in Call to false (it works, tested right now). But you should change it manually all the time.
I have an Android application that makes use of TTS (Text to speech) API. Everything is working perfectly, but now i want to fade in/out or even stop music (in case user is playing music with prebuilt Music Player), when application speaks a text. Right now, i think both music and TTS messages are played on the same stream (MUSIC), and it can be difficult to understand the voice messages.
I've tried to play the text on a different stream, like AudioManager.STREAM_NOTIFICATIONS. It does stop the music, but doesn't come back when the text is spoken, so i didn't achieve the goal. Haven't found anything yet, so i hope someone can help here. Thanks!
I finally got something that is working. Not perfect though. A quite dirty trick. Just in case it can help to someone:
This is fixed on API 8 with requestAudioFocus and abandomAudioFocus methods of AudioManager.
But for former versions, you can try this. Play TTS through a different stream channel, let's say STREAM_NOTIFICATIONS. Then you just need to return audio focus to STREAM_MUSIC. How can you achieve that?. Sending a silence string (" ") to TTS but this time through STREAM_MUSIC. The effect will be: music is stopped, your TTS message gets spoken, and finally your music is back after the voice alert. Not nice or something to feel proud of, but... if someone knows of a different way, i will appreciate it
Here is a way of doing this in Dec-2021
TexToSpeech needs to be initialized and assigned to tts before calling this method
Method 1 (Recommended):
private void speak(String textToSay) {
AudioAttributes mPlaybackAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ASSISTANT)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
//add this below flag if you need the TTS to speak in a louder volume or TTS volume be heard for sure at any cost
//.setFlags(FLAG_AUDIBILITY_ENFORCED)
.build();
tts.setAudioAttributes(mPlaybackAttributes);
AudioFocusRequest mFocusRequest =
new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK)
.setAudioAttributes(mPlaybackAttributes)
.setAcceptsDelayedFocusGain(false)
.setWillPauseWhenDucked(false)
.build();
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.requestAudioFocus(mFocusRequest);
tts.speak(textToSay, TextToSpeech.QUEUE_FLUSH, null, textToSay);
Handler ttsSpeak = new Handler();
Runnable checkTTSRunning = new Runnable() {
#Override
public void run() {
if (tts.isSpeaking()) {
ttsSpeak.postDelayed(this, 1000);
} else am.abandonAudioFocusRequest(mFocusRequest);
}
};
ttsSpeak.postDelayed(checkTTSRunning, 3000);
}
Method 2: Use this only if you need the TTS to speak in a louder volume and/or TTS volume needs to be heard for sure at any cost
private void speak(String textToSay) {
AudioAttributes mPlaybackAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ASSISTANT)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.setFlags(FLAG_AUDIBILITY_ENFORCED) //VERY IMPORTANT
.build();
tts.setAudioAttributes(mPlaybackAttributes);
tts.speak(textToSay, TextToSpeech.QUEUE_FLUSH, null, textToSay);
}
Could you use the TextToSpeech.OnUtteranceCompletedListener along with AudioManager.setStreamVolume to achieve this?