Android为了达到节约电源的目的,在屏幕没有操作时便会自动息屏,那么比如我们在播放视频时,尽管对屏幕没有操作,但是我们此时是不希望它息屏的,如果视频处于暂停状态,此时是希望它自动息屏的。
下面来看一下如何在Chromium全屏播放视频时是如何控制屏幕的。
因为全屏播放是和ContentVideoView.java相关的,那么就在这个类中来实现。
首先在content_switches.h中声明一个PowerSaveBlocker 开关:
CONTENT_EXPORT extern const char kEnableContentVideoViewPowerSaveBlocker[];
在content_switches.cc中初始化:
// Enable the PowerSaveBlocker in ContentVideoView. Android only.
const char kEnableContentVideoViewPowerSaveBlocker[] = "enable-content-video-view-power-save-blocker";
然后在aw_main_delegate.cc中把开关打开:
在AwMainDelegate::BasicStartupComplete中加上
cl->AppendSwitch(switches::kEnableContentVideoViewPowerSaveBlocker)
接下来就要在ContentVideoView.java中来实现了:
首先ContentVideoView要实现一下ViewAndroidDelegate接口:
实现它的三个方法:
@Override
public View acquireAnchorView() {
View anchorView = new View(getContext());
addView(anchorView);
return anchorView;
}
@Override
public void setAnchorViewPosition(View view, float x, float y, float width, float height) {
Log.e(TAG, "setAnchorViewPosition isn't implemented");
}
@Override
public void releaseAnchorView(View anchorView) {
removeView(anchorView);
}
添加一个成员变量:
// The ViewAndroid is used to keep screen on during video playback.
private ViewAndroid mViewAndroid;
在构造函数中实现:
mViewAndroid = new ViewAndroid(new WindowAndroid(context.getApplicationContext()), this);
实现一个函数供jni层调用:
@CalledByNative
private long getNativeViewAndroid() {
return mViewAndroid.getNativePointer();
}
ContentVideoView类对应的jni层类在content_video_view.cc中实现,那么电源管理也主要在这个类中进行:
首先看content_video_view.h,要在content的命名空间中申明PowerSaveBlocker类和添加成员变量和方法:
#include "base/timer/timer.h"
class PowerSaveBlocker;
// Returns the associated NativeView
gfx::NativeView GetNativeView();
void CreatePowerSaveBlocker();
// PowerSaveBlock to keep screen on for fullscreen video.
// There is already blocker when inline video started, and it requires the
// ContentView's container displayed to take effect; but in WebView, apps
// could use another container to hold ContentVideoView, and the blocker in
// ContentView's container can not keep screen on; so we need another blocker
// here, it is no harm, just an additonal blocker.
scoped_ptr<PowerSaveBlocker> power_save_blocker_;
在content_video_view.cc中实现:
gfx::NativeView ContentVideoView::GetNativeView() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (content_video_view.is_null())
return NULL;
return reinterpret_cast<gfx::NativeView>(
Java_ContentVideoView_getNativeViewAndroid(env,
content_video_view.obj()));
}
void ContentVideoView::CreatePowerSaveBlocker() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableContentVideoViewPowerSaveBlocker)) {
// In fullscreen Clank reuses the power save blocker attached to the
// container view that was created for embedded video. The WebView cannot
// reuse that so we create a new blocker instead.
if (power_save_blocker_) return;
power_save_blocker_ = PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
"Playing video").Pass();
static_cast<PowerSaveBlockerImpl*>(power_save_blocker_.get())->
InitDisplaySleepBlocker(GetNativeView());
}
}
在构造函数中调用CreatePowerSaveBlocker
ContentVideoView::ContentVideoView(
BrowserMediaPlayerManager* manager)
: manager_(manager),
weak_factory_(this) {
……
CreatePowerSaveBlocker();
}
在ContentVideoView::OpenVideo()
和ContentVideoView::Play
时调用CreatePowerSaveBlocker()
来保持不息屏:
在ContentVideoView::OnMediaPlayerError
,ContentVideoView::OnPlaybackComplete()
,ContentVideoView::Pause
,ContentVideoView::ExitFullscreen
时调用power_save_blocker_.reset()
来让系统重新控制屏幕。
这样就达到了我们对播放视频是屏幕控制的目的。