【问题标题】:How to record phone calls in Android如何在Android中记录电话
【发布时间】:2015-10-14 18:37:38
【问题描述】:

我正在开发一个可以在 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);
    }

}

【问题讨论】:

  • 检查This Out
  • 我使用的是相同的代码 recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL); //语音下行/上行recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);录音机.setAudioEncoder(AudioEncoder.AAC);但这对我没有帮助。我认为 PlayMarket 上的这些顶级应用程序正在使用 MediaRecorder.AudioSource.MIC 并且还增加了设备上扬声器的声音以记录双方。您对此有何看法?
  • “你在想什么?”听起来你最终会得到一个非常糟糕的录音。另外,也许您不想一直使用免提模式。
  • 好的,所以这不是一个好主意。我在我的应用程序中使用了很多不同的输入和输出(CAMCORDER、DEFAULT、MIC、REMOTE_SUBMIX、VOICE_CALL、VOICE_COMMUNICATION、VOICE_DOWNLINK、VOICE_RECOGNITION、VOICE_UPLINK)。但他们都只录了我的声音,或者根本不工作。

标签: java android phone-call


【解决方案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();
    }

【讨论】:

  • 非常感谢您的回答。你能告诉我更多关于管道的信息吗?如何创建它?
  • 非常感谢您提供的代码!我会尝试在我的应用程序中实现它。目前,我正在使用此代码开始录制(这不是所有代码,而是其中的一些代码) File file = new File(savePath); savePath += "/record_" + System.currentTimeMillis() + ".amr"; mRecorder = new MediaRecorder(); mRecorder.setAudioSource(inputSource); mRecorder.setOutputFormat(outputSource); mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mRecorder.setOutputFile(savePath);
  • 对不起我的坚持,请问lss变量属于哪个类?谢谢)
  • 我认为它的本地服务器套接字。当我回到我的笔记本电脑时会检查。
  • socketId = new Random().nextInt(); lss = new LocalServerSocket("com.companyname.media-" + somesocketId);
猜你喜欢
  • 2013-09-24
  • 2016-09-09
  • 1970-01-01
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多