How to setup audio session for alarm ringtones in flutter? - android

I am creating an alarm clock application, using just_audio to play the alarm ringtones and audio_session to configure the audio type. Without configuring the audio, the app uses the media volume for the audio. I want the app to tell the system that this is an alarm audio, so it uses the system alarm volume for the ringtones and play it even in DnD etc.
What I have tried
Here is the setup that I currently have:
// Configuring audio session using audio_session
final session = await AudioSession.instance;
await session.configure(const AudioSessionConfiguration(
androidAudioAttributes: AndroidAudioAttributes(
flags: AndroidAudioFlags.audibilityEnforced,
usage: AndroidAudioUsage.alarm,
),
));
// Initializing and playing the audio using just_audio
player = AudioPlayer();
await player.setAudioSource(AudioSource.uri(ringtoneUri));
await player.setLoopMode(loopMode);
player.play();
On some devices that I have tested (Android 6 and 8), it uses the phone ringtone volume, while on others (Android 11), it correctly uses the alarm volume.
What is the correct method to do it, so it uses the alarm volume on all devices?

Turns out, it was the AndroidAudioFlags.audibilityEnforced flag, which seems to be pretty unrealiable, and can cause differing behavior on different devices. Removing it causes the volume to be controlled by alarm stream volume.
Android Docs: FLAG_AUDIBILITY_ENFORCED
Working code
final session = await AudioSession.instance;
await session.configure(const AudioSessionConfiguration(
androidAudioAttributes: AndroidAudioAttributes(
usage: AndroidAudioUsage.alarm,
),
));
// Initializing and playing the audio using just_audio
player = AudioPlayer();
await player.setAudioSource(AudioSource.uri(ringtoneUri));
await player.setLoopMode(loopMode);
player.play();

Related

Is it possible to have 2 packages accessing the microphone simultaneously on Android in React Native?

I am tying to record audio from the microphone into a sound file using Expo-AV while also doing speech recognition using react-native-voice. It works as expected on iOS but on Android I can only get 1 or the other working.
import Voice from '#react-native-voice/voice';
import { Audio } from 'expo-av';
Voice.onSpeechStart = startRecording; // Gets called from Voice.start()
async function startRecording() {
// Calls expo-av recording methods to start a recording
}
...
Voice.start("en-us");
Permissions for RECORD_AUDIO is set. When I comment out the recording portion, the voice recognition events from react-native-voice start firing.

How to prevent Android from automatically vibrating on MediaPlayer playback

I have an alarm clock app and some users complain phone vibrates during alarm, while vibrations should be disabled.
After some digging I have found out, that on some devices there's a system option for device to vibrate along alarm music. For example in my test Pixel 4 it is located at Settings->Sound&Vibration->Vibration&Heptics->Alarm vibration.
What this setting, enabled by default, causes, is that vibrations try to "emulate" the music played through MediaPlayer and I cannot find a way to prevent that from happening from within the app or even detect if such setting is present/enabled.
Anyone knows how to get rid of that?
Here's a sample method I used for testing:
private fun startThePlayer(context: Context, playInLoop: Boolean = true) {
try {
mediaPlayer.reset()
mediaPlayer.isLooping = playInLoop
val uri = Settings.System.DEFAULT_RINGTONE_URI
mediaPlayer.setDataSource(context, uri)
mediaPlayer.setOnPreparedListener {
mediaPlayer.start()
}
mediaPlayer.prepareAsync()
} catch (e: Exception) {
log(e.toString())
}
}
VIBRATE permission is necessary for this to work.
Effect on Pixel 4 with Android 13:
Device is vibrating, as if trying to "emulate" the music played. Vibrations strength depends on value set in device's settings, completely ignoring volume set for alarm's music, and also messing up any vibrations set directly in my app.
What's interesting, is that for some reason Android's default clock app ignores this settings and device doesn't vibrate during it's alarms.
First, I suggest that you use android's VibratorManager to control your app vibrations settings (this is how the android development team called this service.. how bizarre). Use the getDefaultVibrator and cancel methods to stop any vibrations produced by your app (official docs to the rescue)
Second, because your app is an alarm clock please consider using the setWakeMode which will allow you to keep your app running in the background regardless to the display (in order to prevent the alarm from stopping if the screen is off). Here's the method documentation and also the PowerManager flags documentation
Hope you will find the right combination to satisfy your needs

