Android中保持屏幕常亮的方法
一、简要记录下,Android中保持屏幕常亮的方法:
1、作用于View的:
setKeepScreenOn(true/false),同样可以在xml中设置android:keepScreenOn="",只要View可见即生效。
2、通过添加flag的形式实现:
添加:mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
清除:getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
3、使用PowerManager.WakeLock:
PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE); if (powerManager != null) { wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "WakeLock"); wakeLock.acquire(); //开启屏幕常亮 //wakeLock.release(); //释放wakeLock,注意此方法可能出现异常.具体可看源码 }
在自测手机中并未出现异常,也就是说,并非一定不可以连续调用wakeLock.acquire()和wakeLock.release()。
4、第三种官方已经不推荐使用,建议使用上述1、2两种方法。
二、其他:
1、在视频录制或播放中,MediaPlayer提供了相关方法实现屏幕常亮,具体如下:
mMediaPlayer.setScreenOnWhilePlaying(true);
源码如下:
/** * Control whether we should use the attached SurfaceHolder to keep the * screen on while video playback is occurring. This is the preferred * method over {@link #setWakeMode} where possible, since it doesn\'t * require that the application have permission for low-level wake lock * access. * * @param screenOn Supply true to keep the screen on, false to allow it * to turn off. */ public void setScreenOnWhilePlaying(boolean screenOn) { if (mScreenOnWhilePlaying != screenOn) { if (screenOn && mSurfaceHolder == null) { Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder"); } mScreenOnWhilePlaying = screenOn; updateSurfaceScreenOn(); //# } } ...... private void updateSurfaceScreenOn() { if (mSurfaceHolder != null) { mSurfaceHolder.setKeepScreenOn(mScreenOnWhilePlaying && mStayAwake); //# } }
2、附上WakeLock的部分源码,它是PowerManager的内部类,可重点查看release(...):
public final class WakeLock { ...... private boolean mRefCounted = true; //默认true ...... WakeLock(int flags, String tag, String packageName) { mFlags = flags; mTag = tag; mPackageName = packageName; mToken = new Binder(); //用于同步synchronized mTraceName = "WakeLock (" + mTag + ")"; } @Override protected void finalize() throws Throwable { synchronized (mToken) { if (mHeld) { Log.wtf(TAG, "WakeLock finalized while still held: " + mTag); Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0); try { mService.releaseWakeLock(mToken, 0); } catch (RemoteException e) { } } } } /** * Sets whether this WakeLock is reference counted. * <p> * Wake locks are reference counted by default. If a wake lock is * reference counted, then each call to {@link #acquire()} must be * balanced by an equal number of calls to {@link #release()}. If a wake * lock is not reference counted, then one call to {@link #release()} is * sufficient to undo the effect of all previous calls to {@link #acquire()}. * </p> * * @param value True to make the wake lock reference counted, false to * make the wake lock non-reference counted. */ public void setReferenceCounted(boolean value) { synchronized (mToken) { mRefCounted = value; } } /** * Acquires the wake lock. * <p> * Ensures that the device is on at the level requested when * the wake lock was created. * </p> */ public void acquire() { synchronized (mToken) { acquireLocked(); } } /** * Acquires the wake lock with a timeout. * <p> * Ensures that the device is on at the level requested when * the wake lock was created. The lock will be released after the given timeout * expires. * </p> * * @param timeout The timeout after which to release the wake lock, in milliseconds. */ public void acquire(long timeout) { synchronized (mToken) { acquireLocked(); mHandler.postDelayed(mReleaser, timeout); } } private void acquireLocked() { if (!mRefCounted || mCount++ == 0) { // Do this even if the wake lock is already thought to be held (mHeld == true) // because non-reference counted wake locks are not always properly released. // For example, the keyguard\'s wake lock might be forcibly released by the // power manager without the keyguard knowing. A subsequent call to acquire // should immediately acquire the wake lock once again despite never having // been explicitly released by the keyguard. mHandler.removeCallbacks(mReleaser); Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0); try { mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource, mHistoryTag); } catch (RemoteException e) { } mHeld = true; } } /** * Releases the wake lock. * <p> * This method releases your claim to the CPU or screen being on. * The screen may turn off shortly after you release the wake lock, or it may * not if there are other wake locks still held. * </p> */ public void release() { release(0); } /** * Releases the wake lock with flags to modify the release behavior. * <p> * This method releases your claim to the CPU or screen being on. * The screen may turn off shortly after you release the wake lock, or it may * not if there are other wake locks still held. * </p> * * @param flags Combination of flag values to modify the release behavior. * Currently only {@link #RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY} is supported. * Passing 0 is equivalent to calling {@link #release()}. */ public void release(int flags) { synchronized (mToken) { if (!mRefCounted || --mCount == 0) { //,满足任意条件即可执行 mHandler.removeCallbacks(mReleaser); if (mHeld) { //满足条件,才能执行mService.releaseWakeLock Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0); try { mService.releaseWakeLock(mToken, flags); } catch (RemoteException e) { } mHeld = false; } } if (mCount < 0) { //抛出异常 throw new RuntimeException("WakeLock under-locked " + mTag); } } } ...... }