Cordova安卓应用播放内部存储Music目录音频文件问题求助
版本信息
- Cordova版本:12.0.0
- cordova-media-plugin版本:7.0.0
- cordova-plugin-file版本:8.1.0
- cordova-plugin-file-transfer版本:2.0.0
- cordova-plugin-wkwebview-file-xhr版本:3.1.1
- Android目标SDK:34
问题与疑问
我正在尝试让基于Cordova的安卓应用播放下载到设备内部存储/Music目录的音频文件,downloadAudio函数可以正常将文件保存到该目录(尽管文件插件文档称该位置为SD卡,但实际设备并非如此),存在以下疑问:
- media插件能否从
file:///storage/emulated/0/Music/[file].mp3路径播放音频?似乎需要cdvfile格式路径,但不确定cdvfile是否支持该外部位置,怀疑它仅适用于应用内部路径?
编辑: 若引用无效路径会提示文件不存在,无此错误说明media插件可识别文件,但修正语法错误后出现“Code 1, Prepare failed.: status=0x1”错误,相关讨论虽有关联但无法理解。 - 无法使用URL转换方法(如toURL返回
TypeError: fileTransferInternalUrl.toURL is not a function)生成适用于media插件的cdvfile路径,均报错。
编辑: 尽管toURL无效,但文件URL似乎可正常工作。 - 若media插件不支持播放应用外部路径的音频,能否使用copyTo(覆盖已有文件)将外部文件复制到media插件可访问的应用临时内部目录?(新版文件插件文档中copyTo的文档缺失,使用时也报错,若可行可提供更多细节)
尝试过相关方案及官方示例均无效。
未收到权限相关错误,若存在权限问题,下载功能应无法正常工作(了解安卓权限有变更)。
更新(2024/10/8)
按建议修改toURL后可返回URL,但出现以下错误,似乎media播放器无法使用该URL:
Media播放器错误:Code 1, AudioPlayer.onError(1, -2147483648) [未知错误]
控制台错误:
java.net.ConnectException: Failed to connect to localhost/127.0.0.1:443 at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:147) at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:542) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:106) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:30) at android.media.MediaHTTPConnection.seekTo(MediaHTTPConnection.java:306) at android.media.MediaHTTPConnection.getMIMEType(MediaHTTPConnection.java:499) at android.media.IMediaHTTPConnection$Stub.onTransact(IMediaHTTPConnection.java:161) at android.os.Binder.execTransactInternal(Binder.java:1220) at android.os.Binder.execTransact(Binder.java:1179)
附带函数代码:
function downloadAudio (fileTransferWebUrl,thisElement) { fileTransferWebUrl = encodeURI(fileTransferWebUrl); if (isAndroidApp == true) { var fileNameMP3Array = fileTransferWebUrl.split("/"); var fileNameMP3 = fileNameMP3Array[fileNameMP3Array.length-1]; //get file name from web URL fileTransferInternalUrl = cordova.file.externalRootDirectory + 'Music/' + fileNameMP3; // file:///storage/emulated/0/Music/[file].mp3 } try { fileTransfer.download( fileTransferWebUrl, fileTransferInternalUrl, function (entry) { alert('Download complete to Music/' + fileNameMP3); }, function(error){ //error alert("Download error source " + error.source + " download error target " + error.target + " download error code " + error.code + " http_status " + error.http_status + " body " + error.body + " exception " + error.exception); }, true, //trust all hosts. safer to be false, set to true accepts all security certificates, not recommended for production use ); } catch (e) { alert(e); } } function playDownloadedAudio (fileTransferWebUrl, thisElement) { var nativePath = ""; fileTransferWebUrl = encodeURI(fileTransferWebUrl); if (isAndroidApp == true) { var fileNameMP3Array = fileTransferWebUrl.split("/"); var fileNameMP3 = fileNameMP3Array[fileNameMP3Array.length-1]; //get file name from web URL fileTransferInternalUrl = cordova.file.externalRootDirectory + 'Music/' + fileNameMP3; //cordova.file.externalRootDirectory alert(fileTransferInternalUrl); // file:///storage/emulated/0/Music/A_casa_vete_y_cuenta_alli.mp3 } resolveLocalFileSystemURL(cordova.file.dataDirectory + fileNameMP3, function (entry) { nativePath = entry.toURL(); console.log("cordova.file.dataDirectory + fileNameMP3 = " + cordova.file.dataDirectory + fileNameMP3 + " | nativePath = " + nativePath); if (my_media != null) { my_media.release(); // clean up old file } my_media = new Media(nativePath, function () //success; { }, function (error) //error { alertOK(translate('Error in playback. Please contact support. \n Code: ','text') + error.code + '\n '+translate('Message:','text')+' '+error.message + '\n'); playing = false; } ); my_media.play(); }); }
AndroidManifest.xml权限配置:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
Config.xml配置:
<?xml version='1.0' encoding='utf-8'?> <widget id="com.hablamedecristo.himnario2" version="6.9.0" versionCode="77" xmlns="http://www.w3.org/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cdv="http://cordova.apache.org/ns/1.0"> <name>Himnos del Evangelio</name> <description> Himnario "Himnos del Evangelio" de cristianos congregados en el Nombre del Señor Jesucristo en Venezuela. </description> <author email="himnosdelevangelio@gmail.com" href="http://salvoxgracia.com/himnarioapp/"> My Site Creations, AguaDeLaVida.info </author> <content src="index.html" /> <preference name="android-installLocation" value="preferExternal" /> <preference name="AndroidPersistentFileLocation" value="Compatibility" /> <!-- use "Internal" instead of "Compatibility" for new apps --> <preference name="android-targetSdkVersion" value="34" /> <preference name="android-compileSdkVersion" value="34" /> <preference name="android-minSdkVersion" value="23" /> <preference name="AndroidGradlePluginVersion" value="8.5.1" /> <preference name="loadUrlTimeoutValue" value="700000" /> <plugin name="cordova-plugin-media" spec="7.0.0" /> <plugin name="cordova-plugin-insomnia" /> <plugin name="cordova-plugin-file" /> <plugin name="cordova-plugin-email-composer" /> <plugin name="cordova-plugin-wkwebview-file-xhr" spec="3.1.1" /> <plugin name="cordova-plugin-file-transfer" /> <icon src="icon.png" /> <allow-navigation href="*" /> <access origin="*" /> <access origin="file:///*" /> <access origin="cdvfile://*" /> <allow-intent href="file:///*" /> <allow-intent href="cdvfile://*" /> <allow-intent href="http://*/*" /> <allow-intent href="https://*/*" /> <allow-intent href="mailto:*" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <!-- not sure if these are needed https://developer.android.com/training/data-storage/shared/media#kotlin <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" /> --> <platform name="android"> <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application"> <application android:usesCleartextTraffic="true" /> </edit-config> <allow-intent href="market:*" /> <!-- <preference name="AndroidWindowSplashScreenAnimatedIcon" value="res/screen/android/splashscreen.xml" /> --> <preference name="FadeSplashScreenDuration" value="0"/> <preference name="SplashScreenDelay" value="0" /> <preference name="AndroidWindowSplashScreenBackground" value="#9D9D9C" /> </platform> <platform name="ios"> <allow-intent href="itms:*" /> <allow-intent href="itms-apps:*" /> </platform> </widget>
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