Why is Galaxy S21 not doing custom notification sounds

I have an app that can emit custom notification sounds triggered by calendar events. This worked perfectly well on my old phone, but on my new Galaxy S21, it emits the system default notification sound instead of the custom notification sound. I tried it on the emulator with an AVD running Android 11, which is the version that the S21 claims to be running, and it works correctly. The custom sound exists on the S21 and is playable using the music player.
Android Notification sound defaulting back instead of playing custom sound is a very old question reporting a similar problem and the answer there suggested rebooting the phone, which I tried and it didn't help.
The code which emits the notification looks like this:-
private void emitNotification(String smallText, String bigText, String path) {
RemoteViews layout = new RemoteViews(
"uk.co.yahoo.p1rpp.calendartrigger",
R.layout.notification);
layout.setTextViewText(R.id.notificationtext, bigText);
DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
layout.setTextViewText(R.id.notificationtime,
df.format(System.currentTimeMillis()));
Notification.Builder NBuilder
= new Notification.Builder(this)
.setSmallIcon(R.drawable.notif_icon)
.setContentTitle(smallText)
.setContent(layout);
if ((path != null) && !path.isEmpty())
{
Uri uri = new Uri.Builder().path(path).build();
AudioAttributes.Builder ABuilder
= new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION);
NBuilder.setSound(uri, ABuilder.build());
}
// Show notification
NotificationManager notifManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notifManager.notify(notifyId++, NBuilder.build());
}
The entire source is available on GitHub at
rparkins999/CalendarTrigger branch fix3.3
I have included a built APK in the git tree if anyone would like to try it on another phone. You can also build from the sources: you will need a ../Keys/Keystore.properties file relative to the project root directory since I'm not publishing my private signing key.
To demonstrate a custom notification sound, run the program, give it all the permissions it wants, touch 'NEW EVENT CLASS', give the class a name, and touch Create: you should then see a screen consisting of buttons that invoke activities to define the characteristics of the class.
Touch 'Event starts action(s) for class ...' and you should see a screen offering various actions that the program can take (not all of which work). Touch 'Show a notification', then 'Play a sound', then 'Browse for a sound file': you should then see a file browser.
When you choose a file it will take you back to the previous screen, but 'Browse for a sound file' will have been replaced by the path to the sound file. Touch the back button to return to the screen of buttons, and then touch 'Immediate event of class ...'. It should play the sound.
On the emulator it does, but on the S21 it plays the default sound instead.
As set up, the class you created will emit a notification on every calendar event. You can stop that by deleting the class or setting some conditions for a calendar event to be in the class: there are buttons for both of these actions on the class definition screen.
I don't know whether this problem is a bug in the S21, or caused by some obscure Setting that I haven't been able to find. Any help would be appreciated, especially information as to whether the app does or doesn't work correctly on other phones running Android 11. Of course, a fix or a workaround would be better still!
I just installed the latest S21 update. Now the problem is worse! I don't get any sound at all from my notifications with custom sounds.
The problem in this particular case was the audio format in the file (.m4a). The music player on the S21 can play it, and the notification sound player in my old phone could play it, but the notification player on the S21 apparently couldn't play it.
I used FFmpeg on my PC to convert from .m4a to .mp3, which the S21 notification player can play, and it now works.
So it isn't safe to assume that if the phone can play a sound format with its music player, the Notification logic can also handle it.

Android Visualizer won't pick up audio from Spotify streaming music

