当前位置: 代码迷 >> Android >> Android项目实战-手机卫士25-监听凭务栈实现程序的锁定
  详细解决方案

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

热度:28   发布时间:2016-04-28 07:44:48.0
Android项目实战--手机卫士25--监听任务栈实现程序的锁定

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

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

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


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

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




今天源码下载




  相关解决方案