Android实现录音功能

Android实现录音功能,第1张

1 Android录音需要声明录音权限

<uses-permission android:name="androidpermissionRECORD_AUDIO" />

<uses-permission android:name="androidpermissionWRITE_EXTERNAL_STORAGE" />

<uses-permission android:name="androidpermissionREAD_EXTERNAL_STORAGE" />

2录音文件要写到文件夹中,创建文件夹,在Application的onCreate方法中创建文件夹

@Override

public void onCreate() {

    superonCreate();

    CrashHandler mCrashHandler = CrashHandlergetInstance();

    mCrashHandlerinit(getApplicationContext(), getClass());

    initFile();

}

private void initFile() {

    //录音文件

    File audioFile = new File(ConstantUrlAudio);

    if (!audioFileexists()) {

        audioFilemkdirs();

    } else if (!audioFileisDirectory()) {

        audioFiledelete();

        audioFilemkdirs();

    }

    //拍摄文件

    File imageFile = new File(ConstantUrlImage);

    if (!imageFileexists()) {

        imageFilemkdirs();

    } else if (!imageFileisDirectory()) {

        imageFiledelete();

        imageFilemkdirs();

    }

}

ConstantUrlImage是个静态的文件路径

//录音文件

public static String UrlAudio = FileUtilgetSdcardPathOnSys()+"/EhmFile/media/audio/";

3在activity中开始录音

import androidxappcompatappAppCompatActivity;

import androidosBundle;

import androidosEnvironment;

import androidosHandler;

import androidosMessage;

import androidmediaMediaRecorder;

import androidtextformatDateFormat;

import androidutilLog;

import androidviewView;

import androidwidgetButton;

import androidwidgetTextView;

import javaioFile;

import javaioIOException;

import javautilCalendar;

import javautilLocale;

public class Record2Activity extends AppCompatActivity {

    // 录音界面相关

    Button btnStart;

    Button btnStop;

    TextView textTime;

    // 录音功能相关

    MediaRecorder mMediaRecorder; // MediaRecorder 实例

    boolean isRecording; // 录音状态

    String fileName; // 录音文件的名称

    String filePath; // 录音文件存储路径

    Thread timeThread; // 记录录音时长的线程

    int timeCount; // 录音时长 计数

    final int TIME_COUNT = 0x101;

    // 录音文件存放目录

    final String audioSaveDir = EnvironmentgetExternalStorageDirectory()getAbsolutePath() + "/audiodemo/";

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        superonCreate(savedInstanceState);

        setContentView(Rlayoutactivity_record2);

        btnStart = (Button) findViewById(Ridbtn_start);

        btnStop = (Button) findViewById(Ridbtn_stop);

        textTime = (TextView) findViewById(Ridtext_time);

        btnStartsetOnClickListener(new ViewOnClickListener() {

            @Override

            public void onClick(View v) {

// 开始录音

                btnStartsetEnabled(false);

                btnStopsetEnabled(true);

                startRecord();

                isRecording = true;

// 初始化录音时长记录

                timeThread = new Thread(new Runnable() {

                    @Override

                    public void run() {

                        countTime();

                    }

                });

                timeThreadstart();

            }

        });

        btnStopsetOnClickListener(new ViewOnClickListener() {

            @Override

            public void onClick(View v) {

// 停止录音

                btnStartsetEnabled(true);

                btnStopsetEnabled(false);

                stopRecord();

                isRecording = false;

            }

        });

    }

    // 记录录音时长

    private void countTime() {

        while (isRecording) {

            Logd("mediaRe","正在录音");

            timeCount++;

            Message msg = Messageobtain();

            msgwhat = TIME_COUNT;

            msgobj = timeCount;

            myHandlersendMessage(msg);

            try {

                timeThreadsleep(1000);

            } catch (InterruptedException e) {

                eprintStackTrace();

            }

        }

        Logd("mediaRec", "结束录音");

        timeCount = 0;

        Message msg = Messageobtain();

        msgwhat = TIME_COUNT;

        msgobj = timeCount;

        myHandlersendMessage(msg);

    }

    /

    开始录音 使用amr格式

    录音文件

   

    @return

    /

    public void startRecord() {

// 开始录音

        / ①Initial:实例化MediaRecorder对象 /

        if (mMediaRecorder == null)

            mMediaRecorder = new MediaRecorder();

        try {

            / ②setAudioSource/setVedioSource /

            mMediaRecordersetAudioSource(MediaRecorderAudioSourceMIC);// 设置麦克风

            /

            ②设置输出文件的格式:THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP(3gp格式

            ,H263视频/ARM音频编码)、MPEG-4、RAW_AMR(只支持音频且音频编码要求为AMR_NB)

            /

            mMediaRecordersetOutputFormat(MediaRecorderOutputFormatMPEG_4);

            / ②设置音频文件的编码:AAC/AMR_NB/AMR_MB/Default 声音的(波形)的采样 /

            mMediaRecordersetAudioEncoder(MediaRecorderAudioEncoderAAC);

            fileName = DateFormatformat("yyyyMMdd_HHmmss", CalendargetInstance(LocaleCHINA)) + "m4a";

            //注意文件夹要创建之后才能使用

            filePath = ConstantUrlAudio + fileName;

            / ③准备 /

            mMediaRecordersetOutputFile(filePath);

            mMediaRecorderprepare();

            / ④开始 /

            mMediaRecorderstart();

        } catch (IllegalStateException e) {

            Logi("mediaEr", "call startAmr(File mRecAudioFile) failed!" + egetMessage());

        } catch (IOException e) {

            eprintStackTrace();

            Logi("mediaEr", "call startAmr(File mRecAudioFile) failed!" + egetMessage());

        }

    }

    /

    停止录音

    /

    public void stopRecord() {

//有一些网友反应在50以上在调用stop的时候会报错,翻阅了一下谷歌文档发现上面确实写的有可能会报错的情况,捕获异常清理一下就行了,感谢大家反馈!

        try {

            mMediaRecorderstop();

            mMediaRecorderrelease();

            mMediaRecorder = null;

            filePath = "";

        } catch (RuntimeException e) {

            Loge("mediaR", etoString());

            mMediaRecorderreset();

            mMediaRecorderrelease();

            mMediaRecorder = null;

            File file = new File(filePath);

            if (fileexists())

                filedelete();

            filePath = "";

        }

    }

    // 格式化 录音时长为 秒

    public static String FormatMiss(int miss) {

        return "" + miss;

    }

    Handler myHandler = new Handler() {

        @Override

        public void handleMessage(Message msg) {

            switch (msgwhat) {

                case TIME_COUNT:

                    int count = (int) msgobj;

                    Logd("meidaRe","count == " + count);

                    textTimesetText(FormatMiss(count));

                    break;

            }

        }

    };

    @Override

    protected void onDestroy() {

        superonDestroy();

        myHandlerremoveCallbacksAndMessages(null);

    }

}

