本来想将一个个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("开机自动启动", "快启动了");
}
}
为了方便直接阅读源码,我这里给出代码调用的流程图
![](https://i-blog.csdnimg.cn/blog_migrate/634542e297a8e0055c491106e5be53a2.png)
当年完成了之后发现几个bug-------------------------
android8.0以上系统不再支持广播功能-------失效!
部分安卓7.0以上的手机来电显示等等悬浮窗口级别太高并且不可逾越-----锁屏失效
源码下载 https://download.csdn.net/download/wanmingjking/10454655