編輯:關於android開發


1.基本思路
①.創建已加鎖應用的數據庫(字段:_id,packagename),如果應用已加鎖,將加鎖應用的包名維護到數據庫中
②.已加鎖+未加鎖 == 手機中所有應用(AppInfoProvider)
2.已加鎖和未加鎖的數據適配器

1 class MyAdapter extends BaseAdapter{
2 private boolean isLock;
3 /**
4 * @param isLock 用於區分已加鎖和未加鎖應用的標示 true已加鎖數據適配器 false未加鎖數據適配器
5 */
6 public MyAdapter(boolean isLock) {
7 this.isLock = isLock;
8 }
9 @Override
10 public int getCount() {
11 if(isLock){
12 tv_lock.setText("已加鎖應用:"+mLockList.size());
13 return mLockList.size();
14 }else{
15 tv_unlock.setText("未加鎖應用:"+mUnLockList.size());
16 return mUnLockList.size();
17 }
18 }
19
20 @Override
21 public AppInfo getItem(int position) {
22 if(isLock){
23 return mLockList.get(position);
24 }else{
25 return mUnLockList.get(position);
26 }
27 }
28
29 @Override
30 public long getItemId(int position) {
31 return position;
32 }
33
34 @Override
35 public View getView(int position, View convertView, ViewGroup parent) {
36 ViewHolder holder = null;
37 if(convertView == null){
38 convertView = View.inflate(getApplicationContext(), R.layout.listview_islock_item, null);
39 holder = new ViewHolder();
40 holder.iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon);
41 holder.tv_name = (TextView) convertView.findViewById(R.id.tv_name);
42 holder.iv_lock = (ImageView) convertView.findViewById(R.id.iv_lock);
43
44 convertView.setTag(holder);
45 }else{
46 holder = (ViewHolder) convertView.getTag();
47 }
48 final AppInfo appInfo = getItem(position);
49 final View animationView = convertView;
50
51 holder.iv_icon.setBackgroundDrawable(appInfo.icon);
52 holder.tv_name.setText(appInfo.name);
53 if(isLock){
54 holder.iv_lock.setBackgroundResource(R.drawable.lock);
55 }else{
56 holder.iv_lock.setBackgroundResource(R.drawable.unlock);
57 }
58 holder.iv_lock.setOnClickListener(new OnClickListener() {
59 @Override
60 public void onClick(View v) {
61 //添加動畫效果,動畫默認是非阻塞的,所以執行動畫的同時,動畫以下的代碼也會執行
62 animationView.startAnimation(mTranslateAnimation);//500毫秒
63 //對動畫執行過程做事件監聽,監聽到動畫執行完成後,再去移除集合中的數據,操作數據庫,刷新界面
64 mTranslateAnimation.setAnimationListener(new AnimationListener() {
65 @Override
66 public void onAnimationStart(Animation animation) {
67 //動畫開始的是調用方法
68 }
69 @Override
70 public void onAnimationRepeat(Animation animation) {
71 //動畫重復時候調用方法
72 }
73 //動畫執行結束後調用方法
74 @Override
75 public void onAnimationEnd(Animation animation) {
76 if(isLock){
77 //已加鎖------>未加鎖過程
78 //1.已加鎖集合刪除一個,未加鎖集合添加一個,對象就是getItem方法獲取的對象
79 mLockList.remove(appInfo);
80 mUnLockList.add(appInfo);
81 //2.從已加鎖的數據庫中刪除一條數據
82 mDao.delete(appInfo.packageName);
83 //3.刷新數據適配器
84 mLockAdapter.notifyDataSetChanged();
85 }else{
86 //未加鎖------>已加鎖過程
87 //1.已加鎖集合添加一個,未加鎖集合移除一個,對象就是getItem方法獲取的對象
88 mLockList.add(appInfo);
89 mUnLockList.remove(appInfo);
90 //2.從已加鎖的數據庫中插入一條數據
91 mDao.insert(appInfo.packageName);
92 //3.刷新數據適配器
93 mUnLockAdapter.notifyDataSetChanged();
94 }
95 }
96 });
97 }
98 });
99 return convertView;
100 }
101 }
MyAdapter
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.程序鎖必須在服務中去維護

