在后台服务中运行时,AudioRecord不会从MIC或VOICE_DOWNLINK录制语音

时间:2015-01-08 09:21:36

标签: android service android-service audiorecord

我正在解决在语音通话中录制音频的问题。我正在使用AudioRecord来获取录制的缓冲区。现在问题是我想要一个始终运行的后台服务,每当PHONE_STATE为OFFHOOK时,它应该记录来自用户定义的AudioSource(MIC或VOICE_DOWNLINK)的缓冲区。

当我在活动按钮中录制语音时,AudioRecord正在录制缓冲区并将其保存为可在Audacity中播放的PCM格式。它的录制文件大小约为100KB,录制时间为2秒。

但是当我尝试在后台服务中启动AudioRecord时,它是录制无法在Audacity中播放的缓冲区。录制的文件大小约为25MB,录制的2秒钟也无法播放。

我进行了广泛的搜索,但还没有找到任何解决方案。我做错了什么?

以下是我的代码

这是我的CallRecordingService.java

public class CallRecordingService extends Service {
    private final IBinder mBinder = new CallRecordingBinder();
    private AudioRecorder mAudioRecorder;
    private boolean mRecording = false;
    public ByteBuffer buffer;

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

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        IntentFilter callRecordingFilter = new IntentFilter();
        callRecordingFilter.addAction("android.intent.action.PHONE_STATE");
        registerReceiver(phoneStateListener, callRecordingFilter);
        return Service.START_STICKY;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

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

    BroadcastReceiver phoneStateListener = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "Incoming", Toast.LENGTH_SHORT).show();

            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
            if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) {
                Toast.makeText(context, state + "- Recording Started ", Toast.LENGTH_SHORT).show();
                mAudioRecorder = new AudioRecorder(getApplicationContext());
                mAudioRecorder.recordAudio(null);
                mRecording = true;
            }

            if (TelephonyManager.EXTRA_STATE_IDLE.equals(state) && mRecording == true) {
                Toast.makeText(context, state + "- Recording Stopped", Toast.LENGTH_SHORT).show();
                mAudioRecorder.stopRecording();
                mRecording = false;
            }

            if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
                String fname = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                //Toast.makeText(context, state + " : " + fname, Toast.LENGTH_SHORT).show();
            }
        }
    };

    public class CallRecordingBinder extends Binder {
        CallRecordingService getService() {
            return CallRecordingService.this;
        }
    }
}

public class CallRecordingService extends Service { private final IBinder mBinder = new CallRecordingBinder(); private AudioRecorder mAudioRecorder; private boolean mRecording = false; public ByteBuffer buffer; @Override public void onCreate() { super.onCreate(); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { IntentFilter callRecordingFilter = new IntentFilter(); callRecordingFilter.addAction("android.intent.action.PHONE_STATE"); registerReceiver(phoneStateListener, callRecordingFilter); return Service.START_STICKY; } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public IBinder onBind(Intent intent) { return mBinder; } BroadcastReceiver phoneStateListener = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "Incoming", Toast.LENGTH_SHORT).show(); String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(state)) { Toast.makeText(context, state + "- Recording Started ", Toast.LENGTH_SHORT).show(); mAudioRecorder = new AudioRecorder(getApplicationContext()); mAudioRecorder.recordAudio(null); mRecording = true; } if (TelephonyManager.EXTRA_STATE_IDLE.equals(state) && mRecording == true) { Toast.makeText(context, state + "- Recording Stopped", Toast.LENGTH_SHORT).show(); mAudioRecorder.stopRecording(); mRecording = false; } if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) { String fname = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); //Toast.makeText(context, state + " : " + fname, Toast.LENGTH_SHORT).show(); } } }; public class CallRecordingBinder extends Binder { CallRecordingService getService() { return CallRecordingService.this; } } }

在AudioRecorder.java中(自定义类作为android AudioRecord.java的包装器)。我在recordAudio()方法中启动一个线程,读取缓冲区并将其保存在文件中,如下所示。

