android安全问题(二) 程序锁
導(dǎo)讀:本文介紹如何實(shí)現(xiàn)對(duì)應(yīng)用加鎖的功能,無須root權(quán)限
某些人有時(shí)候會(huì)有這樣一種需求,小A下載了個(gè)軟件,只是軟件中的美女過于誘惑與暴露,所以他不想讓別人知道這是個(gè)什么軟件,起碼不想讓別人打開瀏覽。而這款軟件又沒有鎖,任何人都可以打開,腫么辦呢?如果打開它的時(shí)候需要輸入密碼,那該多好阿!于是,程序鎖這種應(yīng)用就產(chǎn)生了
程序鎖不是最近才有的,很久之前android就有這種apk了
這一期我們來苛刻如何實(shí)現(xiàn)程序加鎖功能
首先,我們先明確一下我們要做的程序具有什么功能
1可以選擇需要加鎖的程序
2可以設(shè)置密碼
3可以關(guān)閉程序鎖
這里作為演示,我們就盡量簡(jiǎn)化代碼
我們先說最關(guān)鍵的部分
最關(guān)鍵的地方在于:當(dāng)用戶打開一個(gè)應(yīng)用的時(shí)候,怎么彈出密碼頁(yè)面?
這里沒有什么太好的辦法,需要掃描task中的topActivity
首先,我們先獲得運(yùn)行的task
Java代碼mActivityManager = (ActivityManager) context.getSystemService("activity"); ?
//mActivityManager.getRunningTasks(1);//List<RunningTaskInfo>
getRunningTasks方法返回一個(gè)List,我們來看看這個(gè)List是什么
getRunningTasks 寫道Return a list of the tasks that are currently running, with the most recent being first and older ones after in order.……
返回的List是有序的,第一個(gè)是最近的,所以我們?nèi)〕龅谝粋€(gè)即可,然后得到此task中的最上層的Activity
Java代碼ComponentName topActivity = mActivityManager.getRunningTasks(1).get(0).topActivity; ?
topActivity居然是ComponentName類型,下面的事情就好辦了,獲得包名和類名
Java代碼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); ?
} ?
由于我沒有選擇程序這一步,所以我就固定一個(gè)應(yīng)用做測(cè)試,這里選擇的是htc的note應(yīng)用
Java代碼String testPackageName = "com.htc.notes"; ?
String testClassName = "com.htc.notes.collection.NotesGridViewActivity"; ?
下面我們?cè)撓?#xff0c;這段代碼何時(shí)執(zhí)行了
打開一個(gè)應(yīng)用程序,系統(tǒng)不會(huì)發(fā)送廣播,我們無法直接監(jiān)聽,所以這里我們采取定時(shí)掃描的策略
這里只是一個(gè)簡(jiǎn)單的實(shí)現(xiàn),之后我們?cè)儆懻搩?yōu)化
我們采取每秒中檢查一次task的方式,這里使用Timer吧,用Handler也一樣可以實(shí)現(xiàn)
Java代碼private Timer mTimer; ?
privatevoid startTimer() { ?
if (mTimer == null) { ?
? ? ? ?mTimer = new Timer(); ?
? ? ? ?LockTask lockTask = new LockTask(this); ?
? ? ? ?mTimer.schedule(lockTask, 0L, 1000L); ?
? ?} ?
} ?
到這里,其實(shí)我們的關(guān)鍵代碼就已經(jīng)完成了
下面貼出完整帶代碼,注意:我們只關(guān)注彈出鎖界面這部分,其他部分自行實(shí)現(xiàn)(比如文章末尾提到的)
Task,負(fù)責(zé)檢查task,并在適當(dāng)?shù)臅r(shí)候彈出密碼頁(yè)面
publicclass LockTask extends TimerTask { ?
publicstaticfinal String TAG = "LockTask"; ?
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
publicvoid 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); ?
? ? ? ?} ?
? ?} ?
} ?
LockService,負(fù)責(zé)執(zhí)行定時(shí)任務(wù),取消任務(wù)等
Java代碼publicclass LockService extends Service { ?
private Timer mTimer; ?
publicstaticfinalint FOREGROUND_ID = 0; ?
privatevoid startTimer() { ?
if (mTimer == null) { ?
? ? ? ? ? ?mTimer = new Timer(); ?
? ? ? ? ? ?LockTask lockTask = new LockTask(this); ?
? ? ? ? ? ?mTimer.schedule(lockTask, 0L, 1000L); ?
? ? ? ?} ?
? ?} ?
public IBinder onBind(Intent intent) { ?
returnnull; ?
? ?} ?
publicvoid onCreate() { ?
super.onCreate(); ?
? ? ? ?startForeground(FOREGROUND_ID, new Notification()); ?
? ?} ?
publicint onStartCommand(Intent intent, int flags, int startId) { ?
? ? ? ?startTimer(); ?
returnsuper.onStartCommand(intent, flags, startId); ?
? ?} ?
publicvoid onDestroy() { ?
? ? ? ?stopForeground(true); ?
? ? ? ?mTimer.cancel(); ?
? ? ? ?mTimer.purge(); ?
? ? ? ?mTimer = null; ?
super.onDestroy(); ?
? ?} ?
} ?
MainActivity,測(cè)試用,作為應(yīng)用入口,啟動(dòng)service(產(chǎn)品中,我們可以在receiver中啟動(dòng)service)。
Java代碼publicclass MainActivity extends Activity { ?
publicvoid onCreate(Bundle savedInstanceState){ ?
super.onCreate(savedInstanceState); ?
? ? ? ?startService(new Intent(this, LockService.class)); ?
? ?} ?
} ?
PasswordActivity,密碼頁(yè)面,很粗糙,沒有核對(duì)密碼邏輯,自行實(shí)現(xiàn)
記得重寫onBackPressed函數(shù),不然按返回鍵的時(shí)候……你懂的
Java代碼publicclass PasswordActivity extends Activity { ?
privatestaticfinal String TAG = "PasswordActivity"; ?
? ?Button okButton; ?
? ?EditText passwordEditText; ?
privateboolean mFinish = false; ?
@Override
protectedvoid 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() { ?
publicvoid onClick(View v) { ?
? ? ? ? ? ? ? ?String password = passwordEditText.getText().toString(); ?
? ? ? ? ? ? ? ?Log.v(TAG, "password" + password); ?
? ? ? ? ? ? ? ?mFinish = true; ?
? ? ? ? ? ? ? ?finish(); ?
? ? ? ? ? ?} ?
? ? ? ?}); ?
? ?} ?
publicvoid onBackPressed(){} ?
publicvoid onPause(){ ?
super.onPause(); ?
if(!mFinish){ ?
? ? ? ? ? ?finish(); ?
? ? ? ?} ?
? ?} ?
} ?
xml這里就不貼了,記得添加權(quán)限
Xml代碼<uses-permissionandroid:name="android.permission.GET_TASKS"/>
關(guān)于程序的其他部分,這里只做簡(jiǎn)要說明
選擇應(yīng)用對(duì)其進(jìn)行加鎖部分
1列出系統(tǒng)中所有程序(你也可以自由發(fā)揮,比如過濾掉原始應(yīng)用)
2選擇,然后存入數(shù)據(jù)庫(kù)(當(dāng)然,最好也有取消功能,記得從數(shù)據(jù)庫(kù)中刪除數(shù)據(jù))
程序鎖總開關(guān)
可以使用sharedPreference,設(shè)置一個(gè)boolean開關(guān)
現(xiàn)在,當(dāng)我想要打開htc的note應(yīng)用的時(shí)候,就會(huì)彈出密碼頁(yè)面當(dāng)我解鎖,按home會(huì)回到桌面,長(zhǎng)按home,點(diǎn)擊note,還是會(huì)彈出密碼框
因?yàn)槭敲棵霗z查一次,所以可能會(huì)有一點(diǎn)點(diǎn)延遲,你可以設(shè)置為500毫秒,但是越頻繁,占用資源就越多
上面的代碼我取得topActivity后檢查了其包名行和類名,所以只有當(dāng)打開指定的頁(yè)面的時(shí)候,才會(huì)彈出密碼鎖
比如我對(duì)Gallery應(yīng)用加密了,但是用戶正在編輯短信,這時(shí)候它想發(fā)彩信,于是他通過短信進(jìn)入到了Gallery……
對(duì)于某些用戶的某些需求來說,這是不能容忍的,這時(shí),我們只需簡(jiǎn)單修改下判斷邏輯即可:只檢查包名,包名一致就彈出密碼鎖,這樣就完美了
程序鎖我就分析到這里
最后一句
當(dāng)使用程序鎖的時(shí)候,你長(zhǎng)按home,發(fā)現(xiàn)程序鎖也出現(xiàn)在“最近的任務(wù)”中,腫么辦……給此activity設(shè)置android:excludeFromRecents="true"即可
轉(zhuǎn)載于:https://blog.51cto.com/laokaddk/1211866
總結(jié)
以上是生活随笔為你收集整理的android安全问题(二) 程序锁的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用LFSR实现模2除法的原理
- 下一篇: PostgreSQL在何处处理 sql查