本来想将一个个java代码都说明一遍的,但是仔细一想有点啰嗦。这里实现service后,整个项目就结束了。至于定时锁屏的界面就不再贴一章了,有仔细的注释说明,大家自行阅读吧。
首先,常驻后台的服务 LockService
贴上代码,从代码分析
package com.example.mylock; /* * 锁屏服务,在这里启动锁屏和解锁 * 判断时间与日期等等一系列都在这里完成 */ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.IBinder; import android.util.Log; public class lockService extends Service { private Context MyContext; private static getDataFromSp gdfs;//SP对象 private String day, time[]; private boolean flag = false, clockFlag = false; public IBinder onBind(Intent arg0) { return null; } public void onCreate() { super.onCreate(); init(); /* 注册屏幕唤醒时的广播 */ setLock(); //---------------下面的几行代码貌似并无卵用 IntentFilter mScreenOnFilter = new IntentFilter( "android.intent.action.SCREEN_ON"); lockService.this.registerReceiver(mScreenReceiver, mScreenOnFilter); /* 注册机器锁屏时的广播 */ IntentFilter mScreenOffFilter = new IntentFilter( "android.intent.action.SCREEN_OFF"); lockService.this.registerReceiver(mScreenReceiver, mScreenOffFilter); reStartService(); } public int onStartCommand(Intent intent0, int flags, int startId) { /* 注册屏幕唤醒时的广播 */ init(); setLock(); IntentFilter mScreenOnFilter = new IntentFilter( "android.intent.action.SCREEN_ON"); lockService.this.registerReceiver(mScreenReceiver, mScreenOnFilter); /* 注册机器锁屏时的广播 */ IntentFilter mScreenOffFilter = new IntentFilter( "android.intent.action.SCREEN_OFF"); lockService.this.registerReceiver(mScreenReceiver, mScreenOffFilter); System.out.println("lockservicedakaile"); return START_STICKY; } public void onDestroy() { super.onDestroy(); this.unregisterReceiver(mScreenReceiver); startService(new Intent(lockService.this, lockService.class));//----服务关闭前重启服务 } public void init() { //实例化对象 MyContext = getApplicationContext(); gdfs = new getDataFromSp(MyContext); time = new String[5]; getDataFromSp(); } /* * 然后从相应的SP文件中获取相应模式的时间和日期 1 */ public void getDataFromSp() { day = gdfs.getDayOfWeek(); time[0] = gdfs.getOneTime(); time[1] = gdfs.getTwoTime(); time[2] = gdfs.getThreeTime(); time[3] = gdfs.getFourTime(); time[4] = gdfs.getFiveTime(); } //判断日期是否为空 public boolean dayIsNull() { if (day.equals("")) { return false; } return true; } //判断时间段是否为空,参数是代表第X个时间段 public boolean timeIsNull(int i) { if (time[i].equals("")) { return false; } return true; } /* * 将获取到的日期和时间与系统日期比较 注意要将SP文件中获取的时间转换成可比较的时间 如果日期在设定的日期内并且时间在设定的时间内,返回true */ public boolean compareTimeAndDay() { Log.v("判断定时函数", "进来了"); if (dayIsNull()) { Log.v("判断日期不空", "进来了"); for (int i = 0; i < 5; i++) { if (timeIsNull(i)) { // 如果该时间段不空的话,进去判断时间是否符合,符合就锁,超过时间段就解锁。 int _time[] = gdfs.getTimeOfNum(i + 1);// 获取第i个时间段的整型时间 Log.v("定时时间段不空", "进来了"); boolean day_flag = false; long t = System.currentTimeMillis(); Date date = new Date(t); SimpleDateFormat format = new SimpleDateFormat("E"); String weekDay = format.format(date); format = new SimpleDateFormat("hh"); String hour = format.format(date); format = new SimpleDateFormat("mm"); String minute = format.format(date); Log.v("时:分", hour + ":" + minute); Log.v("星期", weekDay); if (day.length() == 2) { if (day.equals(weekDay)) { // 判断星期的字符串是否匹配,如果匹配,将标志设为true Log.v("文件星期", day); day_flag = true; } } else { for (int j = day.length() - 2; j >= 2; j = j - 2) { String d = day.substring(j, j + 2); if (d.equals(weekDay)) { // 判断星期的字符串是否匹配,如果匹配,将标志设为true Log.v("文件星期", d); day_flag = true; break; } } } if (day_flag) { // 时间段不空,并且星期也匹配。 // 通过获取时间判断是上午还是下午 long time = System.currentTimeMillis(); final Calendar mCalendar = Calendar.getInstance(); mCalendar.setTimeInMillis(time); int apm = mCalendar.get(Calendar.AM_PM);// 值为0 上午 值为1 下午 Log.v("上下午", String.valueOf(apm)); // 如果是上午 if (apm == 0) { // 如果时间到了设定的锁屏时间 Log.v("上午", "匹配了"); if (_time[0] == Integer.parseInt(hour) && _time[1] == Integer.parseInt(minute)) { long time_sum = 0; // 将定时锁屏转换成快速锁屏 // 下面的代码是通过时间段获取锁屏的时长 if (_time[3] > _time[1]) { // time_sum += (_time[3] - _time[1]); time_sum += (_time[2] - _time[0]) * 60; } else if (_time[3] == _time[1]) { time_sum += (_time[2] - _time[0]) * 60; } else if (_time[3] < _time[1]) { time_sum += (_time[3] + 60 - _time[1]); time_sum += (_time[2] - _time[0] - 1) * 60; } // 保存锁屏时长 gdfs.saveClockLockTime(time_sum); // 设置定时锁屏标志位true gdfs.setClockStatusToTrue(); // 锁屏次数加一 gdfs.setLockNum(); // 锁屏时长增加 gdfs.setLockTime_long(time_sum); return true; } } // 如果是下午,hour需要加上12 else if (apm == 1) { Log.v("下午", "匹配了"); // 如果时间到了设定的锁屏时间 if (_time[0] == (Integer.parseInt(hour) + 12) && _time[1] == Integer.parseInt(minute)) { long time_sum = 0; // 将定时锁屏转换成快速锁屏 // 下面的代码是通过时间段获取锁屏的时长 if (_time[3] > _time[1]) { // time_sum += (_time[3] - _time[1]); time_sum += (_time[2] - _time[0]) * 60; } else if (_time[3] == _time[1]) { time_sum += (_time[2] - _time[0]) * 60; } else if (_time[3] < _time[1]) { time_sum += (_time[3] + 60 - _time[1]); time_sum += (_time[2] - _time[0] - 1) * 60; } // 将定时锁屏的时长保存到SP中 Log.v("锁屏时长", String.valueOf(time_sum)); // 锁屏次数+1,总的锁屏时长增加 gdfs.saveClockLockTime(time_sum); ; gdfs.setLockNum(); // 设置定时锁屏时长 gdfs.setLockTime_long(time_sum); // 将应该结束锁屏的时-分保存 gdfs.setStopClockLockTimeOfHour(_time[2]); gdfs.setStopClockLockTimeOfMinute(_time[3]); gdfs.setClockStatusToTrue(); return true; } } long _t = gdfs.getClockLockTime(); Log.v("定时解锁时间", String.valueOf(_t)); // 每过一分钟服务重启的时间时间减去1 if (gdfs.getClockLockTime() > 0 && clockFlag && gdfs.getStatus()) { gdfs.saveClockLockTime(gdfs.getClockLockTime() - 1); return true; } } } } } return false; } //设置快速锁屏方法,比定时锁屏简单多了 public boolean compareFastLockTime() { long time = gdfs.getFastLockTime(); Log.v("快速解锁时间", String.valueOf(time)); // 每次减去一分钟,因为每过一分钟服务就会自动重启,会进到这里 if (gdfs.getFastLockTime() > 0) { if (time > 0 && flag) { gdfs.saveFastLockTime(time - 1); } return true; } else return false; } /* * 如果系统日期跟设定的日期匹配,而且时间匹配,启动锁屏 启动lockActivity */ public void setLock() { // 如果时间-日期都准确,并且定时锁屏的标志值为true并且定时锁屏的开关为true,启动锁屏 if (this.compareTimeAndDay() && gdfs.getClockStatus() && gdfs.getStatus()) { Intent i = new Intent(MyContext, startLockWinService.class); i.setAction(startLockWinService.LOCK_ACTION); MyContext.startService(i); // 启动之后将定时锁屏标志值为FALSE gdfs.setClockStatusToFalse(); Log.v("锁屏启动", "定时锁屏"); } else if (this.compareFastLockTime() && gdfs.getFastStatus()) { Log.v("快速锁", "快速锁上了"); Intent i = new Intent(MyContext, startLockWinService.class); i.setAction(startLockWinService.FAST_LOCK_ACTION); MyContext.startService(i); // 启动之后将快速锁屏标志值为FALSE gdfs.setFastStatusToFalse(); } else if ((gdfs.getFastLockTime() == 0) && (gdfs.getClockLockTime() == 0)) { // 重置解锁计数 gdfs.setCloseClockNumber(0); gdfs.setCloseFastNumber(0); Intent i = new Intent(MyContext, startLockWinService.class); i.setAction(startLockWinService.UNLOCK_ACTION);//解锁 MyContext.startService(i); } } /* * 利用定时器检测服务是否在启动,每隔1分钟更新一次。如果不在启动则重启服务。 */ public void reStartService() { Intent intent = new Intent(this, lockService.class); PendingIntent sender = PendingIntent.getService(this, 0, intent, 0); AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE); alarm.setRepeating(AlarmManager.RTC_WAKEUP, 0, 60 * 1000, sender); flag = true; clockFlag = true; } // 定义一个广播接受者,用于动态接听亮屏和息屏广播 private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // 获取当前的动作 String action = intent.getAction(); // 如果亮屏,启动lockAcivity }
}
真正启动悬浮窗口实现锁屏的服务 startLockWinService
package com.example.mylock; import android.app.AlarmManager; import android.app.KeyguardManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.graphics.PixelFormat; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; import android.view.WindowManager.LayoutParams; import android.view.*; /* * 这个服务是启动悬浮窗口的服务,由lockService启动, * 在启动这个服务的时候需要传递活动是锁屏还是解锁 */ public class startLockWinService extends Service { private Context mContext; private WindowManager mWinMng; private LockView screenView = null; private Intent zdLockIntent = null; private KeyguardManager mKeyguardManager = null; @SuppressWarnings("deprecation") private KeyguardManager.KeyguardLock mKeyguardLock = null; // 自定义action作为启动或者关闭活动的标志 public static final String LOCK_ACTION = "lock";//定时锁 public static final String UNLOCK_ACTION = "unlock";//解锁 public static final String FAST_LOCK_ACTION = "fastLock";//快速锁 public IBinder onBind(Intent intent) { return null; } public void onCreate() { super.onCreate(); // 如果窗口还没设置,获取一堆实例 mContext = getApplicationContext(); mWinMng = (WindowManager) mContext .getSystemService(Context.WINDOW_SERVICE); mKeyguardManager = (KeyguardManager) mContext .getSystemService(Context.KEYGUARD_SERVICE); // 关闭系统的屏保,以免多重锁 mKeyguardLock = mKeyguardManager.newKeyguardLock(""); mKeyguardLock.disableKeyguard(); zdLockIntent = new Intent(startLockWinService.this, startLockWinService.class); zdLockIntent.setAction(startLockWinService.LOCK_ACTION); zdLockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); reStartService(); } public void onDestroy() { super.onDestroy(); startService(zdLockIntent); } public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) { String action = intent.getAction(); // 如果启动的活动是锁屏,添加view if (TextUtils.equals(action, LOCK_ACTION)) { addView(); getDataFromSp gdfs = new getDataFromSp(mContext); final long time = gdfs.getClockLockTime() * 60 * 1000;//锁屏时长,分钟*60*1000位锁屏的毫秒长度 new Thread() { public void run() { Intent intent = new Intent(startLockWinService.this, startLockWinService.class); intent.setAction(startLockWinService.UNLOCK_ACTION); PendingIntent sender = PendingIntent.getService( startLockWinService.this, 0, intent, 0); AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE); alarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + time, sender);// X豪秒后执行时钟 // 解锁 } }.start(); } else if (TextUtils.equals(action, FAST_LOCK_ACTION)) { addView(); getDataFromSp gdfs = new getDataFromSp(mContext); final long time = gdfs.getFastLockTime() * 60 * 1000; new Thread() { public void run() { Intent intent = new Intent(startLockWinService.this, startLockWinService.class); intent.setAction(startLockWinService.UNLOCK_ACTION); PendingIntent sender = PendingIntent.getService( startLockWinService.this, 0, intent, 0); AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE); alarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + time, sender);// X秒后执行 // 解锁 } }.start(); } // 如果是解锁去除view else if (TextUtils.equals(action, UNLOCK_ACTION)) { Log.v("解锁", "定时解锁了"); getDataFromSp gdfs = new getDataFromSp(mContext); gdfs.saveFastLockTime(0); gdfs.setFastStatusToTrue(); gdfs.saveClockLockTime(0); gdfs.setClockStatusToTrue(); removeView(); } } return Service.START_STICKY; } public void reStartService() {//为了确保解锁,我们设置时钟60秒重启这个服务,其实用处不大。有lockService足够了 Intent intent = new Intent(this, startLockWinService.class); PendingIntent sender = PendingIntent.getService(this, 0, intent, 0); AlarmManager alarm = (AlarmManager) getSystemService(ALARM_SERVICE); alarm.setRepeating(AlarmManager.RTC_WAKEUP, 0, 60 * 1000, sender); } public void addView() { if (screenView == null) { //创建悬浮窗口 screenView = new LockView(mContext); LayoutParams param = new LayoutParams(); param.type = 2010;// 窗口在最上层 param.format = PixelFormat.RGBA_8888; param.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; param.gravity = Gravity.TOP; // 窗口的宽和高 param.width = LayoutParams.MATCH_PARENT; param.height = LayoutParams.MATCH_PARENT; mWinMng.addView(screenView, param); } } //销毁窗口 public void removeView() { if (screenView != null) { mWinMng.removeView(screenView); screenView = null; } } }
开机广播接受者 bootBroadcastReceiver
package com.example.mylock; import java.text.SimpleDateFormat; import java.util.Date; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class bootBroadcastReceiver extends BroadcastReceiver { static final String ACTION = "android.intent.action.BOOT_COMPLETED"; public void onReceive(Context p1, Intent p2) { //将定时锁屏和快速锁屏的标志设置为true; getDataFromSp gdfs = new getDataFromSp(p1); gdfs.setFastStatusToTrue(); gdfs.setClockStatusToTrue(); //获取系统现在的时间 long t=System.currentTimeMillis(); Date date=new Date(t); SimpleDateFormat format = new SimpleDateFormat("HH"); int hour = Integer.parseInt(format.format(date)); format = new SimpleDateFormat("mm"); int minute = Integer.parseInt(format.format(date)); //更改锁屏时长,重新启动锁屏时减去关机的时长。 if(gdfs.getClockLockTime() > 0){ //每次重启都添加一次计数 int num = gdfs.getCloseClockNumber(); gdfs.setCloseClockNumber(num+1); //获取应该解锁的时间 int Ch = gdfs.getStopClockLockTimeOfHour(); int Cm = gdfs.getStopClockLockTimeOfMinute(); //重新计算解锁时间 long newTime = 0; if(Cm >= minute){ newTime += (Cm - minute); newTime += (Ch - hour)*60; } else if(Cm < minute){ newTime += (Cm + 60 - minute); newTime += (Ch - 1 - hour)*60; } Log.v("应锁时长", String.valueOf(newTime)); if(newTime > 0) gdfs.saveClockLockTime(newTime); else gdfs.saveClockLockTime(0); } if(gdfs.getFastLockTime() > 0){ int num = gdfs.getCloseFastNumber(); gdfs.setCloseFastNumber(num+1); int Ch = gdfs.getStopFastLockTimeOHour(); int Cm = gdfs.getStopFastLockTimeOfMinute(); long newTime = 0; if(Cm >= minute){ newTime += (Cm - minute); newTime += (Ch - hour)*60; } else if(Cm < minute){ newTime += (Cm + 60 - minute); newTime += (Ch - 1 - hour)*60; } Log.v("应锁时长", String.valueOf(newTime)); if(newTime > 0) gdfs.saveFastLockTime(newTime); else gdfs.saveFastLockTime(0); } if((gdfs.getCloseClockNumber() > 9)) { gdfs.setUnLockNum(); gdfs.saveClockLockTime(0); } if((gdfs.getCloseFastNumber() > 9)) { gdfs.saveFastLockTime(0); //解锁次数++ gdfs.setUnLockNum(); } Intent i = new Intent(p1,lockService.class); p1.startService(i); Log.v("开机自动启动", "快启动了"); } }
为了方便直接阅读源码,我这里给出代码调用的流程图
当年完成了之后发现几个bug-------------------------
android8.0以上系统不再支持广播功能-------失效!
部分安卓7.0以上的手机来电显示等等悬浮窗口级别太高并且不可逾越-----锁屏失效
源码下载 https://download.csdn.net/download/wanmingjking/10454655