【问题标题】:How to play video when there is no activity? And how to make the video fullscreen?没有活动时如何播放视频?以及如何使视频全屏?
【发布时间】:2016-11-17 22:16:57
【问题描述】:

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

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

我上面描述的东西在这个应用程序中实现了

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,然后更改它,我无法立即将其设置为正常大小,因为如果我这样做,窗口中应该是 VideoView 的区域变为在加载视频之前是透明的。我也不能点击VideoView 并让系统处理点击事件。如果我这样做,我会得到BadTokenException: token null is not valid, is your activity running。该活动未运行,因此我必须自己处理单击事件以防止崩溃。这些 hack 让我觉得我做错了。

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

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

【问题讨论】:

  • 你试过了吗?

标签: android video android-activity service popupwindow


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多