• 如我们所知,现在有很多牛逼的安全软件都带有程序锁的功能。当然,名字可能不一样,有的叫隐私保护,有的叫软件锁。等等。但是这种名字其实都是表达一种意思,就是可以给你手机里面的app加以保护。只有你给你的App设置了程序锁,这样每次在你进入这个App的时候就要先输入密码,然后才能进入。
  • 程序锁功能并不是什么高大上的技术,也不是很难的技术点。于是,受到灰驹的启发,我就写了一个简单的,UI比较丑陋的程序锁的小Demo。
  • 国际惯例:先分析一下做一个程序锁功能所涉及到的知识点:

    • Service组建的使用。
    • Broadcast组建的使用(当然,这个不是必须的,在实现这个功能上)。
    • Activity启动模式的了解。
    • ActivityManager的APi使用。
    • PackageManager的API的使用。
    • 数据库SQLiteDatabase的使用。(这个也不是必须的)
    • InputMethodManager的API的使用。(有些手机不主动打开软键盘,就需要使用这个类)

  • OK,介绍就这些了,下面是代码区:

    • 关于UI方面,简单说明一下,里面就一个主Activity,作用就是让用户选择添加需要加锁的应用,进行加锁操作。然后就是一个弹出让用户给加锁的应用输入密码的Activity。在用户点击要打开已经加锁的应用时候弹出。
  • 首先是xml代码:
    • MainActivity的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" ><TextViewandroid:gravity="center_horizontal"android:id="@+id/tvTitle"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentTop="true"android:layout_centerHorizontal="true"android:layout_marginBottom="8dp"android:background="@android:color/darker_gray"android:clickable="true"android:padding="8dp"android:text="未加锁"android:textColor="@android:color/white"android:textSize="16sp" /><ListViewandroid:id="@+id/lockListView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/tvTitle" ></ListView></RelativeLayout>
* 输入密码界面的布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" ><TextView
        android:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:padding="10dp"android:text="加锁了" /><EditText
        android:id="@+id/et_pwd"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@id/textView1" /><Button
        android:onClick="open"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/textView1"android:layout_centerHorizontal="true"android:layout_marginTop="99dp"android:text="芝麻开门" /></RelativeLayout>
  • xml布局就没有了。
  • 需要注意一下,程序锁功能里面需要添加的权限:
<uses-permission android:name="android.permission.GET_TASKS" />
  • 然后是Java代码:

    • 首先是程序的MainActivity
