Is there a reliable way in Android to detect the beginning and end of incoming and outgoing calls, in order to do things like pause and play audio.
I have done the following:
telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
callEventListener = new PhoneStateListener(){
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
if (state == TelephonyManager.CALL_STATE_IDLE){
//....
}
else if (state == TelephonyManager.CALL_STATE_RINGING){
//....
}
}
};
telephonyManager.listen(callEventListener, PhoneStateListener.LISTEN_CALL_STATE);
Which seems to work for incoming calls, but for outgoing calls I get the CALL_STATE_IDLE when the other person picks up...not when the phone call ends. I figure I must be doing something stupid, or missing something else that I can check?
You are correct in that you don't get any state updates when a out going call is started.
You need to hook into the intent broadcast ACTION_NEW_OUTGOING_CALL. Here is a Android Developer Blog that may help understand the fact that it's a ordered broadcast. And here is a blog post with a simple example of how to setup and use this broadcast.
Related
I'm very new to mobile development and to Xamarin.
I created a new Xamarin.Forms solution "AndroidApp1" which by default consists of two projects, "AndroidApp1.Android" and "AndroidApp1".
If I understood correctly what I read, the first one contains the code specific to Android and the second one contains the code that can be used in Android, iOS or Windows Phone.
My solution runs in an Android emulation in debug mode, now I'd like to be notified when there's an incoming call, I'd like to get the telephone number that is calling me.
Google told me, that I need to create a class that inherits from BroadcastReceiver and override the OnReceive function.
I assume that this class needs to reside in the Android specific project (AndroidApp1.Android), so I created the class here, but now what?
I can't find any information about what to do with this class? Where do I instantiate it? How do I get the notification and the phone number to react on in my "AndroidApp1" project?
Here's the source code of my BroadcastReceiver (copied from the internet):
[BroadcastReceiver(Enabled = true, Exported = false)]
[IntentFilter(new[] { "android.intent.action.PHONE_STATE" })]
public class IncomingCallReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// ensure there is information
if (intent.Extras != null)
{
// get the incoming call state
string state = intent.GetStringExtra(TelephonyManager.ExtraState);
// check the current state
if (state == TelephonyManager.ExtraStateRinging)
{
// read the incoming call telephone number...
string telephone = intent.GetStringExtra(TelephonyManager.ExtraIncomingNumber);
// check the reade telephone
if (string.IsNullOrEmpty(telephone))
telephone = string.Empty;
}
else if (state == TelephonyManager.ExtraStateOffhook)
{
// incoming call answer
}
else if (state == TelephonyManager.ExtraStateIdle)
{
// incoming call end
}
}
}
}
You need to register brodcast receiver for the call state.
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
and create a notification once your get broadcast events.
Make sure you have defined permission.
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
You need to have a Broadcast Receiver something like this.
/**
* Listener to detect incoming calls.
*/
private class CallStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
// called when someone is ringing to this phone
Toast.makeText(ctx, "Incoming: "+incomingNumber,
Toast.LENGTH_LONG).show();
break;
}
}
You can register the lister for incoming call events.
tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);
Here is the more info
https://stackoverflow.com/questions/9684866/how-to-detect-when-phone-is-answered-or-rejected
Finally I am one step forward. I created a class StateListener that inherits from PhoneStateListener in the Android specific project like this:
public class StateListener : PhoneStateListener
{
public override void OnCallStateChanged(CallState state, string incomingNumber)
{
base.OnCallStateChanged(state, incomingNumber);
switch (state)
{
case CallState.Ringing:
break;
case CallState.Offhook:
break;
case CallState.Idle:
break;
}
}
}
Then I instantiated this class in the OnCreate function of the MainActivity class of the Android specific project with these three lines of code:
StateListener phoneStateListener = new StateListener();
TelephonyManager telephonyManager = (TelephonyManager)GetSystemService(Context.TelephonyService);
telephonyManager.Listen(phoneStateListener, PhoneStateListenerFlags.CallState);
Now when I set break points in the case parts of the switch (state) in OnCallStateChanged they break, but the incomingNumber is always empty, although I've set the corresponding rights in the manifest.
So, that will be my next step, to get the calling number.
I have written an interceptor to access a call data when there is an incoming call. I listen to state change action to decide whether it is a missed call or received call. I have written a code to do things whenever call ends.
public class PhoneStateBroadcastReceiver extends BroadcastReceiver {
public static final String TAG = "PHONE STATE";
private static String mLastState = TelephonyManager.CALL_STATE_IDLE;
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (!state.equals(mLastState)) {
mLastState = state;
Log.e(TAG, state);
return;
}
//Code to do stuff based on last state and state
}
}
The code works fine. But I noticed my app failed to process some of the calls. As this issue was hard to reproduce, I monitored my app for a whole day based on my call activity. When I debugged the issue, I found out that mLastState wasn't changing in such cases. It was still IDLE in case when incoming call ends where it should have been RINGING or OFFHOOK. The reason for that was my app was getting killed and mLastState was being reinitialized. So I was losing the last state.
How to handle this situation? First solution came to my mind was to persist a mLastState to a sharedpreference. Is there any other way to handle this?
Can I get incoming call pick up and end call event in android through coding? I want to that when I received incoming call then should be show toast message. Like incoming call I want to that when we end call then should be show toast message in my app.please suggest me.
If you want it to only when your application's one activity then use following code :
PhoneStateListener phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (state == TelephonyManager.CALL_STATE_RINGING) {
// Incoming call: Pause music
Log.i("Phone", "Ringing");
} else if (state == TelephonyManager.CALL_STATE_IDLE) {
Log.i("Phone", "Idle");
} else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
// A call is dialing, active or on hold
Log.i("Phone", "offhook");
}
super.onCallStateChanged(state, incomingNumber);
}
};
Or if you want to show toast eve outside of your application then try to make service.
There are some nice tutorials on service available.
First read this on developer.
And also look into this tutorial.
You need to use a BroadcastReceiver. Try out this tutorial.
I am developing an application which has a countdown timer. I want to pause that timer only if there is an incoming call on the phone. Is there any way to fire an event whenever we receive a call?
I think you should extends PhoneStateListener class.In that class you handle the phone state.For that use the permission in the manifest file for handling phone state (i.e. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">).
And use TelephonyManager to get the status of phone.
TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
manager.listen(this, LISTEN_CALL_STATE); // Registers a listener object to receive notification of changes in specified telephony states.
And override this method.
#Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_RINGING:
// Here you can perform your task while phone is ringing.
break;
case TelephonyManager.CALL_STATE_IDLE:
break;
}
}
When a Phone-Call is received OS fires a Message, technically called Broadcast.
Any Application can view/Respond to this message via Registering for PhoneIntentReceiver,
if more than one Application installed has registered for this, then all of them are given a chance to view this message based on Priority.
You can register for PhoneIntentReceiver via Manifest or Programatically. In both case you specify a Class that extends broadcast receiver in your project, that will receive a callback on detecting an Incoming call.
Then in this class the control is passed on to onReceive method. Its here that you can Stop your Timmer.
This is the story behind it.Happy Coding.
You have to write the Broadcast receiver which listens for incoming call
see this link for more info...
you have to use broadcast receiver for that........
First of all register your receiver in manifest.xml
<receiver android:name="com.cygnet.phonefinder.receiver.PhoneIntentReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
then you have to handle that reciever in
public class PhoneIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) { } }
I would say the best implementation would be to utilize time stamps, timers (java.util.Timer or android.app.AlarmManager), and then listen for phone events using a broadcast receiver.
Basically every time you need to start an alarm for a certain period of time store a timestamp for the start of that alarm(probably easiest in an sql db) and then start the timer/alarm. When an alarm goes off make sure to clean up your stored timestamps.
Make sure to listen to phone state changes and on a phone call answered change clear all your alarms/timers and record the stop dates along with the previous timestamps and then when the phone call ends (from your reciever event) restart the timers/alarms for the remaining time.
In your Broadcastreceiver onReceive() write following code
Don't forget to give appropriate permission
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
MyCallStateListener customPhoneListener = new MyCallStateListener();
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
if (!intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
return;
public class MyCallStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
}
}
}
public class OutgoingCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "My Toast", Toast.LENGTH_LONG).show();
}
}
Try This receiver to fire an event
I am new to android.
I am implementing one application related to incoming and outgoing call details.
I am getting outgoing call and incoming call details by using brodcast receivers.
The problem is when the incoming call will come the brodcast receiver will rise,
And i make an outgoing call the brodcast receiver raised.
That is fine,but when i click the green button the outgoing call will start,but
i want exact time of answering the call from otherside.
How i get this?
If any one know please help me.
Thanks in advance.
Try using a TelephonyManager
if ((intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL) || (intent
.getAction()
.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)))) {
String phoneState = intent.getExtras().getString(
TelephonyManager.EXTRA_STATE);
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
Log.d(TAG, "Outgoing call");
if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(phoneState)) {
Log.d(TAG, "Incoming call/Outgng call Started");
}
if (TelephonyManager.EXTRA_STATE_IDLE.equals(phoneState)) {
Log.d(TAG,"Call ended");
}
if (TelephonyManager.EXTRA_STATE_RINGING.equals(phoneState)) {
Log.d(TAG,"Call ringing");
}
}
Continuously check when device state is changed from CALL_STATE_IDLE, to CALL_STATEOFFHOOK... It gives the exact time of your call being answered