Control audio playing in background android - android

Can I provide play / pause / next and previous control for audio playing in background?
my app play stream audio in Asynck class which make the audio play in background.
I want to allow user to control that playing as in iPhone control center or as music player of samsung devices
plz , help find what I'm looking for
I used the code on section Use Hardware Playback Control Keys to Control Your App’s Audio Playback in doc , but nothing work with me
set up the receiver
<receiver android:name=".RemoteControlReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
public class RemoteControlReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()) {
// Handle key press.
}
}
}
}
but registering the RemoteControl is not accepted by code
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
am.registerMediaButtonEventReceiver(RemoteControlReceiver);
thanks in advance

Related

Android API 31 media button detection using MediaSession .setCallback .setMediaButtonBroadcastReceiver and BroadcastReceiver

Android API 31 supports at least three different methods claiming to handle media buttons. Despite multiple attempts I have not managed to get any of them to detect a button press on a connected audio headset
Can anyone suggest how to receive button presses on a connected audio headset in Android API 31+?
The API 31+ restriction arises because I am using mediaRecorder to record the audio stream from the headset
The latest three methods I have attempted to use are described below
MediaSession.setCallback is described as "Set the callback to receive updates for the MediaSession. This includes media button events and transport controls."
mediaSession = MediaSession(this, packageName)
mediaSession.setCallback(object : MediaSession.Callback() {
override fun onMediaButtonEvent(mediaButtonIntent: Intent): Boolean {
Log.d(TAG, "mediaSession.callback ${mediaButtonIntent.action}")
return super.onMediaButtonEvent(mediaButtonIntent)
}
})
MediaSession.setMediaButtonBroadcastReceiver is described as "Set the component name of the manifest-declared android.content.BroadcastReceiver class that should receive media buttons"
val componentName = ComponentName(this, "HeadsetMediaButtonReceiver()")
mediaSession.setMediaButtonBroadcastReceiver(componentName)
With the associated MediaButtonReceiver:
class HeadsetMediaButtonReceiver : MediaButtonReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.d(TAG, "HeadsetMediaButtonReceiver() - ${intent?.action}")
}
}
and the receiver field in the Manifest
<receiver android:name=".MainActivity$HeadsetMediaButtonReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
The generic BroadcastReceiver
registerReceiver(HeadsetMediaButtonBroadcastReceiver(), IntentFilter(Intent.ACTION_MEDIA_BUTTON))
To test the above three methods I connect to a Bluetooth headset and use mediaRecorder to record the audio. During the recording I press the headset call button but nothing is logged
The generic BroadcastReceiver is fired using sendBroadcast(), but the two MediaSession button handlers do nothing (even if I only enable one)
findViewById(R.id.send_event_button).setOnClickListener {
sendBroadcast(Intent("android.intent.action.MEDIA_BUTTON"))
}

Send Extra data on Audio Manager object to ensure android.media.RINGER_MODE_CHANGED Action Receiver receives this information

I have a Broadcast Receiver that listens to Ringer mode change action as follows:
public class RingerModeStateChangeReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("RECEIVER", "Ringer Change detected.");
}
}
The manifest declaration is as follows:
<receiver android:name=".receivers.RingerModeStateChangeReceiver" >
<intent-filter>
<action android:name="android.media.RINGER_MODE_CHANGED" />
</intent-filter>
</receiver>
My app changes the Ringer mode by making use of Audio Manager as shown below:
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if(someCondition) {
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
} else {
audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
}
Is there a way to detect the ringer change to be coming from Audio Manager(may be by adding some extra content to the audio manager object) in my broadcast receiver?
UPDATE:
I have solved this problem by making use of 2 boolean variables, one representing the updates made to RINGER by some external force and the other representing the updates made by my code. The former is true by default and the later false. The later becomes true only when the update to Ringer is about to be made by my code.
This allows the broadcast receiver to differentiate between external and internal changes made to the RINGER.
Although, this still is a workaround and I am still nowhere close to finding a solution internal to the android system (if at all one does exist).

Release WAKELOCK when screen is off

I'm making an Android TV and Amazon Fire TV app that uses WAKELOCK to prevent the TV device from going to sleep. What I need to do though is release the WAKELOCK when the screen gets turned off, e.g. when someone presses the power button on the TV, as in this case the Amazon Fire TV Stick etc stay active although the TV is powered off.
I then need to re-add the WAKELOCK when the TV is powered on. What is the accepted best practice for handling this?
EDIT: as per comment I'm updating this response with the most effective method.
In a nutshell you can achieve this in two ways:
Check if the HDMI gets disconnected (mainly works on phones, keep reading for TV)
Check if the audio channel becomes noisy. As per Android documentation (https://developer.android.com/guide/topics/media/mediaplayer.html#noisyintent) you can do something like the following (change with ):
"You can ensure your app stops playing music in these situations by handling the ACTION_AUDIO_BECOMING_NOISY intent, for which you can register a receiver by adding the following to your manifest:
<receiver android:name=".MusicIntentReceiver">
<intent-filter>
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
</intent-filter>
</receiver>
This registers the MusicIntentReceiver class as a broadcast receiver for that intent. You should then implement this class:
public class MusicIntentReceiver extends android.content.BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().equals(
android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
// signal your service to stop playback
// (via an Intent, for instance)
}
}
}

How can we disable the start of music player in android phone , when headset button is pressed?

In some of the Samsung galaxy mobile, when we press the headset button, the Music player is started. I want to disable this functionality. On pressing the headset button, I want to do another task.
How can I achieve this?
The Intent.ACTION_MEDIA_BUTTON is received only in My application and music player should not receive the inten. So that the music player is not started and I will do what I wanted to do in my application.
bit late but this can be useful for others.
In manifest file set your intent filter priority to "high" (android:priority). I think highest possible value by documentation is 999.
<receiver android:name="media_button">
<intent-filter android:priority="999">
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
Then in your receiver code abort broadcast to other intents. You can do this by calling abortBroadcast() function.
public class media_button extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
//your code ...
//abort other actions
this.abortBroadcast();
}
}
}

Android setStreamVolume for STREAM_RING doesn't always work while RINGING

I am trying to do this simple App that allows the phone to ring but not to play a sound when receiving notifications under Android 4 (ICS). In order to do that I set the ring/notification stream to 0 (mute). When receiving a call I set the ring volume to max (p.e. 7) and then, on Idle, I turn it back to 0 (mute).
To do that I use this simple code.
public class ReceiverClass extends BroadcastReceiver
{
#Override public void onReceive(Context context, Intent intent)
{
if ("android.intent.action.PHONE_STATE".equals(intent.getAction()))
{ String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
AudioManager amanager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (TelephonyManager.EXTRA_STATE_IDLE.equals(state))
{ amanager.setStreamVolume(AudioManager.STREAM_RING, 0, 0);
}
else if (TelephonyManager.EXTRA_STATE_RINGING.equals(state))
{ amanager.setStreamVolume(AudioManager.STREAM_RING, 7, 0);
}
}
}
}
The problem is that it sometime works and it sometime doesn't. I cannot find a reason. I call myself ten times and the ring sounds maybe 6. The other 4 were muted. strange??
I understand that my application could take "too long" to call setStreamVolume to 7 so maybe that is way sometimes gets on time (and sounds) and sometimes it is too late (so it doesn't sound) because the call already started with 0 volume. So, is there a way to restart the ringing sound? Could anybody help me with this? Thanks.
I must say you should try giving your Broadcast Receiver high priority. which can be done like below
<intent-filter android:priority="1000">
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
refer the link >>
Highest priority
It can/may solve your problem.

Categories

Resources