界面效果图:
在加载安装的应用程序列表时,显示进度条:
布局文件:
<?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的,当加载完毕后发送消息通知,消息处理过程隐藏掉进度控件即可。
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>
用来显示程序图标的ImageView,显示应用程序名的TextView,和锁定状态的ImageView。
界面在加载时先获取已安装的程序列表,保存应用程序的信息用一个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;
}
}
其中AppLockDBOpenHelper:
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;
}
}
这里使用了一个动画效果,当点击时相对左移一定距离,效果图: