• android4.0 锁屏实现(转)


    转载请表明出处http://blog.csdn.net/wdaming1986/article/details/8837023

            好了,言归正传,说说锁屏了,其实把锁屏做成apk的形式,会引起很多问题的,导致不必要的麻烦,就像市场上的流行的Go锁屏和91锁屏也是会有一些问题的,只是影响不大,最好的做法是修改源码,在源码中定制自己的锁屏,这样一劳永逸;

    首先做锁屏考虑的事有以下四点;

            (1)替换掉系统的锁屏,不能让系统的锁屏显示出来;

            (2)屏蔽掉Home键盘,back键,menu键;

            (3)在其他界面或Launcher界面,长按home键,不能让自己的锁屏apk显示在最近任务中;

            (4)每次开机显示自己的锁屏

            针对这四点一一做解答,不一定是完整的代码,只是提供以下思路,有兴趣的同学可以提出疑问;

             针对(1),这个比较容易,就调用disableKeyguard掉系统的就可以了;

    1. mKeyguardManager = (KeyguardManager)Class.this.getSystemService(Context.KEYGUARD_SERVICE);  
    2.         mKeyguardLock = mKeyguardManager.newKeyguardLock("my_lockscreen");   
    3.         mKeyguardLock.disableKeyguard();  

    注意:在Manifext.xml中加入权限:

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

             针对(2),这个Home键的处理,我看网上有同学写博客了,有同学这么处理:

    1. public class LockLayer {     
    2.     private Activity mActivty;     
    3.     private WindowManager mWindowManager;     
    4.     private View mLockView;     
    5.     private LayoutParams mLockViewLayoutParams;     
    6.     private static LockLayer mLockLayer;     
    7.     private boolean isLocked;     
    8.         
    9.     public static synchronized LockLayer getInstance(Activity act){     
    10.         if(mLockLayer == null){     
    11.             mLockLayer = new LockLayer(act);     
    12.         }     
    13.         return mLockLayer;     
    14.     }     
    15.         
    16.     private LockLayer(Activity act) {     
    17.         mActivty = act;     
    18.         init();     
    19.     }     
    20.     
    21.     private void init(){     
    22.         isLocked = false;     
    23.         mWindowManager = mActivty.getWindowManager();     
    24.         mLockViewLayoutParams = new LayoutParams();     
    25.         mLockViewLayoutParams.width = LayoutParams.MATCH_PARENT;     
    26.         mLockViewLayoutParams.height = LayoutParams.MATCH_PARENT;     
    27.         //实现关键     
    28.         mLockViewLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR;     
    29.         //apktool value,这个值具体是哪个变量还请网友帮忙     
    30.         mLockViewLayoutParams.flags = 1280;     
    31.     }     
    32.     public synchronized void lock() {     
    33.         if(mLockView!=null&&!isLocked){     
    34.             mWindowManager.addView(mLockView, mLockViewLayoutParams);     
    35.         }     
    36.         isLocked = true;     
    37.     }     
    38.     public synchronized void unlock() {     
    39.         if(mWindowManager!=null&&isLocked){     
    40.             mWindowManager.removeView(mLockView);     
    41.         }     
    42.         isLocked = false;     
    43.     }     
    44.     public synchronized void setLockView(View v){     
    45.         mLockView = v;     
    46.     }     
    47. }    

       原理:是把这个view当成系统的错误的view,

    这个在PhoneWindowManager.java中的interceptKeyBeforeDispatching()方法中也有根据,请看真相:

    1. final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;  
    2.                 for (int i=0; i<typeCount; i++) {  
    3.                     if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {  
    4.                         // don't do anything, but also don't pass it to the app  
    5.                         return -1;  
    6.                     }  
    7.                 }  


    看注释:如果设置了这两个属性的其中一个,就不做任何处理,home键不对这个app生效;

    而WINDOW_TYPES_WHERE_HOME_DOESNT_WORK数据的定义如下:

    1. private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {  
    2.             WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,  
    3.             WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,  
    4.         };  


    这下你就明白为什么上述代码设置为TYPE_SYSTEM_ERROR,其实设置为TYPE_SYSTEM_ALERT也可以的。

    再来看看sdk文档有解释说明,

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

    这个error的view在所有的view的最上面,所以就可以达到屏蔽home键的效果了;

    问题来了:在这个界面长按power键,关机界面也弹不出来了,这个我试验过,所以这个方法不可取;

           还有同学说这么做:

    private static final int FLAG_HOMEKEY_DISPATCHED = 0x80000000;

    1. 在app 的你要屏蔽home 键的activity 中,只需要添加该标志就可以了  
    2.   
    3. this.getWindow().setFlags(FLAG_HOMEKEY_DISPATCHED, FLAG_HOMEKEY_DISPATCHED);  
    4.   
    5. 如果要使home 键有效,再 clearFlags 即可。  
    6.   
    7. getWindow().clearFlags(WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED);  

    注意:以上代码要加在setContentView()之前才行;

    这个代码来源于PhoneWindowManager.java这个类的interceptKeyBeforeDispatching()方法中,

    1. if ((flag & WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED) != 0) {  
    2.                    // the window wants to handle the home key, so dispatch it to it.  
    3.                    return 0;  
    4.                }      

    这样设置,有的同学感觉好用,有的同学感觉不好用;

    原因:android4.0的源码的PhoneWindowManager.java没有添加上述代码,所以不起作用,

    而4.1的源码PhoneWindowManager.java中有这个代码,所以好用,这个请大家看看对应的源码是否有上述代码;


             针对(3),这个就模仿Go锁屏和91锁屏,在启动锁屏的activity中配置

    1. <category android:name="android.intent.category.HOME" />  

    这个属性,然后先清除系统启动的默认设置,就是选择系统点击Home键启动哪个home,设置为启动自己的锁屏,然后再设置解锁后启动那个桌面,这个自己处理下逻辑就可以了,大致思路就是这个样子的;

                 针对(4),这个Go锁屏还有91锁屏处理的都不太理想,回头我想到好的思路再更新,大致思路是:监听开机广播, <action android:name="android.intent.action.BOOT_COMPLETED"/>,这个写一个MYBootCompletedReceiver类,作用是disable掉系统的锁屏,然后启动自己的锁屏的服务,监听屏幕亮和灭的广播,这个屏幕亮和灭的广播要动态监听;大家有好的思路或见解可以留言讨论?

  • 相关阅读:
    WinRT下GridView/ListView随滚动条自动加载
    C# 获取属性名
    Xaml System Resources 系统资源
    WinRT常见而又困扰的问题
    .net 解压 zip 包完全不用第三方 library (.net unzip zip file without third party library)
    团队.Net技术手册,现代.Net技术栈摸索梳理
    C# 构建可扩展的应用程序(插件)
    分别用MVC,MCP,MVVM实现一个井字棋游戏
    Android系统属性
    ThreadLocal 和 Countdaowlatch
  • 原文地址:https://www.cnblogs.com/zlfoak/p/4728914.html
Copyright © 2020-2023  润新知