如何在Android中录制电话

时间:2015-07-24 07:27:54

标签: java android phone-call

我正在开发一个可以在Android中录制通话的应用程序。我已经阅读了很多讨论呼叫录音问题的主题。我知道并非所有Android手机都可以录制通话。但我想知道如何在Play Market上录制最受欢迎的应用程序,例如https://play.google.com/store/apps/details?id=com.appstar.callrecorderhttps://play.google.com/store/apps/details?id=polis.app.callrecorder。我认为你不是在MediaRecorder课上使用它来完成这项工作,而是还有别的东西。因为我已经开发了自己的应用程序,但我只能录制我的声音。但是这两个应用程序正在记录我的声音和我呼唤的男人的声音。他们是怎么做到的?我知道我们无法访问设备扬声器来录制声音。你能给我一些关于如何录制语音电话的想法吗?这是我在我的应用程序中使用的代码:

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);
    }

}

1 个答案:

答案 0 :(得分:1)

我认为他们确实使用了MediaRecorder。也许它的主要问题在于,将数据从其中写入其他东西而不是本地存储上的文件是很棘手的。为了解决它,你可以创建一个管道。然后使用其文件描述符作为MediaRecorder的输入fd。然后管道输出可以由一些线程控制,该线程将读取音频包(格式,aac或..甚至wav中的一种),然后随意对数据做任何事情。

这是一些代码。注意,这是一个原型,可能甚至不能编译,只是为了给你一个想法。

        /* 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();
    }