首页 > 解决方案 > java.lang.NoSuchMethodError: 类 Landroid/media/MediaPlayer 错误中没有虚拟方法 setDataSource(Landroid/content/res/AssetFileDescriptor;)V

问题描述

我想使用textureview播放视频..但是在运行应用程序时,它停止并且我面临以下错误。我不知道该怎么做我尝试了很多并花了近8个小时来解决这个问题..但我不能..请帮我摆脱这个..

java.lang.NoSuchMethodError: No virtual method setDataSource(Landroid/content/res/AssetFileDescriptor;)V in class Landroid/media/MediaPlayer; or its super classes (declaration of 'android.media.MediaPlayer' appears in /system/framework/framework.jar)
        at com.vcube.textureview.MainActivity.onSurfaceTextureAvailable(MainActivity.java:42)
        at android.view.TextureView.getHardwareLayer(TextureView.java:370)
        at android.view.View.updateDisplayListIfDirty(View.java:14170)
        at android.view.View.getDisplayList(View.java:14215)
        at android.view.View.draw(View.java:14985)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3431)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3224)
        at android.view.View.updateDisplayListIfDirty(View.java:14188)
        at android.view.View.getDisplayList(View.java:14215)
        at android.view.View.draw(View.java:14985)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3431)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3224)
        at android.view.View.updateDisplayListIfDirty(View.java:14188)
        at android.view.View.getDisplayList(View.java:14215)
        at android.view.View.draw(View.java:14985)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3431)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3224)
        at android.view.View.updateDisplayListIfDirty(View.java:14188)
        at android.view.View.getDisplayList(View.java:14215)
        at android.view.View.draw(View.java:14985)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3431)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3224)
        at android.view.View.updateDisplayListIfDirty(View.java:14188)
        at android.view.View.getDisplayList(View.java:14215)
        at android.view.View.draw(View.java:14985)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3431)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3224)
        at android.view.View.updateDisplayListIfDirty(View.java:14188)
        at android.view.View.getDisplayList(View.java:14215)
        at android.view.View.draw(View.java:14985)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3431)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3224)
        at android.view.View.draw(View.java:15260)
        at android.widget.FrameLayout.draw(FrameLayout.java:598)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2731)
        at android.view.View.updateDisplayListIfDirty(View.java:14193)
        at android.view.View.getDisplayList(View.java:14215)
        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:273)
        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:279)
        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:318)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2628)
        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2444)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2074)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1116)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6098)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:773)
        at android.view.Choreographer.doCallbacks(Choreographer.java:586)
        at android.view.Choreographer.doFrame(Choreographer.java:556)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:759)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:159)
        at android.app.ActivityThread.main(ActivityThread.java:5461)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)

我在资产文件夹中包含了视频..我不知道我错在哪里..

以下是我使用的 java 代码。

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.content.res.AssetFileDescriptor;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.view.Surface;
import android.view.TextureView;


import java.io.IOException;

public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener {

    private TextureView textureview;
    private MediaPlayer mediaPlayer;

    private AssetFileDescriptor fileDescriptor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textureview = (TextureView) findViewById(R.id.textureView);
        textureview.setSurfaceTextureListener(this);
        mediaPlayer = new MediaPlayer();
        try {
            fileDescriptor = getAssets().openFd("random.mp4");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        Surface surfaceTexture = new Surface(surface);
        try {
            mediaPlayer.setDataSource(fileDescriptor);
            mediaPlayer.setSurface(surfaceTexture);
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mediaPlayer.start();
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    @Override
    protected void onPause() {
        if(mediaPlayer!=null && mediaPlayer.isPlaying()){
            mediaPlayer.pause();
        }
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if(mediaPlayer!=null){
            mediaPlayer.start();
        }
    }

    @Override
    protected void onDestroy() {
        if(mediaPlayer!=null){
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer =null;
        }
        super.onDestroy();
    }
}

你能建议我任何解决方案吗?谢谢

标签: javaandroidtextureview

解决方案


setDataSource(AssetFileDescriptor)仅在 API 级别 24 (Android 7.0) 中添加。尝试在较早的运行时版本上调用它会导致这样的崩溃。

@RequiresApi(api = Build.VERSION_CODES.N)仅在编译时使用注释您的方法会抑制“此调用需要 API 级别 24,最小 SDK 为 15”的 lint 错误。它在运行时什么都不做。它确实让直接调用者获取 API 级别 24 的 lint 检查,但由于它是一个被覆盖的方法,它不会被任何代码直接调用,调用者也不会出错。

该怎么办?您可以查看源代码,setDataSource(AssetFileDescriptor)例如https://cs.android.com/android/platform/superproject/+/android-9.0.0_r8:frameworks/base/media/java/android/media/MediaPlayer.java;l =1209并发现您可以使用早期 SDK 版本中提供的方法实现相同的功能,例如setDataSource(FileDescriptor, long, long)

public void setDataSource(@NonNull AssetFileDescriptor afd)
        throws IOException, IllegalArgumentException, IllegalStateException {
    Preconditions.checkNotNull(afd);
    // Note: using getDeclaredLength so that our behavior is the same
    // as previous versions when the content provider is returning
    // a full file.
    if (afd.getDeclaredLength() < 0) {
        setDataSource(afd.getFileDescriptor());
    } else {
        setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
    }
}

推荐阅读