**It doesn't break while loop while it is in OffHook State . Remain in while loop. Funtion calling in both state is working correctly but **
PhoneStateListener phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
// TODO Auto-generated method stub
// super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
callStatus=true;
while(callStatus)
{
OnOff();
if(state==TelephonyManager.CALL_STATE_OFFHOOK)
{
break;
}
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
callStatus=false;
Off();
break;
default:
break;
}
I got the full working code from here.
Call Receiver Code.
public class CallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Log.w("intent " , intent.getAction().toString());
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
MyPhoneStateListener customPhoneListener = new MyPhoneStateListener();
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
Bundle bundle = intent.getExtras();
String phone_number = bundle.getString("incoming_number");
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;
}
if (phone_number == null || "".equals(phone_number)) {
return;
}
customPhoneListener.onCallStateChanged(context, state, phone_number);
Toast.makeText(context, "Phone Number " + phone_number , Toast.LENGTH_SHORT).show();
}}
Call Listener
public void onCallStateChanged(Context context, int state, String phoneNumber){
if(lastState == state){
//No change, debounce extras
return;
}
System.out.println("Number inside onCallStateChange : " + phoneNumber);
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
Toast.makeText(context, "Incoming Call Ringing " + phoneNumber, Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
callStartTime = new Date();
Toast.makeText(context, "Outgoing Call Started " + phoneNumber, Toast.LENGTH_SHORT).show();
}
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
Toast.makeText(context, "Ringing but no pickup" + phoneNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();
}
else if(isIncoming){
Toast.makeText(context, "Incoming " + phoneNumber + " Call time " + callStartTime , Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(context, "outgoing " + phoneNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();
}
break;
}
lastState = state;
}
Each time a broadcast reciever is called, a new instance of it is created. So your code won't work- it will never get the OFFHOOK on the same object. It might work if callStatus is a static, but even then is bad code- you're busy looping on the ui thread.
Related
Can anyone provide me sample code for detecting outgoing call state on Android Oreo and Above ?
My code is working fine up to android 6 but not working on Android 8.1 and Android 9. Almost all answers on stack overflow are consisting deprecated code.
Manifest is having necessary permissions and doesn't have any registered receiver as per guidelines by Google
BroadcastReceiver
public class CallReceiver extends BroadcastReceiver{
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber;
#Override
public void onReceive(Context context, Intent intent) {
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);
}
}
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;
Toast.makeText(context, "Incoming Call Ringing" , Toast.LENGTH_SHORT).show();
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();
Toast.makeText(context, "Outgoing Call Started" , Toast.LENGTH_SHORT).show();
}
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
Toast.makeText(context, "Ringing but no pickup" + savedNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();
}
else if(isIncoming){
Toast.makeText(context, "Incoming " + savedNumber + " Call time " + callStartTime , Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(context, "Outgoing "+ savedNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();
}
break;
}
lastState = state;
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private CallReceiver callReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
callReceiver = new CallReceiver();
}
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.PHONE_STATE");
filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
registerReceiver(callReceiver, filter);
}
#Override
protected void onPause() {
try {
unregisterReceiver(callReceiver);
} catch (Exception e) {
e.getMessage();
}
super.onPause();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
I want to know the outgoing call is answered or not in android program.I just want to know the outgoing call has answered or not.I am new in android.Please help me to solve this problem.For getting the call answered time i use this.
I want to know the outgoing call is answered or not in android program. I just want to know the outgoing call has answered or not. I am new in android. Please help me to solve this problem. For getting the call answered time I use this.
BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
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);
}
}
};
protected void onIncomingCallStarted(Context ctx, String number, Date start) {
}
protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
SimpleDateFormat localDateFormat = new SimpleDateFormat("HH:mm:ss");
startime = localDateFormat.format(start);
endtime = localDateFormat.format(end);
long aa = start.getTime();
long bb = end.getTime();
long cc = bb - aa;
long diffMinutes = cc / 1000 % 60;
duration = Long.toString(diffMinutes);
Bundle bundle = new Bundle();
bundle.putString("start", startime);
bundle.putString("end", endtime);
bundle.putString("duration", duration);
Call_End dFragment = new Call_End();
dFragment.setArguments(bundle);
dFragment.show(fragmentManager, "Dialog Fragment");
}
protected void onMissedCall(Context ctx, String number, Date start) {
}
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;
onIncomingCallStarted(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
//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);
}
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;
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Intent", intent.toString());
if(intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
{
Log.e("Call_state","outgoing call detected");
}
// Checking for the call status
try {
// TELEPHONY MANAGER class object to register one listner
TelephonyManager tmgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
//Create Listner
MyPhoneStateListener PhoneListener = new MyPhoneStateListener();
// Register listener for LISTEN_CALL_STATE
tmgr.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
e.printStackTrace();
}
}
private class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.e("Call_state","call ringing");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.e("Call_state","call offhook");
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.e("Call_state","call idle");
break;
}
}
}
You can do like this but this will not work on all phone.
Create notification listener service which tell you another person has pick up the call.public class CallNotification extends NotificationListenerService {
public void onNotificationPosted(StatusBarNotification sbn)
{
//your code here after you getting notification another person has pick up the call
}
}
Ask for the allow notification from the system.
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivity(intent);
Here I'm Calling PhoneStateChangeListener class in onCreate method.
the code is:
PhoneStateChangeListener pscl = new PhoneStateChangeListener(MainActivity.this,true);
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);
PhoneStateChangeListener class is:
class PhoneStateChangeListener extends PhoneStateListener {
Context context;
Boolean doRecording=false;
public PhoneStateChangeListener(Context context,Boolean doRecording) {
this.context = context;
this.doRecording=doRecording;
}
public void onCallStateChanged(int state, String incomingNumber) {
Log.d("CallRecorder", "PhoneListener::onCallStateChanged state:" + state + " incomingNumber:" + incomingNumber);
//Intent callIntent = new Intent(context, RecordService.class);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.d("CallRecorder", "CALL_STATE_IDLE, stoping recording");
Boolean stopped = context.stopService(new Intent(context, RecordService.class));
Log.e("CallRecorder", "CALL_STATE_IDLE starting recording---------------------------------"+isMyServiceRunning((getClass())));
Log.i("CallRecorder", "stopService for RecordService returned " + stopped);
break;
case TelephonyManager.CALL_STATE_RINGING:
Log.d("CallRecorder", "CALL_STATE_RINGING");
doRecording=false;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if(doRecording) {
Log.d("CallRecorder", "CALL_STATE_OFFHOOK starting recording");
Log.e("CallRecorder", "CALL_STATE_OFFHOOK starting recording---------------------------------" + isMyServiceRunning((getClass())));
Intent callIntent = new Intent(context, RecordService.class);
ComponentName name = context.startService(callIntent);
if (null == name) {
Log.e("CallRecorder", "startService for RecordService returned null ComponentName");
} else {
Log.i("CallRecorder", "startService returned " + name.flattenToString());
}
}
break;
}
}
}
The phonestatechangelistener is working well below nougat, Issue is when a call starts it calls CALL_STATE_OFFHOOK and the service gets started but when the call is ended it doesn't call CALL_STATE_IDLE and thus service is not stopped this problem is there above marshmallow.
Just deactivate your PhoneStateListener when your call ends:
private void deactivatePhoneStateListener(){
if(mPhoneStateListener != null){
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
}
mPhoneStateListener = null;
}
Activate it again whenever you need it:
private void activatePhoneStateListener(Context context){
mPhoneStateListener = new MyPhoneStateListener();
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
i'have confuse about my code. I'm open activity it the time of Incoming Call/ Missed Call. But its open only 1st time till the received call. after receiving 1st call Not work Ringing state.
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.v("idle state", "CALL_STATE_IDLE");
// CALL_STATE_IDLE;
if (ring == true && callReceived == false && CheckMissCall.isRunning== false) {
Log.v("missed call", "Missed call from : " + incomingNumber);
if(CheckMissCall.isShown)
{
c.stopService(new Intent(c, Unlock_hud.class));
}
flag = true;
if (prefs.getBoolean("main_state", true))
{
Intent inter = new Intent(c, MissCall.class);
inter.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
inter.putExtra("CellNumber", incomingNumber);
c.startActivity(inter);
}
}
if(ring == true && callReceived == true && CheckMissCall.isReject == true)
{
Intent inter = new Intent(c, callLog.class);
inter.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.startActivity(inter);
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// CALL_STATE_OFFHOOK;
callReceived = true;
Log.v("call received", "CALL_STATE_OFFHOOK " + incomingNumber);
break;
case TelephonyManager.CALL_STATE_RINGING:
ring = true;
// CALL_STATE_RINGING
Log.v("call ringing", "CALL_STATE_RINGING " + incomingNumber);
Log.d("flags", "flags: " + flag);
if (flag ) {
//cut = true;
//flag = false;
CheckMissCall call = new CheckMissCall(c);
call.setName(incomingNumber);
call.setNumber4Sms(incomingNumber);
call.setContactPhoto();
Log.d("main", "state ringing");
prefs = PreferenceManager.getDefaultSharedPreferences(c);
if (!prefs.getBoolean("main_state", false))
{
return;
}
/* if (!isScreenOn && CheckMissCall.isRunning) {
return;
}*/
if (CheckMissCall.isRunning) {
return;
}
else {
Log.d("main", "EEEEEEEEEEEEEEEE: Unlock hud");
Intent in = new Intent(c, Unlock_hud.class);
in.setFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
c.startService(in);
// c.stopService(new Intent(c, Unlock_hud.class));
}
}
break;
Broadcast Receiver
public void onReceive(final Context context, Intent intent) {
Log.d("main", "receive");
cut = false;
prefs = PreferenceManager.getDefaultSharedPreferences(context);
// String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
TelephonyManager tmanager = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
if (listener == null) {
listener = new MyPhoneStateListener(context);
if (prefs.getBoolean("main_state", false)) {
tmanager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
Now what i have to do ..??
I'd put a breakpoint in there and test where the logic goes that you don't expect it to. It looks like you aren't properly resetting some of your state variables. But I have a working version of a call detector here Get phonenumber programmatically - Android and a blog post describing how it works at http://gabesechansoftware.com/is-the-phone-ringing/
I have Developing Application of Full Caller Id. In that dynamic screen call at the time of Incoming call / After Missed Call. Now this is work one time. When i received call. Than after it is not work or Not call any dynamic screen at the time Incoming call/ Missed call.
I have very confuse about my problem.
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.v("idle state", "CALL_STATE_IDLE");
// CALL_STATE_IDLE;
if(ring == true && callReceived == true && CheckMissCall.isReject == true)
{
Intent inter = new Intent(c, callLog.class);
inter.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.startActivity(inter);
}
if (ring == true && callReceived == false && CheckMissCall.isRunning== false) {
Log.v("missed call", "Missed call from : " + incomingNumber);
if(CheckMissCall.isShown)
{
c.stopService(new Intent(c, Unlock_hud.class));
}
flag = true;
if (prefs.getBoolean("main_state", true))
{
Intent inter = new Intent(c, MissCall.class);
inter.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
inter.putExtra("CellNumber", incomingNumber);
c.startActivity(inter);
}
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// CALL_STATE_OFFHOOK;
callReceived = true;
Log.v("call received", "CALL_STATE_OFFHOOK " + incomingNumber);
break;
case TelephonyManager.CALL_STATE_RINGING:
ring = true;
// CALL_STATE_RINGING
Log.v("call ringing", "CALL_STATE_RINGING " + incomingNumber);
Log.d("flags", "flags: " + flag);
if (flag) {
//cut = true;
//flag = false;
CheckMissCall call = new CheckMissCall(c);
call.setName(incomingNumber);
call.setNumber4Sms(incomingNumber);
call.setContactPhoto();
Log.d("main", "state ringing");
//prefs = PreferenceManager.getDefaultSharedPreferences(c);
if (!prefs.getBoolean("main_state", false)) {
return;
}
/* if (!isScreenOn && CheckMissCall.isRunning) {
return;
}*/
if (CheckMissCall.isRunning) {
return;
}
else {
Log.d("main", "EEEEEEEEEEEEEEEE: Unlock hud");
Intent in = new Intent(c, Unlock_hud.class);
in.setFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
c.startService(in);
// c.stopService(new Intent(c, Unlock_hud.class));
}
}
break;
}
this is because when any call comes your app goes into background, while for the first time when you receive call your MyPhoneStateListener listens for the call and it ends..
now do one thing.. Run your code in service it will run in background and it will call your dynamic screen
in your main activity start service for this i have used toggle button(to enable or disable service)
tgl_switch.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(tgl_switch.isChecked()){
startService(new Intent(getApplicationContext(),LogsService.class));
Toast.makeText(getApplicationContext(), "Call Logger Active",
Toast.LENGTH_SHORT).show();
}else{
stopService(new Intent(getApplicationContext(),LogsService.class));
Toast.makeText(getApplicationContext(), "Call Logger Deactive",
Toast.LENGTH_SHORT).show();
}
}});
for example i did this
public class LogsService extends Service {
String name;
String phNumber;
String callType;
String callDate;
Date callDayTime;
String callDuration;
String dir ;
String fileName;
boolean wasRinging=false, wasoffHook=false, wasidle=false;
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, Intent intent) {
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
// This code will execute when the phone has an incoming call
Log.d("ring ", "Detected");
wasRinging = true;
// get the phone number
// String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
// Toast.makeText(context, "Call from:" +incomingNumber, Toast.LENGTH_LONG).show();
} else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_OFFHOOK)){
wasoffHook=true;
// Toast.makeText(context, "hang up", Toast.LENGTH_LONG).show();
}
else if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_IDLE)) {
// This code will execute when the call is disconnected
wasidle=true;
// Toast.makeText(context, "IDLE STATE", Toast.LENGTH_LONG).show();
if((wasRinging && wasoffHook && wasidle)){
// this is received call event
startActivity(new Intent(getApplicationContext(), Incoming.class));
} else if(wasRinging && wasidle){
// this is missed call event
startActivity(new Intent(getApplicationContext(), MissCall.class));
}
wasidle = false;
wasoffHook = false;
wasRinging=false;
}
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
IntentFilter filter = new IntentFilter();
filter.addAction(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED);
registerReceiver(receiver, filter);
}
#Override
public void onDestroy() {
unregisterReceiver(receiver);
}
}
i used this code to get details of last call you can modify it in your way