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

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

[java] view plaincopy
  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. public LockLayer(Activity act) {
  10. mActivty = act;
  11. init();
  12. }
  13. private void init() {
  14. isLocked = false;
  15. mWindowManager = mActivty.getWindowManager();
  16. mLockViewLayoutParams = new LayoutParams();
  17. mLockViewLayoutParams.width = LayoutParams.MATCH_PARENT;
  18. mLockViewLayoutParams.height = LayoutParams.MATCH_PARENT;
  19. // 这一行实现屏蔽Home
  20. mLockViewLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR;
  21. mLockViewLayoutParams.flags = FLAG_APKTOOL_VALUE;
  22. }
  23. public synchronized void lock() {
  24. if (mLockView != null && !isLocked) {
  25. mWindowManager.addView(mLockView, mLockViewLayoutParams);
  26. }
  27. isLocked = true;
  28. }
  29. public synchronized void unlock() {
  30. if (mWindowManager != null && isLocked) {
  31. mWindowManager.removeView(mLockView);
  32. }
  33. isLocked = false;
  34. }
  35. public synchronized void setLockView(View v) {
  36. mLockView = v;
  37. }
  38. }

RoundSpinView.java 自定义锁屏界面

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

Android自定义锁屏的实现相关推荐

  1. 浅谈 Android 自定义锁屏页的发车姿势

    作者:blowUp ,原文链接:http://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=2653577446&idx=2&sn ...

  2. 【腾讯Bugly干货分享】浅谈Android自定义锁屏页的发车姿势

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57875330c9da73584b025873 一.为什么需要自定义锁屏页 锁屏 ...

  3. 浅谈Android自定义锁屏页的发车姿势

    一.为什么需要自定义锁屏页 锁屏作为一种黑白屏时代就存在的手机功能,至今仍发挥着巨大作用,特别是触屏时代的到来,锁屏的功用被发挥到了极致.多少人曾经在无聊的时候每隔几分钟划开锁屏再关上,孜孜不倦,其酸 ...

  4. 【腾讯Bugly干货分享】浅谈 Android 自定义锁屏页的发车姿势

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57875330c9da73584b025873 一.为什么需要自定义锁屏页 锁屏 ...

  5. Android 自定义锁屏_三星Key Cafe 2021最新版下载-三星Key Cafe自定义键盘输入app v1.0.00.26...

    这次小编要为大家带来一款由三星官方正式推出的自定义键盘输入工具"Key Cafe",帮助大家能够自由定制手机输入法的主题和键位,允许用户能够自由定制键盘布局,增删案件等,设计一套最 ...

  6. Android实现自定义锁屏控制

    当在Android手机上需要实现自定义的锁屏,  往往在进入自定义的锁屏界面界面之前需要先解开屏幕锁, 以顺利的进入自定义锁屏界面 ,并能方便用户即时的做其他操作,下面用代码来实现这一功能: 1.点亮 ...

  7. Android 4.0 自定义锁屏

    在Android 4.0上做锁屏有一段时间了,期间改了很多bug,也按不同需求做了不少锁屏,其中比较满意的作品包括两个.一是,添加一个锁屏可以和原生锁屏进行切换:二是,自己写一个锁屏view去替换原生 ...

  8. 安卓 14 可自定义锁屏时钟尺寸、颜色和透明度

    以下内容来自公众号code小生,关注每日干货及时送达 根据最新报道,预估在本月发布的安卓 14 Beta 3 更新中,将原生引入自定义锁屏时钟特性. 有媒体表示用户当前可以为锁屏和主屏幕设置不同的壁纸 ...

  9. android 游戏 锁屏界面开发,android 锁屏程序开发

    参考http://blog.csdn.net/wdaming1986/article/details/8837023 锁屏程序的步骤如下: 1.替换系统锁屏 2.屏蔽Home键,back键.menu键 ...

  10. android锁屏密码文件夹,深入理解Android M 锁屏密码存储方式

    Android M 之前锁屏密码的存储 在 Android M 之前,锁屏密码的存储格式很简单,其使用了 64 位随机数作为 salt 值,此 salt 值被存储在 sqlite 数据库 /data/ ...

最新文章

  1. 课后习题代码持续更新。。。。。。。。。。。。。
  2. Keras 最新《面向小数据集构建图像分类模型》
  3. ASP.NET Web页面(.aspx)添加用户控件(.ascx)无显示的问题
  4. 全链路压测自动化实践
  5. c# 带返回值的action_C#委托Action、ActionT、FuncT、PredicateT
  6. 荣幸参加 微软 Teched 2012 会议
  7. 在共享dll中使用mfc_在SpringBoot中使用Spring Session解决分布式会话共享问题
  8. linux下svn常用指令
  9. leetcode面试题 10.01. 合并排序的数组
  10. 【跃迁之路】【706天】程序员高效学习方法论探索系列(实验阶段463-2019.1.26-27)...
  11. vscode open in browser 默认浏览器
  12. 李迟2021年4月知识总结
  13. hql将指定字段排在最后,然后再根据别的字段排序
  14. 教育行业 A 股 IPO 第一股,如何做成程序员培训这门生意 | 极客头条
  15. 如何退出vim编辑器?
  16. 【OpenGL】OpenGL GLUT扩展库安装与配置(Windows Visual Studio2008)
  17. multisim中pwl_Multisim 14电路设计与仿真
  18. bt磁力链接转换种子中的问题
  19. Nacos指南-服务发现:删除服务
  20. php构建webservice,php webservice实例(简单易懂)

热门文章

  1. 找不到设备 将计算机连接到USB打印机,打印机连接电脑没反应怎么办
  2. Windows10 V2004 正式版发布
  3. Linux下的任务管理器 top命令
  4. 多级放大电路(直接耦合、阻容耦合、变压器耦合、光电耦合)
  5. 撤销 git rebase
  6. windows s2019安装crucible-4.8.2
  7. 摘录整理:日本文化常识之历史篇
  8. android修改默认的返回图标
  9. He's a Pirate---David Garrett
  10. 什么是带宽,举个例子说一下,整天说的服务器带宽有限,是什么意思?