sasha199568
sasha199568

Reputation: 1153

How to play video when there is no activity? And how to make the video fullscreen?

I have a video url, which I can play with whatever player or VideoView. But here is what I am trying to do.

There is RecyclerView in which each element contains a video's title and thumbnails. When user clicks on the video a popup window appear. This popup window contains a VideoView (or whatever can play a video from url) and plays the video. The user can drag this window around. The trick is to make it so, that if user presses the back button the current activity closes, the window should remain and continue playing the video. While the video is being played the user can do whatever he wants in other apps, while the window with the video remains on top and continues to play the video. At any time user can press on the window (or on button in it) and video will become fullscreen. At the time user decides to play fullscreen the app activity might not be there.

Something like I described above is implemented in this app

https://play.google.com/store/apps/details?id=com.djit.apps.stream&hl=en

I can create a window with a view which will remain there when the user closes the app activity. For this purpose I use this library

https://github.com/pingpongboss/StandOut

If you check the source code of the lib you will see that StandOutWindow is Service which creates a popup window.

I actually can play a video in this window. Here is my window class

public class FloatingWindow extends StandOutWindow {
    private static final int WIDTH = 400;
    private static final int HEIGHT = 361;

    /*
    I didn't think of a better way to set video url
       therefore I made it static and set it with a static method
       I know it is bad, but it works.
       I will do it another way later
       Now I have other issues
    */
    private static String videoUrl = null;

    public static void setVideoUrl(String videoUrl) {
        FloatingWindow.videoUrl = videoUrl;
    }

    @Override
    public String getAppName() {
        return getApplicationContext().getResources().getString(R.string.app_name);
    }

    @Override
    public int getAppIcon() {
        return android.R.drawable.ic_menu_close_clear_cancel;
    }

    @Override
    public void createAndAttachView(int id, FrameLayout frame) {
        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.floating_window, frame, true);

        /*
            As you can see I didn't use MediaController for this videoView
            VideoView works with it, except for device
            On this one device MediaController crashed the app with BadTokenException: token null is not valid, is your activity running
        */
        final VideoView videoView = (VideoView) view.findViewById(R.id.textureVideoView);
        final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.videoProgressBar);
        final ScrollView description = (ScrollView) view.findViewById(R.id.videoDescription);
        videoView.setVideoURI(Uri.parse(videoUrl));
        videoView.requestFocus();
        videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                videoView.start();
                /*
                   I don't want my video view to be visible until it is ready
                   Because while it is preparing it gets transparent
                   But I want a progress bar instead
                   Therefore initially set its dimensions to 1x1 and change the size when it's ready 
                */
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                params.gravity = Gravity.CENTER;
                videoView.setLayoutParams(params);
                progressBar.setVisibility(View.GONE);
            }
        });
        /*
           When the activity is not present VideoView crashes when clicked
           To avoid crash I overrided setOnTouchListener method and return true from it
        */
        videoView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(event.getAction() == MotionEvent.ACTION_UP) {
                    if (videoView.isPlaying()) {
                        videoView.pause();
                    } else {
                        videoView.start();
                    }
                }
                return true;
            }
        });
    }

    @Override
    public StandOutLayoutParams getParams(int id, Window window) {
        return new StandOutLayoutParams(id, WIDTH, HEIGHT,
                StandOutLayoutParams.CENTER, StandOutLayoutParams.CENTER);
    }

    @Override
    public int getFlags(int id) {
        return super.getFlags(id)
                | StandOutFlags.FLAG_BODY_MOVE_ENABLE
                | StandOutFlags.FLAG_WINDOW_FOCUSABLE_DISABLE
                | StandOutFlags.FLAG_DECORATION_SYSTEM
                | StandOutFlags.FLAG_ADD_FUNCTIONALITY_DROP_DOWN_DISABLE
                | StandOutFlags.FLAG_DECORATION_CLOSE_DISABLE;
    }

    @Override
    public String getPersistentNotificationMessage(int id) {
        return "Click here to close floating window";
    }

    @Override
    public Intent getPersistentNotificationIntent(int id) {
        return StandOutWindow.getCloseIntent(this, FloatingWindow.class, id);
    }
}

The code above works, but there are several problems with it.

  1. I tested it on three devices and emulator and it worked. But there is a device at which it crashed at first. I remove MediaController and now it almost works. When user changes the size of the window the VideoView size gets weird. Perhaps I should test the device, on which the code does not work for Android compatibility. But, anyway maybe how I am doing the windowed player is wrong and you know a better way.

  2. I have to set the size of the VideoView to 1x1 and then change it, I cannot make it normal size right away, because if I do it the area in the window where VideoView should be becomes transparent until the video is loaded. Also I cannot click on the VideoView and let the system process the click event. If I do it I get BadTokenException: token null is not valid, is your activity running. The activity is not running, therefore I have to process the click event myself to prevent the crash. These hacks make me think that I am doing it wrong.

  3. I cannot think of a way to make video fullscreen. The only thing I thought of is to start a fullscreen activity and pass url and video position to it. Maybe this is the way to go. In this case the user will have to wait for video to load again when (s)he hits the fullscreen button. Plus I have no idea how the window will behave when fullscreen activity is started.

It feels like video was not intended to be played without activity. Maybe there is way to make this window player in such a way that there is always an invisible activity which would miss all the touch events and pass them down to the activity stack. And such an activity could be used for video playback.

Upvotes: 2

Views: 346

Answers (1)

Contextioner
Contextioner

Reputation: 75

You can make it to full screen by inflating the layout with these dimensions:

LayoutParams.y = getApplicationContext().getResources().getDisplayMetrics().heightPixels

LayoutParams.x = getApplicationContext().getResources().getDisplayMetrics().widthPixels

Upvotes: 0

Related Questions