package com.duck.husband;import java.util.List;import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;public class MainActivity extends Activity implements OnItemClickListener {private ListView listView;private Context context;private AppInfoDao infoDao;private List<String> unLockedDatas;private List<String> lockedDatas;private List<String> adapterDatas;private TextView tvTitle;private LockAdapter adapter;private WatchDogDao watchDogDao;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);context = this;setContentView(R.layout.activity_main);Intent intent = new Intent(this, WatchDogService.class);startService(intent);watchDogDao = new WatchDogDao(context);updateData();initTitle();initListView();}private void initTitle() {tvTitle = (TextView) findViewById(R.id.tvTitle);tvTitle.setText("未加锁");adapterDatas = unLockedDatas;tvTitle.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (tvTitle.getText().toString().equals("未加锁")) {tvTitle.setText("已加锁");// TODO: 去 已加锁界面adapterDatas = lockedDatas;} else {tvTitle.setText("未加锁");// TODO:去 未加锁界面adapterDatas = unLockedDatas;}adapter.notifyDataSetChanged();}});}private void updateData() {infoDao = new AppInfoDao();unLockedDatas = infoDao.getAllApps(context);lockedDatas = watchDogDao.queryAllInfos();for (String text : lockedDatas) {if (unLockedDatas.contains(text))unLockedDatas.remove(text);}}private void initListView() {setTitle("程序锁功能");listView = (ListView) findViewById(R.id.lockListView);adapter = new LockAdapter();listView.setAdapter(adapter);listView.setOnItemClickListener(this);}private class LockAdapter extends BaseAdapter {@Overridepublic int getCount() {return adapterDatas.size();}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = new TextView(context);}TextView textView = (TextView) convertView;textView.setPadding(8, 8, 8, 8);textView.setTextSize(18);textView.setText(adapterDatas.get(position));return textView;}}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {System.out.println("position: " + position);System.out.println("id: " + id);vtoast("position: " + position + "\n id: " + id);if (tvTitle.getText().toString().equals("未加锁")) {String removedPackageName = unLockedDatas.remove(position);watchDogDao.insert(removedPackageName);lockedDatas.add(removedPackageName);adapter.notifyDataSetInvalidated();} else {String removedPackageName = lockedDatas.remove(position);watchDogDao.delete(removedPackageName);unLockedDatas.add(removedPackageName);adapter.notifyDataSetInvalidated();}}protected void vtoast(String text) {Toast.makeText(context, text, Toast.LENGTH_SHORT).show();}
}
  • 然后是WatchDogService
package com.duck.husband;import java.util.List;import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.IntentService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.SystemClock;public class WatchDogService extends IntentService {private static final boolean DEBUG = false;private static final String COM_DUCK_HUSBAND_UNCHECKED = "com.duck.husband.UNCHECKED";private Context context;private WatchDogDao watchDogDao;private String unCheckedPackageName;private UnCheckedReceiver receiver;public WatchDogService() {super("abcde");context = this;watchDogDao = new WatchDogDao(context);}@Overridepublic void onCreate() {super.onCreate();receiver = new UnCheckedReceiver();IntentFilter filter = new IntentFilter();filter.addAction(COM_DUCK_HUSBAND_UNCHECKED);filter.addAction(Intent.ACTION_SCREEN_OFF);registerReceiver(receiver, filter);}@Overrideprotected void onHandleIntent(Intent intent) {while (true) {ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);List<RunningTaskInfo> runningTasks = am.getRunningTasks(99);String packageName = runningTasks.get(0).topActivity.getPackageName();// 获取最近打开的App包名boolean b = watchDogDao.query(packageName);if (b) {// 说明是加锁的程序if (packageName.equals(unCheckedPackageName)) {} else {Intent intent2 = new Intent(context, LockActivity.class);intent2.putExtra("packageName", packageName);// TODO:这一行不加,就没有办法去临时取消保护了!!!intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivity(intent2);}} else {}if (DEBUG) {System.out.println("packageName 0:" + packageName);}SystemClock.sleep(300);}}@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();if (receiver != null) {unregisterReceiver(receiver);receiver = null;}}class UnCheckedReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (intent != null) {if (intent.getAction().equals(COM_DUCK_HUSBAND_UNCHECKED)) {unCheckedPackageName = intent.getStringExtra("packageName");System.out.println("unCheckedPackageName: "+ unCheckedPackageName);} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {unCheckedPackageName = null;}}}}
}
  • 然后是将需要包含的App包名存放到数据库的代码
package com.duck.husband;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;public class WatchDogOpenHelper extends SQLiteOpenHelper {public static final String TABLENAME = "appLocktb";public WatchDogOpenHelper(Context context, String name, int version) {super(context, name, null, version);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL("create table if not exists appLocktb(_id integer primary key, packageName text not null)");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}}

以及

package com.duck.husband;import java.util.ArrayList;
import java.util.List;import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;public class WatchDogDao {public static final String TABLENAME = WatchDogOpenHelper.TABLENAME;public static final String PACKAGENAME = "packageName";private WatchDogOpenHelper openHelper;public WatchDogDao(Context context) {openHelper = new WatchDogOpenHelper(context, "watchDog.db", 1);// "create table if not exists appLocktb(_id integer primary key, packageName text not null)");}/*** 插入一条数据,如果数据已经存在,就不插入* * @param packageName* @return 插入成功.失败*/public boolean insert(String packageName) {boolean insert = false;SQLiteDatabase db = openHelper.getWritableDatabase();Cursor cursor = db.rawQuery("select * from appLocktb where packageName=?",new String[] { packageName });if (cursor != null) {insert = cursor.moveToNext();cursor.close();}ContentValues values = new ContentValues();values.clear();if (insert) {return insert;} else {values.put(PACKAGENAME, packageName);long data = db.insert(TABLENAME, null, values);db.close();if (data != -1) {return true;} else {return false;}}}/*** 删除一条数据,如果数据不存在,就不删除* * @param packageName* @return 删除成功.失败*/public boolean delete(String packageName) {boolean delete = false;SQLiteDatabase db = openHelper.getWritableDatabase();Cursor cursor = db.rawQuery("select * from appLocktb where packageName=?",new String[] { packageName });if (cursor != null) {delete = cursor.moveToNext();cursor.close();}ContentValues values = new ContentValues();values.clear();if (delete) {// 说明有这条数据,删除int data = db.delete(TABLENAME, PACKAGENAME + "=?",new String[] { packageName });db.close();if(data>0){return true;}else {return false;}} else {// 说明没有有这条数据,删除return false;}}/*** 查询数据库有没有对应的数据* @param packageName*/public boolean  query(String packageName){SQLiteDatabase db = openHelper.getReadableDatabase();Cursor cursor = db.rawQuery("select * from appLocktb where packageName=?",new String[] { packageName });if(cursor!=null){boolean moveToNext = cursor.moveToNext();cursor.close();db.close();if(moveToNext)return true;else {return false;}}return false;}public List<String> queryAllInfos(){List<String> packageNames = new ArrayList<String>();SQLiteDatabase db = openHelper.getReadableDatabase();Cursor cursor = db.rawQuery("select * from appLocktb", null);if(cursor!=null){while(cursor.moveToNext()){String name = cursor.getString(cursor.getColumnIndex(PACKAGENAME));packageNames.add(name);}cursor.close();}db.close();return packageNames;}
}
  • 然后是获取手机里面已安装应用的工具类
package com.duck.husband;import java.util.ArrayList;
import java.util.List;import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;public class AppInfoDao {/*** 获取手机中所有的app包名集合* @param context* @return 包名的集合*/public List<String> getAllApps(Context context){List<String> packageNames  = new ArrayList<String>();PackageManager pm = context.getPackageManager();List<PackageInfo> infos = pm.getInstalledPackages(0);for (PackageInfo info : infos) {String packageName = info.packageName;packageNames.add(packageName);}return packageNames;}
}
  • 最后是输入密码的界面:
package com.duck.husband;import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnFocusChangeListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Toast;public class LockActivity extends Activity {private static final String COM_DUCK_HUSBAND_UNCHECKED = "com.duck.husband.UNCHECKED";private EditText etPwd;private Context context;private String packageName;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);context = this;setContentView(R.layout.lock_ui);packageName = getIntent().getStringExtra("packageName");etPwd = (EditText) findViewById(R.id.et_pwd);etPwd.setOnFocusChangeListener(new OnFocusChangeListener() {@Overridepublic void onFocusChange(View v, boolean hasFocus) {InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);if (hasFocus) {// //显示软键盘//imm.showSoftInputFromInputMethod(v.getWindowToken(), 0);} else {// 隐藏软键盘//imm.hideSoftInputFromWindow(v.getWindowToken(), 0);}}});}public void open(View view) {String text = etPwd.getText().toString().trim();if (text.equalsIgnoreCase("123")) {Intent intent = new Intent(COM_DUCK_HUSBAND_UNCHECKED);intent.putExtra("packageName", packageName);sendBroadcast(intent);finish();} else {vtoast("密码不对");}}@Overridepublic void onBackPressed() {/** <activity android:name="com.android.launcher2.Launcher"* android:launchMode="singleTask" android:clearTaskOnLaunch="true"* android:stateNotNeeded="true" android:theme="@style/Theme"* android:screenOrientation="nosensor"* android:windowSoftInputMode="stateUnspecified|adjustPan">* <intent-filter> <action android:name="android.intent.action.MAIN" />* <category android:name="android.intent.category.HOME" /> <category* android:name="android.intent.category.DEFAULT" /> <category* android:name="android.intent.category.MONKEY"/> </intent-filter>* </activity>*/// 打开桌面Intent intent = new Intent();intent.setAction("android.intent.action.MAIN");intent.addCategory("android.intent.category.HOME");startActivity(intent);// super.onBackPressed();}@Overrideprotected void onStop() {// TODO Auto-generated method stubsuper.onStop();}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();}protected void vtoast(String text) {Toast.makeText(context, text, Toast.LENGTH_SHORT).show();}
}
  • 以上代码运行OK。
  • 简单说明一下:
    • 对于MainActivity里面的数据操作,还是比较生硬的,应该可以有更好的方式。
    • 特别要注意的是广播的使用,我在写这个Demo的时候,差不多浪费了20多分钟就是为了处理广播。其实广播相对来说并不难。但是使用起来还是比较繁琐的。首先,你要搞一个意图,意图里面要包含你的行为(和数据,数据可以没有),然后以发送广播的方式发送这个意图。然后,你要搞一个对应的接收器,去接收对应的意图,和里面的数据(如果没有发数据,那就没有数据收到。只是收到意图了)。但是,如果就到此为止了,那这个广播就白做了。你还要在你需要接收广播的地方,先去注册这个广播.(这个好像也可以直接写在清单文件里面),注册了之后,算是可以使用这个广播了。然后往往还要去反注册这个广播,在不再使用的时候。总之就是比较麻烦吧。如果仅仅是为了数据的传递。个人更倾向于使用回调接口的形式来传递。但是这次为什么使用广播?因为我对广播不熟悉,也希望通过这个Demo,去熟悉一下广播的使用。
    • 这里面的数据库的操作就没有什么说的,因为这真的是一个非常简单是表,里面几乎没有内容。
    • 最后需要稍微注意一下的是,有的手机在你的EditText 里面不主动打开软件盘。你点半天就是不出来软键盘,这样你就没有办法输入了。于是,这时候就需要去主动打开软键盘让用户可以输入。
    • 完整项目

Android:程序锁功能的简单实现相关推荐

  1. Android程序锁的实现

    1.程序功能介绍 本程序实现对特定应用的监听,当特定应用前台运行时,立刻弹出本程序锁应用界面,用户输入正确密码后,才能转到特定应用继续使用,用户点击后退按钮无效,点击home键后,再启动被锁应用后,仍 ...

  2. android程序锁预研

    项目要求增加程序锁功能.要预研一下. 网上反编了比较流行的程序锁,了解到大概方向: 1 后台服务不断监视显示在前台的应用. 2 当是需要锁住的应用,启动程序锁密码页面. 3 密码成功则关闭程序锁密码页 ...

  3. Android 程序锁

    导读:本文介绍如何实现对应用加锁的功能,无须root权限 某些人有时候会有这样一种需求,小A下载了个软件,只是软件中的美女过于诱惑与暴露,所以他不想让别人知道这是个什么软件,起码不想让别人打开浏览.而 ...

  4. 实现安卓应用程序锁功能

    一.实现原理: 1.监听屏幕关闭广播. 2.监听home键广播. 二.实现代码 1.创建一个自定义的Application,在Application中注册监听的广播: public class Ass ...

  5. Android 程序常用功能《清除缓存》

    用户在使用我们所研发的App的时候,通常都会遇到如下的问题: 使用过程中可能会遇到应用程序或软件更新失败,因为用户的智能手机存储空间不足. 由于应用程序崩溃和其他问题,用户的数字设备运行速度比以前慢. ...

  6. Android 实现日历功能特别简单

    一. 接下来讲一下安卓实现日历功能,网上也有很多,我感觉这个相对简单一点. 效果图: 日期选择 效果图:时间选择 二.这个特别简单哈这,边弄了一个方法直接复制代码就可以使用了. 主要是下面单独写的那两 ...

  7. Android Studio 画笔功能绘制简单图形

    一 设置页面布局 设置activity_main.xml为帧布局便于画图时直接使用位置进行绘制 二 新建java类用于编写绘图代码 在mainactivity目录下新建myview类 三 继承原有vi ...

  8. android实现计算器功能吗,简单实现Android计算器功能

    自己写的安卓的计算器: 注:这个是在mac中开发的,如果要在windows的eclipse中运行可能会出现路径问题,解决办法从windows中已有的安卓工程根目录下复制一下classpath文件,然后 ...

  9. Android开发——程序锁的实现(可用于开发钓鱼登录界面)

    1. 程序锁原理 1.1 实现效果: 在用户打开一个应用时,若此应用是我们业务内的逻辑拦截目标,那就在开启应用之后,弹出一个输入密码的界面,输入密码正确则进入目标应用.若不输入直接按返回键,则直接返回 ...

最新文章

  1. 宝塔Linux/Windows面板如何添加网站?附图文教程
  2. python index函数时间复杂度_初学python之以时间复杂度去理解列表常见使用方法
  3. apache应用进阶
  4. List - Map 工具类,list转为map
  5. 『ACM-算法-离散化』信息竞赛进阶指南--离散化
  6. css3 animation动画事件
  7. eclipse 环境安装
  8. 算法:Design Circular Deque(设计一个双端队列)
  9. Python——基础习题(300题)
  10. cad插入块_CAD中块插入点定义错了,插入位置不对怎么办?
  11. xp系统与时间服务器同步出错,解决XP时间同步出错的问题
  12. tableau各种精典示例经验总结03
  13. CSR867x — 实现SPP数据收发
  14. Kafka的灵魂伴侣Logi-KafkaManger(4)之运维管控–集群运维(数据迁移和集群在线升级)
  15. Material Theme on sublime text 3 一个用起来很好的Sublime主题
  16. vs2008简易闹钟制作
  17. 【发生系统错误5。拒绝访问】的解决办法
  18. Solidworks模型导入Vrep(CoppeliaSim Edu)
  19. 离心泵水力设计——叶轮设计——5 进口边
  20. 变长子网划分讲解(计网)

热门文章

  1. 呕心沥血60道Vue、Vue-Router、Vuex面试题及详解!
  2. mel表达式_Maya Mel基础知识教程 了解运用Mel
  3. OSChina 周二乱弹 —— 将娱乐进行到底
  4. 1030: 判断直角三角形 C语言
  5. 敏捷项目管理敏捷工作之发布计划
  6. ElementUI引入自定义图标
  7. acc--›Android无障碍开发手势操作
  8. 秒杀系统架构设计思路
  9. 秒杀系统的设计五大原则
  10. 1小时紧急上线大屏?别怕,你还有即视