You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AndroidManifest.xml报多根标签等错误,录音应用点击按钮崩溃求助

解决Android录音应用Manifest错误与录制崩溃问题

先处理AndroidManifest.xml的标签错误

虽然你觉得Manifest结构规范,但AS提示的Multiple root tags和Top level element is not completed肯定是XML结构有问题,按以下步骤排查:

  • 检查是否有多余的根标签:整个Manifest只能有一个<manifest>根标签,不能在它外面加任何其他标签(比如不小心把<uses-permission>写在了<manifest>外面)
  • 检查标签闭合:确认所有标签都有对应的闭合标签,比如<activity>必须有</activity>,<intent-filter>不能漏了</intent-filter>
  • 排查注释错误:如果有XML注释,确保<!--和-->是成对出现的,半拉注释会破坏XML结构
  • 可以把Manifest代码复制到XML校验工具里(本地或离线的),快速定位结构错误

给你一个标准的录音应用Manifest模板,对比检查你的代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.your_recorder">

    <!-- 录音必需权限 -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <!-- Android 10以下需要存储权限保存录音文件 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.RecorderApp">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

再解决录制按钮崩溃问题

Manifest的结构错误可能导致组件注册异常,加上录音权限处理不当,都会引发崩溃,按以下步骤排查:

  1. 权限问题:Android 6.0(API 23)以上,录音权限属于危险权限,必须动态申请,不能只在Manifest里声明。如果没申请权限就调用录制逻辑,会直接崩溃
  2. MediaRecorder初始化错误:比如输出文件路径不存在、未正确设置音频源/编码器,都会抛出IO异常导致崩溃
  3. 查看崩溃日志:打开Android Studio底部的Logcat,选择你的应用包名,过滤Error级别,点击录制按钮后,查看具体的异常信息(比如SecurityException是权限问题,NullPointerException是空指针)

给你一段基础的MainActivity录制逻辑示例,包含权限申请:

import android.Manifest;
import android.content.pm.PackageManager;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    private static final int RECORD_PERMISSION_REQUEST = 1;
    private MediaRecorder mediaRecorder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button recordBtn = findViewById(R.id.btn_record);
        recordBtn.setOnClickListener(v -> checkRecordPermission());
    }

    private void checkRecordPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.RECORD_AUDIO},
                    RECORD_PERMISSION_REQUEST);
        } else {
            startRecording();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == RECORD_PERMISSION_REQUEST) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startRecording();
            } else {
                Toast.makeText(this, "需要授予录音权限才能录制", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void startRecording() {
        mediaRecorder = new MediaRecorder();
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        // 用应用私有目录存储录音,无需存储权限(Android 10+)
        String outputPath = getExternalFilesDir(Environment.DIRECTORY_AUDIO_RECORDINGS) + "/recording.3gp";
        mediaRecorder.setOutputFile(outputPath);
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            mediaRecorder.prepare();
            mediaRecorder.start();
            Toast.makeText(this, "正在录制...", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "录制失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
            releaseRecorder();
        }
    }

    private void releaseRecorder() {
        if (mediaRecorder != null) {
            try {
                mediaRecorder.stop();
            } catch (RuntimeException e) {
                // 处理未开始录制就停止的情况
            }
            mediaRecorder.release();
            mediaRecorder = null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseRecorder();
    }
}

内容的提问来源于stack exchange,提问作者Dinesen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 22:10:30