Android自定义锁屏的实现

 最近研究了一下锁屏,要实现锁屏大体的实现思路是自定义一个后台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中动态注册了监听屏幕开关事件

[java]  view plain copy
  1. public class LockService extends Service {  
  2.     private String TAG = "LockService";  
  3.     private Intent zdLockIntent = null;  
  4.   
  5.     @Override  
  6.     public IBinder onBind(Intent arg0) {  
  7.         return null;  
  8.     }  
  9.   
  10.     public void onCreate() {  
  11.         super.onCreate();  
  12.         zdLockIntent = new Intent(LockService.this, ShowLockActivity.class);  
  13.         zdLockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  14.         /* 注册广播 */  
  15.         IntentFilter mScreenOnFilter = new IntentFilter("android.intent.action.SCREEN_ON");  
  16.         LockService.this.registerReceiver(mScreenOnReceiver, mScreenOnFilter);  
  17.   
  18.         /* 注册广播 */  
  19.         IntentFilter mScreenOffFilter = new IntentFilter("android.intent.action.SCREEN_OFF");  
  20.         LockService.this.registerReceiver(mScreenOffReceiver, mScreenOffFilter);  
  21.     }  
  22.   
  23.     public void onDestroy() {  
  24.         Log.i(TAG, "----------------- onDestroy------");  
  25.         super.onDestroy();  
  26.         this.unregisterReceiver(mScreenOnReceiver);  
  27.         this.unregisterReceiver(mScreenOffReceiver);  
  28.         // 在此重新启动,使服务常驻内存  
  29.         startService(new Intent(this, LockService.class));  
  30.     }  
  31.   
  32.     private KeyguardManager mKeyguardManager = null;  
  33.     private KeyguardManager.KeyguardLock mKeyguardLock = null;  
  34.     // 屏幕变亮的广播,我们要隐藏默认的锁屏界面  
  35.     private BroadcastReceiver mScreenOnReceiver = new BroadcastReceiver() {  
  36.         @Override  
  37.         public void onReceive(Context context, Intent intent) {  
  38.             if (intent.getAction().equals("android.intent.action.SCREEN_ON")) {  
  39.                 Log.i(TAG, "----------------- android.intent.action.SCREEN_ON------");  
  40.             }  
  41.         }  
  42.     };  
  43.   
  44.     // 屏幕变暗/变亮的广播 , 我们要调用KeyguardManager类相应方法去解除屏幕锁定  
  45.     private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {  
  46.         @Override  
  47.         public void onReceive(Context context, Intent intent) {  
  48.             String action = intent.getAction();  
  49.             if (action.equals("android.intent.action.SCREEN_OFF") || action.equals("android.intent.action.SCREEN_ON")) {  
  50.                 mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);  
  51.                 mKeyguardLock = mKeyguardManager.newKeyguardLock("");  
  52.                 mKeyguardLock.disableKeyguard();  
  53.                 startActivity(zdLockIntent);  
  54.             }  
  55.         }  
  56.     };  
  57. }  

LockLayer.java这个类用来屏蔽状态啦下拉和home键的

[java]  view plain copy
  1. public class LockLayer {  
  2.     private Activity mActivty;  
  3.     private WindowManager mWindowManager;  
  4.     private View mLockView;  
  5.     private LayoutParams mLockViewLayoutParams;  
  6.     private boolean isLocked;  
  7.     // 这个值具体用于实现全屏  
  8.     private final static int FLAG_APKTOOL_VALUE = 1280;  
  9.   
  10.     public LockLayer(Activity act) {  
  11.         mActivty = act;  
  12.         init();  
  13.     }  
  14.   
  15.     private void init() {  
  16.         isLocked = false;  
  17.         mWindowManager = mActivty.getWindowManager();  
  18.         mLockViewLayoutParams = new LayoutParams();  
  19.         mLockViewLayoutParams.width = LayoutParams.MATCH_PARENT;  
  20.         mLockViewLayoutParams.height = LayoutParams.MATCH_PARENT;  
  21.         // 这一行实现屏蔽Home  
  22.         mLockViewLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR;  
  23.         mLockViewLayoutParams.flags = FLAG_APKTOOL_VALUE;  
  24.     }  
  25.   
  26.     public synchronized void lock() {  
  27.         if (mLockView != null && !isLocked) {  
  28.             mWindowManager.addView(mLockView, mLockViewLayoutParams);  
  29.         }  
  30.         isLocked = true;  
  31.     }  
  32.   
  33.     public synchronized void unlock() {  
  34.         if (mWindowManager != null && isLocked) {  
  35.             mWindowManager.removeView(mLockView);  
  36.         }  
  37.         isLocked = false;  
  38.     }  
  39.   
  40.     public synchronized void setLockView(View v) {  
  41.         mLockView = v;  
  42.     }  
  43. }  

