没有活动时如何播放视频?以及如何将视频设为全屏?

时间:2016-11-17 22:16:58

标签: android video android-activity service popupwindow

我有一个视频网址,我可以使用任何播放器或VideoView播放。但这就是我想要做的事情。

RecyclerView其中每个元素都包含视频的标题和缩略图。当用户点击视频时,会出现一个弹出窗口。此弹出窗口包含VideoView(或任何可以播放来自网址的视频)并播放视频。用户可以拖动此窗口。诀窍是这样做,如果用户按下后退按钮,当前活动关闭,窗口应保持并继续播放视频。在播放视频时,用户可以在其他应用程序中执行任何操作,而带有视频的窗口仍然位于顶部并继续播放视频。用户可以随时按下窗口(或其中的按钮),视频将变为全屏。当用户决定全屏播放时,应用活动可能不在那里。

上面描述的内容已在此应用中实现

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

我可以创建一个视图窗口,当用户关闭应用程序活动时,该窗口将保留在那里。为此我使用这个库

https://github.com/pingpongboss/StandOut

如果你检查了lib的源代码,你会看到StandOutWindowService,它会创建一个弹出窗口。

我实际上可以在这个窗口中播放视频。这是我的窗口类

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);
    }
}

上面的代码有效,但有几个问题。

  1. 我在三台设备和模拟器上测试了它并且它工作正常。但是有一个设备首先崩溃了。我删除了MediaController,现在几乎可以了。当用户更改窗口大小时,VideoView大小会变得奇怪。也许我应该测试设备,代码不适用于Android兼容性。但是,无论如何也许我如何做窗口播放器是错误的,你知道更好的方法。

  2. 我必须将VideoView的大小设置为1x1然后更改它,我不能立即使其正常大小,因为如果我这样做,{{1}窗口中的区域在视频加载之前,应该变得透明。此外,我无法单击VideoView并让系统处理click事件。如果我这样做,我会得到VideoView。活动未运行,因此我必须自己处理click事件以防止崩溃。这些黑客让我觉得我做错了。

  3. 我想不出一种让视频全屏的方法。我唯一想到的是启动全屏活动并将网址和视频位置传递给它。也许这是要走的路。在这种情况下,当用户点击全屏按钮时,用户将不得不等待视频再次加载。另外,我不知道在启动全屏活动时窗口的行为方式。

  4. 感觉视频不是在没有活动的情况下播放的。也许有办法让这个窗口播放器的方式总是存在一个不可见的活动,它会错过所有的触摸事件并将它们传递给活动堆栈。这样的活动可以用于视频播放。

1 个答案:

答案 0 :(得分:0)

您可以通过使用以下尺寸对布局进行充气来使其全屏显示:

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

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