Android AppLock(應(yīng)用鎖)開發(fā)

android App Lock開發(fā)半等,主要有幾個點:
第一個是所謂的應(yīng)用鎖带欢,就是在應(yīng)用打開的時候覆蓋一個Activity(或者是一個全局的Dialog念颈,甚至WindowManager懸浮窗也可以)在應(yīng)用上面汗销,要通過解鎖才能夠看到應(yīng)用跟束。
所以,問題來了:1萨咕、怎么知道用戶打開和關(guān)閉了加鎖的應(yīng)用统抬。2、用戶關(guān)閉解鎖界面的時候怎么把界面底下的應(yīng)用也關(guān)了。

問題一:
android里面沒有直接能監(jiān)聽?wèi)?yīng)用打開和關(guān)閉的方法聪建,所以做法是不斷遍歷應(yīng)用棧钙畔,獲取棧頂?shù)膽?yīng)用的包名來對比,如果是加鎖的包名金麸,則彈出解鎖界面擎析,如果不是則不處理。
獲取棧頂包名的方法有好幾個挥下,根據(jù)不同的android版本方法也不一樣叔锐,在android5.0以上,推薦使用UsageStatsManager來獲取见秽,具體方法:

public String getLauncherTopApp(Context context, ActivityManager activityManager) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            List<ActivityManager.RunningTaskInfo> appTasks = activityManager.getRunningTasks(1);
            if (null != appTasks && !appTasks.isEmpty()) {
                return appTasks.get(0).topActivity.getPackageName();
            }
        } else {
            //5.0以后需要用這方法
            UsageStatsManager sUsageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
            long endTime = System.currentTimeMillis();
            long beginTime = endTime - 10000;
            String result = "";
            UsageEvents.Event event = new UsageEvents.Event();
            UsageEvents usageEvents = sUsageStatsManager.queryEvents(beginTime, endTime);
            while (usageEvents.hasNextEvent()) {
                usageEvents.getNextEvent(event);
                if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
                    result = event.getPackageName();
                }
            }
            if (!android.text.TextUtils.isEmpty(result)) {
                return result;
            }
        }
        return "";
    }

使用UsageStatsManager需要獲取權(quán)限相關(guān)代碼:

    /**
     * 判斷是否已經(jīng)獲取 有權(quán)查看使用情況的應(yīng)用程序 權(quán)限
     *
     * @param context
     * @return
     */
    public static boolean isStatAccessPermissionSet(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                PackageManager packageManager = context.getPackageManager();
                ApplicationInfo info = packageManager.getApplicationInfo(context.getPackageName(), 0);
                AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
                appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, info.uid, info.packageName);
                return appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, info.uid, info.packageName) == AppOpsManager.MODE_ALLOWED;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        } else {
            return false;
        }
    }

    /**
     * 查看是存在查看使用情況的應(yīng)用程序界面
     *
     * @return
     */
    public static boolean isNoOption(Context context) {
        PackageManager packageManager = context.getPackageManager();
        Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
        List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        return list.size() > 0;
    }

    /**
     * 轉(zhuǎn)跳到 有權(quán)查看使用情況的應(yīng)用程序 界面
     *
     * @param context
     */
    public static void startActionUsageAccessSettings(Context context) {
        Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
        context.startActivity(intent);
    }

這里有坑愉烙,就是有些手機是不存在這個權(quán)限和申請這個權(quán)限的設(shè)置界面的,所以要先判斷是否存在這個節(jié)面解取。

應(yīng)用鎖的主要核心代碼就這些步责。

問題二:
只需要修改返回鍵,使返回鍵的功能跟Home賤一樣即可:

    /**
     * Home鍵操作
     */
    public static void goHome(BaseActivity activity) {
        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
        homeIntent.addCategory(Intent.CATEGORY_HOME);
        activity.startActivity(homeIntent);
        activity.finish();
    }

關(guān)于加載手機的應(yīng)用列表:
加載手機的應(yīng)用列表是耗時的禀苦,需要放在子線程中加載蔓肯,但如果是在進(jìn)入列表頁面的時候才加載,那樣時間也會比較長振乏,最好的方法是一進(jìn)應(yīng)用就開啟一個后臺服務(wù)去加載好蔗包,在進(jìn)入列表頁面的時候直接取,這樣體驗會好很多慧邮。

怎么判斷應(yīng)用的打開和關(guān)閉:
上面說到调限,因為判斷是否打開了加鎖應(yīng)用是在一個死循環(huán)里面進(jìn)行的,如果用戶解鎖了误澳,就不應(yīng)該再次加鎖耻矮,應(yīng)該等用戶退出這個應(yīng)用的時候再加鎖,不然就會導(dǎo)致解鎖了就立馬又彈出解鎖界面這樣的錯誤忆谓。所以要有一個標(biāo)志位去判斷裆装。

