基于Ionic 4开发本地音频播放器:如何从设备存储获取音频文件
我来帮你搞定Ionic 4 + Cordova获取本地音频文件的需求,这是我在项目里验证过的靠谱方案,一步步来:
1. 先装必备的插件
要实现这个功能,你需要三个核心插件:
cordova-plugin-file:用来访问设备文件系统,获取FileEntry或文件路径cordova-plugin-android-permissions:安卓平台必须,用来申请存储访问权限@ionic-native/file和@ionic-native/android-permissions:Ionic Native的封装层,让你能在TypeScript里更方便调用插件
安装命令直接复制运行就行:
# 安装Cordova插件 ionic cordova plugin add cordova-plugin-file ionic cordova plugin add cordova-plugin-android-permissions # 安装对应的Ionic Native包 npm install @ionic-native/file @ionic-native/android-permissions
别忘了在app.module.ts里把这两个服务加入providers数组,不然没法注入使用。
2. 权限处理(重中之重)
安卓10+对存储权限管控很严,iOS也需要配置权限描述,这一步没做好直接拿不到文件:
安卓端
- 先在代码里请求
READ_EXTERNAL_STORAGE权限:
import { AndroidPermissions } from '@ionic-native/android-permissions/ngx'; constructor(private androidPermissions: AndroidPermissions) {} async requestStoragePermission() { const result = await this.androidPermissions.requestPermission( this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE ); if (result.hasPermission) { // 权限已获取,可以开始扫描文件 this.scanAudioFiles(); } else { // 权限被拒绝,提示用户去设置开启 console.log('存储权限被拒绝,请前往设置开启'); } }
- 还要在
config.xml里添加安卓10+的兼容配置,避免Scoped Storage限制:
<platform name="android"> <edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application"> <application android:requestLegacyExternalStorage="true" /> </edit-config> </platform>
iOS端
在config.xml的iOS平台下添加权限描述,告诉用户为什么需要访问音频文件:
<platform name="ios"> <edit-config file="*-Info.plist" mode="merge" target="NSAppleMusicUsageDescription"> <string>需要访问您的本地音频文件以提供播放服务</string> </edit-config> <edit-config file="*-Info.plist" mode="merge" target="NSFileProviderDomainUsageDescription"> <string>需要访问您的本地存储以读取音频文件</string> </edit-config> </platform>
3. 核心逻辑:扫描本地音频文件
接下来就是遍历设备存储,筛选出音频格式的文件(比如.mp3、.wav、.flac等),获取FileEntry或者完整路径:
import { File } from '@ionic-native/file/ngx'; constructor(private file: File) {} async scanAudioFiles() { let audioFiles = []; // 安卓端:外部存储根目录,你也可以指定具体的音频目录比如Music文件夹 const rootDir = this.file.externalRootDirectory; // iOS端:如果是访问用户的音乐库,可能需要额外插件,这里先以文档目录为例,或者根据需求调整 // const rootDir = this.file.documentsDirectory; try { // 递归遍历目录 await this.traverseDirectory(rootDir, audioFiles); console.log('找到的音频文件:', audioFiles); // 这里的audioFiles里就包含了每个文件的FileEntry和fullPath } catch (error) { console.error('扫描文件出错:', error); } } async traverseDirectory(dirPath: string, audioFiles: any[]) { try { const directoryEntries = await this.file.listDir(dirPath, ''); for (const entry of directoryEntries) { if (entry.isDirectory) { // 如果是目录,递归遍历 await this.traverseDirectory(entry.fullPath, audioFiles); } else if (entry.isFile) { // 筛选音频格式的文件 const allowedExtensions = ['.mp3', '.wav', '.flac', '.m4a']; const fileExt = entry.name.toLowerCase().substring(entry.name.lastIndexOf('.')); if (allowedExtensions.includes(fileExt)) { // 保存FileEntry和完整路径 audioFiles.push({ fileEntry: entry, fullPath: entry.fullPath, fileName: entry.name }); } } } } catch (error) { console.error('遍历目录出错:', error); } }
4. 关键说明
entry.fullPath就是文件的完整本地路径,比如安卓上的/storage/emulated/0/Music/song.mp3- 如果需要操作文件内容,可以用
entry.file()方法获取File对象,比如读取文件数据:
const fileObject = await entry.file(); const reader = new FileReader(); reader.onloadend = () => { // reader.result就是文件的二进制数据 }; reader.readAsArrayBuffer(fileObject);
- iOS如果要访问系统音乐库,上面的方法可能不够,需要额外用
cordova-plugin-media或者专门的音乐库访问插件,但如果是用户自己存储在APP目录或文档目录的音频,上面的逻辑完全没问题。
注意事项
- 遍历大存储目录时,建议加上加载提示,避免界面卡顿
- 安卓13+的权限有变化,可能需要申请
READ_MEDIA_AUDIO权限,记得根据系统版本适配 - 测试时一定要用真实设备,模拟器的存储结构可能和真机不一样
内容的提问来源于stack exchange,提问作者Artur Chilingaryan
相关产品推荐
相关产品推荐

