Search code examples
androidjakarta-mailtelephonymanager

CALL_STATE_IDLE call multiple times?


I have created call recording application that record all incoming and outgoing call. Application works perfectly I have tested it. I need to send background email (without user invention using JAVAMAIL) for recorded file. I have working code for sending mail with attachment. I have created broadcast receiver that listen PHONE_STATE and NEW_OUTGOING_CALL. Broadcast Receiver start/stop Recording service as per Phone state change. My question is how should I integrate my email sending code with application. I know I have to called mail sending method in CALL_STATE_IDLE. But as the method call multiple time I am not able to do so.

I am confused that is CALL_STATE_IDLE is right place to send email in background because it occurs multiple time.

For Incoming Call Phone State is CALL_STATE_RINGING CALL_STATE_OFFHOOK CALL_STATE_IDLE

For Outgoing Call Phone State is CALL_STATE_IDLE CALL_STATE_OFFHOOK CALL_STATE_IDLE

any help plz.. thanks in advance

CallBroadcastReceiver.java

public class CallBroadcastReceiver extends BroadcastReceiver {
    public static boolean IsOutgoingCall = false;
    public static String callNumber = "";

    public void onReceive(Context context, Intent intent) {

        Log.d("CallRecorder", "CallBroadcastReceiver::onReceive got Intent: "
                + intent.toString());
        if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {

            String numberToCall = intent
                    .getStringExtra(Intent.EXTRA_PHONE_NUMBER);
            Log.d("CallRecorder",
                    "CallBroadcastReceiver intent has EXTRA_PHONE_NUMBER: "
                            + numberToCall);
            IsOutgoingCall = true;
            callNumber = numberToCall;
        }

        PhoneListener phoneListener = new PhoneListener(context, intent);
        TelephonyManager telephony = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
        Log.d("PhoneStateReceiver::onReceive", "set PhoneStateListener");

    }
}

PhoneListener

public class PhoneListener extends PhoneStateListener {
    public static Context context;
    private Intent intent;

    public PhoneListener(Context c, Intent i) {
        Log.i("CallRecorder", "PhoneListener constructor");
        context = c;
        intent = i;
    }

    public void onCallStateChanged(int state, String incomingNumber) {
        Log.d("CallRecorder", "PhoneListener::onCallStateChanged state:"
                + state + " incomingNumber:" + incomingNumber);

        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.i("CallRecorder", "stopService for RecordService returned "
                    + stopped);

            break;
        case TelephonyManager.CALL_STATE_RINGING:

            Log.d("CallRecorder", "CALL_STATE_RINGING");
            Log.d("CallRecorder",
                    "CallBroadcastReceiver intent has EXTRA_PHONE_NUMBER: "
                            + incomingNumber);
            CallBroadcastReceiver.IsOutgoingCall = false;

            CallBroadcastReceiver.callNumber = incomingNumber;

            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:

            Log.d("CallRecorder", "CALL_STATE_OFFHOOK starting recording");
            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;
        }
    }
}

sendEmailWithAttachment()

File attachedFile = new File("/mnt/sdcard/Recording/123456789.mp4");
if(attachedFile.exists() && attachedFile.canRead()) {
    Log.v("SendMail", "File Exists");
    GMailSender sender = new GMailSender("your@gmail.com","your@gmail.com"); //<<< Enter Here
    sender.sendMail("Subject", "Body ", 
            "your@gmail.com", "to@gmail.com", attachedFile);

    emailsStatus = 1; // Send
} else {
    emailsStatus = 2; // File Not Exists
    Log.v("SendMail", "File Not Exists");
}

Solution

  • When Incoming call the state will be,

    If picked by the recepient:

    CALL_STATE_RINGING CALL_STATE_OFFHOOK CALL_STATE_IDLE
    

    If not picked by the recepient:

    CALL_STATE_RINGING CALL_STATE_IDLE
    

    When Outgoing call the state will be:

    If picked by the recepient:

    NEW_OUTGOING_CALL CALL_STATE_OFFHOOK CALL_STATE_IDLE
    

    If not picked by the recepient:

    NEW_OUTGOING_CALL  CALL_STATE_IDLE
    

    In your case you would want to send the mail only if the call was received, so I would suggest in CALL_STATE_OFFHOOK set a boolean variable to true to know the call was received and later in if the variable is true then in CALL_STATE_IDLE send the mail and set the variable false for next call. You don't mind if it was incoming call or outgoing call.

    Boolean iscallreceived=false;
    switch (state) {
        case TelephonyManager.CALL_STATE_OFFHOOK:
           iscallreceived=true;
            //your other code
        case TelephonyManager.CALL_STATE_IDLE:
           if(iscallreceived){
              sendmail();
              iscallreceived=false;
     }