Mariam Donbosco
Mariam Donbosco

Reputation: 1

Is it possible to record both incoming and outgoing calls in android, I tried using media recorder, but the need was not fulfilled

This is my Receiver Class where i'm getting phone state of both incoming and outgoing calls

public class MyBroadcastReceiver extends BroadcastReceiver {

    private static final String TAG = "MyBroadcastReceiver";
    //The receiver will be recreated whenever android feels like it.  We need a static variable to remember data between instantiations

    private String phoneIncomingNumber = "";
    private String PhoneState = "";
    private String Message = "";
    private MediaRecorder recorder;

    Context context;

    //Call Recording varibales
    private static final String AUDIO_RECORDER_FILE_EXT_3GP = ".3gp";
    private static final String AUDIO_RECORDER_FILE_EXT_MP4 = ".mp3";
    private static final String AUDIO_RECORDER_FOLDER = "Recordings";

    Uri audiouri;
    ParcelFileDescriptor file;
    AudioManager audioManager;
    private int currentFormat = 0;
    private int output_formats[] = { MediaRecorder.OutputFormat.MPEG_4,
            MediaRecorder.OutputFormat.THREE_GPP };
    private String file_exts[] = { AUDIO_RECORDER_FILE_EXT_MP4,
            AUDIO_RECORDER_FILE_EXT_3GP };

    //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) {
        // TODO: This method is called when the BroadcastReceiver is receiving
//        Registering service
        context.startService(new Intent(context, MyService.class));

//      Getting Call Details
        String stateStr = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        phoneIncomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

        Log.d("Call Status1", "Number1: " + phoneIncomingNumber + ":STATE : " + stateStr);

