本项目是一个比较有趣的项目源码,可以给其他项目加锁,程序锁的原理是一个“看门狗”的服务定时监视顶层activity,如果activity对应的包名是之前上锁的应用程序的,则弹出一个页面要求输入解锁密码。
效果如下:
1.基本思路
①.创建已加锁应用的数据库(字段:_id,packagename),如果应用已加锁,将加锁应用的包名维护到数据库中
②.已加锁+未加锁 == 手机中所有应用(AppInfoProvider)
2.已加锁和未加锁的数据适配器
class MyAdapter extends BaseAdapter{ private boolean isLock; /** * @param isLock 用于区分已加锁和未加锁应用的标示 true已加锁数据适配器 false未加锁数据适配器 */ public MyAdapter(boolean isLock) { this.isLock = isLock; } @Override public int getCount() { if(isLock){ tv_lock.setText("已加锁应用:"+mLockList.size()); return mLockList.size(); }else{ tv_unlock.setText("未加锁应用:"+mUnLockList.size()); return mUnLockList.size(); } } @Override public AppInfo getItem(int position) { if(isLock){ return mLockList.get(position); }else{ return mUnLockList.get(position); } } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){ convertView = View.inflate(getApplicationContext(), R.layout.listview_islock_item, null); holder = new ViewHolder(); holder.iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon); holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name); holder.iv_lock = (ImageView) convertView.findViewById(R.id.iv_lock); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } final AppInfo appInfo = getItem(position); final View animationView = convertView; holder.iv_icon.setBackgroundDrawable(appInfo.icon); holder.tv_name.setText(appInfo.name); if(isLock){ holder.iv_lock.setBackgroundResource(R.drawable.lock); }else{ holder.iv_lock.setBackgroundResource(R.drawable.unlock); } holder.iv_lock.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //添加动画效果,动画默认是非阻塞的,所以执行动画的同时,动画以下的代码也会执行 animationView.startAnimation(mTranslateAnimation);//500毫秒 //对动画执行过程做事件监听,监听到动画执行完成后,再去移除集合中的数据,操作数据库,刷新界面 mTranslateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { //动画开始的是调用方法 } @Override public void onAnimationRepeat(Animation animation) { //动画重复时候调用方法 } //动画执行结束后调用方法 @Override public void onAnimationEnd(Animation animation) { if(isLock){ //已加锁------>未加锁过程 //1.已加锁集合删除一个,未加锁集合添加一个,对象就是getItem方法获取的对象 mLockList.remove(appInfo); mUnLockList.add(appInfo); //2.从已加锁的数据库中删除一条数据 mDao.delete(appInfo.packageName); //3.刷新数据适配器 mLockAdapter.notifyDataSetChanged(); }else{ //未加锁------>已加锁过程 //1.已加锁集合添加一个,未加锁集合移除一个,对象就是getItem方法获取的对象 mLockList.add(appInfo); mUnLockList.remove(appInfo); //2.从已加锁的数据库中插入一条数据 mDao.insert(appInfo.packageName); //3.刷新数据适配器 mUnLockAdapter.notifyDataSetChanged(); } } }); } }); return convertView; } }
mLockAdapter = new MyAdapter(true); lv_lock.setAdapter(mLockAdapter); mUnLockAdapter = new MyAdapter(false); lv_unlock.setAdapter(mUnLockAdapter);
3.已加锁和未加锁条目点击事件处理
holder.iv_lock.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //添加动画效果,动画默认是非阻塞的,所以执行动画的同时,动画以下的代码也会执行 animationView.startAnimation(mTranslateAnimation);//500毫秒 //对动画执行过程做事件监听,监听到动画执行完成后,再去移除集合中的数据,操作数据库,刷新界面 mTranslateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { //动画开始的是调用方法 } @Override public void onAnimationRepeat(Animation animation) { //动画重复时候调用方法 } //动画执行结束后调用方法 @Override public void onAnimationEnd(Animation animation) { if(isLock){ //已加锁------>未加锁过程 //1.已加锁集合删除一个,未加锁集合添加一个,对象就是getItem方法获取的对象 mLockList.remove(appInfo); mUnLockList.add(appInfo); //2.从已加锁的数据库中删除一条数据 mDao.delete(appInfo.packageName); //3.刷新数据适配器 mLockAdapter.notifyDataSetChanged(); }else{ //未加锁------>已加锁过程 //1.已加锁集合添加一个,未加锁集合移除一个,对象就是getItem方法获取的对象 mLockList.add(appInfo); mUnLockList.remove(appInfo); //2.从已加锁的数据库中插入一条数据 mDao.insert(appInfo.packageName); //3.刷新数据适配器 mUnLockAdapter.notifyDataSetChanged(); } } }); } });
4.程序锁必须在服务中去维护
①基本思路
public class WatchDogService extends Service { private boolean isWatch; private AppLockDao mDao; private List<String> mPacknameList; private InnerReceiver mInnerReceiver; private String mSkipPackagename; private MyContentObserver mContentObserver; @Override public void onCreate() { //维护一个看门狗的死循环,让其时刻监测现在开启的应用,是否为程序锁中要去拦截的应用 mDao = AppLockDao.getInstance(this); isWatch = true; watch(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("android.intent.action.SKIP"); mInnerReceiver = new InnerReceiver(); registerReceiver(mInnerReceiver, intentFilter); //注册一个内容观察者,观察数据库的变化,一旦数据有删除或者添加,则需要让mPacknameList重新获取一次数据 mContentObserver = new MyContentObserver(new Handler()); getContentResolver().registerContentObserver( Uri.parse("content://applock/change"), true, mContentObserver); super.onCreate(); } class MyContentObserver extends ContentObserver{ public MyContentObserver(Handler handler) { super(handler); } //一旦数据库发生改变时候调用方法,重新获取包名所在集合的数据 @Override public void onChange(boolean selfChange) { new Thread(){ public void run() { mPacknameList = mDao.findAll(); }; }.start(); super.onChange(selfChange); } } class InnerReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { //获取发送广播过程中传递过来的包名,跳过次包名检测过程 mSkipPackagename = intent.getStringExtra("packagename"); } } private void watch() { //1,子线程中,开启一个可控死循环 new Thread(){ public void run() { mPacknameList = mDao.findAll(); while(isWatch){ //2.监测现在正在开启的应用,任务栈 //3.获取activity管理者对象 ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); //4.获取正在开启应用的任务栈 List<RunningTaskInfo> runningTasks = am.getRunningTasks(1); RunningTaskInfo runningTaskInfo = runningTasks.get(0); //5.获取栈顶的activity,然后在获取此activity所在应用的包名 String packagename = runningTaskInfo.topActivity.getPackageName(); //如果任务栈指向应用有切换,将mSkipPackagename空字符串 //6.拿此包名在已加锁的包名集合中去做比对,如果包含次包名,则需要弹出拦截界面 if(mPacknameList.contains(packagename)){ //如果现在检测的程序,以及解锁了,则不需要去弹出拦截界面 if(!packagename.equals(mSkipPackagename)){ //7,弹出拦截界面 Intent intent = new Intent(getApplicationContext(),EnterPsdActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra("packagename", packagename); startActivity(intent); } } //睡眠一下,时间片轮转 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }; }.start(); } @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onDestroy() { //停止看门狗循环 isWatch = false; //注销广播接受者 if(mInnerReceiver!=null){ unregisterReceiver(mInnerReceiver); } //注销内容观察者 if(mContentObserver!=null){ getContentResolver().unregisterContentObserver(mContentObserver); } super.onDestroy(); } }
public class EnterPsdActivity extends Activity { private String packagename; private TextView tv_app_name; private ImageView iv_app_icon; private EditText et_psd; private Button bt_submit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //获取包名 packagename = getIntent().getStringExtra("packagename"); setContentView(R.layout.activity_enter_psd); initUI(); initData(); } private void initData() { //通过传递过来的包名获取拦截应用的图标以及名称 PackageManager pm = getPackageManager(); try { ApplicationInfo applicationInfo = pm.getApplicationInfo(packagename,0); Drawable icon = applicationInfo.loadIcon(pm); iv_app_icon.setBackgroundDrawable(icon); tv_app_name.setText(applicationInfo.loadLabel(pm).toString()); } catch (NameNotFoundException e) { e.printStackTrace(); } bt_submit.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String psd = et_psd.getText().toString(); if(!TextUtils.isEmpty(psd)){ if(psd.equals("123")){ //解锁,进入应用,告知看门口不要再去监听以及解锁的应用,发送广播 Intent intent = new Intent("android.intent.action.SKIP"); intent.putExtra("packagename",packagename); sendBroadcast(intent); finish(); }else{ ToastUtil.show(getApplicationContext(), "密码错误"); } }else{ ToastUtil.show(getApplicationContext(), "请输入密码"); } } }); } private void initUI() { tv_app_name = (TextView) findViewById(R.id.tv_app_name); iv_app_icon = (ImageView) findViewById(R.id.iv_app_icon); et_psd = (EditText) findViewById(R.id.et_psd); bt_submit = (Button) findViewById(R.id.bt_submit); } @Override public void onBackPressed() { //通过隐式意图,跳转到桌面 Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); startActivity(intent); super.onBackPressed(); } }
5.隐藏最近打开的activity
<activity android:excludeFromRecents="true" android:name="com.itheima.mobilesafe.EnterPwdActivity" android:launchMode="singleInstance" />
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
主要内容:1 Lock接口,1.1 Lock接口概述,1.2 Lock接口的API方法,3.3 锁获取与中断,3.4 Synchronized和Lock的区别,2 不可重入独占锁简单实现上文详细介绍了AQS的设计思想,以及总体设计结构。下面我们来介绍一下另一个和锁与AQS相关的接口,Lock接口,然后借用AQS和Lock接口快速实现一个自定义锁。 1 Lock接口 1.1 Lock接口概述 public interface Lock Lock接口本来和AQS没有太多关系的,但是如果想要是实现一个
有人了解智能锁吗?它是如何工作的? 我想开发一个应用程序,实现在Android应用程序的密码智能锁。 我在跟踪https://developers.google.com/identity/smartlock-passwords/android/. 我已经初始化了< code>GoogleApiClient 生成的<code>凭证 要使用<code>凭据API<code>保存凭据,我使用 我的具有以
本文向大家介绍python基于mysql实现的简单队列以及跨进程锁实例详解,包括了python基于mysql实现的简单队列以及跨进程锁实例详解的使用技巧和注意事项,需要的朋友参考一下 通常在我们进行多进程应用开发的过程中,不可避免的会遇到多个进程访问同一个资源(临界资源)的状况,这时候必须通过加一个全局性的锁,来实现资源的同步访问(即:同一时间里只能有一个进程访问资源)。 举个例子如下: 假设我们
问题内容: 我对Java编程真的很陌生,因此如果这听起来像一个愚蠢的问题,我会提前道歉。 我正在尝试构建一个用普通C语言编写的简单应用程序,该应用程序必须创建一个,然后通过加载基于的Java代码来创建一个新窗口。 遵循本技术说明,我了解到仅在Mac OSX中,必须从不同于主线程的线程中调用JavaVM,以便能够基于AWT创建GUI。 因此,在C应用程序的功能中,我创建了一个新线程,该线程执行从ja
本文向大家介绍Android 5.0及以上编程实现屏幕截图功能的方法,包括了Android 5.0及以上编程实现屏幕截图功能的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android 5.0及以上编程实现屏幕截图功能的方法。分享给大家供大家参考,具体如下: 在Android 5.0,API 21 之前想要截图系统屏幕必须Root才能完成,5.0之后开放了接口,下面看我们是怎么实现
本文向大家介绍Android ExpandableListView单选以及多选实现代码,包括了Android ExpandableListView单选以及多选实现代码的使用技巧和注意事项,需要的朋友参考一下 一、概述 ExpandableListView是常用的一个控件,今天自己做了个小练习,主要需求是单选以及多选的实现,看似比较简单,但是还是比较复杂,把代码贴给大家,有这种需求的可以参考一下。