Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect the end of an answered incoming call by user in android? (not declined)

In my android application, I have created a BroadcastReceiver that detects incoming call; my code is running very well. If there is an incoming call (EXTRA_STATE_RINGING), I can see my incommingNumber in the logcat, also when the user answered the call (EXTRA_STATE_OFFHOOK)

  • I used shared preferences to store incoming number (String) in ringing state , then get it in Off HOOK state.

This is my code, it works perfectly:

 public class IncomingCallReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

           String incomingNumber = null ;
          if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) 
          {
            // Ringing state
            // Phone number 
              incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

              Log.i("test2", incomingNumber);

              SharedPreferences myPrefs = context.getSharedPreferences("myPrefs",Context.MODE_WORLD_WRITEABLE);
              SharedPreferences.Editor prefsEditor = myPrefs.edit();
              prefsEditor.putString("Incomingnumber", incomingNumber);
              //Not forgot to commit.
              prefsEditor.commit();


          } 

          else if  (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) 
          {
              //get the incoming number 
              SharedPreferences myPrefs = context.getSharedPreferences("myPrefs",Context.MODE_WORLD_READABLE);
              String incomNumber = myPrefs.getString("Incomingnumber", incomingNumber);

              // This code will execute when the call is answered

              Log.i("test2", incomNumber);
              Toast.makeText(context,incomNumber, Toast.LENGTH_LONG).show();

          }

BUT : My problem that my code can display a toast when the user just Accept the incoming call.

So, I need to know how I can detect the end of an answered the incoming call to do something else (display an alert dialog or launch an activity)

like image 979
Zied R. Avatar asked Feb 24 '14 14:02

Zied R.


1 Answers

I've posted this here before- here's my class for detecting incoming calls start and end, outgoing calls start and end, and missed calls.

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.PhoneStateListener;
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
    static PhonecallStartEndDetector listener;
    String outgoingSavedNumber;
    protected Context savedContext;


    @Override
    public void onReceive(Context context, Intent intent) {
        savedContext = context;
        if(listener == null){
            listener = new PhonecallStartEndDetector();
        }

        //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")) {
            listener.setOutgoingNumber(intent.getExtras().getString("android.intent.extra.PHONE_NUMBER"));
            return;
        }

        //The other intent tells us the phone state changed.  Here we set a listener to deal with it
        TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 
        telephony.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
    }

    //Derived classes should override these to respond to specific events of interest
    protected abstract void onIncomingCallStarted(String number, Date start);
    protected abstract void onOutgoingCallStarted(String number, Date start);
    protected abstract void onIncomingCallEnded(String number, Date start, Date end); 
    protected abstract void onOutgoingCallEnded(String number, Date start, Date end);
    protected abstract void onMissedCall(String number, Date start);

    //Deals with actual events
    public class PhonecallStartEndDetector extends PhoneStateListener {
        int lastState = TelephonyManager.CALL_STATE_IDLE;
        Date callStartTime;
        boolean isIncoming;
        String savedNumber;  //because the passed incoming is only valid in ringing

        public PhonecallStartEndDetector() {}

        //The outgoing number is only sent via a separate intent, so we need to store it out of band
        public void setOutgoingNumber(String number){
            savedNumber = number;
        }

        //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
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            if(lastState == state){
                //No change, debounce extras
                return;
            }
            switch (state) {
                case TelephonyManager.CALL_STATE_RINGING:
                    isIncoming = true;
                    callStartTime = new Date();
                    savedNumber = incomingNumber;
                    onIncomingCallStarted(incomingNumber, callStartTime);
                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    //Transition of ringing->offhook are pickups of incoming calls.  Nothing donw on them
                    if(lastState != TelephonyManager.CALL_STATE_RINGING){
                        isIncoming = false;
                        callStartTime = new Date();
                        onOutgoingCallStarted(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(savedNumber, callStartTime);
                    }
                    else if(isIncoming){
                        onIncomingCallEnded(savedNumber, callStartTime, new Date());                        
                    }
                    else{
                        onOutgoingCallEnded(savedNumber, callStartTime, new Date());                                                
                    }
                    break;
            }
            lastState = state;
        }

    }



}
like image 105
Gabe Sechan Avatar answered Sep 19 '22 15:09

Gabe Sechan