天天看点

自定义锁屏的实现一、引言二、自定义锁屏的实现方案三、问题与总结

一、引言

1、软件项目概述

       基于用户使用app过程中,手机屏幕关闭后,重新点亮手机屏幕,能够快速看见用户的所需信息的需求,来设计app的自定义锁屏效果。

2、概述

       本文档就自定义锁屏的实现进行讲解。

二、自定义锁屏的实现方案

1、方案一

1)、总体实现

       在app需要时开启一个service,在service中时刻监听系统息屏(SCREEN_OFF)广播,当屏幕熄灭时,Service监听到广播,开启锁屏页Activity,在屏幕的最上层显示。并在activity创建时隐藏掉系统锁屏(有密码的情况下是禁止不掉的)。

2)、详细实现

(1)、开启服务注册广播

//开启服务

startService(this,LockScreenService.class);
           

//注册屏幕熄灭广播

IntentFiltermScreenOffFilter = new IntentFilter();
mScreenOffFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenOffReceiver, mScreenOffFilter);
           

(2)、监听广播开启锁屏

if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {

    Intent mLockIntent = new Intent(context, LockScreenActivity.class);

    mLockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK );

    startActivity(mLockIntent);

}
           

       注意:将锁屏Activity的启动模式设置为singleTask,否则锁屏Activity实质上还是建立在原来的App的task栈中(可以根据需求做修改)。

(3)、去掉系统锁屏

       在启动自定义锁屏的同时,去掉系统锁屏。当然如果设置了系统锁屏密码,系统锁屏是无法去掉的,具体代码如下:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
           

       FLAG_DISMISS_KEYGUARD用于去掉系统锁屏页。

       FLAG_SHOW_WHEN_LOCKED使Activity在锁屏时能够显示。

       去掉系统锁屏需要添加权限如下:

<uses-permissionandroid:name="android.permission.DISABLE_KEYGUARD" />
           

(4)、屏蔽Back和Menu键

       重写onKeyDown方法屏蔽,代码如下:

public boolean onKeyDown(int keyCode,KeyEvent event) {
    int key = event.getKeyCode();
    switch (key) {
    case KeyEvent.KEYCODE_BACK:
         return true;
    case KeyEvent.KEYCODE_MENU:
         return true;
    default:
         break;
    }
    return super.onKeyDown(keyCode,event);
}
           

       当熄灭屏幕后,就可以看到我们的自定义锁屏页了。

(5)、滑屏解锁

       当手指在屏幕上滑动时,拦截并处理滑动事件,使锁屏页随着手指运动,当超过一定距离,锁屏消失,否则重新覆盖屏幕。

       注意:需要给锁屏Activity设置透明主题,否则滑动看不见背景页面。

关键代码如下:

publicboolean onTouchEvent(MotionEvent event) {
        mWidth = getWidth();
        int action = event.getAction();
        float nx = event.getX();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mStartX = nx;
                break;
            case MotionEvent.ACTION_MOVE:
                handleMoveView(nx);
                break;
            case MotionEvent.ACTION_UP:
            caseMotionEvent.ACTION_CANCEL:
                doMoveEvent(nx);
                break;
        }
        return true;
    }
           

       mStartX:用来记录滑动的起始位置。

       handleMoveView():根据滑动的x轴距离,来控制view的移动。

       doMoveEvent():根据结束位置和起始位置的距离,来判断是否超过阈值,如果超过了阈值,view滑出屏幕,销毁锁屏;否则重新覆盖屏幕

(6)、近期任务不显示锁屏Activity

       在清单文件中,设置锁屏Activity属性:android:excludeFromRecents=”true”,让锁屏Activity不显示在近期任务中。

3)、结论

       这套方案完成锁屏页的实现,可以满足用户方便查看运动状态的需求。

2、方案二

1)、总体实现

       同方案一。

2)、详细实现

(1)步骤

       详细实现步骤同方案一,只是加载布局的方式不同。

(2)加载布局

       方案一调用Activity的setContentView()方法加载布局;

       方案二将布局inflate()成View后设成系统错误的view。

       原理:是把这个view当成系统的错误的view,sdk文档解释说明。

      Window type: internal system error windows, appear on top of everything theycan. In multiuser systems shows only on the owning user's window.

关键代码如下:

mWindowManager = (WindowManager)mContext.getApplicationContext().getSystemService("window");
mParams = new LayoutParams();
mParams.type = LayoutParams.TYPE_SYSTEM_ERROR;
mWindowManager.addView(mLockView, mParams);
           

3)、结论

       这个error的view在所有的view的最上面,可以达到屏蔽home键的,Recent键以及下拉效果,并且长按power键,关机界面也弹不出来。这套方案同样可以满足用户方便查看详细信息的需求。

三、问题与总结

1、禁止Home键与Recent键

      Home键与Recent键(调出最近打开应用的按键)的点击事件是在Framework层进行处理的,因此onKeyDown与dispatchKeyEvent都捕获不到点击事件,所以无法屏蔽其点击效果。关于这两个按键的屏蔽方法,网上用到了反射,有的是通过改变Window的标志位和Type等,总的来说,这些方法只对部分Android版本有效,有的则无法编译通过。所以无法在应用层屏蔽掉Home键以及Recent键。

2、总结

      方案二虽然屏蔽掉了按键的响应,但也一定程度上影响了用户体验,例如:关机操作。所以不建议使用。

      方案一在满足用户的需求的同时,并没有影响到用户的体验。并且与市场上qq音乐,keep的锁屏页实现了相同的效果(并没有对home键,Recent键以及下拉菜单做相应的处理),所以方案一比较合适。

代码下载

http://download.csdn.net/detail/chendeshan330/9916014