java - 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();
}
}
你能建议我任何解决方案吗?谢谢
解决方案
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());
}
}
推荐阅读
- javascript - JS / Node.js If 和 Else 语句问题
- python - 使用 Django 将值(字符串)从 html 输入发送到 python 脚本(views.py)
- ruby - Ruby - 类方法中的问号用法
- node.js - 访问组件外的 cookie 数据
- macos - 调试器可执行文件“/usr/local/bin/gdb”未签名。因此,调试可能无法正常工作
- java - 线程“主”io.micronaut.context.exceptions.DependencyInjectionException 中的异常:无法为类的参数注入值
- spring-boot - 如何在 SpringBootTest 中为 logback 设置环境变量?
- angular - Angular 在部署服务器上刷新页面时抛出 404
- c++ - 一个键多值对的容器,在 Qt 中具有简单的插入和查找功能?
- docker - docker pull vote-app throws access to the resource is denied 错误