①基本思路
1.判斷當前開啟的應用(現在手機可見任務棧)
2.如果開啟的應用在已加鎖的列表中,彈出攔截界面
3.看門狗服務,一直(死循環(子線程,可控))對開啟的應用做監聽

1 public class WatchDogService extends Service {
2 private boolean isWatch;
3 private AppLockDao mDao;
4 private List<String> mPacknameList;
5 private InnerReceiver mInnerReceiver;
6 private String mSkipPackagename;
7 private MyContentObserver mContentObserver;
8 @Override
9 public void onCreate() {
10 //維護一個看門狗的死循環,讓其時刻監測現在開啟的應用,是否為程序鎖中要去攔截的應用
11 mDao = AppLockDao.getInstance(this);
12 isWatch = true;
13 watch();
14
15 IntentFilter intentFilter = new IntentFilter();
16 intentFilter.addAction("android.intent.action.SKIP");
17
18 mInnerReceiver = new InnerReceiver();
19 registerReceiver(mInnerReceiver, intentFilter);
20
21
22 //注冊一個內容觀察者,觀察數據庫的變化,一旦數據有刪除或者添加,則需要讓mPacknameList重新獲取一次數據
23 mContentObserver = new MyContentObserver(new Handler());
24 getContentResolver().registerContentObserver(
25 Uri.parse("content://applock/change"), true, mContentObserver);
26 super.onCreate();
27 }
28
29 class MyContentObserver extends ContentObserver{
30
31 public MyContentObserver(Handler handler) {
32 super(handler);
33 }
34
35 //一旦數據庫發生改變時候調用方法,重新獲取包名所在集合的數據
36 @Override
37 public void onChange(boolean selfChange) {
38 new Thread(){
39 public void run() {
40 mPacknameList = mDao.findAll();
41 };
42 }.start();
43 super.onChange(selfChange);
44 }
45 }
46
47 class InnerReceiver extends BroadcastReceiver{
48 @Override
49 public void onReceive(Context context, Intent intent) {
50 //獲取發送廣播過程中傳遞過來的包名,跳過次包名檢測過程
51 mSkipPackagename = intent.getStringExtra("packagename");
52 }
53 }
54
55 private void watch() {
56 //1,子線程中,開啟一個可控死循環
57 new Thread(){
58 public void run() {
59 mPacknameList = mDao.findAll();
60 while(isWatch){
61 //2.監測現在正在開啟的應用,任務棧
62 //3.獲取activity管理者對象
63 ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
64 //4.獲取正在開啟應用的任務棧
65 List<RunningTaskInfo> runningTasks = am.getRunningTasks(1);
66 RunningTaskInfo runningTaskInfo = runningTasks.get(0);
67 //5.獲取棧頂的activity,然後在獲取此activity所在應用的包名
68 String packagename = runningTaskInfo.topActivity.getPackageName();
69
70 //如果任務棧指向應用有切換,將mSkipPackagename空字符串
71
72 //6.拿此包名在已加鎖的包名集合中去做比對,如果包含次包名,則需要彈出攔截界面
73 if(mPacknameList.contains(packagename)){
74 //如果現在檢測的程序,以及解鎖了,則不需要去彈出攔截界面
75 if(!packagename.equals(mSkipPackagename)){
76 //7,彈出攔截界面
77 Intent intent = new Intent(getApplicationContext(),EnterPsdActivity.class);
78 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
79 intent.putExtra("packagename", packagename);
80 startActivity(intent);
81 }
82 }
83 //睡眠一下,時間片輪轉
84 try {
85 Thread.sleep(500);
86 } catch (InterruptedException e) {
87 e.printStackTrace();
88 }
89 }
90 };
91 }.start();
92
93 }
94 @Override
95 public IBinder onBind(Intent arg0) {
96 return null;
97 }
98 @Override
99 public void onDestroy() {
100 //停止看門狗循環
101 isWatch = false;
102 //注銷廣播接受者
103 if(mInnerReceiver!=null){
104 unregisterReceiver(mInnerReceiver);
105 }
106 //注銷內容觀察者
107 if(mContentObserver!=null){
108 getContentResolver().unregisterContentObserver(mContentObserver);
109 }
110 super.onDestroy();
111 }
112 }
WatchDogService

