1. 程式人生 > >如何使Android錄音實現內錄功能

如何使Android錄音實現內錄功能

背景

之前在做直播的時候需要使用到內錄功能,比如經常看到遊戲主播在直播玩遊戲,遊戲的聲音不是通過MIC錄製的,而是內錄完成的。故在此記錄一下。

相信大家都很熟悉Android如果錄音的了:

         int frequency = 44100;
        int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
        int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
        int minBufferSize = AudioRecord.getMinBufferSize(frequency, channelConfiguration,    audioEncoding);
        int
audioSource = MediaRecorder.AudioSource.MIC; AudioRecord audioRecord = new AudioRecord(audioSource, frequency, channelConfiguration, audioEncoding, minBufferSize); audioRecord.startRecording(); ...

AudioSource輸入源介紹

專案 介紹 許可權
DEFAULT 預設。在原始碼 system/media/audio/include/system/audio.h配置預設項
MIC 麥克風
VOICE_UPLINK 電話錄音上行線路 android.permission.CAPTURE_AUDIO_OUTPUT,系統許可權不允許第三方app使用
VOICE_DOWNLINK 電話錄音下行線路 android.permission.CAPTURE_AUDIO_OUTPUT,系統許可權不允許第三方app使用
VOICE_CALL 電話錄音上下線路 android.permission.CAPTURE_AUDIO_OUTPUT,系統許可權不允許第三方app使用
CAMCORDER 攝像頭的麥克風
VOICE_RECOGNITION 語音識別
VOICE_COMMUNICATION 網路電話
REMOTE_SUBMIX 傳輸到遠端的音訊混合流。預設情況下如何用該項錄音,本地揚聲器或者耳機的聲音將會被截走 android.permission.CAPTURE_AUDIO_OUTPUT,系統許可權不允許第三方app使用

好了,現在我們知道了REMOTE_SUBMIX可以實現內錄功能了。有兩點比較麻煩:

  • 需要系統許可權

  • 會截走揚聲器和耳機的聲音,也就是說再錄音時本地無法播放聲音

系統許可權問題

這個對我來說比較好辦,因為我是直接在android裝置板子上開發,可以直接使用系統簽名編譯。首先在AndroidManifest.xml新增
android:sharedUserId="android.uid.system"
其次,

第一種方法:

adb shell 執行:
signapk.jar platform.x509.pem platform.pk8 app-unsigned.apk signed.apk
adb push signed.apk /system/app

第二種方法:

編寫Android.mk : 設定簽名為platform

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src) 
LOCAL_PACKAGE_NAME := YourApp
LOCAL_CERTIFICATE := platform
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))

截走揚聲器和耳機的聲音問題

修改framework下av/services/audiopolicy/AudioPolicyManager.cpp

audio_devices_t AudioPolicyManager::getDeviceForStrategy(routing_strategy strategy,
                                                             bool fromCache)

getDeviceForStrategy方法下找到

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

意思是聲音輸出的裝置添加了耳機和揚聲器,這裡可根據實際情況設定。
至此,將最開始的錄音程式碼

int audioSource = MediaRecorder.AudioSource.MIC;

改成

int audioSource = MediaRecorder.AudioSource.REMOTE_SUBMIX;

就可以實現內錄功能了。
<br/>

ps:

在不修改原始碼的情況下,第三方app目前暫不知如何實現內錄。

延伸閱讀

5.0以後請求Android錄屏預設會彈出確認框,但在系統app下請求就不會彈出了(具體可以去看原始碼)。這也是為了谷歌為了安全考慮。
不過5.0的時候這個彈框卻是一個大漏洞,被國內360發現了,給你們連結^_^
Android 5.0螢幕錄製漏洞