Android项目实战--手机卫士25--监听任务栈实现程序的锁定

上一次,我们已经把那个锁的逻辑写好了,已经能够把要锁定的应用放到数据库里面了,那么今天我们就要完成真正的锁定了,要完成锁定,我们之前也说过了,就是通过监听

Android运行的任务栈,然后看看,当时是不是在运行我们已经在锁定的应用,如果真的是运行已经锁定的应用,那么就弹出输入密码的界面。因为我们是通过一个Service来控制是否打这个程序锁定的服务的,所有我们就要在设置中心里面进行一个设置的界面。

好,根据上面说我,我们就先把输入密码的界面先做出来

Android项目实战--手机卫士25--监听任务栈实现程序的锁定_第1张图片

这个界面非常的简单啦,就是几个控件。

lock.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical" >
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dip"
        android:background="@drawable/title_background"
        android:gravity="center_vertical|center_horizontal"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/lock"
            android:textColor="@android:color/white"
            android:textSize="22sp" />
    </LinearLayout>
    
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:gravity="center_vertical|center_horizontal"
        android:orientation="horizontal">
        
        <ImageView 
            android:id="@+id/iv_lock_app_icon"
            android:layout_width="48dip"
            android:layout_height="48dip"
            android:src="@drawable/app"
            android:contentDescription="@string/hello_world"/>
        
        <TextView
            android:id="@+id/tv_lock_app_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dip"
            android:textColor="#ffbc04e5"
            android:text="@string/hello_world"/>
        
    </LinearLayout>
    
    <EditText 
        android:id="@+id/et_lock_pwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:hint="@string/inputPassword"
        android:inputType="textPassword"/>
    
    <Button 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:text="@string/protectedYes"
        android:onClick="confirm"/>

</LinearLayout>

com.xiaobin.security.ui.LockActivity

package com.xiaobin.security.ui;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.xiaobin.security.R;
import com.xiaobin.security.utils.MD5Encoder;

public class LockActivity extends Activity
{
	private ImageView iv_app_icon;
	private TextView tv_app_name;
	private EditText et_app_pwd;
	private String password;
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.lock);
		
		iv_app_icon = (ImageView) findViewById(R.id.iv_lock_app_icon);
		tv_app_name = (TextView) findViewById(R.id.tv_lock_app_name);
		et_app_pwd = (EditText) findViewById(R.id.et_lock_pwd);
		
		//拿到真实的密码
		//这里我们为了方便,就使用了手机防盗里面的那个密码,大家可以自己做成可以让用户设置的功能
		password = getSharedPreferences("config", Context.MODE_PRIVATE).getString("password", "");
		
		try
		{
			String packageName = getIntent().getStringExtra("packageName");
			//通过包名拿到applicationInfo
			ApplicationInfo appInfo = getPackageManager().getPackageInfo(packageName, 0).applicationInfo;
			//应用图标
			Drawable app_icon = appInfo.loadIcon(getPackageManager());
			//应用的名字
			String app_name = appInfo.loadLabel(getPackageManager()).toString();
			
			iv_app_icon.setImageDrawable(app_icon);
			tv_app_name.setText(app_name);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
	
	//按钮的点击事件
	public void confirm(View v)
	{
		String input = et_app_pwd.getText().toString().trim();
		if(TextUtils.isEmpty(password))
		{
			Toast.makeText(this, "您的密码还没有设置,请进入手机防盗进行设定", Toast.LENGTH_SHORT).show();
		}
		else if(TextUtils.isEmpty(input))
		{
			Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show();
		}
		else if(password.equals(MD5Encoder.encode(input)))
		{
			finish();
		}
		else
		{
			Toast.makeText(this, "密码错误", Toast.LENGTH_SHORT).show();
		}
	}
	
	//不让用户按后退键
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		//屏蔽后退键
		if(KeyEvent.KEYCODE_BACK == event.getKeyCode())
		{
			return true;//阻止事件继续向下分发
		}
		return super.onKeyDown(keyCode, event);
	}

}

上面的那个逻辑也很简单了,也就是拿到用户之前在手机防盗里面设置的密码,然后进行判断,当然,各位也可以自己做一下,那个密码设置的功能。


那么接下来,我们就要讲一下那个锁定应用的核心了,也就是监听任务栈了,其实这个监听也很简单,就是我们开启一条线程,每隔一段时间就扫描一个Android的任务栈,看看是不是有我们已经锁定的应用要启动,如果有,那就启动我们的密码输入界面,如果没有,那就睡眠一段时间

通过任务栈拿到要启动的Activity也很简单的

//得到当前运行的任务栈,参数就是得到多少个任务栈,1就是只拿一个任务栈
						//1对应的也就是正在运行的任务栈啦
						List<RunningTaskInfo> runningTaskInfos = activityManager.getRunningTasks(1);
						//拿到当前运行的任务栈
						RunningTaskInfo runningTaskInfo = runningTaskInfos.get(0);
						//拿到要运行的Activity的包名
						String packageName = runningTaskInfo.topActivity.getPackageName();

因为我们这些是要在后台长时间运行的,所以我们就要放到Service里面

