【问题标题】:Android AudioRecord initialization fails every timeAndroid AudioRecord 初始化每次都失败
【发布时间】:2010-12-19 10:06:54
【问题描述】:

我的问题很容易解释——我试图创建一个 AudioRecord 对象,但它初始化失败(即在构造函数之后,getState 返回 0,表示失败)。我在运行 OS 2.2.1 的 MotoDroid 1 上从 Eclipse 运行它。我的 AndroidManifest.xml 是,AFAIK,使用正确的权限,RECORD_AUDIO(我不知道如何确认):

<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <activity android:name=".SphinxMic"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

我执行以下操作来创建 AudioRecord:

bufferSize = AudioRecord.getMinBufferSize(8000, CHANNEL_IN_MONO, ENCODING_PCM_8BIT);
audioRecorder = new AudioRecord(AudioSource.MIC, 8000, CHANNEL_IN_MONO, ENCODING_PCM_8BIT, 50*bufferSize);
if (audioRecorder.getState() != AudioRecord.STATE_INITIALIZED)
  throw new Exception("AudioRecord init failed");

audioRecorder.getState() 返回 0(即 STATE_UNINITIALIZED)

我还没有找到任何使用此 API 的完整示例,而且我是一名 Android 初学者,因此解决方案可能很简单。我该怎么做才能找出失败的原因?

有些人提出了类似的问题,但他们肯定遇到了与我不同的问题,因为他们批准的修复对我没有帮助。最值得注意的是this。但是批准的解决方案令人困惑,无论如何都对我不起作用。我还尝试了各种比特率(8000、16000、11025、44100),包括单声道和立体声以及 8 位和 16 位。没有组合返回成功初始化。

【问题讨论】:

  • logcat 说什么?还可以尝试将使用权限移出应用程序。 afaik 它应该放在清单中。
  • 由于某种原因,LogCat 在运行几次后停止显示大部分日志信息——但这是另一个问题。我会将您的使用权限评论标记为答案......如果它是一个(因为它有效!)

标签: android microphone audiorecord android-audiorecord


【解决方案1】:

我花了几个小时解决这个问题,发现移动

<uses-permission android:name="android.permission.RECORD_AUDIO" />

应用程序块外居然解决了!

...
    </application>

    <uses-permission android:name="android.permission.RECORD_AUDIO" /> 
</manifest>

【讨论】:

  • 将用户权限节点移到外面解决了这个问题。谢谢大佬!
【解决方案2】:

另一个可能的问题:

我在清单中启用了RECORD_AUDIO 权限,但对于 API 级别 23,我还必须在运行时请求该权限。

【讨论】:

  • 你是如何在运行时请求权限的?
【解决方案3】:

试试 16 位。这对我有用:

try {
        // Create a new AudioRecord object to record the audio.
        bufferSize = AudioRecord.getMinBufferSize(frequency,channelConfiguration,audioEncoding);

        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 
                                                  frequency, channelConfiguration, 
                                                  audioEncoding, bufferSize);
    } catch (Throwable t) {
        Log.e("AudioRecord","Recording Failed");
    }

我设置了以下变量:

int frequency = 8000;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;

【讨论】:

  • 我今天正在处理这个问题,发现如果你在最后调用 audioRecord.release() 会有很大的不同。显然,在您执行此操作之前,该对象不会被释放。出于某种原因,即使在某些代码的末尾调用了 audioRecord.release() ,它实际上也会在放入后的第一次尝试中起作用。我一直在试验并且不明白,但我发现它有帮助初始化很重要。
  • 如果您下载应用程序 Audalyzer 并尝试运行它,但它被冻结了,您可能占用了 AudioRecord 资源。重启手机可以解决这个问题。
【解决方案4】:

如果有人需要为 API 23+ 手动请求磁盘权限,这是我使用的一种方法。只需在相关位中交换permission.RECORD_AUDIO。方法逻辑依赖于一些外部位(例如strings.xmlActivityCompatSnackbar),但认为它可能对某人有所帮助。

/**
 * Requests the Storage permissions.
 * If the permission has been denied previously,
 * a SnackBar will prompt the user to grant the
 * permission, otherwise it is requested directly.
 */
private void requestStoragePermissions() {

    // Newer versions Android 18+
    if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) {
        /**
         * Permissions required to read and write storage.
         */
        final String[] PERMISSIONS_STORAGE = {
                permission.READ_EXTERNAL_STORAGE,
                permission.WRITE_EXTERNAL_STORAGE,
        };

        final boolean readResult =
                ActivityCompat.shouldShowRequestPermissionRationale(
                        this, permission.READ_EXTERNAL_STORAGE);
        final boolean writeResult =
                ActivityCompat.shouldShowRequestPermissionRationale(
                        this, permission.WRITE_EXTERNAL_STORAGE);

        if (readResult || writeResult) {

            // Provide an additional rationale to the user if the permission was not granted
            // and the user would benefit from additional context for the use of the permission.
            // For example, if the request has been denied previously.
            Log.i(TAG,
                    "Displaying disk permission rationale to provide additional context.");

            // Display a SnackBar with an explanation and a button to trigger the request.
            Snackbar.make(mainView, R.string.permission_storage_rationale,
                    Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.ok, new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            ActivityCompat
                                    .requestPermissions(MainActivity.this,
                                            PERMISSIONS_STORAGE,
                                            REQUEST_STORAGE);
                        }
                    })
                    .show();
        } else {
            // Storage permissions have not been granted. Request them directly.
            ActivityCompat.requestPermissions(
                    this, PERMISSIONS_STORAGE, REQUEST_STORAGE);
        }

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-26
    • 2011-05-08
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多