I'm making an Android audio visualizer app for streaming Spotify music. I'm using Spotify's android-streaming-sdk which creates a local service (no need to have the Spotify app installed) and it plays music from within the app. I'm having a difficult time getting Androids Visualizer library to pick up any audio from Spotify (it works fine if I use a local .mp3 file).
//Start playing spotify track
player.playUri(MainActivity.operationCallback,
VisualizerModel.getInstance().getTrackURI(), 0, 0);
.... other code ....
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
int audioSessionId = mediaPlayer.getAudioSessionId();
visualizer = new Visualizer(audioSessionId);
visualizer.setCaptureSize(audioSampleSize);
visualizer.setDataCaptureListener(this, Visualizer.getMaxCaptureRate(), true, true);
visualizer.setEnabled(true);
If I run this, everything compiles and runs okay, but the visualizer does not pick up any audio. This makes me thing that the audio sessionId is not the same one as Spotify is playing on. However, if I switch the audioSessionId to 0 (which should listen to all the audio sessions mixed from what I understand) it crashes with this error:
E/AudioEffect: set(): AudioFlinger could not create effect, status: -1
E/visualizers-JNI: Visualizer initCheck failed -3
E/Visualizer-JAVA: Error code -3 when initializing Visualizer.
According to their documentation that error means: Operation failed due to bad object initialization.
I'm targetting API 24 (Android 7.0).
Please let me know if you have suggestions or an alternative to using Android's Visualizer library. I feel like my main problem is that I'm not sure how to find the audioSessionId that Spotify is playing on, and because Spotify's android-streaming-sdk is in beta (and not mentioned on their website) there is virtually no documentation on it from what I can see on Github.
Thank you for taking the time to read my issue!
I was facing the same error. Adding "android.permission.RECORD_AUDIO" to manifest and requesting for runtime permissions fixed the issue.
to protect privacy of certain audio data (e.g voice mail) the use of the visualizer requires the permission android.permission.RECORD_AUDIO
Also
Creating a Visualizer on the output mix (audio session 0) requires permission Manifest.permission.MODIFY_AUDIO_SETTINGS
Android docs for Visualizer class

Playing audio simultaneously with camera shutter sound

How do I play a sound simultaneously with the camera shutter going off?
In my application, I have an inset camera preview. It takes 3 pictures automatically after 5 seconds of the activity starting. During this time the application is receiving a range of values via Bluetooth. Everytime the values are greater than a preset threshold, the application plays a tone, which is done using MediaPlayer.
The problem is that when the camera goes off, the shutter click sound seems to take over all the audio, and the tone being played stops and only resumes after the 3 shutter clicks. I don't want to silence the camera shutter, so is there a way I can get the tone to play with shutter clicks? This is all happening in one activity.
Thanks
One possible solution would be to use the hidden ENFORCED_AUDIBLE stream type for your tones. This is the stream type that the camera shutter sound most likely will use, so it won't be muted unless the shutter sound has been muted.
Note that this stream type wasn't introduced until ICS (or maybe it was GB/HC, I can't say for sure off the top of my head), so it won't be compatible with every version of Android in existence. The integer value for this stream type identifier is 7, but if you want to check if exists / get its value programmatically you might be able to do so using reflection on the AudioSystem class.
Here's an example of how this could be done:
public static boolean mHasEnforcedStream = true;
public static int STREAM_SYSTEM_ENFORCED = 0;
...
static
{
try
{
Class asClass = Class.forName("android.media.AudioSystem");
Field sseField = asClass.getDeclaredField("STREAM_SYSTEM_ENFORCED");
STREAM_SYSTEM_ENFORCED = sseField.getInt(null);
}
catch (Exception e)
{
mHasEnforcedStream = false;
}
}
Keep in mind that if you use this stream type you'll always get your tones in the loudspeaker even if the user has e.g. a 3.5mm wired headset attached, and even if the user has put his/her phone in silent mode.
I think this is what you should need. This should contain what you need. The first link is probably more useful than the 2nd since you want to still have other sounds, though its possible you'd be able to disable the audio channel specific to the camera shuttle sounds.
Is there any way to replace or silence the camera shutter sound in android?
stop camera click sound programmatically in android
Well since I am still new to programming, I would do a google search on what files give off the camera sound, and I would put in your app to where it would rename those files with different extension so the sound would not go off and have them rename back to the original files. OR I would look on how to make the camera silent through changing the camera values. I know on my Samsung Galaxy SIII I had to change the camera file names. (sprint carrier)

Categories

Resources