Android中實(shí)現(xiàn)系統(tǒng)聲音錄制-RK3399開(kāi)發(fā)板源碼修改
前言
這幾天做系統(tǒng)聲音錄制,通過(guò)改源碼編譯后成功的;那就詳細(xì)介紹下內(nèi)置聲源的錄制方案。
Android中可以通過(guò)使用MediaRecorder.AudioSource.REMOTE_SUBMIX來(lái)實(shí)現(xiàn)系統(tǒng)聲音的錄制,這個(gè)屬性只有系統(tǒng)應(yīng)用能夠使用。
而且這個(gè)屬性會(huì)截掉耳機(jī)和揚(yáng)聲器的聲音,聽(tīng)不到手機(jī)中播放音樂(lè)或者視頻時(shí)的聲音。
這個(gè)時(shí)候我們就要來(lái)改系統(tǒng)源碼。
一、錄音的簡(jiǎn)單實(shí)現(xiàn)
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.REMOTE_SUBMIX
, captureSampleRate
, captureChannel
, AudioFormat.ENCODING_PCM_16BIT
, recordBufferSize);
new Thread(new Runnable() {
public void run() {
final byte[] bytes = new byte[recordBufferSize];
audioRecord.read(bytes, 0, bytes.length);
audioRecord.setPositionNotificationPeriod(captureSampleRate / 25);
audioRecord.setRecordPositionUpdateListener(new AudioRecord.OnRecordPositionUpdateListener() {
public void onMarkerReached(AudioRecord recorder) {
}
public void onPeriodicNotification(AudioRecord recorder) {
singleThreadPool.execute(new Runnable() {
public void run() {
try {
if(audioRecord!=null){
audioRecord.read(bytes, 0, bytes.length);
PcmBuffer.clear();
PcmBuffer.put(bytes, 0, recordBufferSize);
audioFrameParam.sampleRate = ZEGO_AUDIO_SAMPLE_RATE_44K;
//聲音的處理
}
}catch (Exception e){
e.printStackTrace();
}
}
});
}
});
audioRecord.startRecording();
}
}).start();
二、AudioSource輸入源介紹?
public final class AudioSource {
private AudioSource() {}
/** Default audio source **/
public static final int DEFAULT = 0;
/** Microphone audio source */
public static final int MIC = 1;
/** Voice call uplink (Tx) audio source */
public static final int VOICE_UPLINK = 2;
/** Voice call downlink (Rx) audio source */
public static final int VOICE_DOWNLINK = 3;
/** Voice call uplink + downlink audio source */
public static final int VOICE_CALL = 4;
/** Microphone audio source with same orientation as camera if available, the main
* device microphone otherwise */
public static final int CAMCORDER = 5;
public static final int VOICE_RECOGNITION = 6;
public static final int VOICE_COMMUNICATION = 7;
public static final int REMOTE_SUBMIX = 8;
}
- DEFAULT:默認(rèn)為MIC,android.permission.RECORD_AUDIO。
- MIC:麥克風(fēng),android.permission.RECORD_AUDIO。
- VOICE_UPLINK:電話(huà)錄音上行線路,android.permission.CAPTURE_AUDIO_OUTPUT,系統(tǒng)權(quán)限不允許第三方app使用 。
- VOICE_DOWNLINK:電話(huà)錄音下行線路,android.permission.CAPTURE_AUDIO_OUTPUT,系統(tǒng)權(quán)限不允許第三方app使用。
- VOICE_CALL:電話(huà)錄音上下線路,android.permission.CAPTURE_AUDIO_OUTPUT,系統(tǒng)權(quán)限不允許第三方app使用 。
- CAMCORDER:攝像頭的麥克風(fēng),android.permission.RECORD_AUDIO。
- VOICE_RECOGNITION:語(yǔ)音識(shí)別,android.permission.RECORD_AUDIO。
- VOICE_COMMUNICATION:網(wǎng)絡(luò)電話(huà),android.permission.RECORD_AUDIO。
- REMOTE_SUBMIX:傳輸?shù)竭h(yuǎn)程的音頻混合流,默認(rèn)情況下如果用該項(xiàng)錄音,本地?fù)P聲器或者耳機(jī)的聲音將會(huì)被截走,android.permission.CAPTURE_AUDIO_OUTPUT,系統(tǒng)權(quán)限不允許第三方app使用。
REMOTE_SUBMIX使用的注意事項(xiàng)
(1)需要系統(tǒng)權(quán)限 。
(2)會(huì)截走揚(yáng)聲器和耳機(jī)的聲音,也就是說(shuō)再錄音時(shí)本地?zé)o法播放聲音。
對(duì)于系統(tǒng)權(quán)限,需要在在AndroidManifest.xml添加 android:sharedUserId="android.uid.system",然后使用系統(tǒng)簽名來(lái)打包應(yīng)用,這樣就第三方應(yīng)用打包為系統(tǒng)應(yīng)用,就可以使用系統(tǒng)權(quán)限了。
三、源碼修改
1、Android 10及以下的錄屏
frameworks\av\services\audiopolicy\enginedefault\src\Engine.cpp
if(mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}
修改為:
if (mAvailableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
device2 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_WIRED_HEADPHONE);
device2 |= (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER);
}
2、Android 11
目標(biāo)frameworks\av\services\audiopolicy\enginedefault\src\Engine.cpp
if ((remoteSubmix = availableOutputDevices.getDevice(
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0"),
AUDIO_FORMAT_DEFAULT)) != nullptr) {
devices2.add(remoteSubmix);
}
修改為?:
if ((remoteSubmix = availableOutputDevices.getDevice(
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0"),
AUDIO_FORMAT_DEFAULT)) != nullptr) {
devices2 = availableOutputDevices.getDevicesFromTypes({
AUDIO_DEVICE_OUT_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_WIRED_HEADPHONE, AUDIO_DEVICE_OUT_SPEAKER});
}
總結(jié)?
要實(shí)現(xiàn)安卓錄制系統(tǒng)聲音,正常情況下是獲取不到的,這個(gè)方案是修改源碼的方式來(lái)實(shí)現(xiàn)。
后面可以介紹下系統(tǒng)是怎么實(shí)現(xiàn)的,可以把源碼貼出來(lái),大家一起學(xué)習(xí)。