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.
Based on these three states:
TelephonyManager.CALL_STATE_IDLE
TelephonyManager.CALL_STATE_OFFHOOK
TelephonyManager.CALL_STATE_RINGING:
Is it possible to tell if there is an incoming our outgoing call?
Specifically, if there is an incoming call,
Is there a state for when user answers the call?
A state for when the call ends?
Are there similar states for outgoing calls?
Also, is there a state for rejecting a call?
You should use your own class extending PhoneStateListener to handle when the call state changes :
CallStateListener callListener= new CallStateListener ();
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE);
Then, the following code for your own class :
public class CallStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.d(CallStateListener.class.getSimpleName(), "CALL_STATE_IDLE");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(CallStateListener.class.getSimpleName(), "CALL_STATE_OFFHOOK");
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d(CallStateListener.class.getSimpleName(), "CALL_STATE_RINGING");
break;
}
}
}
To detect when an outgoing call is answered, I tried creating a PhoneStateListener and listening for TelephonyManager's CALL_STATE_RINGING, CALL_STATE_OFFHOOK, and CALL_STATE_IDLE, from this question, but it does not seem to work, as explained below.
First, I registered the following permission in the manifest:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
Then, a BroadcastReceiver called OutCallLogger that catches the NEW_OUTGOING_CALL event whenever an outgoing call is made:
<receiver android:name=".listener.OutCallLogger">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Next, my implementation of OutCallLogger. I set up a boolean called noCallListenerYet to avoid attaching a new PhoneStateListener to the TelephonyManager whenever onReceive() is invoked.
public class OutCallLogger extends BroadcastReceiver {
private static boolean noCallListenerYet = true;
#Override
public void onReceive(final Context context, Intent intent) {
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
if (noCallListenerYet) {
final TelephonyManager tm = (TelephonyManager) context.getSystemService(
Context.TELEPHONY_SERVICE);
tm.listen(new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.d(This.LOG_TAG, "RINGING");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(This.LOG_TAG, "OFFHOOK");
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.d(This.LOG_TAG, "IDLE");
break;
default:
Log.d(This.LOG_TAG, "Default: " + state);
break;
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
noCallListenerYet = false;
}
}
}
Now, when I make an outgoing call in my device, CALL_STATE_RINGING is NEVER invoked. I always only get printouts of "IDLE" to "OFFHOOK" when the other line starts ringing, nothing when the call is answered, and a printout of "IDLE" again when the call is ended.
How can I reliably detect when an outgoing call is answered in Android, or is that even possible?
Since Android 5.0 this is possible for system apps. But you need to use the hidden Android API.
I got it to work like this:
<uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
<receiver android:name=".listener.OutCallLogger">
<intent-filter>
<action android:name="android.intent.action.PRECISE_CALL_STATE" />
</intent-filter>
</receiver>
public class OutCallLogger extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
switch (intent.getIntExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, -2) {
case PreciseCallState.PRECISE_CALL_STATE_IDLE:
Log.d(This.LOG_TAG, "IDLE");
break;
case PreciseCallState.PRECISE_CALL_STATE_DIALING:
Log.d(This.LOG_TAG, "DIALING");
break;
case PreciseCallState.PRECISE_CALL_STATE_ALERTING:
Log.d(This.LOG_TAG, "ALERTING");
break;
case PreciseCallState.PRECISE_CALL_STATE_ACTIVE:
Log.d(This.LOG_TAG, "ACTIVE");
break;
}
}
}
You can find all possible call states in PreciseCallState.java and all extras that the intent contains in TelephonyRegistry.java.
It looks like the RINGING state is reached only by incoming calls. Outgoing calls change from IDLE to OFFHOOK, so looking at the Phone State maybe is not possible to achieve this.
I think that it could be possible using internal functions, look at this: What does the different Call states in the Android telephony stack represent?
Maybe try to use CallManager? Check out http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.3_r1/com/android/internal/telephony/CallManager.java. I also found CallManager.java among the SDK files on my computer. The following text from the linked page seems promising:
Register for getting notifications for change in the Call State Call.State This is
called PreciseCallState because the call state is more precise than the Phone.State
which can be obtained using the android.telephony.PhoneStateListener Resulting events
will have an AsyncResult in Message.obj. AsyncResult.userData will be set to the obj
argument here. The h parameter is held only by a weak reference.
1051
1052 public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){
1053 mPreciseCallStateRegistrants.addUnique(h, what, obj);
1054 }
I haven't tried to code anything, so really don't know if it can do what you want, but I am curious to know.
Please pay your attention at:
tm.listen(new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.d(This.LOG_TAG, "RINGING");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(This.LOG_TAG, "OFFHOOK");
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.d(This.LOG_TAG, "IDLE");
break;
default:
Log.d(This.LOG_TAG, "Default: " + state);
break;
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
Do you see "incomingNumber" argument? Yes, that code just can only detect your phone-call-state when there is an incoming-phone-call to your device.
You could do the following... not very precise but could do the trick:
You use the receiver for the android.intent.action.NEW_OUTGOING_CALL action
When the receiver is called you store somewhere (for instance a static var) the NEW_OUTGOIN_CALL state and the time in ms when this happened (i.e. new Date().getTime())
You use the another receiver for android.intent.action.PHONE_STATE and in the onReceive you do the following:
if (intent.getAction().equals("android.intent.action.PHONE_STATE")) {
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
switch(state) {
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
case TelephonyManager.CALL_STATE_RINGING:
break;
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
}
In the CALL_STATE_OFFHOOK case you check that the last stored state was NEW_OUTGOING_CALL and that the no more than aprox. 10 seconds have passed since the last state change. This means that the phone initiated a call at most 10 seconds ago and that now he is in the offhook state (meaning active call) without passing through idle or ringing. This could mean that the call was answered.
Here your answer is that you have implemented CallStateListener in OutGoingCallReceiver which is wrong. You have to implement CallStateListener in PhoneStateListener
I have also tried this thing in my earlier project, I had faced the same issue, then I solved it like as below. I took 3 classes as below.
AutoCallReceiver: Register the TelephonyManager with PhoneStateListener.LISTEN_CALL_STATE
CallStateListener which listens three states as TelephonyManager.CALL_STATE_IDLE,TelephonyManager.CALL_STATE_OFFHOOK,TelephonyManager.CALL_STATE_RINGING
3.OutGoingCallReceiver which handles out going call
public class OutGoingCallReceiver extends BroadcastReceiver {
/* onReceive will execute on out going call */
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "OutGoingCallReceiver", Toast.LENGTH_SHORT).show();
}
}
public class CallStateListener extends PhoneStateListener {
String number=""; // variable for storing incoming/outgoing number
Context mContext; // Application Context
//Constructor that will accept Application context as argument
public CallStateListener(Context context) {
mContext=context;
}
// This function will automatically invoke when call state changed
public void onCallStateChanged(int state,String incomingNumber)
{
boolean end_call_state=false; // this variable when true indicate that call is disconnected
switch(state) {
case TelephonyManager.CALL_STATE_IDLE:
// Handling Call disconnect state after incoming/outgoing call
Toast.makeText(mContext, "idle", Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// Handling outgoing call
Toast.makeText(mContext, "OFFHOOK", Toast.LENGTH_SHORT).show();
// saving outgoing call state so that after disconnect idle state can act accordingly
break;
case TelephonyManager.CALL_STATE_RINGING:
Toast.makeText(mContext, "RINGING", Toast.LENGTH_SHORT).show();
break;
}
}
}
public class AutoCallReceiver extends BroadcastReceiver {
/* onReceive will execute on call state change */
#Override
public void onReceive(Context context, Intent intent) {
// Instantiating PhoneStateListener
CallStateListener phoneListener=new CallStateListener(context);
// Instantiating TelephonyManager
TelephonyManager telephony = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
// Registering the telephony to listen CALL STATE change
telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
}
}
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<application ...>
<receiver android:name=".OutGoingCallReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
<receiver android:name=".AutoCallReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
I am trying to know how to alert when the callee lifts the call. I have used PhoneStateListener along with BroadcastReceiver.
Generally it has three states CALL_STATE_IDLE , CALL_STATE_OFFHOOK, CALL_STATE_RINGING.
CALL_STATE_OFFHOOK state was calling when call is connecting, No state of the above three states was called after callee answered
call.
Here is my BroadcastReceiver.
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);
}
public class CustomPhoneStateListener extends PhoneStateListener
{
Context context; //Context to make Toast if required
ActivityManager activityManager;
public CustomPhoneStateListener(Context context)
{
super();
this.context = context;
}
#Override
public void onCallStateChanged(int state, String incomingNumber)
{
super.onCallStateChanged(state, incomingNumber);
Log.v("PhoneStateBroadcastReceiver", "onCallStateChanged state"+state);
switch (state)
{
case TelephonyManager.CALL_STATE_IDLE:
Toast.makeText(context, "=CALL_STATE_IDLE==", Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Toast.makeText(context, "CALL_STATE_OFFHOOK", Toast.LENGTH_LONG).show();
break;
case TelephonyManager.CALL_STATE_RINGING:
Toast.makeText(context, "CALL_STATE_RINGING", Toast.LENGTH_LONG).show();
break;
default:
break;
}
}
}
}
I have seen some applications there are recording a voice when call was accepted. I want to know the state of accepting call.
Is there any other state or listener to know when the callee is answered the call?
The state will be OFF_HOOK
Device call state: Off-hook. At least one call exists that is dialing, active, or on hold, and no calls are ringing or waiting.
You can see on this link:
http://developer.android.com/reference/android/telephony/TelephonyManager.html
I know this is a asked question. By using broadcast receiver and using
android.intent.action.PHONE_STATE
in receiver tag, you can know the actions of a phone. But how can I identify whether it is an incoming call or a outgoing call?
here is my code
#Override
public void onReceive(Context context, Intent intent)
{
this.context = context ;
System.out.println(":::called onReceiver:::");
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(phoneCallListener, PhoneStateListener.LISTEN_CALL_STATE);
}
private final PhoneStateListener phoneCallListener = new PhoneStateListener()
{
#Override
public void onCallStateChanged(int state, String incomingNumber)
{
switch(state)
{
case TelephonyManager.CALL_STATE_RINGING:
isRinging = true;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if (isRinging)
{
hasAttended = true ;
isRinging = false;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (hasAttended)
{
isCallEnded = true ;
hasAttended = false;
}
break;
}
if(isCallEnded)
{
isCallEnded=false;
Intent callIntent = new Intent(context.getApplicationContext(),MyActivity.class);
callIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(callIntent);
}
super.onCallStateChanged(state, incomingNumber);
}
};
here each time a phoneCallListener object is created and increases the calling rate of onCallStateChanged by one each time..
This is a handy tutorial that uses both broadcast receiver and using android.intent.action.PHONE_STATE that creates different toasts to appear depending on the calls state. When you get this working you will be able to manipulate the code to do what you want when a call is either incoming or outgoing
First your class must extend BroadcastReceiver
Next you have to create a method that will listen to the phones state... PhoneStateListener which will listen to when the Phone state changes
Then do a simple switch case to catch the call depending on if it is an incoming call or an outgoing call
EDIT
All you need to do is write some code to check if the previous state was 'ringing'. If the current state is idle and the previous state was ringing, they cancelled/missed the call. If the current state is offhook and the previous state was ringing, they answered the call.
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.i(LOG_TAG, "RINGING");
wasRinging = true;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i(LOG_TAG, "OFFHOOK");
if (!wasRinging) {
// Start your new activity
} else {
// Cancel your old activity
}
// this should be the last piece of code before the break
wasRinging = true;
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.i(LOG_TAG, "IDLE");
// this should be the last piece of code before the break
wasRinging = true;
break;
}