最近研究了一下锁屏,要实现锁屏大体的实现思路是自定义一个后台service监听手机屏幕开关事件,监听到屏幕关闭的时候替换系统锁屏并调用自定义的锁屏界面,自定义锁屏界面需要屏蔽返回键和home键,以及屏蔽状态栏下拉。
系统屏幕开关的时候会发出相应的广播,我们可以接收对应的广播来调用自己的锁屏界面。屏幕开关的时候会发出以下两个广播事件。
android.intent.action.SCREEN_ON
android.intent.action.SCREEN_OFF
替换系统锁屏要调用KeyguardManager类相应方法去解除屏幕锁定,这里需要在配置文件中添加
<uses-permissionandroid:name="android.permission.DISABLE_KEYGUARD" />权限配置
屏蔽系统锁屏代码
mKeyguardManager= (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
mKeyguardLock= mKeyguardManager.newKeyguardLock("");
mKeyguardLock.disableKeyguard();
以下是自定义service代码,service中动态注册了监听屏幕开关事件
- public class LockService extends Service {
- private String TAG = "LockService";
- private Intent zdLockIntent = null;
- @Override
- public IBinder onBind(Intent arg0) {
- return null;
- }
- public void onCreate() {
- super.onCreate();
- zdLockIntent = new Intent(LockService.this, ShowLockActivity.class);
- zdLockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- /* 注册广播 */
- IntentFilter mScreenOnFilter = new IntentFilter("android.intent.action.SCREEN_ON");
- LockService.this.registerReceiver(mScreenOnReceiver, mScreenOnFilter);
- /* 注册广播 */
- IntentFilter mScreenOffFilter = new IntentFilter("android.intent.action.SCREEN_OFF");
- LockService.this.registerReceiver(mScreenOffReceiver, mScreenOffFilter);
- }
- public void onDestroy() {
- Log.i(TAG, "----------------- onDestroy------");
- super.onDestroy();
- this.unregisterReceiver(mScreenOnReceiver);
- this.unregisterReceiver(mScreenOffReceiver);
- // 在此重新启动,使服务常驻内存
- startService(new Intent(this, LockService.class));
- }
- private KeyguardManager mKeyguardManager = null;
- private KeyguardManager.KeyguardLock mKeyguardLock = null;
- // 屏幕变亮的广播,我们要隐藏默认的锁屏界面
- private BroadcastReceiver mScreenOnReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals("android.intent.action.SCREEN_ON")) {
- Log.i(TAG, "----------------- android.intent.action.SCREEN_ON------");
- }
- }
- };
- // 屏幕变暗/变亮的广播 , 我们要调用KeyguardManager类相应方法去解除屏幕锁定
- private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals("android.intent.action.SCREEN_OFF") || action.equals("android.intent.action.SCREEN_ON")) {
- mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
- mKeyguardLock = mKeyguardManager.newKeyguardLock("");
- mKeyguardLock.disableKeyguard();
- startActivity(zdLockIntent);
- }
- }
- };
- }
LockLayer.java这个类用来屏蔽状态啦下拉和home键的
- public class LockLayer {
- private Activity mActivty;
- private WindowManager mWindowManager;
- private View mLockView;
- private LayoutParams mLockViewLayoutParams;
- private boolean isLocked;
- // 这个值具体用于实现全屏
- private final static int FLAG_APKTOOL_VALUE = 1280;
- public LockLayer(Activity act) {
- mActivty = act;
- init();
- }
- private void init() {
- isLocked = false;
- mWindowManager = mActivty.getWindowManager();
- mLockViewLayoutParams = new LayoutParams();
- mLockViewLayoutParams.width = LayoutParams.MATCH_PARENT;
- mLockViewLayoutParams.height = LayoutParams.MATCH_PARENT;
- // 这一行实现屏蔽Home
- mLockViewLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR;
- mLockViewLayoutParams.flags = FLAG_APKTOOL_VALUE;
- }
- public synchronized void lock() {
- if (mLockView != null && !isLocked) {
- mWindowManager.addView(mLockView, mLockViewLayoutParams);
- }
- isLocked = true;
- }
- public synchronized void unlock() {
- if (mWindowManager != null && isLocked) {
- mWindowManager.removeView(mLockView);
- }
- isLocked = false;
- }
- public synchronized void setLockView(View v) {
- mLockView = v;
- }
- }
RoundSpinView.java 自定义锁屏界面
- public class RoundSpinView extends View {
- private String TAG = "RoundSpinView";
- private Activity act;
- private Context ctx;
- private Paint mPaint = new Paint();
- // 图片列表列表
- private BigStone[] mStones;
- // 中心点stone
- private BigStone centerStones;
- // 数目
- private static final int STONE_COUNT = 4;
- // 圆心坐标
- private int mPointX = 0, mPointY = 0;
- // 半径
- private int mRadius = 0;
- // 每两个点间隔的角度
- private int mDegreeDelta;
- //
- private Bitmap lockscre_pressed_bit ;
- private Bitmap lockscreen_normal_bit;
- private Bitmap select_bg_bit;
- private int[] normal_img = { R.drawable.ic_lockscreen_message_normal, R.drawable.ic_lockscreen_unlock_normal, R.drawable.ic_lockscreen_phone_normal, R.drawable.ic_tab_theme_normal };
- private int[] select_img = { R.drawable.ic_lockscreen_message_activated, R.drawable.ic_lockscreen_unlock_activated, R.drawable.ic_lockscreen_phone_activated, R.drawable.ic_tab_theme_selected };
- private Bitmap[] normal_img_bitmap = new Bitmap[STONE_COUNT];
- private Bitmap[] select_img_bitmap = new Bitmap[STONE_COUNT];
- public RoundSpinView(Context context,Activity act, int px, int py, int radius) {
- super(context);
- this.ctx = context;
- this.act = act;
- init(px, py, radius);
- }
- public RoundSpinView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
- public RoundSpinView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public RoundSpinView(Context context) {
- super(context);
- }
- public void init(int px, int py, int radius) {
- mPaint.setColor(Color.WHITE);
- mPaint.setStrokeWidth(0);
- mPaint.setAntiAlias(true);
- mPaint.setStyle(Style.STROKE);
- lockscre_pressed_bit = BitmapFactory.decodeResource(getResources(), R.drawable.lockscre_pressed);
- lockscreen_normal_bit = BitmapFactory.decodeResource(getResources(), R.drawable.lockscreen_normal);
- select_bg_bit = BitmapFactory.decodeResource(getResources(), R.drawable.template_checkbox_normal);
- for (int index = 0; index < STONE_COUNT; index++) {
- normal_img_bitmap[index] = BitmapFactory.decodeResource(getResources(), normal_img[index]);
- select_img_bitmap[index] = BitmapFactory.decodeResource(getResources(), select_img[index]);
- }
- setBackgroundResource(R.drawable.bg1);
- mPointX = px / 2;
- mPointY = py / 3 * 2;
- mRadius = radius;
- setupStones();
- computeCoordinates();
- }
- /**
- * 初始化每个点
- */
- private void setupStones() {
- mStones = new BigStone[STONE_COUNT];
- BigStone stone;
- int angle = 0;
- mDegreeDelta = 360 / STONE_COUNT;
- centerStones = new BigStone();
- centerStones.angle = angle;
- centerStones.x = mPointX;
- centerStones.y = mPointY;
- for (int index = 0; index < STONE_COUNT; index++) {
- stone = new BigStone();
- stone.angle = angle;
- angle += mDegreeDelta;
- mStones[index] = stone;
- }
- }
- /**
- * 计算每个点的坐标
- */
- private void computeCoordinates() {
- BigStone stone;
- for (int index = 0; index < STONE_COUNT; index++) {
- stone = mStones[index];
- stone.x = mPointX + (float) ((mRadius + select_bg_bit.getWidth()/2) * Math.cos(stone.angle * Math.PI / 180));
- stone.y = mPointY + (float) ((mRadius + select_bg_bit.getHeight()/2) * Math.sin(stone.angle * Math.PI / 180));
- stone.bitmap = normal_img_bitmap[index];
- stone.angle = computeCurrentAngle(stone.x, stone.y);
- }
- }
- /**
- * 计算坐标点与圆心直径的角度
- *
- * @param x
- * @param y
- * @return
- */
- private int computeCurrentAngle(float x, float y) {
- float distance = (float) Math.sqrt(((x - mPointX) * (x - mPointX) + (y - mPointY) * (y - mPointY)));
- int degree = (int) (Math.acos((x - mPointX) / distance) * 180 / Math.PI);
- if (y < mPointY) {
- degree = -degree;
- }
- return degree;
- }
- private boolean isPressLock = false;// 标记是否按住中心锁图片
- @Override
- public boolean dispatchTouchEvent(MotionEvent event) {
- float x, y;
- int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- x = event.getX();
- y = event.getY();
- isPressLock = isPressLockPic(x, y);
- setIsVisible(isPressLock);
- invalidate();
- break;
- case MotionEvent.ACTION_MOVE:
- x = event.getX();
- y = event.getY();
- // 算出当前坐标和圆心的距离
- centerStones.angle = computeCurrentAngle(x, y);
- if (isPressLock) {
- centerStones.bitmap = lockscre_pressed_bit;
- computeCoordinates();
- if (getDistance(x, y) <= mRadius) {
- centerStones.x = x;
- centerStones.y = y;
- } else {// 大于直径时根据角度算出坐标
- centerStones.x = mPointX + (float) ((mRadius) * Math.cos(centerStones.angle * Math.PI / 180));
- centerStones.y = mPointY + (float) ((mRadius) * Math.sin(centerStones.angle * Math.PI / 180));
- if (centerStones.angle <= (mStones[0].angle + 15) && centerStones.angle >= (mStones[0].angle - 15)) {
- mStones[0].bitmap = select_img_bitmap[0];
- centerStones.bitmap = select_bg_bit;
- centerStones.x = mStones[0].x;
- centerStones.y = mStones[0].y;
- }
- if (centerStones.angle <= (mStones[1].angle + 15) && centerStones.angle >= (mStones[1].angle - 15)) {
- mStones[1].bitmap = select_img_bitmap[1];
- centerStones.bitmap = select_bg_bit;
- centerStones.x = mStones[1].x;
- centerStones.y = mStones[1].y;
- }
- if (centerStones.angle <= (mStones[2].angle + 15) && centerStones.angle >= (mStones[2].angle - 15)) {
- mStones[2].bitmap = select_img_bitmap[2];
- centerStones.bitmap = select_bg_bit;
- centerStones.x = mStones[2].x;
- centerStones.y = mStones[2].y;
- }
- if (centerStones.angle <= (mStones[3].angle + 15) && centerStones.angle >= (mStones[3].angle - 15)) {
- mStones[3].bitmap = select_img_bitmap[3];
- centerStones.bitmap = select_bg_bit;
- centerStones.x = mStones[3].x;
- centerStones.y = mStones[3].y;
- }
- }
- invalidate();
- }
- break;
- case MotionEvent.ACTION_UP:
- //处理Action_Up事件: 判断是否解锁成功,成功则结束我们的Activity ;否则 ,缓慢回退该图片。
- handleActionUpEvent(event);
- break;
- }
- return true;
- }
- private void handleActionUpEvent(MotionEvent event){
- boolean islocksuc = false;// 是否解锁成功
- float x = event.getX();
- float y = event.getY();
- centerStones.angle = computeCurrentAngle(x, y);
- if (getDistance(x, y) >= mRadius) {
- if (centerStones.angle <= (mStones[0].angle + 15) && centerStones.angle >= (mStones[0].angle - 15) && mStones[0].isVisible) {
- islocksuc = true;
- Log.i(TAG,"解锁-短信 跳转到短信界面");
- act.finish();
- }
- if (centerStones.angle <= (mStones[1].angle + 15) && centerStones.angle >= (mStones[1].angle - 15) && mStones[1].isVisible) {
- islocksuc = true;
- Log.i(TAG,"解锁-解锁");
- act.finish();
- }
- if (centerStones.angle <= (mStones[2].angle + 15) && centerStones.angle >= (mStones[2].angle - 15) && mStones[2].isVisible) {
- islocksuc = true;
- Log.i(TAG,"解锁-电话 跳转到电话界面");
- act.finish();
- }
- if (centerStones.angle <= (mStones[3].angle + 15) && centerStones.angle >= (mStones[3].angle - 15) && mStones[3].isVisible) {
- islocksuc = true;
- Log.i(TAG,"解锁-相机 跳转到相机界面");
- act.finish();
- }
- }
- if(!islocksuc) { // 未解锁成功
- backToCenter();
- }
- }
- //回退动画时间间隔值
- private static int BACK_DURATION = 20 ; // 20ms
- //水平方向前进速率
- private static float VE_HORIZONTAL = 0.8f ; //0.1dip/ms
- private Handler mHandler =new Handler ();
- private void backToCenter() {
- mHandler.postDelayed(BackDragImgTask, BACK_DURATION);
- }
- //通过延时控制当前绘制bitmap的位置坐标
- private Runnable BackDragImgTask = new Runnable(){
- public void run(){
- //一下次Bitmap应该到达的坐标值
- if(centerStones.x>=mPointX){
- centerStones.x = centerStones.x - BACK_DURATION * VE_HORIZONTAL;
- if(centerStones.x<mPointX){
- centerStones.x = mPointX;
- }
- } else {
- centerStones.x = centerStones.x + BACK_DURATION * VE_HORIZONTAL;
- if(centerStones.x>mPointX){
- centerStones.x = mPointX;
- }
- }
- centerStones.y = mPointY + (float) ((centerStones.x-mPointX) * Math.tan(centerStones.angle * Math.PI / 180));
- invalidate();//重绘
- boolean shouldEnd = getDistance(centerStones.x, centerStones.y) <= 8 ;
- if(!shouldEnd)
- mHandler.postDelayed(BackDragImgTask, BACK_DURATION);
- else { //复原初始场景
- centerStones.x = mPointX;
- centerStones.y = mPointY;
- isPressLock = false;
- setIsVisible(isPressLock);
- invalidate();
- }
- }
- };
- /**
- * 获取坐标点与圆心直径的距离
- * @param x
- * @param y
- * @return
- */
- private float getDistance(float x, float y) {
- float distance = (float) Math.sqrt(((x - mPointX) * (x - mPointX) + (y - mPointY) * (y - mPointY)));
- return distance;
- }
- /**
- * 判断手指按下的时候是否按住中心锁图片
- *
- * @param x
- * @param y
- * @return
- */
- private boolean isPressLockPic(float x, float y) {
- float l = centerStones.x - centerStones.bitmap.getWidth() / 2;
- float r = centerStones.x + centerStones.bitmap.getWidth() / 2;
- float t = centerStones.y - centerStones.bitmap.getHeight() / 2;
- float b = centerStones.y + centerStones.bitmap.getHeight() / 2;
- if (x >= l && x <= r && y >= t && y <= b) {
- return true;
- }
- return false;
- }
- @Override
- public void onDraw(Canvas canvas) {
- if (isPressLock) {// 手指按下状态
- canvas.drawCircle(mPointX, mPointY, mRadius, mPaint);// 画圆
- drawInCenter(canvas, centerStones.bitmap, centerStones.x, centerStones.y);// 画中心锁图片
- for (int index = 0; index < STONE_COUNT; index++) {
- if (!mStones[index].isVisible)
- continue;
- drawInCenter(canvas, mStones[index].bitmap, mStones[index].x, mStones[index].y);
- }
- } else {
- centerStones.bitmap = lockscreen_normal_bit;
- drawInCenter(canvas, centerStones.bitmap, centerStones.x, centerStones.y);// 画中心锁图片
- }
- }
- /**
- * 把中心点放到中心处
- *
- * @param canvas
- * @param bitmap
- * @param left
- * @param top
- */
- void drawInCenter(Canvas canvas, Bitmap bitmap, float left, float top) {
- canvas.drawBitmap(bitmap, left - bitmap.getWidth() / 2, top - bitmap.getHeight() / 2, null);
- }
- private void setIsVisible(boolean isVisible){
- for (int index = 0; index < STONE_COUNT; index++) {
- mStones[index].isVisible = isVisible;
- }
- }
- class BigStone {
- // 图片
- public Bitmap bitmap;
- // 角度
- public int angle;
- // x坐标
- public float x;
- // y坐标
- public float y;
- // 是否可见
- public boolean isVisible = false;
- }
- }