33

I want to know whether I am in a call.

If I am in a call then start the service (service part is clear). How do I do this?

While attending the call I need to call the service... I am unaware of how to do this? Any help?

Vaibhav Jani
  • 12,428
  • 10
  • 61
  • 73
Rockin
  • 723
  • 4
  • 25
  • 51
  • 4
    Do you mean in a "phone call", a "method call" or some other call? (Mating call? Curtain call? Lauren Bacall? :-)) – Stephen C May 10 '11 at 11:02

4 Answers4

58

You need broadcast receiver ...

In manifest declare broadcast receiver ...

<receiver android:name=".PhoneStateBroadcastReceiver">
        <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE"/>     
        </intent-filter>
</receiver>

Also declare uses-permission ...

<uses-permission android:name="android.permission.READ_PHONE_STATE" />  

The broadcast receiver class ...

package x.y;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

public class PhoneStateBroadcastReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {

        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(new CustomPhoneStateListener(context), PhoneStateListener.LISTEN_CALL_STATE);

    }

}

And one class to customize phone state listener...

package x.y;
import android.content.Context;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

public class CustomPhoneStateListener extends PhoneStateListener {

    //private static final String TAG = "PhoneStateChanged";
    Context context; //Context to make Toast if required 
    public CustomPhoneStateListener(Context context) {
        super();
        this.context = context;
    }

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        super.onCallStateChanged(state, incomingNumber);

        switch (state) {
        case TelephonyManager.CALL_STATE_IDLE:
            //when Idle i.e no call
            Toast.makeText(context, "Phone state Idle", Toast.LENGTH_LONG).show();
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:
            //when Off hook i.e in call
            //Make intent and start your service here
            Toast.makeText(context, "Phone state Off hook", Toast.LENGTH_LONG).show();
            break;
        case TelephonyManager.CALL_STATE_RINGING:
            //when Ringing
            Toast.makeText(context, "Phone state Ringing", Toast.LENGTH_LONG).show();
            break;
        default:
            break;
        }
    }
}
Vaibhav Jani
  • 12,428
  • 10
  • 61
  • 73
  • ONE problem when install this applicaton and phone receives a call...in debug mode the control doesnt come to onReceive – Rockin May 10 '11 at 14:51
  • vaibhav..after CALL_STATE_RINGING:i put system.out.println("rining")i put a breakpoint..and debugged..in phone..i called from another phone...state is ringing..shouldnt the breakpoint get hitted.?it ws not happening so.. – Rockin May 11 '11 at 03:58
  • check logcat when first time phone rings case TelephonyManager.CALL_STATE_RINGING:it prints logcat once...second call it prints two times...third...its goes like this – Rockin May 11 '11 at 09:01
  • 1
    this is because you are leaking listeners. – jBilbo Mar 15 '13 at 23:37
  • what does each of the states mean exactly? off-hook? idle? why can't it be : ringing/addedCall/hangedCall/hangedAll ? – android developer Sep 11 '13 at 07:57
  • what if i want to change display name of incoming call on screen? – Uniruddh Feb 06 '14 at 07:00
  • it doesn't detect `Phone state Off hook` if app installed on the phone from which you call... it only detects if somebody calls you and you accept... – user924 Apr 05 '18 at 19:27
  • 1
    starting Android O you need to take in app permission to read Phone State – ruben Jul 23 '19 at 21:15
33

TelephonyManager.getCallState() returns one of

  • CALL_STATE_IDLE
  • CALL_STATE_OFFHOOK
  • CALL_STATE_RINGING

If this fits your requirements, it's much less code than Pied Piper's more comprehensive solution.

Daniel Kutik
  • 6,997
  • 2
  • 27
  • 34
Adam
  • 2,616
  • 33
  • 29
  • 2
    I think it's a much better solution. In the first case, a new listener is added each phone state change. – Goo Nov 15 '13 at 16:47
  • +1 I didn't know that method exist. But this method will be only help if we want to know call state at particular time but it will not help in monitoring phone call states all the time. – Vaibhav Jani Oct 07 '14 at 08:55
  • 7
    ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE)).getCallState() for newbie – Vivek Bansal Feb 02 '16 at 18:44
1

You can only come to know call is coming but you can't modify this. :( see this why 2.3 version of android does not hava android.permission.MODIFY_PHONE_STATE ? and what is the solution for this?

Community
  • 1
  • 1
Dhrupal
  • 1,863
  • 1
  • 23
  • 38
0

This is an old question, no doubt. But it pops up as the first result on Google. Hence, I decided to add another useful method.

When the phone state is changed, the system sends the TelephonyManager.ACTION_PHONE_STATE_CHANGED broadcast. This broadcast has an extra state that can be extracted using TelephonyManager.EXTRA_STATE.

The extra state can have three alternatives:

  • EXTRA_STATE_IDLE
  • EXTRA_STATE_OFFHOOK
  • EXTRA_STATE_RINGING

You can design a broadcast receiver that will take care of all these:

public class PhoneStateReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent){

        if (intent.getAction().equals(TelephonyManager.ACTION_CALL_STATE_CHANGED){

            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);

            if (state.equals(TelephonyManager.EXTRA_STATE_IDLE){

                // No call currently active.

            } else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING){

                // A call is ringing

            } else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK){

                // Call has been answered.

            }
        }
    }
}

You can read more about it here:

https://developer.android.com/reference/android/telephony/TelephonyManager#ACTION_PHONE_STATE_CHANGED

Note: The broadcast receiver will be triggered in background and as of Android O+, you cannot start a background service from a background process. Consider starting a foreground service with context.startForegroundService(intent). In the onStartCommand(...) of the service, call startForeground(...). Otherwise, the system raise a fatal exception. However, below Android O, you can safely use context.startService(intent) instead of startForegroundService(...).

Wrichik Basu
  • 1,005
  • 17
  • 28