IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> AudioRecord报错startRecording() called on an uninitialized AudioRecord.总结 -> 正文阅读

[移动开发]AudioRecord报错startRecording() called on an uninitialized AudioRecord.总结

一、前言

最近写一个Android项目,想使用AudioRecord录制手机内部声音,但是调用开始录音的方法startRecording()时,总是遇到这个错误:

startRecording() called on an uninitialized AudioRecord.

在此总结一下。

二、分析

1.百度发现,报这个错可能是AudioRecord没有初始化(没有new)。正确写法可以这样写:

private AudioRecord mRecord = null;
private final int kFrameSize = 2048;
private final int kSampleRate = 44100;
private final int kChannelMode = AudioFormat.CHANNEL_IN_STEREO;
private final int kEncodeFormat = AudioFormat.ENCODING_PCM_16BIT;

//标志位,通过修改这个,决定录音是否停止
public boolean mReqStop = true;

public void recordAndPlay(File f) {
        //修改标志位,开始录音
        mReqStop = false;
        FileOutputStream os = null;
        if(mRecord == null) {
            int minBufferSize = AudioRecord.getMinBufferSize(kSampleRate, kChannelMode, kEncodeFormat);
            mRecord = new AudioRecord(MediaRecorder.AudioSource.REMOTE_SUBMIX, kSampleRate, kChannelMode, kEncodeFormat, minBufferSize * 2);
            //mRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, kSampleRate, kChannelMode, kEncodeFormat, minBufferSize * 2);
        }
        try {
            mRecord.startRecording();
        }catch (Exception e){
            Log.e("错误!",e.getMessage());
            return;
        }
        try {
            os = new FileOutputStream(f);
            byte[] buffer = new byte[kFrameSize];
            int num = 0;
            while (!mReqStop) {
                num = mRecord.read(buffer, 0, kFrameSize);
                os.write(buffer, 0, num);
            }
            os.close();
        } catch (IOException e) {
            Log.e("IO错误!",e.getMessage());
        }
        mRecord.stop();
        mRecord.release();
        mRecord = null;
    }

这个方法可以开始录音,保存为pcm文件。
这个方法已经确实把AudioRecord初始化了,但是还是会报错

2.继续百度,发现没有权限也会报这个错,需要在AndroidManifest.xml增加权限


    <uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />  
    <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"/>  
    <uses-permission android:name="android.permission.RECORD_AUDIO" />  
    <uses-sdk  
        android:minSdkVersion="19"  
        android:targetSdkVersion="19" />  
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

3.为了保险,又在Android代码中增加了申请权限的方法

    @SuppressLint("NewApi")
    private boolean checkAudio2(){
        if (checkSelfPermission(Manifest.permission.CAPTURE_AUDIO_OUTPUT) == PackageManager.PERMISSION_GRANTED){
            return true;
        }
        else{
            return false;
        }
    }

    @SuppressLint("NewApi")
    private void requestAudio2Permission() {
        if (!checkAudio2()) {
            requestPermissions(new String[]{Manifest.permission.CAPTURE_AUDIO_OUTPUT}, 0);
        } else {
        }
    }

然后给录音按钮增加了个功能,点击按钮时,调用requestAudio2Permission()方法,应该就出现申请权限的对话框才对,但是点击后没有反应

3.继续百度发现,MediaRecorder.AudioSource.REMOTE_SUBMIX功能只有系统应用才能使用,不开放给其它应用。
因此按照教程,把apk重新签名为系统应用。

(1)在AndroidManifest.xml文件的application标签中,增加配置:android:sharedUserId="android.uid.system"

(2)打release包,然后使用signapk.jar重新签名为系统应用。

●signapk.jar下载地址:

https://gitee.com/code_to_success/signapk.git

其中包含了platform.x509.pem与platform.pk8这2个文件。

●可以把自己打的release包改名为test.apk,然后执行下面的命令:

java -jar signapk.jar platform.x509.pem platform.pk8 ./test.apk final.apk

需要把相关文件放在命令中对应的路径下,然后生成的final.apk就是有系统签名的apk了。

备注:
那2个文件可以从android官网下载,platform.x509.pem和platform.pk8在Android源码的build/target/product/security目录下。
signapk.jar可以从https://code.google.com/p/signapk/下载。

注意这种方法录音时扬声器不能输出。

(3)安装apk测试,发现没有用,还是报错
不知道是不是由于platform.x509.pem和platform.pk8不是最新版的问题。

4.经过多次测试,使用MediaRecorder.AudioSource.MIC、申请
Manifest.permission.RECORD_AUDIO权限后,是可以正常使用手机录音功能的,不过录制的是麦克风;
而使用MediaRecorder.AudioSource.REMOTE_SUBMIX,无法申请Manifest.permission.CAPTURE_AUDIO_OUTPUT权限、并且无法录音,报错:startRecording() called on an uninitialized AudioRecord

5.所以最后暂时没有实现录制手机内部声音的功能,改为了使用MIC参数、录制麦克风的声音。

三、总结

●AudioRecord报错startRecording() called on an uninitialized AudioRecord,可能是没有初始化AudioRecord没有申请权限使用REMOTE_SUBMIX等不开放给非系统应用的参数导致的。
●目前暂时没有解决REMOTE_SUBMIX无法使用、无法录制手机内部声音的问题。
待后续研究。

四、后记

2021.9.26
1.关于录制手机内部声音问题
现在是android11版本,第三方软件实现手机内录功能比较困难,因此还是使用系统自带的录屏软件->选择录制内部声音,然后使用视频音频提取APP,提取录屏视频中的音频为mp3的方式好些。

相关网址:
https://zhidao.baidu.com/question/396545963009870525.html
https://www.zhihu.com/question/265086051

2.关于AudioRecord使用的参数
可以使用以下参数:

//声音来源等参数
Audio Source: MIC
Sample rate: 16000
Number of channels: CHANNEL_CONFIGURATION_MONO
Format: ENCODING_PCM_16BIT
Buffer size: 16000 * 30 (30 second buffer)

//Java中写法
AudioRecord mRecord = new AudioRecord(
                          MediaRecorder.AudioSource.MIC,
                          16000,
                          AudioFormat.CHANNEL_CONFIGURATION_MONO,
                          AudioFormat.ENCODING_PCM_16BIT,
                          16000*30);
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 14:12:28  更:2021-09-27 14:15:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:54:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码