一、簡要記錄下,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); } } } ...... }