Android MediaPlayer мерцает при воспроизведении видео на Android 4.2.2

У меня возникла странная проблема с классом Android MediaPlayer. Я использую MediaPlayer для воспроизведения видео в VideoView. Это хорошо работает на всех устройствах, за исключением Samsung GT-I8200N с Android 4.2.2. Ну, я действительно слышал сообщения о том, что видео не будет воспроизводиться на некоторых устройствах Samsung 4.1.X, но я не смог получить доступ к одному из этих устройств. Я не получаю никаких ошибок в Google Android Emulators.

Дополнительная информация: Samsung GT-I8200N с Android 4.2.2 способен воспроизводить видео в одном фрагменте, но не в другом, даже если тот же код используется для воспроизведения видео. Когда видео запускает весь экран flickrs черный, за исключением места, где должно быть видео.

Вот код:

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 не удалось:

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: status = -1

E/v_hwc (115): _Set (1007): выполнить неудачу


Полный вывод logcat можно найти здесь: Проблема Github (полный логарифм)

Код видео:

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


Полный макет xml фрагмента можно найти здесь: макет xml (полный фрагмент)

Ответ 1

Я не уверен, что это решит проблему, но я просто сообщу о том, что кажется импровизируемым там.

Чтобы реализовать размер вашего 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" />