【发布时间】: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 的源代码,您会看到 StandOutWindow 是 Service,这会创建一个弹出窗口。
我实际上可以在这个窗口中播放视频。这是我的窗口类
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);
}
}
上面的代码可以工作,但是有几个问题。
我在三台设备和模拟器上对其进行了测试,它工作正常。但是有一个设备一开始就崩溃了。我删除了
MediaController,现在它几乎可以工作了。当用户更改窗口大小时,VideoView的大小会变得很奇怪。也许我应该测试设备,因为代码不适用于 Android 兼容性。但是,无论如何,也许我做窗口播放器的方式是错误的,你知道更好的方法。我必须将
VideoView的大小设置为 1x1,然后更改它,我无法立即将其设置为正常大小,因为如果我这样做,窗口中应该是VideoView的区域变为在加载视频之前是透明的。我也不能点击VideoView并让系统处理点击事件。如果我这样做,我会得到BadTokenException: token null is not valid, is your activity running。该活动未运行,因此我必须自己处理单击事件以防止崩溃。这些 hack 让我觉得我做错了。我想不出让视频全屏的方法。我唯一想到的就是启动一个全屏活动并将 url 和视频位置传递给它。也许这是要走的路。在这种情况下,当用户点击全屏按钮时,用户将不得不等待视频再次加载。另外,我不知道启动全屏活动时窗口的行为。
感觉好像视频不打算在没有活动的情况下播放。也许有办法让这个窗口播放器总是有一个不可见的活动,它会错过所有的触摸事件并将它们传递到活动堆栈。并且这样的活动可以用于视频播放。
【问题讨论】:
-
你试过了吗?
标签: android video android-activity service popupwindow