Android自定义屏保
2018-03-14 本文已影响108人
OkCoco
Android亮屏、熄屏的时候会发出广播,通常在熄屏广播中启动屏保
- 注册屏幕广播
/**
* 注册广播
*
* @param mContext 上下文环境
* @param receiver 将要注册的广播
*/
public void registerScreenSaverReceiver(Context mContext, ScreenReceiver receiver) {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
mContext.registerReceiver(receiver, filter);
}
在该广播的Action中有着这样的注释:
/**
* Broadcast Action: Sent when the device wakes up and becomes interactive.
* <p>
* For historical reasons, the name of this broadcast action refers to the power
* state of the screen but it is actually sent in response to changes in the
* overall interactive state of the device.
* </p><p>
* This broadcast is sent when the device becomes interactive which may have
* nothing to do with the screen turning on. To determine the
* actual state of the screen, use {@link android.view.Display#getState}.
* </p><p>
* See {@link android.os.PowerManager#isInteractive} for details.
* </p>
* You <em>cannot</em> receive this through components declared in
* manifests, only by explicitly registering for it with
* {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
* Context.registerReceiver()}.
*
* <p class="note">This is a protected intent that can only be sent
* by the system.
*/
这就是说,由于历史原因,该广播Action表示屏幕的电信号状态,但是实际上该广播是在屏幕不可进行交互时发出
注:不能通过在Manifest.xml文件注册的方式接收该广播,仅仅支持通过代码registerReceiver(Broadcast ,IntentFilter)的方式进行注册
在 onReceive(Context context, Intent intent) 方法中进行开启自定义屏保:
public class ScreenReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//拿到屏幕锁,亮屏,随即释放,否则屏幕就会保持常量
WakeUtil.getInstance().wakeScreenLock();
WakeUtil.getInstance().releaseScreenLock();
//屏蔽系统的屏保
mKeyguardManager = (KeyguardManager) MyApplication.getInstance().getSystemService(Context.KEYGUARD_SERVICE);
mKeyguardLock = mKeyguardManager.newKeyguardLock("ScreenLockService");
mKeyguardLock.disableKeyguard();
//TODO 开启自定义的屏保;例如:跳转一个Activity,显示屏保图片
}
}
- 保持屏幕常量
通常,保持屏幕常量有如下方法:
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
官方注释:
/** Window flag: as long as this window is visible to the user, keep the device's screen turned on and bright. */
public static final int FLAG_KEEP_SCREEN_ON = 0x00000080;
即当window对用户可见时,保持屏幕常量。
- 通过PowerManager.WakeLock
mScreenWakeLock = powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK,
this.getClass().getCanonicalName());
if (!mScreenWakeLock.isHeld()) {
mScreenWakeLock.acquire();
}
对于方法newWakeLock(int levelAndFlags, String tag),下面看看该flag和level分别代表什么意义。
PowerManager.ACQUIRE_CAUSES_WAKEUP|PowerManager.SCREEN_DIM_WAKE_LOCK
/**
* 获得唤醒锁时亮屏
* <p>
* 正常情况下,唤醒锁并不能真正唤醒设备,一旦屏幕已经打开,它们就只能继续工作。
* 正如视频软件正常工作一样。
* </p>
*/
public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
/**
* 保证亮屏状态 (可能会变暗);
* 允许关闭背光
* @deprecated Most applications should use
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
* of this type of wake lock, as it will be correctly managed by the platform
* as the user moves between applications and doesn't require a special permission.
*/
@Deprecated
public static final int SCREEN_DIM_WAKE_LOCK = 0x00000006;
可以看出该方法已经过时,系统更推荐使用方法1.
3.通过设置系统进入屏保的时间
try {
Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, paramInt);
} catch (Exception localException) {
localException.printStackTrace();
}
paramInt代表进入屏保或锁屏的时间,单位毫秒ms。这里可设置为Integer.MAX_VALUE。
同样可以通过这种方式进行屏幕亮度(0-255)等的设置:
try {
Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, paramInt);
} catch (Exception localException) {
localException.printStackTrace();
}
- 进入浅休眠(熄屏状态下CPU仍在运行)
mCpuWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getCanonicalName());
synchronized (WakeUtil.class) {
if (!mCpuWakeLock.isHeld()) {
mCpuWakeLock.acquire();
}
}