Android - PhoneStateListener onCallStateChanged() not working - android

I want to implement onCallStateChanged() of PhoneStateListener and use it's functionality to change audio settings when a call is received.
private final class CallStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
Utils.log("CallStateListener");
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Utils.log("Idle");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Utils.log("OFFHOOK");
break;
case TelephonyManager.CALL_STATE_RINGING:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
if(prefs.getBoolean(Constants.PREF_OPTION_1, false)){
final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int maxStreamValue = audioManager.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION);
int volumeLevel = prefs.getInt(Constants.PREF_VOLUME_LEVEL, Constants.PREF_VOLUME_LEVEL_DEFAULT);
int volume = (int) Math.ceil(maxStreamValue * (volumeLevel / 100.0));
if(prefs.getBoolean(Constants.PREF_OPTION_3, false)){
Utils.log("Option3 true ringing");
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
Utils.changeNotificationVolume(audioManager, volume);
Utils.log("RINGING");
}
break;
}
callState = state;
}
}
I want to silent just the notifications if Option 1 and Option 3 are on, but a lots of new companies provide only one option for notifications and calls.
If Option 1 and Option 3 are on, i have set my device to SILENT MODE, but whenever a call is received i want my device to ring. Therefore in CALL_STATE_RINGING, i have my code to turn off SILENT MODE and ring the device.
This things only works sometime. After trying a lots of devices i have found out that usually this thing doesn't work on mobiles which lags a lot( are really slow).
I think this is because if audio settings are changed before mobile starts ringing this work, and if not this doesn't work even if settings are changed. Am i right? Is there any solution to this problem? Is there a way to delay ringing of android device? Or can i do something to make it work every time?

Related

Android - MIC external for speechRecognition

I need to know which event is triggered when connecting a microphone or a headset to your device, and I am using speech recognition and have observed that does not follow the same flow as when nothing is connected to the device.
I would like to know if there is some kind of solution because the application I'm creating at the moment is tested in a Smartphone, but in the future will require connecting a microphone or a headset.
A greeting and I hope your answers
PS: At the moment in the code I have nothing on external microphone or headset, but at the moment everything is running according to device microphone and speaker.
EDIT
I see the way of knowing whether the headset is connected is as follows:
private class MusicIntentReceiver extends BroadcastReceiver {
#Override public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", -1);
switch (state) {
case 0:
Log.d(TAG, "Headset is unplugged");
break;
case 1:
Log.d(TAG, "Headset is plugged");
break;
default:
Log.d(TAG, "I have no idea what the headset state is");
}
}
}
}
But how to redirect the audio input to the microphone of the headset? and the audio output to the headphone output?

Consistent graceful disconnect from Bluetooth server when receiving BluetoothAdapter.STATE_TURNING_OFF

I am having trouble disconnecting gracefully from a server when the user turns off the bluetooth. Android generates an event when that happens that you are supposed to use to send a final disconnection message to the server; before your app loses access to bluetooth functionality.
I register the event like this:
context.registerReceiver(this, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
Then I listen for the specific event:
public void onReceive(Context context, Intent intent) {
final int state =
intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_TURNING_OFF:
_bt.stop();
break;
//...
}
}
This works some times but not every time. I tried giving the thread a higher priority to see if it would help with (alternatively) both of these:
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
... but no luck. Any ideas on how to accomplish this consistently are welcome, thanks!
So, what ended up working for me is to use both priority statements and try to send the message as soon as the event is generated. This way, I consistently get a graceful disconnection from the server. This is how my code ended up looking:
public void onReceive(Context context, Intent intent) {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
final int state =
intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_TURNING_OFF:
// send disconnection message
_bt.stop();
break;
//...
}
}
Hope it helps someone else.

How to play sound when headphone connected in android programatically?