RoundSpinView.java 自定义锁屏界面

[java]  view plain copy
  1. public class RoundSpinView extends View {  
  2.     private String TAG = "RoundSpinView";  
  3.       
  4.     private Activity act;  
  5.     private Context ctx;  
  6.       
  7.     private Paint mPaint = new Paint();  
  8.       
  9.     // 图片列表列表  
  10.     private BigStone[] mStones;  
  11.     // 中心点stone  
  12.     private BigStone centerStones;  
  13.     // 数目  
  14.     private static final int STONE_COUNT = 4;  
  15.     // 圆心坐标  
  16.     private int mPointX = 0, mPointY = 0;  
  17.     // 半径  
  18.     private int mRadius = 0;  
  19.     // 每两个点间隔的角度  
  20.     private int mDegreeDelta;  
  21.     //   
  22.     private Bitmap lockscre_pressed_bit ;  
  23.     private Bitmap lockscreen_normal_bit;  
  24.     private Bitmap select_bg_bit;  
  25.   
  26.     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 };  
  27.     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 };  
  28.     private Bitmap[] normal_img_bitmap = new Bitmap[STONE_COUNT];  
  29.     private Bitmap[] select_img_bitmap = new Bitmap[STONE_COUNT];  
  30.       
  31.     public RoundSpinView(Context context,Activity act, int px, int py, int radius) {  
  32.         super(context);  
  33.         this.ctx = context;  
  34.         this.act = act;  
  35.         init(px, py, radius);  
  36.     }  
  37.   
  38.     public RoundSpinView(Context context, AttributeSet attrs, int defStyle) {  
  39.         super(context, attrs, defStyle);  
  40.     }  
  41.   
  42.     public RoundSpinView(Context context, AttributeSet attrs) {  
  43.         super(context, attrs);  
  44.     }  
  45.   
  46.     public RoundSpinView(Context context) {  
  47.         super(context);  
  48.     }  
  49.   
  50.     public void init(int px, int py, int radius) {  
  51.         mPaint.setColor(Color.WHITE);  
  52.         mPaint.setStrokeWidth(0);  
  53.         mPaint.setAntiAlias(true);  
  54.         mPaint.setStyle(Style.STROKE);  
  55.           
  56.         lockscre_pressed_bit = BitmapFactory.decodeResource(getResources(), R.drawable.lockscre_pressed);  
  57.         lockscreen_normal_bit = BitmapFactory.decodeResource(getResources(), R.drawable.lockscreen_normal);  
  58.         select_bg_bit = BitmapFactory.decodeResource(getResources(), R.drawable.template_checkbox_normal);  
  59.         for (int index = 0; index < STONE_COUNT; index++) {  
  60.             normal_img_bitmap[index] = BitmapFactory.decodeResource(getResources(), normal_img[index]);  
  61.             select_img_bitmap[index] = BitmapFactory.decodeResource(getResources(), select_img[index]);  
  62.         }  
  63.           
  64.         setBackgroundResource(R.drawable.bg1);  
  65.   
  66.         mPointX = px / 2;  
  67.         mPointY = py / 3 * 2;  
  68.         mRadius = radius;  
  69.   
  70.         setupStones();  
  71.         computeCoordinates();  
  72.     }  
  73.   
  74.     /** 
  75.      * 初始化每个点 
  76.      */  
  77.     private void setupStones() {  
  78.         mStones = new BigStone[STONE_COUNT];  
  79.         BigStone stone;  
  80.         int angle = 0;  
  81.         mDegreeDelta = 360 / STONE_COUNT;  
  82.   
  83.         centerStones = new BigStone();  
  84.         centerStones.angle = angle;  
  85.         centerStones.x = mPointX;  
  86.         centerStones.y = mPointY;  
  87.   
  88.         for (int index = 0; index < STONE_COUNT; index++) {  
  89.             stone = new BigStone();  
  90.             stone.angle = angle;  
  91.             angle += mDegreeDelta;  
  92.   
  93.             mStones[index] = stone;  
  94.         }  
  95.     }  
  96.   
  97.   
  98.     /** 
  99.      * 计算每个点的坐标 
  100.      */  
  101.     private void computeCoordinates() {  
  102.         BigStone stone;  
  103.         for (int index = 0; index < STONE_COUNT; index++) {  
  104.             stone = mStones[index];  
  105.             stone.x = mPointX + (float) ((mRadius + select_bg_bit.getWidth()/2) * Math.cos(stone.angle * Math.PI / 180));  
  106.             stone.y = mPointY + (float) ((mRadius + select_bg_bit.getHeight()/2) * Math.sin(stone.angle * Math.PI / 180));  
  107.             stone.bitmap = normal_img_bitmap[index];  
  108.             stone.angle = computeCurrentAngle(stone.x, stone.y);  
  109.         }  
  110.     }  
  111.   
  112.     /** 
  113.      * 计算坐标点与圆心直径的角度 
  114.      *  
  115.      * @param x 
  116.      * @param y 
  117.      * @return 
  118.      */  
  119.     private int computeCurrentAngle(float x, float y) {  
  120.         float distance = (float) Math.sqrt(((x - mPointX) * (x - mPointX) + (y - mPointY) * (y - mPointY)));  
  121.         int degree = (int) (Math.acos((x - mPointX) / distance) * 180 / Math.PI);  
  122.         if (y < mPointY) {  
  123.             degree = -degree;  
  124.         }  
  125.         return degree;  
  126.     }  
  127.   
  128.     private boolean isPressLock = false;// 标记是否按住中心锁图片  
  129.   
  130.     @Override  
  131.     public boolean dispatchTouchEvent(MotionEvent event) {  
  132.         float x, y;  
  133.         int action = event.getAction();  
  134.         switch (action) {  
  135.         case MotionEvent.ACTION_DOWN:  
  136.             x = event.getX();  
  137.             y = event.getY();  
  138.             isPressLock = isPressLockPic(x, y);  
  139.             setIsVisible(isPressLock);  
  140.             invalidate();  
  141.             break;  
  142.         case MotionEvent.ACTION_MOVE:  
  143.             x = event.getX();  
  144.             y = event.getY();  
  145.             // 算出当前坐标和圆心的距离  
  146.             centerStones.angle = computeCurrentAngle(x, y);  
  147.             if (isPressLock) {  
  148.                 centerStones.bitmap = lockscre_pressed_bit;  
  149.                 computeCoordinates();  
  150.                 if (getDistance(x, y) <= mRadius) {  
  151.                     centerStones.x = x;  
  152.                     centerStones.y = y;  
  153.                 } else {// 大于直径时根据角度算出坐标  
  154.                     centerStones.x = mPointX + (float) ((mRadius) * Math.cos(centerStones.angle * Math.PI / 180));  
  155.                     centerStones.y = mPointY + (float) ((mRadius) * Math.sin(centerStones.angle * Math.PI / 180));  
  156.                     if (centerStones.angle <= (mStones[0].angle + 15) && centerStones.angle >= (mStones[0].angle - 15)) {  
  157.                         mStones[0].bitmap = select_img_bitmap[0];  
  158.                         centerStones.bitmap = select_bg_bit;  
  159.                         centerStones.x = mStones[0].x;  
  160.                         centerStones.y = mStones[0].y;  
  161.                     }  
  162.                     if (centerStones.angle <= (mStones[1].angle + 15) && centerStones.angle >= (mStones[1].angle - 15)) {  
  163.                         mStones[1].bitmap = select_img_bitmap[1];  
  164.                         centerStones.bitmap = select_bg_bit;  
  165.                         centerStones.x = mStones[1].x;  
  166.                         centerStones.y = mStones[1].y;  
  167.                     }  
  168.                     if (centerStones.angle <= (mStones[2].angle + 15) && centerStones.angle >= (mStones[2].angle - 15)) {  
  169.                         mStones[2].bitmap = select_img_bitmap[2];  
  170.                         centerStones.bitmap = select_bg_bit;  
  171.                         centerStones.x = mStones[2].x;  
  172.                         centerStones.y = mStones[2].y;  
  173.                     }  
  174.                     if (centerStones.angle <= (mStones[3].angle + 15) && centerStones.angle >= (mStones[3].angle - 15)) {  
  175.                         mStones[3].bitmap = select_img_bitmap[3];  
  176.                         centerStones.bitmap = select_bg_bit;  
  177.                         centerStones.x = mStones[3].x;  
  178.                         centerStones.y = mStones[3].y;  
  179.                     }  
  180.                 }  
  181.                 invalidate();  
  182.             }  
  183.             break;  
  184.   
  185.         case MotionEvent.ACTION_UP:  
  186.             //处理Action_Up事件:  判断是否解锁成功,成功则结束我们的Activity ;否则 ,缓慢回退该图片。  
  187.             handleActionUpEvent(event);  
  188.             break;  
  189.         }  
  190.         return true;  
  191.     }  
  192.       
  193.     private void handleActionUpEvent(MotionEvent event){  
  194.         boolean islocksuc = false;// 是否解锁成功  
  195.         float x = event.getX();  
  196.         float y = event.getY();  
  197.         centerStones.angle = computeCurrentAngle(x, y);  
  198.         if (getDistance(x, y) >= mRadius) {  
  199.             if (centerStones.angle <= (mStones[0].angle + 15) && centerStones.angle >= (mStones[0].angle - 15) && mStones[0].isVisible) {  
  200.                 islocksuc = true;  
  201.                 Log.i(TAG,"解锁-短信 跳转到短信界面");  
  202.                 act.finish();  
  203.             }  
  204.             if (centerStones.angle <= (mStones[1].angle + 15) && centerStones.angle >= (mStones[1].angle - 15) && mStones[1].isVisible) {  
  205.                 islocksuc = true;  
  206.                 Log.i(TAG,"解锁-解锁");  
  207.                 act.finish();  
  208.             }  
  209.             if (centerStones.angle <= (mStones[2].angle + 15) && centerStones.angle >= (mStones[2].angle - 15) && mStones[2].isVisible) {  
  210.                 islocksuc = true;  
  211.                 Log.i(TAG,"解锁-电话 跳转到电话界面");  
  212.                 act.finish();  
  213.             }  
  214.             if (centerStones.angle <= (mStones[3].angle + 15) && centerStones.angle >= (mStones[3].angle - 15) && mStones[3].isVisible) {  
  215.                 islocksuc = true;  
  216.                 Log.i(TAG,"解锁-相机 跳转到相机界面");  
  217.                 act.finish();  
  218.             }  
  219.         }   
  220.         if(!islocksuc) { // 未解锁成功  
  221.             backToCenter();  
  222.         }  
  223.     }  
  224.       
  225.       
  226.     //回退动画时间间隔值   
  227.     private static int BACK_DURATION = 20 ;   // 20ms  
  228.     //水平方向前进速率  
  229.     private static float VE_HORIZONTAL = 0.8f ;  //0.1dip/ms  
  230.     private Handler mHandler =new Handler ();  
  231.       
  232.     private void backToCenter() {  
  233.         mHandler.postDelayed(BackDragImgTask, BACK_DURATION);  
  234.     }  
  235.       
  236.     //通过延时控制当前绘制bitmap的位置坐标  
  237.     private Runnable BackDragImgTask = new Runnable(){  
  238.         public void run(){  
  239.             //一下次Bitmap应该到达的坐标值  
  240.             if(centerStones.x>=mPointX){  
  241.                 centerStones.x = centerStones.x - BACK_DURATION * VE_HORIZONTAL;  
  242.                 if(centerStones.x<mPointX){  
  243.                     centerStones.x = mPointX;  
  244.                 }  
  245.             } else {  
  246.                 centerStones.x = centerStones.x + BACK_DURATION * VE_HORIZONTAL;  
  247.                 if(centerStones.x>mPointX){  
  248.                     centerStones.x = mPointX;  
  249.                 }  
  250.             }   
  251.             centerStones.y = mPointY + (float) ((centerStones.x-mPointX) * Math.tan(centerStones.angle * Math.PI / 180));  
  252.               
  253.             invalidate();//重绘         
  254.             boolean shouldEnd = getDistance(centerStones.x, centerStones.y) <= 8 ;             
  255.             if(!shouldEnd)  
  256.                 mHandler.postDelayed(BackDragImgTask, BACK_DURATION);  
  257.             else { //复原初始场景  
  258.                 centerStones.x = mPointX;  
  259.                 centerStones.y = mPointY;  
  260.                 isPressLock = false;  
  261.                 setIsVisible(isPressLock);  
  262.                 invalidate();  
  263.             }                 
  264.         }  
  265.     };  
  266.   
  267.     /** 
  268.      * 获取坐标点与圆心直径的距离 
  269.      * @param x 
  270.      * @param y 
  271.      * @return 
  272.      */  
  273.     private float getDistance(float x, float y) {  
  274.         float distance = (float) Math.sqrt(((x - mPointX) * (x - mPointX) + (y - mPointY) * (y - mPointY)));  
  275.         return distance;  
  276.     }  
  277.   
  278.     /** 
  279.      * 判断手指按下的时候是否按住中心锁图片 
  280.      *  
  281.      * @param x 
  282.      * @param y 
  283.      * @return 
  284.      */  
  285.     private boolean isPressLockPic(float x, float y) {  
  286.         float l = centerStones.x - centerStones.bitmap.getWidth() / 2;  
  287.         float r = centerStones.x + centerStones.bitmap.getWidth() / 2;  
  288.         float t = centerStones.y - centerStones.bitmap.getHeight() / 2;  
  289.         float b = centerStones.y + centerStones.bitmap.getHeight() / 2;  
  290.         if (x >= l && x <= r && y >= t && y <= b) {  
  291.             return true;  
  292.         }  
  293.         return false;  
  294.     }  
  295.   
  296.     @Override  
  297.     public void onDraw(Canvas canvas) {  
  298.         if (isPressLock) {// 手指按下状态  
  299.             canvas.drawCircle(mPointX, mPointY, mRadius, mPaint);// 画圆  
  300.             drawInCenter(canvas, centerStones.bitmap, centerStones.x, centerStones.y);// 画中心锁图片  
  301.             for (int index = 0; index < STONE_COUNT; index++) {  
  302.                 if (!mStones[index].isVisible)  
  303.                     continue;  
  304.                 drawInCenter(canvas, mStones[index].bitmap, mStones[index].x, mStones[index].y);  
  305.             }  
  306.         } else {  
  307.             centerStones.bitmap = lockscreen_normal_bit;  
  308.             drawInCenter(canvas, centerStones.bitmap, centerStones.x, centerStones.y);// 画中心锁图片  
  309.         }  
  310.     }  
  311.   
  312.     /** 
  313.      * 把中心点放到中心处 
  314.      *  
  315.      * @param canvas 
  316.      * @param bitmap 
  317.      * @param left 
  318.      * @param top 
  319.      */  
  320.     void drawInCenter(Canvas canvas, Bitmap bitmap, float left, float top) {  
  321.         canvas.drawBitmap(bitmap, left - bitmap.getWidth() / 2, top - bitmap.getHeight() / 2null);  
  322.     }  
  323.       
  324.     private void setIsVisible(boolean isVisible){  
  325.         for (int index = 0; index < STONE_COUNT; index++) {  
  326.             mStones[index].isVisible = isVisible;  
  327.         }  
  328.     }  
  329.   
  330.     class BigStone {  
  331.         // 图片  
  332.         public Bitmap bitmap;  
  333.         // 角度  
  334.         public int angle;  
  335.         // x坐标  
  336.         public float x;  
  337.         // y坐标  
  338.         public float y;  
  339.         // 是否可见  
  340.         public boolean isVisible = false;  
  341.     }  
  342. }  
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值