2、环境搭建与权限:AndroidManifest配置、存储权限、依赖库导入
好,咱们正式开始动手了。这一章其实特别关键,但很多人容易忽略。我见过不少新手,代码写了大半天,一运行直接崩溃,最后发现是AndroidManifest里少写了一行权限。嗯,这种坑咱们今天一次性填平。
2.1 项目创建与最低版本要求
我个人习惯用Android Studio直接创建新项目。选一个空Activity模板就行,别整那些花里胡哨的。
关于最低版本,我建议你至少设到API 21(Android 5.0)。为什么?因为MediaExtractor在API 16就有了,但有些高级特性(比如HDR、HEVC)在API 21之后才稳定。你想想看,现在市面上低于5.0的设备几乎绝迹了,所以设到API 21既安全又省心。
在 app/build.gradle 里,这样配:
android {
compileSdk 34
defaultConfig {
applicationId "com.example.mediaextractordemo"
minSdk 21
targetSdk 34
versionCode 1
versionName "1.0"
}
}
这里有个小细节——compileSdk 尽量用最新的,这样你能用到最新的API。但 targetSdk 别乱升,要测试过再改。我在项目中遇到过,升了targetSdk后存储权限全变了,代码跑不起来,折腾了一下午。
2.2 AndroidManifest 权限配置
做音视频提取,说白了就是要读文件。读文件就需要权限。Android的权限分两种:普通权限和危险权限。咱们这个场景,核心就两个:
- READ_EXTERNAL_STORAGE — 读取外部存储的文件
- WRITE_EXTERNAL_STORAGE — 写入提取后的文件(如果需要保存)
在 AndroidManifest.xml 里,加在 <manifest> 标签下:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我曾经有个项目,在Android 11手机上死活读不到SD卡里的视频文件。查了半天,发现是忘了加 MANAGE_EXTERNAL_STORAGE 权限。如果你需要管理所有文件(比如用户选择任意目录),Android 11以上还得加这个:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
但这个权限审核比较严,Google Play上架可能被拒。一般场景用 READ_EXTERNAL_STORAGE 就够了。
2.3 运行时权限申请
光在Manifest里声明还不够。Android 6.0以上,危险权限需要运行时弹窗让用户同意。这个逻辑咱们得写代码里。
我一般这样写:
// 检查权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// 请求权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_CODE_STORAGE);
} else {
// 已有权限,直接开始提取
startExtract();
}
然后重写回调方法:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE_STORAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startExtract();
} else {
Toast.makeText(this, "没有存储权限,无法提取", Toast.LENGTH_SHORT).show();
}
}
}
shouldShowRequestPermissionRationale() 判断是否要弹解释对话框。我一般会在用户拒绝两次后,直接跳转到应用设置页面。
2.4 依赖库导入
MediaExtractor 是 Android 框架自带的类,不需要额外导入第三方库。但咱们做音视频提取,往往不只是提取,还要处理、播放、保存。这时候就需要一些辅助库了。
我个人常用的依赖:
| 库名 | 用途 | 是否必需 |
|---|---|---|
| androidx.core | 运行时权限、兼容性 | ✅ 必需 |
| androidx.appcompat | UI兼容 | ✅ 必需 |
| exoplayer | 播放提取后的音视频 | ❌ 可选 |
| mp4parser | 解析MP4文件结构 | ❌ 可选 |
在 app/build.gradle 的 dependencies 块里加:
dependencies {
implementation 'androidx.core:core:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
// 可选:ExoPlayer 用于播放
// implementation 'com.google.android.exoplayer:exoplayer:2.19.1'
// 可选:mp4parser 用于深度解析
// implementation 'com.googlecode.mp4parser:isoparser:1.1.22'
}
这里要提醒一下:别一股脑把所有库都加进来。我见过一个项目,build.gradle里躺了二十多个依赖,编译一次五分钟。咱们做音视频提取,核心就靠MediaExtractor,其他库按需添加就行。
2.5 知识体系总览
这一章的内容其实就三个块:权限声明、权限申请、依赖管理。我画了个图帮你理清关系:
2.6 常见问题与避坑
最后,我把自己踩过的坑列一下,你遇到了直接对照排查:
- 权限声明了但运行时没弹窗 — 检查一下是不是忘了在Activity里调用
requestPermissions()。光写Manifest是不够的。 - Android 10以上读不到文件 — 分区存储机制搞的鬼。试试用
MediaStore的URI方式访问,别直接用文件路径。 - 编译报错:Duplicate class — 依赖库版本冲突了。我一般用
./gradlew app:dependencies命令查看依赖树,找到冲突的库然后排除掉。 - 提取出来的音频文件是0字节 — 大概率是写入权限没拿到。检查一下
WRITE_EXTERNAL_STORAGE有没有被用户拒绝。
嗯,环境搭建这块就这些。别看内容不多,但每一步都关系到后面能不能顺利跑起来。配好了,后面写代码就一路畅通了。