本来想将一个个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)) { // 判断星期的字符串是否匹配,如果匹配,将标志设为trueLog.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)) { // 判断星期的字符串是否匹配,如果匹配,将标志设为trueLog.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);// 设置定时锁屏标志位truegdfs.setClockStatusToTrue();// 锁屏次数加一gdfs.setLockNum();// 锁屏时长增加gdfs.setLockTime_long(time_sum);return true;}}// 如果是下午,hour需要加上12else 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));// 每过一分钟服务重启的时间时间减去1if (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;} elsereturn 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);// 启动之后将定时锁屏标志值为FALSEgdfs.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);// 启动之后将快速锁屏标志值为FALSEgdfs.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() {@Overridepublic 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();// 如果启动的活动是锁屏,添加viewif (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();}// 如果是解锁去除viewelse 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);elsegdfs.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