1 public class EnterPsdActivity extends Activity {
2 private String packagename;
3 private TextView tv_app_name;
4 private ImageView iv_app_icon;
5 private EditText et_psd;
6 private Button bt_submit;
7
8 @Override
9 protected void onCreate(Bundle savedInstanceState) {
10 super.onCreate(savedInstanceState);
11 //獲取包名
12 packagename = getIntent().getStringExtra("packagename");
13 setContentView(R.layout.activity_enter_psd);
14 initUI();
15 initData();
16 }
17
18 private void initData() {
19 //通過傳遞過來的包名獲取攔截應用的圖標以及名稱
20 PackageManager pm = getPackageManager();
21 try {
22 ApplicationInfo applicationInfo = pm.getApplicationInfo(packagename,0);
23 Drawable icon = applicationInfo.loadIcon(pm);
24 iv_app_icon.setBackgroundDrawable(icon);
25 tv_app_name.setText(applicationInfo.loadLabel(pm).toString());
26 } catch (NameNotFoundException e) {
27 e.printStackTrace();
28 }
29
30 bt_submit.setOnClickListener(new OnClickListener() {
31 @Override
32 public void onClick(View v) {
33 String psd = et_psd.getText().toString();
34 if(!TextUtils.isEmpty(psd)){
35 if(psd.equals("123")){
36 //解鎖,進入應用,告知看門口不要再去監聽以及解鎖的應用,發送廣播
37 Intent intent = new Intent("android.intent.action.SKIP");
38 intent.putExtra("packagename",packagename);
39 sendBroadcast(intent);
40
41 finish();
42 }else{
43 ToastUtil.show(getApplicationContext(), "密碼錯誤");
44 }
45 }else{
46 ToastUtil.show(getApplicationContext(), "請輸入密碼");
47 }
48 }
49 });
50 }
51
52 private void initUI() {
53 tv_app_name = (TextView) findViewById(R.id.tv_app_name);
54 iv_app_icon = (ImageView) findViewById(R.id.iv_app_icon);
55
56 et_psd = (EditText) findViewById(R.id.et_psd);
57 bt_submit = (Button) findViewById(R.id.bt_submit);
58 }
59
60 @Override
61 public void onBackPressed() {
62 //通過隱式意圖,跳轉到桌面
63 Intent intent = new Intent(Intent.ACTION_MAIN);
64 intent.addCategory(Intent.CATEGORY_HOME);
65 startActivity(intent);
66 super.onBackPressed();
67 }
68 }
EnterPsdActivity

5.隱藏最近打開的activity
<activity
android:excludeFromRecents="true"
android:name="com.itheima.mobilesafe.EnterPwdActivity"
android:launchMode="singleInstance" />
[android] 手機衛士自定義對話框布局,android衛士
[android] 手機衛士自定義對話框布局,android衛士手機防盜頁面部分 點擊手機防盜,進行判斷,如果沒有設置密碼,顯示一個設置密碼的對話框,如果已經設置密碼了,
Android Volley 的基本使用/設置HTTP請求參數、apikey,androidapikey
Android Volley 的基本使用/設置HTTP請求參數、apikey,androidapikey最近在做一個Android的新聞客戶端,感覺收獲頗豐。 這裡分享一
我的Android進階之旅------)關於android:layout_weight屬性的詳細解析
我的Android進階之旅------)關於android:layout_weight屬性的詳細解析 關於android:layout_weight屬性的詳細解析 效
AIDL
AIDL 官網地址詳解分析: http://developer.android.com/guide/components/aidl.html 一)什麼是A