I have set phoneStateListener in my app which turns the phone silent when the phone is turned upside down during an incoming call. The problem is that the phone gets silent irrespective of any condition. Here is my code-
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
TelephonyManager telephonyManager;
PhoneStateListener phoneStateListener;
telephonyManager = (TelephonyManager) this
.getSystemService(Context.TELEPHONY_SERVICE);
phoneStateListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
// callStateStr = "ringing. Incoming number is: "
// + incomingNumber;
if (z1 > -10 && z1 < -9) {//this is to detect if the phone is turned upside down or not. consider this defined.
am.setStreamVolume(AudioManager.STREAM_RING, 0,
AudioManager.FLAG_ALLOW_RINGER_MODES);
Log.d("abc", "turning silent");
Toast.makeText(getApplicationContext(), "turning silent",Toast.LENGTH_SHORT).show();
}
break;
}
}
};
During an incoming call, the code under if condition is executed whether i turn my phone or not.
What am I doing wrong? Is there any other method to achieve this purpose?
Related
I have made a sample app and the PhoneStateListener
TelephonyManager telephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object
telephony.listen(new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
Log.i("brian", "call state = " + state + " incoming number " + incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_RINGING:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
}
}
}, PhoneStateListener.LISTEN_CALL_STATE); //Register our listener with TelephonyManager
Log.i("brian", "READ_PHONE_STATE = " + ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_PHONE_STATE));
Works as expected, but when I add the above code to my much larger application the onCallStateChanged is only called when it is subscribed initially. No phone state changes are notified to me. On both projects the bottom log line "READ_PHONE_STATE = " was always granted and I'm targeting sdk 22 so no runtime permissions I think. In my larger app I have the code pasted in both the main activity and a long standing service, neither get state change events. They both work when I run my code on an android < 7.0 and I have no idea why. Don't see anything substantial in the warning or error logs.
As Vairavan mentioned in this answer, there was an internal change in how the PhoneStateListener is referenced:
Local reference to PhoneStateListener is kept track internally only by
a weak reference. This makes it eligible for garbage collection upon
function exit and once the listener is finalized, apps will not
receive any further updates. Solution is to keep a reference to
PhoneStateListener via class member variable.
See: https://github.com/aosp-mirror/platform_frameworks_base/commit/f5d7c587e86c64e657a15a12ad70e75d47c48d99#diff-5af2ac899de823cf60597e554bf67fe0.
Try registering your listener in onCreate method of your service. It's works for me.Find example code below :
private TelephonyManager tm;
#Override
public void onCreate() {
super.onCreate();
//Set listener for TelephonyManager tm.
tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
tm.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
private PhoneStateListener phoneStateListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING) {
Log.i(LOG_TAG,"State : RING RING");
}
if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
Log.i(LOG_TAG,"State : OFFHOOK");
}
if (state == TelephonyManager.CALL_STATE_IDLE) {
Log.i(LOG_TAG,"State : IDLE");
}
}
};
Can I get the number that is calling by native dialer ?
I want to show the "toast message" with information about cost per minute according to a dialing number. But I do not know how to get this number.
It could be good to have sample which show "toast message" with dialed number during of call.
yes you can do it.You need to implement PhoneStateListener
public class CustomPhoneStateListener extends PhoneStateListener {
public static Boolean phoneRinging = false;
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.d("DEBUG", "IDLE");
phoneRinging = false;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d("DEBUG", "OFFHOOK");
phoneRinging = false;
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d("DEBUG", "RINGING");
phoneRinging = true;
break;
}
}
}
To register the listener do this:
CustomPhoneStateListener phoneListener = new CustomPhoneStateListener();
telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
Note that access to some telephony information is permission-protected. Your application won't receive updates for protected information unless it has the appropriate permissions declared in its manifest file. Where permissions apply, they are noted in the appropriate LISTEN_ flags.
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.
I want to create an android application that changes the mode to ringing from vibration when incoming call from particular number
For Changing ringing from vibration on incoming call use Use TelephonyManager,AudioManager and PhoneStateListener as:
TelephonyManager mTelephonyMgr = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyMgr.listen(new TeleListener(), PhoneStateListener.LISTEN_CALL_STATE);
class TeleListener extends PhoneStateListener
{
public void onCallStateChanged(int state, String incomingNumber)
{
super.onCallStateChanged(state, incomingNumber);
switch (state)
{
case TelephonyManager.CALL_STATE_IDLE:
//CALL_STATE_IDLE;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//CALL_STATE_OFFHOOK;
break;
case TelephonyManager.CALL_STATE_RINGING:
//CALL_STATE_RINGING
//CHECK YOUR PARTICULAR NUMBER HERE
if(incomingNumber=="1234567890")
{
// USE AudioManager for Settingringing from vibration
AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
switch (am.getRingerMode()) {
case AudioManager.RINGER_MODE_NORMAL:
Log.i("MyApp","NORMAL mode");
am.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
break;
}
}
else
{
//DO SOMETHING HERE
}
break;
default:
break;
}
}
}
add <uses-permission android:name="android.permission.READ_PHONE_STATE"> permission in manifest.xml
or How we Get Phone State using BroadcastReceiver see this tutorial:
Get Phone State When Someone is calling using BroadcastReceiver Example
I would like to get only active calls from PhoneStateListener.
I have created the listener with method onCallStateChanged.
Once I dial (and the call is picked up) the state is already off-hook.
Well, it doesn't really surprise me, because of the text in the API:
Device call state: Off-hook. At least one call exists that is dialing, active, or on hold, and no calls are ringing or waiting.
But is there a possibility to get only active calls?
From what I tried on my nexus one, active call wake CALL_STATE_OFFHOOK,
try use log file to watch the steps.
Try this ..
private PhoneStateListener mPhoneListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.d(TAG, "ringing goes here");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(TAG, "Active call goes here");
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.d(TAG, "CALL STATE IDLE goes here");
break;
default:
Log.d(TAG, "Unknown state=" + state);
}
}
and then call it :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TelephonyManager tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
tm.listen(mPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
}
Don't forget add permission to your Mainifest file:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>