Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to record phone calls in Android

I am developing an application which can record calls in Android. I have read a lot of topics where the call recording problem was discussed. And i know that not all Android phones can record calls. But i am wondering how can record calls the most popular applications on Play Market, such as https://play.google.com/store/apps/details?id=com.appstar.callrecorder or https://play.google.com/store/apps/details?id=polis.app.callrecorder. I think that thy are using not on MediaRecorder class to do this job, but also something else. Because i have developed my own application, but i can record only my voice. But these two applications are recording both my voice and the voice of a man to whom i am calling. How they are doing this? I know that we can't get an access to device speaker to record sound from it. Could you give me some ideas of how to record voice calls? Here is my code that i am using in my application:

public class CallRecorderService extends Service {

    private MediaRecorder mRecorder;
    private boolean isRecording = false;

    private PhoneStateListener phoneStateListener = new PhoneStateListener() {

        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            switch (state) {
                case TelephonyManager.CALL_STATE_IDLE:
                    stopRecording();
                break;
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    startRecording(incomingNumber);
                break;
                case TelephonyManager.CALL_STATE_RINGING:
                break;
                default:

                break;
            }
        }
    };

    @Override
    public void onCreate() {
        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void startRecording(String number) {
        try {
            String savePath = Environment.getExternalStorageDirectory().getAbsolutePath();
            savePath += "/Recorded";
            File file = new File(savePath);
            if (!file.exists()) {
                file.mkdir();
            }

            savePath += "/record_" + System.currentTimeMillis() + ".amr";
            mRecorder = new MediaRecorder();

            SharedPreferences sPrefs = getSharedPreferences(Constants.PREFERENCES_NAME, Context.MODE_PRIVATE);
            int inputSource = sPrefs.getInt(Constants.SOURCE_INPUT, Constants.SOURCE_VOICE_CALL);
            int outputSource = sPrefs.getInt(Constants.SOURCE_OUTPUT, Constants.OUTPUT_MPEG4);

            switch (inputSource) {
                case Constants.SOURCE_MIC:
                    increaseSpeakerVolume();
                break;
            }

            mRecorder.setAudioSource(inputSource);
            mRecorder.setOutputFormat(outputSource);
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mRecorder.setOutputFile(savePath);
            mRecorder.prepare();
            mRecorder.start();
            isRecording = true;

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void stopRecording(){
        if (isRecording) {
            isRecording = false;
            mRecorder.stop();
            mRecorder.release();
        }
    }

    private void increaseSpeakerVolume(){

        AudioManager audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        audio.adjustStreamVolume(AudioManager.STREAM_VOICE_CALL,
                AudioManager.ADJUST_RAISE,
                AudioManager.FLAG_SHOW_UI);
    }

}
like image 641
bukka.wh Avatar asked Jul 24 '15 07:07

bukka.wh


1 Answers

I think they do use MediaRecorder. Perhaps main problem with it is that, it is tricky to write the data from it into something else but file on local store. In order to work it around, you could create a pipe. Then use its file descriptor as an input fd for MediaRecorder. And the pipe output then could be controlled by some thread that will read the audio packages (in one of format, aac or.. wav even) and then do whatever you want with the data.

Here is some code. Note, this is a proto, may not even compile, just to give you an idea.

        /* 2M buffer should be enough. */
        private final static int SOCKET_BUF_SIZE = 2 * 1024 * 1000;

        private void openSockets() throws IOException {
            receiver = new LocalSocket();
            receiver.connect(new LocalSocketAddress("com.companyname.media-" + socketId));
            receiver.setReceiveBufferSize(SOCKET_BUF_SIZE);
            sender = lss.accept();
            sender.setSendBufferSize(SOCKET_BUF_SIZE);
        }

        private void closeSockets() {
            try {
                if (sender != null) {
                    sender.close();
                    sender = null;
                }
                if (receiver != null) {
                    receiver.close();
                    receiver = null;
                }
            } catch (Exception ignore) {
            }
        }


      public void prepare() throws IllegalStateException, IOException {
        int samplingRate;

        openSockets();

        if (mode == MODE_TESTING) {
            samplingRate = requestedSamplingRate;
        } else {
            samplingRate = actualSamplingRate;
        }
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        try {
            Field name = MediaRecorder.OutputFormat.class.getField("AAC_ADTS");
            if (BuildConfig.DEBUG)
                Log.d(StreamingApp.TAG, "AAC ADTS seems to be supported: AAC_ADTS=" + name.getInt(null));
            mediaRecorder.setOutputFormat(name.getInt(null));
        } catch (Exception e) {
            throw new IOException("AAC is not supported.");
        }

        try {
            mediaRecorder.setMaxDuration(-1);
            mediaRecorder.setMaxFileSize(Integer.MAX_VALUE);
        } catch (RuntimeException e) {
            Log.e(StreamingApp.TAG, "setMaxDuration or setMaxFileSize failed!");
        }

        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mediaRecorder.setAudioChannels(1);
        mediaRecorder.setAudioSamplingRate(samplingRate);
        mediaRecorder.setOutputFile(sender.getFileDescriptor());

        startListenThread(receiver.getInputStream());
        mediaRecorder.start();
    }
like image 172
Cynichniy Bandera Avatar answered Nov 14 '22 23:11

Cynichniy Bandera