在Android 4.2.2上播放视频时,Android MediaPlayer会闪烁

时间:2016-09-28 07:24:46

标签: android video android-mediaplayer

我遇到了Android 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} } 类的一个奇怪问题。我正在使用MediaPlayer在VideoView中播放视频。这适用于所有设备,除了搭载Android 4.2.2的Samsung GT-I8200N。好吧,我实际上已经听说过这些视频无法在某些三星4.1.X设备上播放的报道,但是我无法将这些视频放到其中一个设备上。我在Google Android模拟器中没有任何错误。

更多细节:使用Android 4.2.2的三星GT-I8200N能够以一个片段播放视频,但不能在另一个片段中播放,即使使用相同的代码播放视频。当视频开始播放时,除了视频应该在的空间外,整个屏幕都会闪烁黑色。

以下是代码:

< VideoView
android:id="@+id/signTrainerVideoView"
android:layout_width="0dip"
android:layout_height="0dip"
android:layout_below="@+id/signTrainerQuestionText"
android:layout_centerHorizontal="true" />

这是logcat输出,当屏幕闪烁时循环:

  

D / v_gal(115):[tid = 275] gcmVERIFY_ARGUMENT失败:

     

D / v_gal(115):[tid = 275] gcmONERROR:   status = -1(gcvSTATUS_INVALID_ARGUMENT)@ _Blit(2208)

     

E / v_hwc(115):_Blit:status = -1

失败      

D / v_gal(115):[tid = 275] gcmONERROR:   status = -1(gcvSTATUS_INVALID_ARGUMENT)@ hwcComposeG2D(615)

     

E / v_hwc(115):hwcComposeG2D失败:状态= -1

     

E / v_hwc(115):_ Set(1007):撰写失败


完整的logcat输出可以在这里找到:Github issue (full logcat)

视频观看代码:

ildasm /text /pubonly _dll_


可以在此处找到片段的完整布局xml:layout xml (full fragment)

1 个答案:

答案 0 :(得分:0)

我不确定这是否可以解决问题,但我只会报告那里似乎可以改进的内容。

为了实现您的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" />