zoukankan      html  css  js  c++  java
  • android开发 锁屏 真正的锁屏,是go锁屏那种。

    想做个锁屏界面很久了,最近一周,历经千辛万苦,越过种种挫折,终于完美实现了这一要求,在此将锁屏思路分享出来。

    注意:这不是什么一键锁屏,是类似“go锁屏”那样的锁屏界面。

    准备:本程序共需要

    两个activity:home、main。

    一个service:myService

    一个receiver:bootReceiver

    一个layout:layout

    其中home作为屏幕home键专用的activity,main则是主要的展示锁屏界面的activity。

    service用于接收锁屏/解锁广播,layout则是main所需要展示的界面。

    思路:

    !注意:以下代码没有顺序联系,具体请参考源码!

    1,给程序添加服务,当此服务接收到 锁屏/解锁广播 时,关闭系统锁屏界面,打开自己的锁屏界面。

    关键代码:

    /onReceive中:
    
    keyguardManager = (KeyguardManager)context.getSystemService(context.KEYGUARD_SERVICE);
    keyguardLock = keyguardManager.newKeyguardLock("");
    keyguardLock.disableKeyguard();//解锁系统锁屏
    startActivity(toMainIntent);//跳转到主界面

    注意,上面的代码需要注册权限:

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

    另外,为了防止主界面被重复调用,我们在设置intent时还要加上一些filter:

    //设置myservice中intent的filter
    toMainIntent = new Intent(myService.this, Main.class);
    toMainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//这个flags表示如果已经有这个activity,则将已有的提到栈顶,否则新建一个activity。
    //在manifest中讲主界面的启动模式更改为:singleTask,功能和上面的“Intent.FLAG_ACTIVITY_NEW_TASK”类似
    <activity
    android:name="com.example.screenlocker.Main"
    android:label="@string/app_name"
    android:launchMode="singleTask" >
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>

    当然,我们还可以在onDestroy中设置服务重启,以保证此服务一直在后台运行

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(screenReceiver);
        //重启此服务
        startActivity(new Intent(myService.this,myService.class));
    }

    将一些其他的事项,如注册服务、在主界面中启动服务等设置完成后,我们可以run一遍了~

    如果没出错,那么解锁后首先打开的将是我们的锁屏界面。

    2,实现了锁屏,但是还有一个问题,当按返回键或者home键的时候,我们的界面就轻易被KO了。别担心,咱们一一屏蔽他们。

    首先,拿返回键开刀:只需要在主界面中添加如下代码即可:

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
      switch (keyCode) {
      case KeyEvent.KEYCODE_BACK:
        return true;
      }
      return super.onKeyDown(keyCode, event);
    }

    可是,home键并不能通过此方法屏蔽或者捕捉。这对程序猿来说是个很头疼的问题,在网上也有各种解决的办法,但是笔者参考总结,决定用“GO锁屏”的方式来实现:

    这种办法的思路是:把自己的程序设置为系统主屏幕!这样,本来按home键是要转到主屏幕的,设置好后,按home键则直接跳转到我们的界面里来了!

    好了,让我们新建一个activity,命名为“home”,用来抢夺home键。然后在manifest中设置如下:

    <activity android:name="com.example.screenlocker.Home" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

    这样,当按home键的时候,如果是在main界面按的,系统不做反应。如果是在其他时候按下home键,就会跳转到这个activity中来。

    (首次运行时,会让你选择按home键跳转到“主屏幕”或者“test1(咱们自己写的程序的appName)”)

    也就是说,我们已经实现了锁屏界面对home的屏蔽。如果是在非锁屏状态下按home,就会调用home界面。我们只需在home界面里如此设置即可:

    onCreate(){
    跳转到系统主屏幕;//具体代码见下文
    finish();//结束这个activity
    }

    所以,这个activity没有必要加载界面。故此,我们要将这个activity的theme设置为“不显示”,这样,不但避免浪费,更可以避免在跳转的时候屏幕闪一下,影响用户体验

    //manifest设置home的theme为noDisplay
    <activity
        android:name="com.example.screenlocker.Home"
        android:theme="@android:style/Theme.NoDisplay" >
            <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.HOME" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

    我们可以在home的oncreate里打这样一行代码:

    Log.e("", "home is called");finish();//调用finish以防止程序卡在一个不展示的activity

    然后运行一遍试试效果,就可以清楚的发现,当我们何时按home键时,会调用这一activity。

    3,home键已经抢过来了。那么接下来,我们要做的是让home界面跳转到主界面:

    首先,我们要获取一个列表:列出所以可以作为主屏幕的程序:

    List<String> pkgNamesT = new ArrayList<String>();
    List<String> actNamesT = new ArrayList<String>();
    List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
      for (int i = 0; i < resolveInfos.size(); i++) {
        String string = resolveInfos.get(i).activityInfo.packageName;
        if (!string.equals(context.getPackageName())) {//排除自己的包名
          pkgNamesT.add(string);
          string = resolveInfos.get(i).activityInfo.name;
          actNamesT.add(string);
        }
      }

    然后,可以用alertDialog的方式让用户选择要跳到哪个主屏幕,并用sharedPreferences记录用户的选择。

    new AlertDialog.Builder(context).setTitle("请选择解锁后的屏幕").setCancelable(false).setSingleChoiceItems(names, 0, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            editor.putString(packageName, pkgNames.get(which));
            editor.putString(activityName, actNames.get(which));
            editor.commit();
            originalHome();
            dialog.dismiss();
        }
    }).show();

    这样,下次的时候就可以根据包名和类名,直接跳转到用户所设置的主屏幕了:

    String pkgName = sharedPreferences.getString(packageName, null);
    String actName = sharedPreferences.getString(activityName, null);
    ComponentName componentName = new ComponentName(pkgName, actName);
    Intent intent = new Intent();
    intent.setComponent(componentName);
    context.startActivity(intent);
    ((Activity) context).finish();

    4,当然,最后,我们也希望可以将其设置为开机启动:

    public class BootReceiver extends BroadcastReceiver{
        String myPkgName = "com.example.screenlocker";//#包名
        String myActName = "com.example.acts.myService";//#类名
        
        @Override
        public void onReceive(Context context, Intent intent) {
            //启动监听服务
            Intent myIntent=new Intent();
            myIntent.setAction(myPkgName+"."+myActName);
            context.startService(myIntent);    
        }
    }

    注意:别忘了在manifest中添加开机启动的权限哦:

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

    不过我更推荐在home中加这么一行代码:

    startService(new Intent(Home.this, ScreenReceiver.class));

    这样,每次打开主屏幕都能打开这个后台服务,哈哈哈……

    下载源码

    附言

    笔者在查资料时,发现极难找到此类资料。要么晦涩难懂,要么资料不全。深深的体会到了四处碰壁的绝望,故此才有了此文。

    本文将锁屏实现思路及源码分享出来,稍加修改即可使用,希望能帮到有同样需求的人。希望有收获的人能花半秒钟推荐一下,方便其余coder查阅。

  • 相关阅读:
    作业3
    数组求和
    2.自己的Github试用过程
    2.自己的Github注册流程
    图片左右滑动整理为插件
    artDialog中的time参数,ajax请求中的异步与同步
    简单的图片放大镜效果插件
    3月份学习安排
    前端好的网站
    web app开发中遇到的问题
  • 原文地址:https://www.cnblogs.com/coderzhuoke/p/3696292.html
Copyright © 2011-2022 走看看