        if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
            savedNumber = intent.getStringExtra("android.intent.extra.PHONE_NUMBER");
        } else {
            phoneIncomingNumber = intent.getStringExtra(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;
                startRecording(getRecordFileName(phoneIncomingNumber), context);
            } else if (stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
                state = TelephonyManager.CALL_STATE_RINGING;
            }
            onCallStateChanged(context, state, phoneIncomingNumber);
        }
    }

    //Derived classes should override these to respond to specific events of interest
    protected void onIncomingCallStarted(Context ctx, String number, Date start) {

        Message = "Call from : \"+number+\" on DATE \"+start+\" started";
        Log.d("Call Status", "INCOMING CALL STARTED");

    }

    protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
        Message = "Call to : \"+number+\" on DATE \"+start+\" started";
        Log.d("Call Status", "OUTGOING CALL STARTED to :" + number);
        PhoneState = "OFFHOOK";

    }

    protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
        Log.d("Call Status", "INCOMING CALL ENDED");
        Message = "Call from : \"+number+\" on DATE \"+start+\" ended";
        stopRecording();
    }

    protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
        Message = "Call to : \"+number+\" on DATE \"+start+\" ended";
        Log.d("Call Status", "OUTGOING CALL ENDED");
        stopRecording();
    }

    protected void onMissedCall(Context ctx, String number, Date start) {
        Message = "Missed call : \"+number+\" on DATE \"+start+\"";
        Log.d("Call Status", "MISSED CALL");
      
    }

    //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) {
        Log.d("Call", "Number: " + number);
        if (lastState == state) {
            //No change, debounce extras
            return;
        }
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                isIncoming = true;
                callStartTime = new Date();
                savedNumber = number;
                PhoneState = "RINGING";
                onIncomingCallStarted(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();
                    PhoneState = "OFFHOOK";
                    onOutgoingCallStarted(context, phoneIncomingNumber, 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
                    PhoneState = "IDLE";
                    onMissedCall(context, phoneIncomingNumber, callStartTime);
                } else if (isIncoming) {
                    PhoneState = "INCOMING CALL ENDED";
                    onIncomingCallEnded(context, phoneIncomingNumber, callStartTime, new Date());
                } else {
                    PhoneState = "OUTGOING CALL ENDED";
                    onOutgoingCallEnded(context, phoneIncomingNumber, callStartTime, new Date());
                }
                break;
        }
        lastState = state;
    }

 

    private MediaRecorder.OnErrorListener errorListener = new MediaRecorder.OnErrorListener() {
        @Override
        public void onError(MediaRecorder mr, int what, int extra) {
            Toast.makeText(context,
                    "Error: " + what + ", " + extra, Toast.LENGTH_SHORT).show();
        }
    };

    private MediaRecorder.OnInfoListener infoListener = new MediaRecorder.OnInfoListener() {
        @Override
        public void onInfo(MediaRecorder mr, int what, int extra) {
            Toast.makeText(context,
                            "Warning: " + what + ", " + extra, Toast.LENGTH_SHORT)
                    .show();
        }
    };


    //    Recording Audio
    private void startRecording(String fileName, Context ctx) {
        Log.d("Call Status", "Inside");
        ContentValues values = new ContentValues(4);
        values.put(MediaStore.Audio.Media.TITLE, fileName);
        values.put(MediaStore.Audio.Media.DATE_ADDED, (int) (System.currentTimeMillis() / 1000));
        values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/mpeg");
        values.put(MediaStore.Audio.Media.RELATIVE_PATH, "Music/Recordings/");

        audiouri = ctx.getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
        Log.d("Call Status", "Call Status: "+audiouri);
        try {
            file = ctx.getContentResolver().openFileDescriptor(audiouri, "w");
        } catch (Exception e) {
            Log.d("Call Status", "File Error"+e);
        }


        audioManager = (AudioManager) ctx.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
        audioManager.setMode(AudioManager.MODE_IN_CALL);
//        audioManager.setSpeakerphoneOn(true);

        recorder = new MediaRecorder();
        recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
        recorder.setOutputFormat(output_formats[currentFormat]);
        //recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        recorder.setOutputFile(file.getFileDescriptor());
        recorder.setOnErrorListener(errorListener);
        recorder.setOnInfoListener(infoListener);

        try {
            recorder.prepare();
            recorder.start();
        } catch (IllegalStateException e) {
            Log.e("REDORDING :: ",e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            Log.e("REDORDING :: ",e.getMessage());
            e.printStackTrace();
        }
         }

    private void stopRecording() {
//        audioManager.setSpeakerphoneOn(false);

        try{
            if (null != recorder) {
                recorder.stop();
                recorder.reset();
                recorder.release();

                recorder = null;
            }
        }catch(Exception stopException){
            Log.d("Exce",stopException+"");
        }
    }

    private String getRecordFileName(String phoneNumber) {
        // Generate a unique file name based on the phone number and the current time
        String timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        return phoneNumber + "_" + timeStamp + ".wav";
    }

}

My Service Class to run receiver as a forground service

public class MyService extends Service {

private static final int SERVICE_NOTIFICATION_ID =2 ;
private static final String CHANNEL_ID = "PhoneStateModule";

public MyService() {
}

private Handler handler = new Handler();
private Runnable runnableCode = new Runnable() {
    @Override
    public void run() {
        try{
            handler.postDelayed(this, 2000);
        }catch (Exception ex){
            Log.d("Error",ex+"");
        }

    }
};

private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "PhoneStateModule", importance);
        channel.setDescription("CHANEL DESCRIPTION");
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    this.handler.post(this.runnableCode); // Starting the interval
    // Turning into a foreground service
    createNotificationChannel(); // Creating channel for API 26+
    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT|PendingIntent.FLAG_MUTABLE);
    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Phone Recording Service")
            .setContentText("Running…")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(contentIntent)
            .setOngoing(true)
            .build();
    startForeground(SERVICE_NOTIFICATION_ID, notification);
    return START_STICKY;
}

@Override
public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
   return null;
}

}

Can anyone help me with the issue facing, I am using device with android 10 and am not getting the recordings, even if the recording is saved inside folder I'm not getting any audio.

Upvotes: 0

Views: 144

Answers (0)

Related Questions