com.xiaobin.security.service.WatchDogService

package com.xiaobin.security.service;

import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import com.xiaobin.security.dao.AppLockDao;
import com.xiaobin.security.ui.LockActivity;

public class WatchDogService extends Service
{
	private AppLockDao dao;
	private List<String> apps;
	private ActivityManager activityManager;
	private Intent intent;
	private boolean flag = true;

	@Override
	public IBinder onBind(Intent intent)
	{
		return null;
	}

	@Override
	public void onCreate()
	{
		super.onCreate();

		dao = new AppLockDao(this);
		apps = dao.getAllPackageName();
		activityManager = (ActivityManager) getSystemService(Service.ACTIVITY_SERVICE);

		intent = new Intent(this, LockActivity.class);
		// 服务里面是没有任务栈的,所以要指定一个新的任务栈,不然是无法在服务里面启动activity的
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

		new Thread()
		{
			public void run()
			{
				while (flag)
				{
					try
					{
						// 得到当前运行的任务栈,参数就是得到多少个任务栈,1就是只拿一个任务栈
						// 1对应的也就是正在运行的任务栈啦
						List<RunningTaskInfo> runningTaskInfos = activityManager
								.getRunningTasks(1);
						// 拿到当前运行的任务栈
						RunningTaskInfo runningTaskInfo = runningTaskInfos
								.get(0);
						// 拿到要运行的Activity的包名
						String packageName = runningTaskInfo.topActivity
								.getPackageName();
						if (apps.contains(packageName))
						{
							intent.putExtra("packageName", packageName);
							startActivity(intent);
						}
						else
						{

						}
						sleep(1000);
					}
					catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				}
			}
		}.start();
	}

	@Override
	public void onDestroy()
	{
		super.onDestroy();
		flag = false;
	}

}

好啦,写完这个之后,我们就要去做一个开启这个服务的开关了,我们这次写在设置中心里面,其实我们设置中心的界面也和高级工具里的界面是差不多的了

setting.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical" >
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="40dip"
        android:background="@drawable/title_background"
        android:gravity="center_vertical|center_horizontal"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/setting"
            android:textColor="@android:color/white"
            android:textSize="22sp" />
    </LinearLayout>
    
    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dip">
        
        <LinearLayout 
            android:layout_width="280dip"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:orientation="vertical">
            
            <TextView 
                android:layout_width="280dip"
                android:layout_height="wrap_content"
                android:textSize="20sp"
                android:text="@string/lock_service"/>
            
            <TextView 
                android:id="@+id/tv_lock_tips"
                android:layout_width="280dip"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:textColor="#ffff0000"
                android:text="@string/lock_tips"/>
            
        </LinearLayout>
        
        <CheckBox 
            android:id="@+id/cb_lock_state"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"/>
        
    </RelativeLayout>
    
</LinearLayout>

com.xiaobin.security.ui.SettingActivity

package com.xiaobin.security.ui;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Window;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;

import com.xiaobin.security.R;
import com.xiaobin.security.service.WatchDogService;

public class SettingActivity extends Activity
{
	private TextView tv_lock_tips;
	private CheckBox cb_lock_state;
	private Intent appLockIntent;
	private SharedPreferences sp;
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.setting);
		
		appLockIntent = new Intent(this, WatchDogService.class);
		
		tv_lock_tips = (TextView) findViewById(R.id.tv_lock_tips);
		cb_lock_state = (CheckBox) findViewById(R.id.cb_lock_state);
		
		sp = getSharedPreferences("config", Context.MODE_PRIVATE);
		boolean isAppLockStart = sp.getBoolean("appLock", false);
		if(isAppLockStart)
		{
			tv_lock_tips.setText("服务已经开启");
			cb_lock_state.setChecked(false);
		}
		else
		{
			tv_lock_tips.setText("服务没有开启");
			cb_lock_state.setChecked(true);
		}
		
		cb_lock_state.setOnCheckedChangeListener(new OnCheckedChangeListener()
		{

			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
			{
				if(isChecked)
				{
					startService(appLockIntent);
					tv_lock_tips.setText("服务已经开启");
				}
				else
				{
					stopService(appLockIntent);
					tv_lock_tips.setText("服务没有开启");
				}
			}
		});
	}

}

大家也可以看到,现在我们的设置中心还是非常的简单的,就只是开启和关闭服务而已,但我们会在后面慢慢完善的啦


好啦,写到这里,我们就差不多要完成这个程序锁的功能的了,但现在还要做一个操作,那就是在AndroidMainfest文件里面拿到权限才行

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

好啦,现在我们就可以测试一下我们的程序锁的啦,一测试,我们会发现,这个程序锁还是有很多bug来的,比如说,我们一输入密码后,进入到了相应的应用了,但它马上又会变回到输入密码的界面的了,还有一些其他问题的,修复这些问题都比较麻烦,所以我们明天再来修复它。

今天就先到这里了


最后,和大家说一下

为了方便大家的交流,我创建了一个群,这样子大家有什么疑问也可以在群上交流

群号是298440981




今天源码下载




你可能感兴趣的:(Android开发,项目实战,手机卫士,任务栈,程序锁)