2016-09-28 80 views
10

我正面临Android MediaPlayer类的一个奇怪问题。我使用MediaPlayer在VideoView中播放视频。这适用于所有设备,除了Android 4.2.2的三星GT-I8200N。那么,我确实听说过这些视频不能在某些三星4.1.X设备上播放,但我无法获得这些设备中的一种。我在Google Android模拟器中没有遇到任何错误。在Android 4.2.2上播放视频时Android MediaPlayer会闪烁

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

下面是代码:

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的输出时,屏幕flickrs哪些循环:

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" /> 


片段的完整布局XML可以在这里找到:layout xml (full fragment)

+0

严... VideoView是一个非常老的小部件。你有没有尝试过使用TextureView查看这个[link](http://stackoverflow.com/questions/10736517/playing-video-on-textureview) –

回答

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" /> 
+0

Thx的回复。我会尽快检查它。 – ScarOnTheSky