怎么做:
在用戶解鎖成功后將解鎖的應(yīng)用的包名保存在SP文件中,在死循環(huán)遍歷里面去判斷倡缠。如果保存的包名跟當(dāng)前獲取的棧頂包名一樣哨免,則應(yīng)用正在打開,不需要加鎖昙沦,如果不一樣琢唾,則用戶已經(jīng)關(guān)閉了當(dāng)前應(yīng)用,需要重新加鎖桅滋,例子:

//當(dāng)前棧頂?shù)陌?String packageName = getLauncherTopApp(LockService.this, activityManager);
//解鎖后保存的包名
String savePkgName = SpUtil.getInstance().getString(AppConstants.LOCK_LAST_LOAD_PKG_NAME, "");
if (!TextUtils.isEmpty(savePkgName)) {
   if (!TextUtils.isEmpty(packageName)) {
       if (!savePkgName.equals(packageName)) {
            //再加多層判斷慧耍,更加準(zhǔn)確,如果返回了桌面
           if (getHomes().contains(packageName) || packageName.contains("launcher")) { 
               //這是設(shè)置相關(guān)的代碼丐谋,表示是否設(shè)置了不鎖這個應(yīng)用芍碧,可忽略
               boolean isSetUnLock = mLockInfoManager.isSetUnLock(savePkgName);
               if (!isSetUnLock) {
                   //加鎖
                   mLockInfoManager.lockCommApplication(savePkgName);
               }
           }
       }
   }
}

    /**
     * 獲得屬于桌面的應(yīng)用的應(yīng)用包名稱
     */
    private List<String> getHomes() {
        List<String> names = new ArrayList<>();
        PackageManager packageManager = this.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo ri : resolveInfo) {
            names.add(ri.activityInfo.packageName);
        }
        return names;
    }

因為應(yīng)用列表是存在數(shù)據(jù)庫里面的,那么加鎖解鎖的操作其實就是修改數(shù)據(jù)庫中的一個標(biāo)志位而已号俐。

Demo已經(jīng)初步改版好泌豆,地址:https://github.com/lizixian18/AppLock

感謝各位的關(guān)注。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吏饿,一起剝皮案震驚了整個濱河市踪危,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌猪落,老刑警劉巖贞远,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異笨忌,居然都是意外死亡蓝仲,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門官疲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袱结,“玉大人,你說我怎么就攤上這事途凫」讣校” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵维费,是天一觀的道長果元。 經(jīng)常有香客問我,道長犀盟,這世上最難降的妖魔是什么噪漾? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮且蓬,結(jié)果婚禮上欣硼,老公的妹妹穿的比我還像新娘。我一直安慰自己恶阴,他們只是感情好诈胜,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冯事,像睡著了一般焦匈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上昵仅,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天缓熟,我揣著相機與錄音累魔,去河邊找鬼。 笑死够滑,一個胖子當(dāng)著我的面吹牛垦写,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播彰触,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼梯投,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了况毅?” 一聲冷哼從身側(cè)響起分蓖,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎尔许,沒想到半個月后么鹤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡味廊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年午磁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毡们。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡迅皇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出衙熔,到底是詐尸還是另有隱情登颓,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布红氯,位于F島的核電站框咙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏痢甘。R本人自食惡果不足惜喇嘱,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望塞栅。 院中可真熱鬧者铜,春花似錦、人聲如沸放椰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽砾医。三九已至拿撩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間如蚜,已是汗流浹背压恒。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工影暴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人探赫。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓型宙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親期吓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,526評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理倾芝,服務(wù)發(fā)現(xiàn)讨勤,斷路器,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • 今天中午我剛進(jìn)門晨另,兒子就叫我過去潭千,我有點不耐煩說:“干什么?有事就說借尿∨偾纾”“媽媽,你到我房間來看看路翻,你進(jìn)來時要...
    董勝杰麻麻閱讀 140評論 0 2
  • 我們已經(jīng)走遠(yuǎn)了狈癞, 距那扇曾經(jīng)生動的窗口, 總會在寂寞的夜里茂契, 靜靜地蝶桶, 到最初的相逢里去牽手。 恍惚間掉冶, 又走在那...
  • 孩子頂嘴說他沒規(guī)矩真竖,聽話說他沒主見; 活潑好動擔(dān)心是多動癥厌小,內(nèi)向文靜又怕是自閉癥恢共; 打人說他太霸道,被打說他太懦弱...
    藍(lán)心老師閱讀 219評論 0 0