Mathews Mathai
Mathews Mathai

Reputation: 1

VideoView listeners are not triggered

I have written a native module in Java for playing Videos. As per the logs, I can see that the video url and the focus was set successfully. However, the logs in the VideoView listeners like setOnPreparedListener never gets triggered (the logs never get printed) and so the video never starts playing.

Note: This code works fine in a Native Android Project.

I am not sure if I am missing something here.

import static java.security.AccessController.getContext;

import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.MediaController;
import android.widget.VideoView;
import androidx.annotation.NonNull;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.RCTEventEmitter;

public class ReactVideoViewManager extends SimpleViewManager<VideoView> {
    public static final String REACT_CLASS = "ReactVideoView";
    private static final String TAG = "RNViewManager";

    ReactApplicationContext reactContext;

    @NonNull
    @Override
    public String getName() {
        return REACT_CLASS;
    }


    @NonNull
    @Override
    protected VideoView createViewInstance(@NonNull ThemedReactContext reactContext) {
        VideoView videoView = new VideoView(reactContext);
        MediaController mediaController = new MediaController(reactContext);
        mediaController.setAnchorView(videoView);
        videoView.setMediaController(mediaController);
        Log.d(TAG, "VideoView Id when creating: " + videoView.getId());

        return videoView;
    }

    @ReactProp(name = "source")
    public void setVideoSource(VideoView videoView, @NonNull String videoUrl) {
        // Setup listeners
        videoView.setOnPreparedListener(mp -> {
            Log.d(TAG, "Video is ready");
            mp.start(); // Start playback when ready
        });

        videoView.setOnErrorListener((mp, what, extra) -> {
            Log.e(TAG, "Error occurred: what=" + what + " extra=" + extra);
            return true; // Return true to consume the error
        });

        videoView.setOnCompletionListener(mp -> {
            Log.d(TAG, "Playback completed");
        });
        Log.d(TAG, "VideoView Id when adding URI: " + videoView.getId());
        new Handler(Looper.getMainLooper()).post(() -> {
            try {
                Uri videoUri = Uri.parse(videoUrl);
                Log.d(TAG, "Setting video URI after delay");
                videoView.setVideoURI(videoUri);
                videoView.requestFocus();
                if (videoView.hasFocus()) {
                    Log.d(TAG, "The VideoView successfully received focus");
                } else {
                    Log.d(TAG, "The VideoView did not receive focus");
                }
            } catch (Exception e) {
                Log.e(TAG, "Invalid video source: " + videoUrl, e);
            }
        });
    }


    @Override
    public void onDropViewInstance(@NonNull VideoView videoView) {
        if (videoView.hasFocus()) {
            Log.d(TAG, "DROPPING VideoView successfully received focus");
        } else {
            Log.d(TAG, "DROPPING VideoView did not receive focus");
        }
        VideoView v2 = new VideoView(videoView.getContext());

        Log.d(TAG, "Dropping video VIEW ID: " + videoView.getId() + " " + v2.getId());
        super.onDropViewInstance(videoView);

        // Retrieve the URI that was set
        Uri currentUri = (Uri) videoView.getTag();
        if (currentUri != null) {
            Log.d(TAG, "VideoView removed. Last video URI: " + currentUri.toString());
        } else {
            Log.d(TAG, "VideoView removed. No URI was set.");
        }

        // Perform cleanup
        videoView.stopPlayback();
        videoView.setOnPreparedListener(null);
        videoView.setOnErrorListener(null);
        videoView.setOnCompletionListener(null);
    }
}

I am also sure that the View is still on the stack because onDropViewInstance instance is triggered only when I hit the back button and the return value for getId() matches as well.

React Native Version: 0.76.3 Tested with both new architecture enabled and disabled.

I tried out the code in Native Android Project and it works fine. The listeners are triggered as expected. The url used is same in either case.

I am expecting the listeners to be triggered in a React Native Environment.

I want to avoid the use of third party libraries like react-native-video as much as possible.

Upvotes: 0

Views: 20

Answers (0)

Related Questions