private void playVoice(String voicePath){ MediaPlayer player = MediaPlayer.create(context, Uri.parse(voicePath)); player.start();

错误日志:

W/MediaPlayer: Couldn't open https://dq-oss.oss-cn-beijing.aliyuncs.com/...
    java.io.FileNotFoundException: No content provider: https://dq-oss.oss-cn-beijing.aliyuncs.com/audio_recordrecord_20200414_14_32_58.mp3
        at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1688)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1518)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1435)
        at android.media.MediaPlayer.attemptDataSource(MediaPlayer.java:1154)
        at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1112)
        at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1019)
        at android.media.MediaPlayer.create(MediaPlayer.java:926)
        at android.media.MediaPlayer.create(MediaPlayer.java:903)
        at android.media.MediaPlayer.create(MediaPlayer.java:882)
        at com.example.qcsdk.adapter.ChatP2PAdapter.playVoice(ChatP2PAdapter.java:255)
        at com.example.qcsdk.adapter.ChatP2PAdapter.access$000(ChatP2PAdapter.java:40)
        at com.example.qcsdk.adapter.ChatP2PAdapter$2.onClick(ChatP2PAdapter.java:222)
        at android.view.View.performClick(View.java:7161)
        at android.view.View.performClickInternal(View.java:7138)
        at android.view.View.access$3500(View.java:811)
        at android.view.View$PerformClick.run(View.java:27419)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:224)
        at android.app.ActivityThread.main(ActivityThread.java:7520)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

这个错误是在小米上,虽然报错了但是还是会有声音,不过为了防止出现其他问题,还是进行了修复,修改后的代码如下:

