Reputation: 3249
I'm trying to make an app like, when a call comes to the phone I want to detect the number. Below is what I tried, but it's not detecting incoming calls.
I want to run my MainActivity
in background, how can I do that?
I had given the permission in manifest
file.
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Is there anything else should I provide in the manifest?
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
}
public class myPhoneStateChangeListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
if (state == TelephonyManager.CALL_STATE_RINGING) {
String phoneNumber = incomingNumber;
}
}
}
}
Upvotes: 162
Views: 193635
Reputation: 6471
Hack Alert :)
If you are just interested in the incoming call event, consider using the AudioManager and listening to focus changes. Advantage - no permission is required. Disadvantage - won't work in silent mode... in that case, we will increase the volume of the incoming call to the minimum to still get the Audio focus event.
/**
* Register a callback to [AudioManager] to identify an incoming call.
*/
private fun registerAudioFocusChangeListener(){
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val incomingCallVolume = audioManager.getStreamVolume(AudioManager.STREAM_RING)
if(incomingCallVolume == 0) {
// Hack Alert :)
// The user has muted the phone calls, if we still want to intercept the event,
// we set the volume of the incoming call to Minumum otherwise we will not get
// Audio focus event...
try {
audioManager.adjustVolume(
AudioManager.ADJUST_UNMUTE,
AudioManager.FLAG_ALLOW_RINGER_MODES
)
audioManager.setStreamVolume(
AudioManager.STREAM_RING,
audioManager.getStreamMinVolume(AudioManager.STREAM_RING),
0
);
} catch (e : SecurityException){
// DND (Don't Disturb Mode) is probably ON, we are not allowed to set the volume
// in this scenario, But in this case no incoming call is possible anyway.
}
}
val requestBuilder = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
requestBuilder.setOnAudioFocusChangeListener { _ ->
Handler(Looper.getMainLooper()).postDelayed({
val mode = audioManager.mode
if(mode == AudioManager.MODE_RINGTONE || mode == AudioManager.MODE_IN_CALL){
//Ring Ring, do your thing
}
}, 100)
}
audioManager.requestAudioFocus(requestBuilder.build())
}
Upvotes: 1
Reputation: 70
Refer to the answer by Gabe Sechan. As mentioned, in the case of an Outgoing call, we have the following state change: IDLE -> OFFHOOK -> IDLE. In Gabe's original answer, savedNumber
is only set if the phone state becomes RINGING which won't be true for an Outgoing call. A small fix to to also set savedNumber
when the phone state becomes OFFHOOK:
case TelephonyManager.CALL_STATE_OFFHOOK:
if(lastState != TelephonyManager.CALL_STATE_RINGING){
//IDLE to OFFHOOK for example.
isIncoming = false;
callStartTime = new Date();
savedNumber = number;
onOutgoingCallStarted(context, savedNumber, callStartTime);
}
...
This fix allows the dialed number to be passed to Outgoing call methods in the same way that the incoming number is passed to Incoming call or Missed call methods.
Upvotes: 0
Reputation: 490
I fixed Gabe Sechan answer, I used the following code and it worked properly. I noticed when a receiver intent has the "incoming_number" key, I can get the phone number. So I filtered incoming intent and used EXTRA_INCOMING_NUMBER and EXTRA_PHONE_NUMBER to get the phone number.
public class ChangeCallStateListener extends BroadcastReceiver {
private static String lastState = TelephonyManager.EXTRA_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber; //because the passed incoming is only valid in ringing
@Override
public void onReceive(Context context, Intent intent) {
Log.d("CallObserver", "CallReceiver is starting ....");
List<String> keyList = new ArrayList<>();
Bundle bundle = intent.getExtras();
if (bundle != null) {
keyList = new ArrayList<>(bundle.keySet());
Log.e("CallObserver", "keys : " + keyList);
}
if (keyList.contains("incoming_number")) {
String phoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String phoneIncomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
String phoneOutgoingNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
String phoneNumber = phoneOutgoingNumber != null ? phoneOutgoingNumber : (phoneIncomingNumber != null ? phoneIncomingNumber : "");
if (phoneState != null && phoneNumber != null) {
if (lastState.equals(phoneState)) {
//No change, debounce extras
return;
}
Log.e("CallObserver", "phoneState = " + phoneState);
if (TelephonyManager.EXTRA_STATE_RINGING.equals(phoneState)) {
isIncoming = true;
callStartTime = new Date();
//
lastState = TelephonyManager.EXTRA_STATE_RINGING;
if (phoneNumber != null) {
savedNumber = phoneNumber;
}
onIncomingCallStarted(context, savedNumber, callStartTime);
} else if (TelephonyManager.EXTRA_STATE_IDLE.equals(phoneState)) {
if (lastState.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
//
lastState = TelephonyManager.EXTRA_STATE_IDLE;
onMissedCall(context, savedNumber, callStartTime);
} else {
if (isIncoming) {
//
lastState = TelephonyManager.EXTRA_STATE_IDLE;
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
} else {
//
lastState = TelephonyManager.EXTRA_STATE_IDLE;
Log.d("CallObserver", "onOutgoingCallEnded called !! : ");
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
}
} else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(phoneState)) {
if (lastState.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
isIncoming = true;
} else {
isIncoming = false;
}
callStartTime = new Date();
savedNumber = phoneNumber;
//
lastState = TelephonyManager.EXTRA_STATE_OFFHOOK;
onOutgoingCallStarted(context, savedNumber, callStartTime);
}
}
}
}
protected void onIncomingCallStarted(Context ctx, String number, Date start) {
Log.d("CallObserver", "onIncomingCallStarted : " + " number is : " + number);
}
protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
Log.d("CallObserver", "onOutgoingCallStarted : " + " number is : " + number);
}
protected void onIncomingCallEnded(Context context, String number, Date start, Date end) {
}
protected void onOutgoingCallEnded(Context context , String number, Date start, Date end) {
}
protected void onMissedCall(Context context, String number, Date start) {
}
}
Don't forget to get run time permission.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Upvotes: 3
Reputation: 4143
You need a BroadcastReceiver for ACTION_PHONE_STATE_CHANGED
This will call your received whenever the phone-state changes from idle, ringing, offhook so from the previous value and the new value you can detect if this is an incoming/outgoing call.
Required permission would be:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
But if you also want to receive the EXTRA_INCOMING_NUMBER in that broadcast, you'll need another permission: "android.permission.READ_CALL_LOG"
And the code something like this:
val receiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "onReceive")
}
}
override fun onResume() {
val filter = IntentFilter()
filter.addAction("android.intent.action.PHONE_STATE")
registerReceiver(receiver, filter)
super.onResume()
}
override fun onPause() {
unregisterReceiver(receiver)
super.onPause()
}
and in receiver class, we can get current state by reading intent like this:
intent.extras["state"]
the result of extras could be:
RINGING -> If your phone is ringing
OFFHOOK -> If you are talking with someone (Incoming or Outcoming call)
IDLE -> if call ended (Incoming or Outcoming call)
With PHONE_STATE broadcast we don't need to use PROCESS_OUTGOING_CALLS permission or deprecated NEW_OUTGOING_CALL action.
Upvotes: 1
Reputation: 151
Please use the below code. It will help you to get the incoming number with other call details.
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:id="@+id/call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_world" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends Activity {
private static final int MISSED_CALL_TYPE = 0;
private TextView txtcall;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtcall = (TextView) findViewById(R.id.call);
StringBuffer sb = new StringBuffer();
Cursor managedCursor = managedQuery(CallLog.Calls.CONTENT_URI, null,
null, null, null);
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
sb.append("Call Details :");
while (managedCursor.moveToNext()) {
String phNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
Date callDayTime = new Date(Long.valueOf(callDate));
String callDuration = managedCursor.getString(duration);
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
sb.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- "
+ dir + " \nCall Date:--- " + callDayTime
+ " \nCall duration in sec :--- " + callDuration);
sb.append("\n----------------------------------");
}
managedCursor.close();
txtcall.setText(sb);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
and in your manifest request for following permissions:
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
Upvotes: 1
Reputation: 650
Just to update Gabe Sechan's answer. If your manifest asks for permissions to READ_CALL_LOG and READ_PHONE_STATE, onReceive will called TWICE. One of which has EXTRA_INCOMING_NUMBER in it and the other doesn't. You have to test which has it and it can occur in any order.
Upvotes: 9
Reputation: 671
UPDATE: The really awesome code posted by Gabe Sechan no longer works unless you explicitly request the user to grant the necessary permissions. Here is some code that you can place in your main activity to request these permissions:
if (getApplicationContext().checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
// Permission has not been granted, therefore prompt the user to grant permission
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
if (getApplicationContext().checkSelfPermission(Manifest.permission.PROCESS_OUTGOING_CALLS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission has not been granted, therefore prompt the user to grant permission
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.PROCESS_OUTGOING_CALLS},
MY_PERMISSIONS_REQUEST_PROCESS_OUTGOING_CALLS);
}
ALSO: As someone mentioned in a comment below Gabe's post, you have to add a little snippet of code, android:enabled="true
, to the receiver in order to detect incoming calls when the app is not currently running in the foreground:
<!--This part is inside the application-->
<receiver android:name=".CallReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Upvotes: 18
Reputation: 1662
Here is a simple method which can avoid the use of PhonestateListener
and other complications.
So here we are receiving the 3 events from android such as RINGING
,OFFHOOK
and IDLE
. And in order to get the all possible state of call,we need to define our own states like RINGING
, OFFHOOK
, IDLE
, FIRST_CALL_RINGING
, SECOND_CALL_RINGING
.
It can handle every states in a phone call.
Please think in a way that we are receiving events from android and we will define our on call states. See the code.
public class CallListening extends BroadcastReceiver {
private static final String TAG ="broadcast_intent";
public static String incoming_number;
private String current_state,previus_state,event;
public static Boolean dialog= false;
private Context context;
private SharedPreferences sp,sp1;
private SharedPreferences.Editor spEditor,spEditor1;
public void onReceive(Context context, Intent intent) {
//Log.d("intent_log", "Intent" + intent);
dialog=true;
this.context = context;
event = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
incoming_number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d(TAG, "The received event : "+event+", incoming_number : " + incoming_number);
previus_state = getCallState(context);
current_state = "IDLE";
if(incoming_number!=null){
updateIncomingNumber(incoming_number,context);
}else {
incoming_number=getIncomingNumber(context);
}
switch (event) {
case "RINGING":
Log.d(TAG, "State : Ringing, incoming_number : " + incoming_number);
if((previus_state.equals("IDLE")) || (previus_state.equals("FIRST_CALL_RINGING"))){
current_state ="FIRST_CALL_RINGING";
}
if((previus_state.equals("OFFHOOK"))||(previus_state.equals("SECOND_CALL_RINGING"))){
current_state = "SECOND_CALL_RINGING";
}
break;
case "OFFHOOK":
Log.d(TAG, "State : offhook, incoming_number : " + incoming_number);
if((previus_state.equals("IDLE")) ||(previus_state.equals("FIRST_CALL_RINGING")) || previus_state.equals("OFFHOOK")){
current_state = "OFFHOOK";
}
if(previus_state.equals("SECOND_CALL_RINGING")){
current_state ="OFFHOOK";
startDialog(context);
}
break;
case "IDLE":
Log.d(TAG, "State : idle and incoming_number : " + incoming_number);
if((previus_state.equals("OFFHOOK")) || (previus_state.equals("SECOND_CALL_RINGING")) || (previus_state.equals("IDLE"))){
current_state="IDLE";
}
if(previus_state.equals("FIRST_CALL_RINGING")){
current_state = "IDLE";
startDialog(context);
}
updateIncomingNumber("no_number",context);
Log.d(TAG,"stored incoming number flushed");
break;
}
if(!current_state.equals(previus_state)){
Log.d(TAG, "Updating state from "+previus_state +" to "+current_state);
updateCallState(current_state,context);
}
}
public void startDialog(Context context) {
Log.d(TAG,"Starting Dialog box");
Intent intent1 = new Intent(context, NotifyHangup.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
}
public void updateCallState(String state,Context context){
sp = PreferenceManager.getDefaultSharedPreferences(context);
spEditor = sp.edit();
spEditor.putString("call_state", state);
spEditor.commit();
Log.d(TAG, "state updated");
}
public void updateIncomingNumber(String inc_num,Context context){
sp = PreferenceManager.getDefaultSharedPreferences(context);
spEditor = sp.edit();
spEditor.putString("inc_num", inc_num);
spEditor.commit();
Log.d(TAG, "incoming number updated");
}
public String getCallState(Context context){
sp1 = PreferenceManager.getDefaultSharedPreferences(context);
String st =sp1.getString("call_state", "IDLE");
Log.d(TAG,"get previous state as :"+st);
return st;
}
public String getIncomingNumber(Context context){
sp1 = PreferenceManager.getDefaultSharedPreferences(context);
String st =sp1.getString("inc_num", "no_num");
Log.d(TAG,"get incoming number as :"+st);
return st;
}
}
Upvotes: 3
Reputation: 219
@Gabe Sechan, thanks for your code. It works fine except the onOutgoingCallEnded()
. It is never executed. Testing phones are Samsung S5 & Trendy. There are 2 bugs I think.
1: a pair of brackets is missing.
case TelephonyManager.CALL_STATE_IDLE:
// Went to idle- this is the end of a call. What type depends on previous state(s)
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
// Ring but no pickup- a miss
onMissedCall(context, savedNumber, callStartTime);
} else {
// this one is missing
if(isIncoming){
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
} else {
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
}
// this one is missing
break;
2: lastState
is not updated by the state
if it is at the end of the function. It should be replaced to the first line of this function by
public void onCallStateChanged(Context context, int state, String number) {
int lastStateTemp = lastState;
lastState = state;
// todo replace all the "lastState" by lastStateTemp from here.
if (lastStateTemp == state) {
//No change, debounce extras
return;
}
//....
}
Additional I've put lastState
and savedNumber
into shared preference as you suggested.
Just tested it with above changes. Bug fixed at least on my phones.
Upvotes: 1
Reputation: 3145
With Android P - Api Level 28: You need to get READ_CALL_LOG permission
Restricted access to call logs
Android P moves the CALL_LOG
, READ_CALL_LOG
, WRITE_CALL_LOG
, and PROCESS_OUTGOING_CALLS
permissions from the PHONE
permission group to the new CALL_LOG
permission group. This group gives users better control and visibility to apps that need access to sensitive information about phone calls, such as reading phone call records and identifying phone numbers.
To read numbers from the PHONE_STATE intent action, you need both the READ_CALL_LOG
permission and the READ_PHONE_STATE
permission.
To read numbers from onCallStateChanged()
, you now need the READ_CALL_LOG
permission only. You no longer need the READ_PHONE_STATE
permission.
Upvotes: 19
Reputation: 93708
Here's what I use to do this:
Manifest:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<!--This part is inside the application-->
<receiver android:name=".CallReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
My base reusable call detector
package com.gabesechan.android.reusable.receivers;
import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
public abstract class PhonecallReceiver extends BroadcastReceiver {
//The receiver will be recreated whenever android feels like it. We need a static variable to remember data between instantiations
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber; //because the passed incoming is only valid in ringing
@Override
public void onReceive(Context context, Intent intent) {
//We listen to two intents. The new outgoing call only tells us of an outgoing call. We use it to get the number.
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
}
else{
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
state = TelephonyManager.CALL_STATE_IDLE;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, number);
}
}
//Derived classes should override these to respond to specific events of interest
protected abstract void onIncomingCallReceived(Context ctx, String number, Date start);
protected abstract void onIncomingCallAnswered(Context ctx, String number, Date start);
protected abstract void onIncomingCallEnded(Context ctx, String number, Date start, Date end);
protected abstract void onOutgoingCallStarted(Context ctx, String number, Date start);
protected abstract void onOutgoingCallEnded(Context ctx, String number, Date start, Date end);
protected abstract void onMissedCall(Context ctx, String number, Date start);
//Deals with actual events
//Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
//Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
public void onCallStateChanged(Context context, int state, String number) {
if(lastState == state){
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallReceived(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
}
else
{
isIncoming = true;
callStartTime = new Date();
onIncomingCallAnswered(context, savedNumber, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//Went to idle- this is the end of a call. What type depends on previous state(s)
if(lastState == TelephonyManager.CALL_STATE_RINGING){
//Ring but no pickup- a miss
onMissedCall(context, savedNumber, callStartTime);
}
else if(isIncoming){
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
}
else{
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
}
Then to use it, simply derive a class from it and implement a few easy functions, whichever call types you care about:
public class CallReceiver extends PhonecallReceiver {
@Override
protected void onIncomingCallReceived(Context ctx, String number, Date start)
{
//
}
@Override
protected void onIncomingCallAnswered(Context ctx, String number, Date start)
{
//
}
@Override
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end)
{
//
}
@Override
protected void onOutgoingCallStarted(Context ctx, String number, Date start)
{
//
}
@Override
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end)
{
//
}
@Override
protected void onMissedCall(Context ctx, String number, Date start)
{
//
}
}
In addition you can see a writeup I did on why the code is like it is on my blog. Gist link: https://gist.github.com/ftvs/e61ccb039f511eb288ee
EDIT: Updated to simpler code, as I've reworked the class for my own use
Upvotes: 372
Reputation: 54732
private MyPhoneStateListener phoneStateListener = new MyPhoneStateListener();
to register
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
and to unregister
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
Upvotes: 26
Reputation: 3485
this may helps you and also add require permision
public class PhoneListener extends PhoneStateListener
{
private Context context;
public static String getincomno;
public PhoneListener(Context c) {
Log.i("CallRecorder", "PhoneListener constructor");
context = c;
}
public void onCallStateChanged (int state, String incomingNumber)
{
if(!TextUtils.isEmpty(incomingNumber)){
// here for Outgoing number make null to get incoming number
CallBroadcastReceiver.numberToCall = null;
getincomno = incomingNumber;
}
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d("CallRecorder", "CALL_STATE_RINGING");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
}
}
}
Upvotes: 5