布局文件很简单

<xml version="10" encoding="utf-8">

<androidxconstraintlayoutwidgetConstraintLayout xmlns:android=">

如下:

华为手机录音可以用手机自带的录音功能,打开录音机,即可根据 *** 作完成录音。具体 *** 作步骤如下:

工具/原料:华为畅享50、安卓900、录音机10。

1、首先,打开华为手机,在桌面上点击实用工具。

2、进入实用工具后,我们接着点击录音机,如图所示。

3、最后,我们点击下面的红圆点就可以录音了。

之前在做直播的时候需要使用到内录功能,比如经常看到游戏主播在直播玩游戏,游戏的声音不是通过MIC录制的,而是内录完成的。故在此记录一下。

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

int frequency = 44100;        int audioEncoding = AudioFormatENCODING_PCM_16BIT;        int channelConfiguration = AudioFormatCHANNEL_CONFIGURATION_MONO;        int minBufferSize = AudioRecordgetMinBufferSize(frequency, channelConfiguration,    audioEncoding);        int audioSource = MediaRecorderAudioSourceMIC;
AudioRecord audioRecord = new AudioRecord(audioSource, frequency,
channelConfiguration, audioEncoding, minBufferSize);
audioRecordstartRecording();

AudioSource输入源介绍

项目

介绍

权限

DEFAULT    默认。在源码 system/media/audio/include/system/audioh配置默认项    无  

MIC    麦克风    无  

VOICE_UPLINK    电话录音上行线路    androidpermissionCAPTURE_AUDIO_OUTPUT,系统权限不允许第三方app使用  

VOICE_DOWNLINK    电话录音下行线路    androidpermissionCAPTURE_AUDIO_OUTPUT,系统权限不允许第三方app使用  

VOICE_CALL    电话录音上下线路    androidpermissionCAPTURE_AUDIO_OUTPUT,系统权限不允许第三方app使用  

CAMCORDER    摄像头的麦克风    无  

VOICE_RECOGNITION    语音识别    无  

VOICE_COMMUNICATION    网络电话    无  

REMOTE_SUBMIX    传输到远程的音频混合流。默认情况下如何用该项录音,本地扬声器或者耳机的声音将会被截走    androidpermissionCAPTURE_AUDIO_OUTPUT,系统权限不允许第三方app使用  

好了,现在我们知道了REMOTE_SUBMIX可以实现内录功能了。有两点比较麻烦:

需要系统权限

会截走扬声器和耳机的声音,也就是说再录音时本地无法播放声音

系统权限问题

这个对我来说比较好办,因为我是直接在android设备板子上开发,可以直接使用系统签名编译。首先在AndroidManifestxml添加
android:sharedUserId="androiduidsystem"
其次,

第一种方法:

adb shell 执行:
signapkjar platformx509pem platformpk8 app-unsignedapk signedapk
adb push signedapk /system/app

第二种方法:

编写Androidmk : 设置签名为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 := proguardflagsinclude $(BUILD_PACKAGE)include $(call all-makefiles-under,$(LOCAL_PATH))

截走扬声器和耳机的声音问题

修改framework下av/services/audiopolicy/AudioPolicyManagercpp

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

getDeviceForStrategy方法下找到

if (mAvailableOutputDevicesgetDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {       device2 = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
}

修改为

if (mAvailableOutputDevicesgetDevice(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 = MediaRecorderAudioSourceMIC;

改成

int audioSource = MediaRecorderAudioSourceREMOTE_SUBMIX;

就可以实现内录功能了。
<br/>

ps:

在不修改源码的情况下,第三方app目前暂不知如何实现内录。

延伸阅读

50以后请求Android录屏默认会d出确认框,但在系统app下请求就不会d出了(具体可以去看源码)。这也是为了谷歌为了安全考虑。
不过50的时候这个d框却是一个大漏洞,被国内360发现了,给你们链接^_^
Android 50屏幕录制漏洞

     


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12741648.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-27
下一篇 2023-05-27

发表评论

登录后才能评论

评论列表(0条)

保存