转载自:http://blog.csdn.net/asmcvc/article/details/18356007
界面效果图:
在加载安装的应用程序列表时,显示进度条:
布局文件:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="match_parent"
- android:layout_height="match_parent">
- <TextView style="@style/title_center_text"
- android:text="程序锁"/>
- <View style="@style/splitter_view"/>
- <RelativeLayout
- android:layout_height="fill_parent"
- android:layout_width="fill_parent">
- <LinearLayout
- android:id="@+id/ll_applock_loading"
- android:gravity="center"
- android:orientation="vertical"
- android:visibility="invisible"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent">
- <ProgressBar
- android:layout_height="wrap_content"
- android:layout_width="wrap_content" />
- <TextView style="@style/content_text"
- android:text="正在加载程序信息……"/>
- </LinearLayout>
- <ListView
- android:fastScrollEnabled="true"
- android:id="@+id/lv_applock"
- android:layout_height="match_parent"
- android:layout_width="match_parent"/>
- </RelativeLayout>
- </LinearLayout>
ListView的每一个item的布局:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal" android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <ImageView
- android:id="@+id/iv_applock_icon"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_alignParentLeft="true"/>
- <TextView style="@style/content_text"
- android:id="@+id/iv_applock_name"
- android:layout_toRightOf="@+id/iv_applock_icon"/>
- <ImageView
- android:id="@+id/iv_applock_status"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_alignParentRight="true"/>
- </RelativeLayout>
界面在加载时先获取已安装的程序列表,保存应用程序的信息用一个AppInfo类来表示:
- package com.example.mobilesafe.engine;
- import android.graphics.drawable.Drawable;
- /**
- * Created by sing on 14-1-15.
- * desc:
- */
- public class AppInfo {
- private static final String TAG = "AppInfo";
- //包名
- private String packname;
- //应用程序版本号
- private String version;
- //应用程序名
- private String appname;
- //应用程序图标
- private Drawable appicon;
- //标识是否是用户层应用
- private boolean userpp;
- public String getPackname() {
- return packname;
- }
- public void setPackname(String packname) {
- this.packname = packname;
- }
- public String getVersion() {
- return version;
- }
- public void setVersion(String version) {
- this.version = version;
- }
- public String getAppname() {
- return appname;
- }
- public void setAppname(String appname) {
- this.appname = appname;
- }
- public Drawable getAppicon() {
- return appicon;
- }
- public void setAppicon(Drawable appicon) {
- this.appicon = appicon;
- }
- public boolean isUserpp() {
- return userpp;
- }
- public void setUserpp(boolean userpp) {
- this.userpp = userpp;
- }
- }
- package com.example.mobilesafe.engine;
- import android.content.Context;
- import android.content.pm.ApplicationInfo;
- import android.content.pm.PackageInfo;
- import android.content.pm.PackageManager;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by sing on 14-1-15.
- * desc:
- */
- public class AppInfoProvider {
- private static final String TAG = "AppInfoProvider";
- private PackageManager pm;
- public AppInfoProvider(Context context) {
- pm = context.getPackageManager();
- }
- public List<AppInfo> getInstalledApps() {
- List<PackageInfo> packageInfos = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
- List<AppInfo> appInfos = new ArrayList<AppInfo>();
- for (PackageInfo info : packageInfos) {
- AppInfo appinfo = new AppInfo();
- appinfo.setPackname(info.packageName);
- appinfo.setVersion(info.versionName);
- appinfo.setAppname(info.applicationInfo.loadLabel(pm).toString());
- appinfo.setAppicon(info.applicationInfo.loadIcon(pm));
- appinfo.setUserpp(filterApp(info.applicationInfo));
- appInfos.add(appinfo);
- appinfo = null;
- }
- return appInfos;
- }
- public boolean filterApp(ApplicationInfo info) {
- if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
- return false;
- } else if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- return true;
- }
- return false;
- }
- }
用户点击ListView的某一个item时,应进行锁定或解锁,锁定时将应用程序的包名存入到数据库中,以备后面监控使用。
操作数据库的类:
- package com.example.mobilesafe.db;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by sing on 14-1-15.
- * desc:对于锁定的app包名存储在数据库中
- */
- public class AppLockDao {
- private static final String TAG = "AppLockDao";
- private AppLockDBOpenHelper helper;
- public AppLockDao(Context context) {
- helper = new AppLockDBOpenHelper(context);
- }
- /**
- * 查找指定的包名程序是否被锁定
- * @param packname
- * @return
- */
- public boolean find(String packname) {
- boolean result = false;
- SQLiteDatabase db = helper.getReadableDatabase();
- if (db.isOpen()) {
- Cursor cursor = db.rawQuery("select * from applock where packname=?", new String[]{packname});
- if (cursor.moveToFirst()) {
- result = true;
- }
- cursor.close();
- db.close();
- }
- return result;
- }
- /**
- * 数据库中添加一个包名,也就是对这个包名程序进行锁定
- * @param packname
- * @return
- */
- public boolean add(String packname) {
- if (find(packname)) {
- return false;
- }
- SQLiteDatabase db = helper.getWritableDatabase();
- if (db.isOpen()) {
- db.execSQL("insert into applock (packname) values (?)", new String[]{packname});
- db.close();
- }
- return find(packname);
- }
- /**
- * 删除某包名,下次不再对其锁定
- * @param packname
- */
- public void delete(String packname) {
- SQLiteDatabase db = helper.getWritableDatabase();
- if (db.isOpen()) {
- db.execSQL("delete from applock where packname=?", new String[]{packname});
- db.close();
- }
- }
- /**
- * 查询所有被锁定的应用程序包名
- * @return
- */
- public List<String> findAll() {
- List<String> packnames = new ArrayList<String>();
- SQLiteDatabase db = helper.getReadableDatabase();
- if (db.isOpen()) {
- Cursor cursor = db.rawQuery("select packname from applock", null);
- while (cursor.moveToNext()) {
- packnames.add(cursor.getString(0));
- }
- cursor.close();
- db.close();
- }
- return packnames;
- }
- }
- package com.example.mobilesafe.db;
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- /**
- * Created by sing on 14-1-15.
- * desc:
- */
- public class AppLockDBOpenHelper extends SQLiteOpenHelper {
- private static final String TAG = "AppLockDBOpenHelper";
- public AppLockDBOpenHelper(Context context) {
- //参数一:应用上下文,参数二:数据库名称
- //参数三:游标工厂对象,null表示使用系统默认的游标工厂对象,参数四:版本号
- super(context, "applock.db", null, 1);
- }
- /**
- * 数据库第一次被创建的时候执行该方法
- * 在该方法中,一般用于指定数据库的表结构
- */
- @Override
- public void onCreate(SQLiteDatabase db) {
- //创建程序锁的表 (表中包含_id,包名 )
- db.execSQL("create table applock (_id integer primary key autoincrement, packname varchar(20))");
- }
- /**
- * 当数据库的版本号 发生增加的时候调用的方法.
- * 一般用于升级程序后,更新数据库的表结构.
- */
- @Override
- public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i2) {
- }
- }
至此,提供功能的类全部编写完毕,主activity:AppLockerActivity的代码:
- package com.example.mobilesafe;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.animation.Animation;
- import android.view.animation.TranslateAnimation;
- import android.widget.AdapterView;
- import android.widget.BaseAdapter;
- import android.widget.ImageView;
- import android.widget.ListView;
- import android.widget.TextView;
- import com.example.mobilesafe.R;
- import com.example.mobilesafe.db.AppLockDao;
- import com.example.mobilesafe.engine.AppInfo;
- import com.example.mobilesafe.engine.AppInfoProvider;
- import java.util.List;
- /**
- * Created by sing on 14-1-10.
- * desc:
- */
- public class AppLockerActivity extends Activity {
- public static final String TAG = "AppLockerActivity";
- private ListView lv_applock;
- private View ll_loading;
- private AppInfoProvider provider;
- private List<AppInfo> appInfos;
- private AppLockDao dao;
- private List<String> lockedPacknames;
- private Handler handler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- ll_loading.setVisibility(View.INVISIBLE);
- lv_applock.setAdapter(new AppLockAdapter());
- }
- };
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.applockeractivity_layout);
- lv_applock = (ListView) findViewById(R.id.lv_applock);
- ll_loading = findViewById(R.id.ll_applock_loading);
- provider = new AppInfoProvider(this);
- dao = new AppLockDao(this);
- lockedPacknames = dao.findAll();
- ll_loading.setVisibility(View.VISIBLE);
- new Thread(){
- public void run() {
- appInfos = provider.getInstalledApps();
- handler.sendEmptyMessage(0);
- }
- }.start();
- lv_applock.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
- AppInfo appInfo = (AppInfo) lv_applock.getItemAtPosition(i);
- String packname = appInfo.getPackname();
- ImageView iv = (ImageView) view.findViewById(R.id.iv_applock_status);
- TranslateAnimation ta = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0,
- Animation.RELATIVE_TO_SELF, 0.2f,
- Animation.RELATIVE_TO_SELF, 0,
- Animation.RELATIVE_TO_SELF, 0);
- ta.setDuration(200);
- if (lockedPacknames.contains(packname)) {
- dao.delete(packname);
- iv.setImageResource(R.drawable.unlock);
- lockedPacknames.remove(packname);
- }else {
- dao.add(packname);
- iv.setImageResource(R.drawable.lock);
- lockedPacknames.add(packname);
- }
- view.startAnimation(ta);
- }
- });
- }
- private class AppLockAdapter extends BaseAdapter {
- @Override
- public int getCount() {
- return appInfos.size();
- }
- @Override
- public Object getItem(int i) {
- return appInfos.get(i);
- }
- @Override
- public long getItemId(int i) {
- return i;
- }
- @Override
- public View getView(int i, View view, ViewGroup viewGroup) {
- View v;
- ViewHolder holder;
- if (view==null) {
- v = View.inflate(getApplicationContext(), R.layout.app_lock_item, null);
- holder = new ViewHolder();
- holder.iv_icon = (ImageView) v.findViewById(R.id.iv_applock_icon);
- holder.iv_status = (ImageView) v.findViewById(R.id.iv_applock_status);
- holder.tv_name = (TextView) v.findViewById(R.id.iv_applock_name);
- v.setTag(holder);
- }else{
- v = view;
- holder = (ViewHolder)view.getTag();
- }
- AppInfo appInfo = appInfos.get(i);
- holder.iv_icon.setImageDrawable(appInfo.getAppicon());
- holder.tv_name.setText(appInfo.getAppname());
- if (lockedPacknames.contains(appInfo.getPackname())) {
- holder.iv_status.setImageResource(R.drawable.lock);
- }else{
- holder.iv_status.setImageResource(R.drawable.unlock);
- }
- return v;
- }
- }
- public static class ViewHolder {
- ImageView iv_icon;
- ImageView iv_status;
- TextView tv_name;
- }
- }
这里使用了一个动画效果,当点击时相对左移一定距离,效果图:
程序锁原理(二)------阿冬专栏
程序锁的原理是一个“看门狗”的服务定时监视顶层activity,如果activity对应的包名是之前上锁的应用程序的,则弹出一个页面要求输入解锁密码,此页面不运行用户按“BACK”键返回,否则便能不输入密码直接进入应用程序了。如果密码输入正确则进入应用程序。
创建一个Android component,kind为service,类名为:WatchDogService:
- package com.example.mobilesafe.service;
- import android.app.ActivityManager;
- import android.app.Service;
- import android.content.Intent;
- import android.database.ContentObserver;
- import android.net.Uri;
- import android.os.Binder;
- import android.os.Handler;
- import android.os.IBinder;
- import android.util.Log;
- import com.example.mobilesafe.EnterPswdActivity;
- import com.example.mobilesafe.db.AppLockDao;
- import com.example.mobilesafe.engine.IService;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Created by sing on 14-1-16.
- * desc:
- */
- public class WatchDogService extends Service {
- public static final String TAG = "WatchDogService";
- boolean flag;
- private Intent pswdIntent;
- private List<String> lockPacknames;
- private List<String> tempStopProtectPacknames;
- private AppLockDao dao;
- public IBinder onBind(Intent intent) {
- return null;
- }
- @Override
- public void onDestroy() {
- flag = false;
- getContentResolver().unregisterContentObserver(observer);
- observer = null;
- super.onDestroy();
- }
- @Override
- public void onCreate() {
- //注册内容观察者
- Uri uri = Uri.parse("content://com.example.mobilesafe.applock/");
- observer = new MyObserver(new Handler());
- getContentResolver().registerContentObserver(uri, true, observer);
- super.onCreate();
- dao = new AppLockDao(this);
- flag = true;
- lockPacknames = dao.findAll();
- tempStopProtectPacknames = new ArrayList<String>();
- pswdIntent = new Intent(this, EnterPswdActivity.class);
- //服务没有任务栈,如果要开启一个在任务栈中运行的activity,需要为其创建一个任务栈
- pswdIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- new Thread() {
- @Override
- public void run() {
- while (flag) {
- ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
- //获取当前正在栈顶运行的activity
- ActivityManager.RunningTaskInfo taskInfo = am.getRunningTasks(1).get(0);
- String packname = taskInfo.topActivity.getPackageName();
- Log.i(TAG, packname);
- if (tempStopProtectPacknames.contains(packname)) {
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- continue;
- }
- pswdIntent.putExtra("packname", packname);
- if (lockPacknames.contains(packname)) {
- startActivity(pswdIntent);
- }
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }.start();
- }
- public void tempStopProtect(String packname) {
- tempStopProtectPacknames.add(packname);
- }
- }
密码输入页面的类EnterPswdActivity:
- package com.example.mobilesafe;
- import android.app.Activity;
- import android.content.ComponentName;
- import android.content.Intent;
- import android.content.ServiceConnection;
- import android.content.pm.PackageInfo;
- import android.content.pm.PackageManager;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.view.KeyEvent;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ImageView;
- import android.widget.TextView;
- import android.widget.Toast;
- import com.example.mobilesafe.engine.IService;
- import com.example.mobilesafe.service.WatchDogService;
- /**
- * Created by sing on 14-1-16.
- * desc:
- */
- public class EnterPswdActivity extends Activity {
- public static final String TAG = "EnterPswdActivity";
- private ImageView iv_icon;
- private TextView tv_name;
- private EditText et_pswd;
- private Button bt_enter;
- private Intent serviceIntent;
- private IService iService;
- private MyConn conn;
- private String packname;
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.enterpswd_layout);
- iv_icon = (ImageView) findViewById(R.id.iv_icon);
- tv_name = (TextView) findViewById(R.id.tv_name);
- et_pswd = (EditText) findViewById(R.id.et_pswd);
- bt_enter = (Button) findViewById(R.id.bt_enter);
- bt_enter.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- String pswd = et_pswd.getText().toString().trim();
- if (pswd.isEmpty()) {
- Toast.makeText(EnterPswdActivity.this,"密码不能为空",0).show();
- return;
- }
- if (pswd.equals("123")) {
- iService.callTempStopProtect(packname);
- finish();
- }else{
- Toast.makeText(EnterPswdActivity.this,"密码不正确",0).show();
- return;
- }
- }
- });
- //获取到激活当前activity的意图,也就是WatchDogService传递的pswdIntent
- Intent intent = getIntent();
- packname = intent.getStringExtra("packname");
- serviceIntent = new Intent(this, WatchDogService.class);
- conn = new MyConn();
- //绑定服务(非startService),执行WatchDogService中的onCreate-onBing方法
- //如果绑定成功,WatchDogService中onBing方法返回一个IBinder给conn.ServiceConnection
- bindService(serviceIntent, conn, BIND_AUTO_CREATE);
- try {
- PackageInfo info = getPackageManager().getPackageInfo(packname, 0);
- iv_icon.setImageDrawable(info.applicationInfo.loadIcon(getPackageManager()));
- tv_name.setText(info.applicationInfo.loadLabel(getPackageManager()));
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
- }
- private class MyConn implements ServiceConnection {
- @Override
- public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
- iService = (IService) iBinder;
- }
- @Override
- public void onServiceDisconnected(ComponentName componentName) {
- }
- }
- @Override
- protected void onDestroy() {
- super.onDestroy();
- //接触绑定
- unbindService(conn);
- }
- /**
- * 不允许用户按back键后退
- * @param keyCode
- * @param event
- * @return
- */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (event.getAction()==KeyEvent.ACTION_DOWN && event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
- }
布局文件:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_height="wrap_content"
- android:layout_width="match_parent" >
- <RelativeLayout style="@style/relativelayout">
- <ImageView
- android:id="@+id/iv_icon"
- android:layout_alignParentLeft="true"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"/>
- <TextView style="@style/content_text"
- android:id="@+id/tv_name"
- android:gravity="center"
- android:layout_centerVertical="true"
- android:layout_toRightOf="@+id/iv_icon"/>
- </RelativeLayout>
- <EditText
- android:id="@+id/et_pswd"
- android:layout_height="match_parent"
- android:layout_width="match_parent" />
- <Button
- android:id="@+id/bt_enter"
- android:text="确定"
- android:gravity="center"
- android:layout_height="match_parent"
- android:layout_width="match_parent" />
- </LinearLayout>
这里EnterPswdActivity类重载了对onKeyDown消息的处理,如果用户按键为KEYCODE_BACK则直接返回,防止用户在密码输入界面通过按“BACK”键进入到被锁定的应用程序界面。
EnterPswdActivity在启动时通过getIntent获取WatchDogService传递来的intent,进而通过getStringExtra("packname")获取被锁定的应用程序包名。进而通过getPackageManager获取包名对应的应用程序信息:图标和应用程序名。将这两个信息显示提示给用户,也即说明即将进入哪个被锁定的应用程序界面。
如图:
最后通过bindService绑定服务,如果绑定成功WatchDogService中onBing方法返回一个IBinder给conn.ServiceConnection:
- private class MyConn implements ServiceConnection {
- @Override
- public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
- iService = (IService) iBinder;
- }
- @Override
- public void onServiceDisconnected(ComponentName componentName) {
- }
- }
- package com.example.mobilesafe.engine;
- /**
- * Created by sing on 14-1-16.
- * desc:使看门狗服务停止对packname保护的接口
- */
- public interface IService {
- public void callTempStopProtect(String packname);
- }
- private MyBinder binder;
- public IBinder onBind(Intent intent) {
- binder = new MyBinder();
- return binder;
- }
- private class MyBinder extends Binder implements IService {
- @Override
- public void callTempStopProtect(String packname) {
- tempStopProtect(packname);
- }
- }
- private List<String> tempStopProtectPacknames;
- public void tempStopProtect(String packname) {
- tempStopProtectPacknames.add(packname);
- }
- if (tempStopProtectPacknames.contains(packname)) {
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- continue;
- }