I am working on one of the project which need to play sound simultaneously when headphone is connected.
I am using below code but no luck
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_NORMAL);
am.setSpeakerphoneOn(true);
You need to use a BroadcastReceiver to handle the action sent when the headset is plugged. You need after that to check if the action sent by the broadcast equals Intent.ACTION_HEADSET_PLUG in the onReceive method, then you can play your sound using MediaPlayer
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", -1);
switch (state) {
case 0:
//Headset is unplugged
break;
case 1:
//Headset is plugged
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.song);
mediaPlayer.start();
break;
default:
Log.d(TAG, "I have no idea what the headset state is");
}
}
}
Please see this answer https://stackoverflow.com/a/13610712/2354845

AudioManager is unreliable

AudioManager is unreliable in onCallStateChanged. During a phone call I need it to turn on speaker phone and set the volume to max. It sometimes turns on speakerphone (usually during the second or later call) and rarely turns the volume up. My PhoneCallListener class is within my MainActivity class.
private class PhoneCallListener extends PhoneStateListener
{
private boolean isPhoneCalling = false;
#Override
public void onCallStateChanged(int state, String incomingNumber)
{
AudioManager aM = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
aM.setMode(AudioManager.MODE_IN_CALL);
aM.setSpeakerphoneOn(true);
if(TelephonyManager.CALL_STATE_RINGING == state)
{
//phone ringing
aM.setSpeakerphoneOn(true);
aM.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
}
if(TelephonyManager.CALL_STATE_OFFHOOK == state)
{
//phone active
aM.setSpeakerphoneOn(true);
aM.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0);
isPhoneCalling = true;
}
if(TelephonyManager.CALL_STATE_IDLE == state)
{
aM.setSpeakerphoneOn(false);
if(isPhoneCalling)
{
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
isPhoneCalling = false;
}
}
}
}
Within CALL_STATE_OFFHOOK I had to turn off AudioManager.FLAG_SHOW_UI because it would continually show the volume UI. Also, setting aM.setStreamVolume(AudioManager.STREAM_MUSIC, aM.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0); crashes the app for some reason.
Any suggestions on how to make AudioManager work every time so that speakerphone is on and volume is max during a phone call?
Edit: Even with setting speackphoneon to true as soon as the onCallStateChanged method is called, it still is not reliably turning the speakerphone on. The volume is also unreliable and can't seem to set it to max without it crashing.
Below is the code to do this. I have tested in a phone running lollipop. Write your PhoneStateListener as:
private class myPhoneStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_OFFHOOK: //Call is established
Log.d("s#urav", "Call is Offhook now!");
try {
Thread.sleep(500); //We never know when the call is actually OffHook
} catch (InterruptedException e) {
Log.d("s#urav","Exception is:"+e);
}
audioManager.setSpeakerphoneOn(true);
break;
case TelephonyManager.CALL_STATE_IDLE: //Call is finished
//Maintain a flag and do this only if speakerphone has been set on OFFHOOK
/*audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setSpeakerphoneOn(false);*/
break;
}
}
}
For raising the volume of the call you have to increase the volume of STREAM_VOICE_CALL. This code + increasing the volume of call stream will meet you requirements.

Pausing a service in background in android

I am working on an app in which I am playing media player using service. The app is working fine but when i receive a call or a message, the music keeps on playing. My requirement is when I get a call, the music should be paused and on call disconnection, it should resume from where it has stopped. How can I achieve this?
I am not sure how you coded your app but this should help you.
Check out this How to know the moment when the called person picks up his phone You would just need to pause the music in the switch statement for the specified event
TelephonyManager tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
tm.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
private PhoneStateListener mPhoneListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
try {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
// do something...
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// this state is the one you're looking for
break;
case TelephonyManager.CALL_STATE_IDLE:
// do something...
break;
default:
Log.d(TAG, "Unknown phone state=" + state);
}
} catch (RemoteException e) {}
}
};
EDIT: here is another link Detect if an outgoing call has been answered

Categories

Resources