I am trying to get System ring volume change using the content Observer. Using this volume integer number I would like trigger another java file.
I succeeded using the below code but the problem is I am getting two logs always. I am trying to differentiate the previousVolume and ChangedVolume. I am not why am I getting to logs inside change method? Good thing about this is that the values are not changing?
Here is the code I have tried:
public class VolumeChecker extends ContentObserver
{
int previousVolume;
Context context;
public VolumeChecker(Context c, Handler handler)
{
super(handler);
context=c;
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
previousVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC);
}
#Override
public boolean deliverSelfNotifications()
{
return super.deliverSelfNotifications();
}
#Override
public void onChange(boolean selfChange)
{
super.onChange(selfChange);
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int currentVolume = audio.getStreamVolume(AudioManager.STREAM_RING);
Log.e("changed", "Volume"+currentVolume);
}
}
And registering the obersever -from service as:
Volume = new VolumeChecker(this,new handler());
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, Volume );
Does anybody know why it is logging twice inside onChange part?
Related
This is what the file says, but I can't fully understand.
/* modes for setMode/getMode/setRoute/getRoute */
/**
* Audio harware modes.
*/
/**
* Invalid audio mode.
*/
public static final int MODE_INVALID = AudioSystem.MODE_INVALID;
/**
* Current audio mode. Used to apply audio routing to current mode.
*/
public static final int MODE_CURRENT = AudioSystem.MODE_CURRENT;
/**
* Normal audio mode: not ringing and no call established.
*/
public static final int MODE_NORMAL = AudioSystem.MODE_NORMAL;
/**
* Ringing audio mode. An incoming is being signaled.
*/
public static final int MODE_RINGTONE = AudioSystem.MODE_RINGTONE;
/**
* In call audio mode. A telephony call is established.
*/
public static final int MODE_IN_CALL = AudioSystem.MODE_IN_CALL;
/**
* In communication audio mode. An audio/video chat or VoIP call is established.
*/
public static final int MODE_IN_COMMUNICATION = AudioSystem.MODE_IN_COMMUNICATION;
/**
* Call screening in progress. Call is connected and audio is accessible to call
* screening applications but other audio use cases are still possible.
*/
public static final int MODE_CALL_SCREENING = AudioSystem.MODE_CALL_SCREENING;
Could you please explain them with examples?
At the moment, I use video chat service on WebView and I get MODE_CALL_SCREENING, it uses media volume, It should use 'calling' volume. How can I force it?
MODE_IN_CALL
You are talking to someone over audio only call (normal telephone call)
MODE_IN_COMMUNICATION
you are video & audio chatting with your friend or calling them on VoIP
MODE_CALL_SCREENING
your phone is ringing and you are checking then number before you answer the phone
The mode parameter is defined in the AudioSystem class to set the state of the phone
MODE_IN_CALL: Incoming call mode. A phone call is established.
Constant Value: 2 (0x00000002)
public static final int MODE_IN_CALL
private void setAudioNormal() {
AudioManager audioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setSpeakerphoneOn(false);
}
}
Another example
import android.media.AudioManager;
public void startOutgoingRinger(OutgoingRinger.Type type) {
AudioManager audioManager = ServiceUtil.getAudioManager(context);
audioManager.setMicrophoneMute(false);
if (type == OutgoingRinger.Type.SONAR) {
audioManager.setSpeakerphoneOn(false);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
} else {
audioManager.setMode(AudioManager.MODE_IN_CALL);
}
outgoingRinger.start(type);
}
MODE_IN_COMMUNICATION: In communication audio mode. An audio/video chat or VoIP communications are established.
Constant Value: 3 (0x00000003)
public static final int MODE_IN_COMMUNICATION
private void chooseVoiceMode() {
AudioManager audioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
if(mAudioConfiguration.aec) {
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.setSpeakerphoneOn(true);
} else {
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setSpeakerphoneOn(false);
}
}
MODE_CALL_SCREENING: Call screening in progress. There is a call connected but the audio is not in use.
Call screening: It is the process of identifying an incoming caller, giving information about the caller, and determining how best to respond to that call.
Constant Value: 4 (0x00000004)
public static final int MODE_CALL_SCREENING
public int getMode() {
final IAudioService service = getService();
try {
int mode = service.getMode();
int sdk;
try {
sdk = getContext().getApplicationInfo().targetSdkVersion;
} catch (NullPointerException e) {
// some tests don't have a Context
sdk = Build.VERSION.SDK_INT;
}
if (mode == MODE_CALL_SCREENING && sdk <= Build.VERSION_CODES.Q) {
mode = MODE_IN_CALL;
}
return mode;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
Click here For more examples
I need my in-app volume seekbar to change the volume of the audio in my app only. I need it to be totally separate from the main volume of the device. Everything I find changes the device volume when I change the slider in my app.
I want users to have the option of playing audio in my app at a low volume, but maybe still have their device turned up so phone calls and alarms and such could still be at their normal high volume.
How can I make a seekbar in my app only control audio in my app and not bother other device volumes? Here is the code I am using:
Called in onCreate method:
VolumeControls();
Outside of that:
private void VolumeControls() {
final TextView txtView = (TextView)findViewById(R.id.textView1);
SeekBar seekBar = (SeekBar)findViewById(R.id.sbVolume);
final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
seekBar.setMax(audioManager
.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
seekBar.setProgress(audioManager
.getStreamVolume(AudioManager.STREAM_MUSIC));
txtView.setText(String.valueOf(audioManager
.getStreamVolume(AudioManager.STREAM_MUSIC)));
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onStopTrackingTouch(SeekBar arg0){
}
public void onStartTrackingTouch(SeekBar arg0){
}
public void onProgressChanged(SeekBar arg0, int progress, boolean arg2)
{
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
progress, 0);
txtView.setText(String.valueOf(progress));
}
});
}
I am developing an app which needs to listen volume keys down and up events to do something.When the screen is bright,i can override onKeyDown and oneKeyUp methods.But if the phone is locked,this method is no possible to work out. I want to know how can i achieve it after the phone locked?
You can use a SettingsObserver to catch volume change as a backup solution :
SettingsObserver audioObserver = new SettingsObserver(context, new Handler());
And for the settings observer :
public class SettingsObserver extends ContentObserver {
/**
* Application context
*/
private Context context = null;
/**
* build SettingsObserver
*
* #param context retrieve application context to look for Audio Manager service
* #param handler The handler to run {#link #onChange} on, or null if none.
*/
public SettingsObserver(Context context, Handler handler, DroidEvent manager) {
super(handler);
this.context = context;
}
#Override
public boolean deliverSelfNotifications() {
return super.deliverSelfNotifications();
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (audio != null) {
byte newVolumeMedia = (byte) audio.getStreamVolume(AudioManager.STREAM_MUSIC);
byte newVolumeSystem = (byte) audio.getStreamVolume(AudioManager.STREAM_SYSTEM);
byte newVolumeRing = (byte) audio.getStreamVolume(AudioManager.STREAM_RING);
byte newVolumeNotification = (byte) audio.getStreamVolume(AudioManager.STREAM_NOTIFICATION);
byte newVolumeDtmf = (byte) audio.getStreamVolume(AudioManager.STREAM_DTMF);
byte newVolumeVoiceCall = (byte) audio.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
}
}
}
And register your ContentObserver :
context.getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, audioObserver);
This way you can retrieve all type of volume event which will make you know that volume key has been pressed up or down
I wrote this piece of code, it's obviously flawed. How do I go about creating a service which will constantly check for changes in volume? Key listeners cannot be used in services, please don't post an answer with volume key listeners.
My code is wrong because I've given dummy condition for the while loop. What has to be the condition for my service to check for volume change and not crash? It can't be isScreenOn() because volume can be changed while listening to music and the screen is off.
CODE
AudioManager audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int currentVolume = audio.getStreamVolume(AudioManager.STREAM_RING);
int newVolume=0;
while(1==1)
{
newVolume = audio.getStreamVolume(AudioManager.STREAM_RING);
if(currentVolume!=newVolume)
{
Toast.makeText(this, "Volume change detected!", Toast.LENGTH_LONG).show();
}
}
If you want to see when the setting changes, you can register a ContentObserver with the settings provider to monitor it. For example, this is the observer in the settings app:
private ContentObserver mVolumeObserver = new ContentObserver(mHandler) {
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
if (mSeekBar != null && mAudioManager != null) {
int volume = mAudioManager.getStreamVolume(mStreamType);
mSeekBar.setProgress(volume);
}
}
};
And it is registered to observer the settings like this:
import android.provider.Settings;
import android.provider.Settings.System;
mContext.getContentResolver().registerContentObserver(
System.getUriFor(System.VOLUME_SETTINGS[mStreamType]),
false, mVolumeObserver);
I made an Audio-Player and I need to pause it when the user launches google Voice Search.
I just tried 2 ways, but all failed
Write an receiver to receive broadcast action intent
"android.speech.action.RECOGNIZE_SPEECH", but it doesn't work at all, can not receive callback from Voice Search.
Write a service to get SpeechRecognizer, as following, (partial of my codes)
code:
public class VoiceSearchMonitor extends Service
{
#Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate()
{
// Get SpeechRecognizer
SpeechRecognizer recognizer = SpeechRecognizer.createSpeechRecognizer(context);
// Create a new RecognitionListener
RecognitionListener listener = new RecognitionListener()
{
#Override
public void onReadyForSpeech(Bundle params)
{
// *** I want to pause my audio here ***
}
#Override
public void onEndOfSpeech()
{
// *** I want to resume my audio here ***
}
}
// make an intent
Intent intent = new Intent("android.speech.action.RECOGNIZE_SPEECH");
// Start listening
recognizer.setRecognitionListener(listener);
recognizer.startListening(intent);
}
}
Just can not receive the callback onReadyForSpeech, 'onEndOfSpeech' after I launch Voice Search, so there's no way for me to pause my audio. I just wonder if there is a way to get SpeechRecognizer instance of google's Voice Search, so that I can get the callback correctly??
Does anyone know the answer to my question? Thanks for helping!!!
Joy
I took the same route initially for this issue, but the solution is to use the AudioManager rather than the SpeechRecognizer.
Our app was already using a custom listener for AudioManager.OnAudioFocusChangeListener and was correctly responding to the AUDIOFOCUS_GAIN and AUDIOFOCUS_LOSS states. It turns out that the voice search triggers an AUDIOFOCUS_LOSS_TRANSIENT state, so adding that to the change listener resulted in playback being paused while the voice search was performed.
To summarize:
Create the listener
AudioManager.OnAudioFocusChangeListener audioFocusListener =
new AudioManager.OnAudioFocusChangeListener() {
#Override
public void onAudioFocusChange(int focusChange) {
Logging.d(TAG, "audiofocus change");
if(focusChange == AudioManager.AUDIOFOCUS_LOSS || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT)
suspendPlayback();
if(focusChange == AudioManager.AUDIOFOCUS_GAIN)
resumePlayback();
}
};
Get the AudioManager, request focus, and pass the listener
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(audioFocusListener, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);