private void writeAudioDataToFile() {
        // Write the output audio in byte

        String filePath = "/sdcard/voice16K16bitmono.pcm";
        short sData[] = new short[BufferElements2Rec];

        FileOutputStream os = null;
        try {
            os = new FileOutputStream(filePath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        while (isRecording) {

            audioRecord.read(sData, 0, BufferElements2Rec);
            System.out.println("Short writing to file" + sData.toString());
            try {
                // // writes the data to file from buffer
                // // stores the voice buffer
                byte bData[] = short2byte(sData);
                Log.i("Size", "bData Size : " + bData.length);
                os.write(bData, 0, BufferElements2Rec * BytesPerElement);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        Log.i(TAG, "Message - Recording done.");


        try {
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

private byte[] short2byte(short[] sData) {
        int shortArrsize = sData.length;
        byte[] bytes = new byte[shortArrsize * 2];
        for (int i = 0; i < shortArrsize; i++) {
            bytes[i * 2] = (byte) (sData[i] & 0x00FF);
            bytes[(i * 2) + 1] = (byte) (sData[i] >> 8);
            sData[i] = 0;
        }
        return bytes;

    }

这是我开始服务的主要活动课程。

private void writeAudioDataToFile() { // Write the output audio in byte String filePath = "/sdcard/voice16K16bitmono.pcm"; short sData[] = new short[BufferElements2Rec]; FileOutputStream os = null; try { os = new FileOutputStream(filePath); } catch (FileNotFoundException e) { e.printStackTrace(); } while (isRecording) { audioRecord.read(sData, 0, BufferElements2Rec); System.out.println("Short writing to file" + sData.toString()); try { // // writes the data to file from buffer // // stores the voice buffer byte bData[] = short2byte(sData); Log.i("Size", "bData Size : " + bData.length); os.write(bData, 0, BufferElements2Rec * BytesPerElement); } catch (IOException e) { e.printStackTrace(); } } Log.i(TAG, "Message - Recording done."); try { os.close(); } catch (IOException e) { e.printStackTrace(); } } private byte[] short2byte(short[] sData) { int shortArrsize = sData.length; byte[] bytes = new byte[shortArrsize * 2]; for (int i = 0; i < shortArrsize; i++) { bytes[i * 2] = (byte) (sData[i] & 0x00FF); bytes[(i * 2) + 1] = (byte) (sData[i] >> 8); sData[i] = 0; } return bytes; }

这是我的AndroidManifest.xml文件

public class MainActivity extends Activity {

    private CallRecordingService mService = null;
    private Button startRecordingService, stopRecordingService;
    private static MainActivity activityInstance;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityInstance = this;
        setContentView(R.layout.activity_main);

        startRecordingService = (Button) findViewById(R.id.btnStartRecording);
        stopRecordingService = (Button) findViewById(R.id.btnStopRecording);

        startRecordingService.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), CallRecordingService.class);
                bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
                startService(intent);
            }
        });

        stopRecordingService.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                unbindService(mConnection);
            }
        });
    }

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

    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            CallRecordingService.CallRecordingBinder b = (CallRecordingService.CallRecordingBinder) service;
            mService = b.getService();
        }
    };

    public static MainActivity getInstance() {
        return activityInstance;
    }
}

public class MainActivity extends Activity { private CallRecordingService mService = null; private Button startRecordingService, stopRecordingService; private static MainActivity activityInstance; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); activityInstance = this; setContentView(R.layout.activity_main); startRecordingService = (Button) findViewById(R.id.btnStartRecording); stopRecordingService = (Button) findViewById(R.id.btnStopRecording); startRecordingService.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(getApplicationContext(), CallRecordingService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); startService(intent); } }); stopRecordingService.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { unbindService(mConnection); } }); } @Override public void onResume() { super.onResume(); } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { CallRecordingService.CallRecordingBinder b = (CallRecordingService.CallRecordingBinder) service; mService = b.getService(); } }; public static MainActivity getInstance() { return activityInstance; } }

1 个答案:

答案 0 :(得分:0)

我终于解决了这个问题。我必须在Android代码中进行一些框架更改才能启用此功能。由于法律问题,一些OEM禁用了通话记录功能。

相关问题