(4)第一个单机项目手机锁----------Service的实现

本来想将一个个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

猜你喜欢

转载自blog.csdn.net/wanmingjking/article/details/80549979