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.
Related
I managed to prepare an activity when the phone is ringing. Now I need to know how to cancel this activity, when I answer the phone or I reject the call.Do I call EXTRA_STATE_IDLE or EXTRA_STATE_OFFHOOK ?
Any ideas?
Manifest
<receiver android:name=".IncomingBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
IncomingBroadcastReceiver java Class
public class IncomingBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
// If an incoming call arrives
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { //Did my work }
The above answer is completely wrong in case of outgoing calls. In Android there is no way by which one detect whether the call was actually answered (in case of outgoing calls). The moment you dial a number, the off_hook state is fired. This is one of the drawbacks of Android programming.
in your onReceive:
PhoneStateChangeListener pscl = new PhoneStateChangeListener();
TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);
separate class:
private class PhoneStateChangeListener extends PhoneStateListener {
public static boolean wasRinging;
String LOG_TAG = "PhoneListener";
#Override
public void onCallStateChanged(int state, String incomingNumber) {
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 = false;
break;
}
}
}
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 the call.
If the current state is offhook and the previous state was ringing, they answered the call.
Following are the states which it goes through in different scenarios:
1) Answering Received call
CALL_STATE_RINGING => CALL_STATE_OFFHOOK (After Answering call) => CALL_STATE_IDLE (After End call)
2) Rejecting / Not Answering (Missed) Received call
CALL_STATE_RINGING => CALL_STATE_IDLE (After End call)
3) Dialing call
CALL_STATE_OFFHOOK (After dialing) => CALL_STATE_IDLE (After End call)
Code
int prev_state=0;
public class CustomPhoneStateListener extends PhoneStateListener {
private static final String TAG = "CustomPhoneStateListener";
#Override
public void onCallStateChanged(int state, String incomingNumber){
if(incomingNumber!=null&&incomingNumber.length()>0) incoming_nr=incomingNumber;
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.d(TAG, "CALL_STATE_RINGING");
prev_state=state;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(TAG, "CALL_STATE_OFFHOOK");
prev_state=state;
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_nr);
NumberDatabase database=new NumberDatabase(mContext);
if((prev_state==TelephonyManager.CALL_STATE_OFFHOOK)){
prev_state=state;
//Answered Call which is ended
}
if((prev_state==TelephonyManager.CALL_STATE_RINGING)){
prev_state=state;
//Rejected or Missed call
}
break;
}
}
}
In your receiver
onReceive(Context context, Intent intent) {
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object
CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE); //Register our listener with TelephonyManager
Bundle bundle = intent.getExtras();
String phoneNr= bundle.getString("incoming_number");
mContext=context;
}
below is a code of detecting outgoing call by accessibility events -
Add a class which extends AccessibilityService in your projects -
public class CallDetection extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
acquireLock(this);
Log.d("myaccess","after lock");
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
Log.d("myaccess","in window changed");
AccessibilityNodeInfo info = event.getSource();
if (info != null && info.getText() != null) {
String duration = info.getText().toString();
String zeroSeconds = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(0)});
String firstSecond = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(1)});
Log.d("myaccess","after calculation - "+ zeroSeconds + " --- "+ firstSecond + " --- " + duration);
if (zeroSeconds.equals(duration) || firstSecond.equals(duration)) {
Toast.makeText(getApplicationContext(),"Call answered",Toast.LENGTH_SHORT).show();
// Your Code goes here
}
info.recycle();
}
}
}
#Override
protected void onServiceConnected() {
super.onServiceConnected();
Toast.makeText(this,"Service connected",Toast.LENGTH_SHORT).show();
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
info.notificationTimeout = 0;
info.packageNames = null;
setServiceInfo(info);
}
#Override
public void onInterrupt() {
}
}
But to get the function event.getSource() working you have to specify some of your service configuration through xml, so create a xml folder in your project and add a xml file called serviceconfig.xml (you can give any name you want.
The content of serviceconfig is below -
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="#string/callDetection"
android:accessibilityEventTypes="typeWindowContentChanged"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
/>
You can find more about serviceconfig in Here
Now add your service in you Manifest file like this -
<service android:name=".CallDetection"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:label="#string/callDetection">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/serviceconfig" />
</service>
And youre done, just run the app and go to Accessibility settings in your phone, you will find an option named as detection (or whatever name you have given as your service description), switch that on to give accesibility permissions for you app.
Now you will see a toast when call is answered.
you can Code any code you want in there, also you can call a callback function in your activity
Most important - Dont call your call window(android dialer window) untill the call is answered, otherwise this will not work.
Note - As android doesn't provide any solution to detect if the call is answered or not, this is the best alternative i have made, hope it works for you.
//
public class myService extends InCallService
{
// Here... :)
#Override public void onCanAddCallChanged(boolean canAddCall)
{
super.onCanAddCallChanged(canAddCall);
}
}
To detect that a call is received, you can detect a "hello" voice. "hello" voice is the frequency (voice activity) outside of Call progress Frequency. For reference you can have a look at this datasheet part: https://www.cmlmicro.com/products/call-progress-and-voice-detector/
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 managed to prepare an activity when the phone is ringing. Now I need to know how to cancel this activity, when I answer the phone or I reject the call.Do I call EXTRA_STATE_IDLE or EXTRA_STATE_OFFHOOK ?
Any ideas?
Manifest
<receiver android:name=".IncomingBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
IncomingBroadcastReceiver java Class
public class IncomingBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
// If an incoming call arrives
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { //Did my work }
The above answer is completely wrong in case of outgoing calls. In Android there is no way by which one detect whether the call was actually answered (in case of outgoing calls). The moment you dial a number, the off_hook state is fired. This is one of the drawbacks of Android programming.
in your onReceive:
PhoneStateChangeListener pscl = new PhoneStateChangeListener();
TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);
separate class:
private class PhoneStateChangeListener extends PhoneStateListener {
public static boolean wasRinging;
String LOG_TAG = "PhoneListener";
#Override
public void onCallStateChanged(int state, String incomingNumber) {
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 = false;
break;
}
}
}
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 the call.
If the current state is offhook and the previous state was ringing, they answered the call.
Following are the states which it goes through in different scenarios:
1) Answering Received call
CALL_STATE_RINGING => CALL_STATE_OFFHOOK (After Answering call) => CALL_STATE_IDLE (After End call)
2) Rejecting / Not Answering (Missed) Received call
CALL_STATE_RINGING => CALL_STATE_IDLE (After End call)
3) Dialing call
CALL_STATE_OFFHOOK (After dialing) => CALL_STATE_IDLE (After End call)
Code
int prev_state=0;
public class CustomPhoneStateListener extends PhoneStateListener {
private static final String TAG = "CustomPhoneStateListener";
#Override
public void onCallStateChanged(int state, String incomingNumber){
if(incomingNumber!=null&&incomingNumber.length()>0) incoming_nr=incomingNumber;
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.d(TAG, "CALL_STATE_RINGING");
prev_state=state;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d(TAG, "CALL_STATE_OFFHOOK");
prev_state=state;
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_nr);
NumberDatabase database=new NumberDatabase(mContext);
if((prev_state==TelephonyManager.CALL_STATE_OFFHOOK)){
prev_state=state;
//Answered Call which is ended
}
if((prev_state==TelephonyManager.CALL_STATE_RINGING)){
prev_state=state;
//Rejected or Missed call
}
break;
}
}
}
In your receiver
onReceive(Context context, Intent intent) {
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object
CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE); //Register our listener with TelephonyManager
Bundle bundle = intent.getExtras();
String phoneNr= bundle.getString("incoming_number");
mContext=context;
}
below is a code of detecting outgoing call by accessibility events -
Add a class which extends AccessibilityService in your projects -
public class CallDetection extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
acquireLock(this);
Log.d("myaccess","after lock");
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
Log.d("myaccess","in window changed");
AccessibilityNodeInfo info = event.getSource();
if (info != null && info.getText() != null) {
String duration = info.getText().toString();
String zeroSeconds = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(0)});
String firstSecond = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(1)});
Log.d("myaccess","after calculation - "+ zeroSeconds + " --- "+ firstSecond + " --- " + duration);
if (zeroSeconds.equals(duration) || firstSecond.equals(duration)) {
Toast.makeText(getApplicationContext(),"Call answered",Toast.LENGTH_SHORT).show();
// Your Code goes here
}
info.recycle();
}
}
}
#Override
protected void onServiceConnected() {
super.onServiceConnected();
Toast.makeText(this,"Service connected",Toast.LENGTH_SHORT).show();
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
info.notificationTimeout = 0;
info.packageNames = null;
setServiceInfo(info);
}
#Override
public void onInterrupt() {
}
}
But to get the function event.getSource() working you have to specify some of your service configuration through xml, so create a xml folder in your project and add a xml file called serviceconfig.xml (you can give any name you want.
The content of serviceconfig is below -
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="#string/callDetection"
android:accessibilityEventTypes="typeWindowContentChanged"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
/>
You can find more about serviceconfig in Here
Now add your service in you Manifest file like this -
<service android:name=".CallDetection"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:label="#string/callDetection">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="#xml/serviceconfig" />
</service>
And youre done, just run the app and go to Accessibility settings in your phone, you will find an option named as detection (or whatever name you have given as your service description), switch that on to give accesibility permissions for you app.
Now you will see a toast when call is answered.
you can Code any code you want in there, also you can call a callback function in your activity
Most important - Dont call your call window(android dialer window) untill the call is answered, otherwise this will not work.
Note - As android doesn't provide any solution to detect if the call is answered or not, this is the best alternative i have made, hope it works for you.
//
public class myService extends InCallService
{
// Here... :)
#Override public void onCanAddCallChanged(boolean canAddCall)
{
super.onCanAddCallChanged(canAddCall);
}
}
To detect that a call is received, you can detect a "hello" voice. "hello" voice is the frequency (voice activity) outside of Call progress Frequency. For reference you can have a look at this datasheet part: https://www.cmlmicro.com/products/call-progress-and-voice-detector/
I'd like to build an Android application that can contact the current caller via a pre-determined text message. Sending a text message is simple enough but determining the phone number of the current caller in a stand-alone application is the challenge. Is the there an easy way to divine the phone number so I can send them a message while still on the call?
Of course there are manual ways to do this: write down the number, key it into a new text message, enter the message. But I want to define the message up front and be able to "send it to current caller".
#Override
public void onReceive(Context context, Intent intent) {
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneCallStateListener customPhoneListener = new PhoneCallStateListener(context);
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
helper = new ContactDatabaseHelper(context);
list = helper.getAllContacts();
try{
incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (list.size() != 0){
for ( int i = 0, size = list.size(); i < size; i++ ){
if (PhoneNumberUtils.compare(incomingNumber, list.get(i).getContactNumber())){
ToastMsg.showToast(context,list.get(i).getContactName()+" Calling");
}
}
}
}catch (Exception e) {
// TODO: handle exception
}
}
public class PhoneCallStateListener extends PhoneStateListener{
private Context context;
public PhoneCallStateListener(Context context){
this.context = context;
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
break;
case PhoneStateListener.LISTEN_CALL_STATE:
}
super.onCallStateChanged(state, incomingNumber);
}
}
For your sistuation the best I can think of is to use PhoneStateListener. It contains onCallStateChanged handler. One of the arguments is a String containing the incoming phone number.
Source:
http://developer.android.com/reference/android/telephony/PhoneStateListener.html
Ctrl + F and type in "Incoming" and you will find everything you need to know.
EDIT: To make sure you're app starts on the startup of your phone, just add a BroadcastReciever. How to start an Application on startup?
Register a BroadcastReceiver in your manifest that listens to ACTION_PHONE_STATE_CHANGED.
Broadcast intent action indicating that the call state (cellular) on
the device has changed.
The EXTRA_STATE extra indicates the new call state. If the new state
is RINGING, a second extra EXTRA_INCOMING_NUMBER provides the incoming
phone number as a String.
Requires the READ_PHONE_STATE permission.
This was a sticky broadcast in version 1.0, but it is no longer
sticky. Instead, use getCallState() to synchronously query the current
call state.
This way you don't need the user to launch your app before receiving a call.
I have a requirement wherein I want to detect two kind of events related to Calls in Android
Whenever an outgoing call is made, my application should get to know this along with the called number
When the call is hanged up(due to success/failure), my application should get to know this along with the reason of hangup
Is this possible in Android?
You should create a BroadcastReceiver:
public class CallReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_RINGING)) {
// Phone number
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
// Ringing state
// This code will execute when the phone has an incoming call
} else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_IDLE)
|| intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_OFFHOOK)) {
// This code will execute when the call is answered or disconnected
}
}
}
You should register you application to listen to these intents in the manifest:
<receiver android:name=".CallReciever" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
There is a simpler solution using only TelephonyManager and
PhoneStateListener.You donĀ“t even have to register a BroadcastReceiver.
public class MyPhoneStateListener extends PhoneStateListener {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
//Hangup
case TelephonyManager.CALL_STATE_IDLE:
break;
//Outgoing
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
//Incoming
case TelephonyManager.CALL_STATE_RINGING:
break;
}
}
}
And to register it:
public static void registerListener(Context context) {
((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).listen(new MyPhoneStateListener(),
PhoneStateListener.LISTEN_CALL_STATE);
}
You need to create a receiver for the following intent actions:
Outgoing call - ACTION_NEW_OUTGOING_CALL
Call hangup - ACTION_PHONE_STATE_CHANGED