* 播放音频文件 private void playVoice(String voicePath){ // MediaPlayer player = MediaPlayer.create(context, Uri.parse(voicePath)); MediaPlayer player = new MediaPlayer(); try { player.setDataSource(voicePath); }catch (IOException e){ e.printStackTrace(); player.prepareAsync(); player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mediaPlayer) { mediaPlayer.start();

这个问题的原因是因为 Uri.parse(voicePath)把网络路径转换成了本地路径,这时候本地没有这个文件才出现这个问题,比如上述的https://dq-oss.oss-cn-beijing.aliyuncs.com/audio_recordrecord_20200414_14_32_58.mp3使用 Uri.parse(voicePath)转换为路径后结果为/audio_recordrecord_20200414_14_32_58.mp3,这样当然不能播放,不过有的手机即使报错了依然可以播放,还不知道是为什么。不过按照Android源码来看的话,是绝对会报错的。下面解释源码的问题。

问题主要出在MediaPlayer上面,当使用Mediaplayer执行setDataSource(@NonNull Context context, @NonNull Uri uri)函数时候,最终会执行到

setDataSource(@NonNull Context context, @NonNull Uri uri,
            @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies)

里面,这里我们看下这个函数的代码:
MediaPlayer.java

* Sets the data source as a content Uri. * To provide cookies for the subsequent HTTP requests, you can install your own default cookie * handler and use other variants of setDataSource APIs instead. Alternatively, you can use * this API to pass the cookies as a list of HttpCookie. If the app has not installed * a CookieHandler already, this API creates a CookieManager and populates its CookieStore with * the provided cookies. If the app has installed its own handler already, this API requires the * handler to be of CookieManager type such that the API can update the manager’s CookieStore. * <p><strong>Note</strong> that the cross domain redirection is allowed by default, * but that can be changed with key/value pairs through the headers parameter with * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to * disallow or allow cross domain redirection. * @param context the Context to use when resolving the Uri * @param uri the Content URI of the data you want to play * @param headers the headers to be sent together with the request for the data * The headers must not include cookies. Instead, use the cookies param. * @param cookies the cookies to be sent together with the request * @throws IllegalArgumentException if cookies are provided and the installed handler is not * a CookieManager * @throws IllegalStateException if it is called in an invalid state * @throws NullPointerException if context or uri is null * @throws IOException if uri has a file scheme and an I/O error occurs public void setDataSource(@NonNull Context context, @NonNull Uri uri, @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies) throws IOException { if (context == null) { throw new NullPointerException("context param can not be null."); if (uri == null) { throw new NullPointerException("uri param can not be null."); if (cookies != null) { CookieHandler cookieHandler = CookieHandler.getDefault(); if (cookieHandler != null && !(cookieHandler instanceof CookieManager)) { throw new IllegalArgumentException("The cookie handler has to be of CookieManager " + "type when cookies are provided."); // The context and URI usually belong to the calling user. Get a resolver for that user // and strip out the userId from the URI if present. final ContentResolver resolver = context.getContentResolver(); final String scheme = uri.getScheme(); final String authority = ContentProvider.getAuthorityWithoutUserId(uri.getAuthority()); if (ContentResolver.SCHEME_FILE.equals(scheme)) { setDataSource(uri.getPath()); return; } else if (ContentResolver.SCHEME_CONTENT.equals(scheme) && Settings.AUTHORITY.equals(authority)) { // Try cached ringtone first since the actual provider may not be // encryption aware, or it may be stored on CE media storage final int type = RingtoneManager.getDefaultType(uri); final Uri cacheUri = RingtoneManager.getCacheForType(type, context.getUserId()); final Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(context, type); if (attemptDataSource(resolver, cacheUri)) { return; } else if (attemptDataSource(resolver, actualUri)) { return; } else { setDataSource(uri.toString(), headers, cookies); } else { // Try requested Uri locally first, or fallback to media server if (attemptDataSource(resolver, uri)) { return; } else { setDataSource(uri.toString(), headers, cookies);

因为路径是网络链接,以http或者https开头,所以会执行到最后的else代码块中,然后会执行到 attemptDataSource(ContentResolver resolver, Uri uri)函数,下面看下这个函数:
MediaPlayer.java

    private boolean attemptDataSource(ContentResolver resolver, Uri uri) {
        try (AssetFileDescriptor afd = resolver.openAssetFileDescriptor(uri, "r")) {
            setDataSource(afd);
            return true;
        } catch (NullPointerException | SecurityException | IOException ex) {
            Log.w(TAG, "Couldn't open " + (uri == null ? "null uri" : uri.toSafeString()), ex);
            return false;

可以看到第一行代码是用来判断Asset的资源文件,这时候就会出现报错,因为我们的资源是网络资源…
暂时不知道怎么解决这个事情,等Android更新吧…

想验证这个问题的话把try里面的代码

AssetFileDescriptor afd = resolver.openAssetFileDescriptor(uri, "r")

复制出来测试下就行了

String extension = MimeTypeMap.getFileExtensionFromUrl(Url); String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); Intent mediaIntent = new I... 项目中用到了MediaPlayer播放本地视频文件的功能,遇到了一个很奇葩的问题,在4.0的设备上可以完美播放,但是在7.0的设备上死活播放不了,一直报如下错误 错误信息里出现了这几个字眼“No content provider”,然后就被带沟里去了,一直往这个方向去找问题,网上也有很多说就是没有提供content provider的问题,然后就跟着实现了content provider,然并卵... `java.io.FileNotFoundException` 是 Java 在尝试访问一个文件时,如果该文件不存在于指定的路径下,或者由于某种原因(如权限问题、路径错误等)无法被访问时,就会抛出的一个异常。 ### 问题分析 当我们在 Java 程序中执行与文件相关的操作时,比如读取文件内容、写入文件等,如果指定的文件路径不正确或文件不存在,程序就会抛出 `java.io.FileNotFoundException` 异常。 ### 报错原因 1. 文件路径错误:可能是文件路径写错了,或者文件没有 选了android课设,然后做到MediaPlayer这里,按照老师实验指导书上的敲完了之后,运行发现,点击音乐之后,播放了但是没有声音, 没有声音这种小事儿,先检查是不是AndroidStudio的AVD模拟器静音了,我把模拟器的音量调到了最大,也还是播放没有声音,然后想着是不是这个模拟器没有配置喇叭,就去试了试直接在文件管理里面打开音乐,然后发现是可以播放的!!! 很明显,是我写的GGMusic app的问题了,然后又仔细和老师的实验指导书上对照了一遍,发现也没有问题,之后看了下控制台的输出,没有报错 为播放器添加MediaPlayer.OnInfoListener监听,在回调方法中打印what,并参照MediaPlayer提供的类型进行对比,比如MediaPlayer: Couldn't open java.io.FileNotFoundException: No content provide错误,对应的就是801,对应的类型为MediaPlayer.MEDIA_INFO_NOT_SEE... 通过正确处理文件未找到异常,您可以确保您的应用程序在遇到文件丢失问题时能够正确地处理,并提供适当的反馈给用户。当您在编写Java应用程序时,可能会遇到一个常见的异常,即文件未找到异常(java.io.FileNotFoundException)。这个异常表示您的程序无法找到所需的文件,无论是读取还是写入操作。文件路径错误:如果文件的路径不正确,Java将无法找到文件。文件不存在:如果要打开的文件实际上不存在于指定的路径中,该异常将被抛出。检查文件路径:确保文件的路径是正确的,并且您使用的是正确的分隔符。 我在写安卓作业的过程中,使用过几次videoview,通过设置URI播放在线视频,遇到过几次上述问题,我的解决方法: 方法1:开启网络权限 方法2:换用不同型号的设备(一次我将Pixel 2换成Pixel XL,视频成功播放) 方法3:降低安卓版本(一次我将Android10.0降低到Android6.0,视频成功播放) Android 9+ MediaPlayer Couldn't open http://XXXX java.io.FileNotFoundException: No content provider 报错处理 01-错误信息: Exception in thread "main" java.io.FileNotFoundException: e:b (拒绝访问。) at java.io.FileOutputStream.open0(Native Method) at java.io.FileOutputStream.open(Unknown Source) at java.io.FileOutputStream.<init>(Unknown Source) at java.io.FileOu 写了一个音乐播放器,播放的时候,会出现这样的问题:比如说我点击第三首歌曲,结果没有播放第三首歌曲,而直接播放了第四首歌曲。看了一下日志。发现报错:MediaPlayer: Couldn't open /storage/emulated/0/kgmusic/download/陈小春 - 独家记忆.mp3: java.io.FileNotFoundException: No content provi...