- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在 Android MediaPlayer
类中遇到了一个奇怪的问题。我正在使用 MediaPlayer 在 VideoView 中播放视频。这适用于所有设备,但 Samsung GT-I8200N 和 Android 4.2.2 除外。好吧,我确实听说过有关视频无法在某些三星 4.1.X 设备上播放的报道,但我无法亲手使用这些设备之一。我在 Google Android 模拟器中没有收到任何错误。
更多细节:Android 4.2.2 的三星 GT-I8200N 能够在一个 fragment 中播放视频,但不能在另一个 fragment 中播放视频,即使使用相同的代码播放视频也是如此。当视频开始时,整个屏幕闪烁黑色,除了视频应该出现的地方。
代码如下:
public abstract class AbstractSignVideoFragment extends Fragment {
private static final double MAXMIMUM_VIDEO_HEIGHT_ON_LANDSCAPE = 0.4;
private static final double MAXIMUM_VIDEO_WIDTH_ON_PORTRAIT = 0.8;
private final static String TAG = AbstractSignVideoFragment.class.getSimpleName();
private static final String ANDROID_RESOURCE = "android.resource://";
private static final String SLASH = "/";
private static final String RAW = "raw";
protected VideoView videoView;
protected ProgressBar progressBar;
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
protected boolean isSetupVideoViewSuccessful(final Sign sign, final SOUND sound, final CONTROLS controls) {
initializeMediaController();
final String mainActivityPackageName = getActivity().getPackageName();
final int signIdentifier = getActivity().getResources().getIdentifier(sign.getName(), RAW, mainActivityPackageName);
if (0 == signIdentifier) {
return false;
}
final Uri uri = Uri.parse(ANDROID_RESOURCE + mainActivityPackageName + SLASH + signIdentifier);
if (!isVideoViewDimensionSetToMatchVideoMetadata(this.videoView, uri)) {
return false;
}
this.videoView.setVideoURI(uri);
this.videoView.requestFocus();
this.videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
AbstractSignVideoFragment.this.progressBar.setVisibility(View.GONE);
if (sound.equals(SOUND.OFF)) {
mp.setVolume(0f, 0f);
}
AbstractSignVideoFragment.this.videoView.start();
AbstractSignVideoFragment.this.videoView.setContentDescription(getActivity()
.getString(R.string.videoIsPlaying) + ": " + sign.getName());
Log.d(TAG, String.format("Actual width: %s, Actual height: %s",
AbstractSignVideoFragment.this.videoView.getWidth(),
AbstractSignVideoFragment.this.videoView.getHeight()));
// Set the MediaController to null so the controls are not 'popping up'
// when the video plays for the first time.
AbstractSignVideoFragment.this.videoView.setMediaController(null);
}
});
this.videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (controls.equals(CONTROLS.SHOW)) {
initializeMediaController();
}
}
});
return true;
}
private void initializeMediaController() {
final MediaController mediaController = new MediaController(getActivity(), false);
mediaController.setAnchorView(this.videoView);
this.videoView.setMediaController(mediaController);
}
private boolean isVideoViewDimensionSetToMatchVideoMetadata(VideoView videoView, Uri uri) {
String metadataVideoWidth;
String metadataVideoHeight;
try {
final MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(getActivity(), uri);
metadataVideoWidth = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
metadataVideoHeight = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
metaRetriever.release();
Validate.notEmpty(metadataVideoWidth);
Validate.notEmpty(metadataVideoHeight);
} catch (NullPointerException | IllegalArgumentException ex) {
return false;
}
final double videoWidth = Double.valueOf(metadataVideoWidth);
final double videoHeight = Double.valueOf(metadataVideoHeight);
final double videoRatio = videoWidth / videoHeight;
Log.d(TAG, String.format("videoWidth: %s, videoHeight: %s, videoRatio: %s", videoWidth, videoHeight, videoRatio));
boolean isOrientationPortrait = Configuration.ORIENTATION_PORTRAIT == getResources().getConfiguration().orientation;
int displayHeight = getResources().getDisplayMetrics().heightPixels;
int displayWidth = getResources().getDisplayMetrics().widthPixels;
Log.d(TAG, String.format("displayHeight: %s, displayWidth: %s", displayHeight, displayWidth));
final double desiredVideoWidth, desiredVideoHeight;
if (isOrientationPortrait) {
desiredVideoWidth = displayWidth * MAXIMUM_VIDEO_WIDTH_ON_PORTRAIT;
desiredVideoHeight = 1 / (videoRatio / desiredVideoWidth);
Log.d(TAG, String.format("OrientationPortrait: desiredVideoWidth: %s, desiredVideoHeight: %s", desiredVideoWidth, desiredVideoHeight));
} else { // orientation is Landscape
desiredVideoHeight = displayHeight * MAXMIMUM_VIDEO_HEIGHT_ON_LANDSCAPE;
desiredVideoWidth = desiredVideoHeight * videoRatio;
Log.d(TAG, String.format("OrientationLandscape: desiredVideoWidth: %s, desiredVideoHeight: %s", desiredVideoWidth, desiredVideoHeight));
}
final ViewGroup.LayoutParams layoutParams = videoView.getLayoutParams();
layoutParams.width = (int) desiredVideoWidth;
layoutParams.height = (int) desiredVideoHeight;
return true;
}
public enum SOUND {ON, OFF}
public enum CONTROLS {SHOW, HIDE}
}
这是在屏幕闪烁时循环的 logcat 输出:
D/v_gal(115): [tid=275] gcmVERIFY_ARGUMENT failed:
D/v_gal(115): [tid=275] gcmONERROR: status=-1(gcvSTATUS_INVALID_ARGUMENT) @ _Blit(2208)
E/v_hwc(115): Failed in _Blit: status=-1
D/v_gal(115): [tid=275] gcmONERROR: status=-1(gcvSTATUS_INVALID_ARGUMENT) @ hwcComposeG2D(615)
E/v_hwc(115): Failed in hwcComposeG2D: status=-1
E/v_hwc(115): _Set(1007): Compose failed
完整的 logcat 输出可以在这里找到:Github issue (full logcat)
视频观看代码:
< VideoView
android:id="@+id/signTrainerVideoView"
android:layout_width="0dip"
android:layout_height="0dip"
android:layout_below="@+id/signTrainerQuestionText"
android:layout_centerHorizontal="true" />
fragment 的完整布局 xml 可在此处找到:layout xml (full fragment)
最佳答案
我不确定这是否能解决问题,但我只会报告其中似乎可以改进的地方。
为了实现您的 VideoView 尺寸:
final ViewGroup.LayoutParams layoutParams = videoView.getLayoutParams();
layoutParams.width = (int) desiredVideoWidth;
layoutParams.height = (int) desiredVideoHeight;
videoView.setLayoutParams(layoutParams); // Input Changes
videoView.getHolder().setSizeFromLayout(); // Apply Changes
此外,根据我的实验,“0dip”大小意味着使用您似乎没有提供的权重参数进行计算。可能是错误的,但值得一提。
// Add android:weightSum="1" to the sup. Layout
// And set a weight there
<VideoView
android:id="@+id/signTrainerVideoView"
android:layout_width="0dip"
android:layout_height="0dip"
android:layout_weight="1"
android:layout_below="@+id/signTrainerQuestionText"
android:layout_centerHorizontal="true" />
关于Android MediaPlayer 在 Android 4.2.2 播放视频时闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39740692/
我在 logcat 中收到一条警告消息 W/MediaPlayer-JNI(16795): MediaPlayer finalized without being released 请告诉我我错在哪里
我有以下代码。 例如: if(player1 != null){ if(player1.isPlaying()){ //check if it playing //other
我在安卓系统工作。我正在创建一个正在运行音频文件的 mediaPlayer。我有 10 个按钮。我为每个按钮分配了不同的 url。因此,当我按下按钮 1 时,将播放与按钮 1 相关的 url 歌曲。然
我正在使用 MediaPlayer。我想制作在线流媒体广播。现在我有这个 mediaPlayer 对象(MediaPlayer 的),在 fragment 1 中说,当我在 fragment 1 上时
我使用了以下代码: mp = MediaPlayer.create(this, Uri.parse("file://"+filePath)); mp.start(); 这很好用。然后我想播放文件夹中的
我通过下载新文件来启动我的应用程序,如果有任何文件开始播放循环。然后我每 x 秒触发一个任务来寻找新媒体。调用任务后,视频将停止播放,并显示错误 MediaPlayer finalized witho
我的应用程序允许用户从多个音频流中进行选择,当用户点击其中一个播放按钮时,将调用以下代码: @Override public void onClick(View view) { mMediaP
我正在尝试在我的 ViewController 中播放视频。 Mediaplayer.framework 和所有 Headers 都在我的 Frameworks 文件夹中,包括 MediaPlayer
我正在使用 MediaPlayer 和 SurfaceView 播放本地视频文件。 SurfaceView 是 Activity 中的唯一控件,而我的视频文件是 QVGA 或其他。问题是视频被拉伸(s
我正在使用 JavaFX 的 MediaPlayer 播放 mp3 文件,getCurrentTime() 工作正常,但是当我在某个时候使用 seek() 方法时, getCurrentTime()
我将音量设置为 0.0,然后在 while 循环中一点一点地改变音量。然而,音量从 0.0 跳到 1.0?如何顺利改变音量?我试过了 public class EngineSound extends
我为“播放”和“暂停”按钮创建了两个 onClick 方法,但如果先点击“暂停”,然后点击“播放”按钮,则音乐不会播放。下面是代码 package com.example.myaudio; impor
我用 MediaPlayer 控件创建了一个绑定(bind)服务,它可以加载和播放音频。但碰巧的是,有时 mediaPlayer.prepare(); 速度不够快,并不总是准备好播放。 那么我怎样才能
我正在我的应用程序中播放从网络流式传输的 mp3 文件,一些 mp3 文件有奇怪的行为:mediaPlayer.getCurrentPosition() 大于 mediaPlayer.getDurat
我想制作广播播放器示例,但我有一些错误。我无法修复它。 我的源代码 String url = ""; //Shoutcast Radio URL mp = new MediaPlayer();
我知道有一些类似的问题,但没有一个回答我的问题。当我点击一个按钮时,媒体播放器被调用,并且它出现在日志中。 06-02 00:20:38.980 26035-26035/myapp.com.facad
我正在尝试从 URL 流式传输音频。该代码适用于其他 URL,但其中一个 URL 在 OnPrepared 方法中失败,返回此错误代码:(1, -2147483648)。我看过一些人说这是因为权限,但
我在我的 Android 应用程序中使用 MediaPlayer 来播放视频。当通过 mediaPlayer.pause() 方法暂停播放并调用 mediaPlayer.seekTo(msec) 时,
我的应用程序在 MediaPlayer 流媒体方面存在问题,特别是在 Nexus 5 上。我不确定这是 Nexus 5 还是 API 级别 19 导致的问题。基本上我的 MediaPlayer 准备好
不过,我正在使用 RingtoneManager 来获取 Ringtone。 此信息已包含在 this question and answer 中,但 Google 员工不太可能找到它,除非他们已经知
我是一名优秀的程序员,十分优秀!