Android 你不知道的霸道總裁模式

我們平常知道的大多都是Android溫柔颓芭、方便顷锰、易操作等特性。但是他也有霸道總裁的一面咯亡问,只是你不知道罷了~~~

下面我們來說說Android的霸道總裁一面官紫,其實因為是系統(tǒng)是開源的,所以我們直接可以翻閱源碼州藕,做一些霸道級操作束世,比如讓你的手機裝上我這個App之后被控制,狀態(tài)欄無法下拉慎框,無法卸載良狈,且只能使用規(guī)定的應(yīng)用后添,是不是很霸(流)道(氓)啊...

好了 我們下面就說說怎么控制你的手機呢笨枯。

1. 霸道之路之狀態(tài)欄無法下拉

/**
* 指的是這個Activity得到或者失去焦點的時候 就會call
* @param hasFocus
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (!hasFocus && isControlStatusBarEnable) {
//收起狀態(tài)欄
disableStatusBar();
}
}

拉下狀態(tài)欄的時候,顯示的Activity就失去焦點遇西,這就是我們的思路馅精。根據(jù)焦點是不是在此Activity來判斷是否拉下狀態(tài)欄

/**
*通過反射拿到獲取收起狀態(tài)欄的方法并執(zhí)行
*/
public void disableStatusBar() {
try {
Object service = getSystemService("statusbar");
//通過反射獲取StatusBarManager
Class<?> claz = Class.forName("android.app.StatusBarManager");
//獲取StatusBarManager類中的collapse()方法
Method expand = claz.getMethod("collapse");
expand.invoke(service);
} catch (Exception e) {
e.printStackTrace();
}
}

首先通過反射拿到SystemService中的 statusbar,然后又通過反射拿到statusBar管理類StatusBarManager類中的collapse()方法粱檀,并且執(zhí)行此方法洲敢。關(guān)于Method中的invoke(),主要是為了類反射茄蚯,這樣你可以在不知道具體的類的情況下压彭,根據(jù)配置的字符串去調(diào)用一個類的方法。在靈活編程的時候非常有用渗常。invoke方法詳解請猛戳此處

2. 霸道之路之實現(xiàn)App的表面無法卸載壮不,且如果"非法"卸載直接鎖死手機,解鎖密碼你說了算哦~ 興不興奮皱碘,霸(流)不霸(流)道(氓)询一。

首先我們要知道怎么才能讓App裝上之后一般無法卸載呢,其實就是激活此App。思路有了代碼擼起~

/**
* 跳至設(shè)備管理器激活此App健蕊,一般情況無法直接卸載App菱阵,除非進入設(shè)備管理器取消激活此App
*/
private void openDeviceManager(int requestCode){
//DeviceManagerReciver.class 在manifest里面注冊
ComponentName componentName = new ComponentName(this, DeviceManagerReciver.class);
//添加一個隱式意圖,完成設(shè)備權(quán)限的添加
//這個Intent (DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)跳轉(zhuǎn)到 權(quán)限提醒頁面
//并傳遞了兩個參數(shù)EXTRA_DEVICE_ADMIN 缩功、 EXTRA_ADD_EXPLANATION

Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
//權(quán)限列表
//EXTRA_DEVICE_ADMIN參數(shù)中說明了用到哪些權(quán)限晴及,
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
//描述(additional explanation)
//EXTRA_ADD_EXPLANATION參數(shù)為附加的說明
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "您可千萬別激活我啊~~~~");
startActivityForResult(intent, requestCode);
}

上面的代碼我們具體就是進入系統(tǒng)的設(shè)備管理器,大家注意下DeviceManagerReciver.class這個類嫡锌。我們隨后再說抗俄。我們進入設(shè)備管理器之后,可是怎么才能用戶到底有沒有點擊激活按鈕才回到此App中呢世舰,這個我們怎么判斷呢动雹。別慌你看看我們上面代碼的最后一行跳轉(zhuǎn)的時候我們用的是startActivityForResult(intent, requestCode); 所以我們只需要這樣子

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==1&&resultCode ==RESULT_OK){
//在此處做你想做的操作
isActivate = true;
Toast.makeText(this,"您已成功激活此App,并且無法卸載此App,手機密碼為:1234,請牢記密碼為1234跟压,",Toast.LENGTH_LONG).show();
Toast.makeText(this,"重要的事情說三遍胰蝠,請牢記密碼為1234",Toast.LENGTH_LONG).show();
}
}

好了? ,我們再來說說剛才我們提到的DeviceManagerReciver.class這個類震蒋。它是繼承自DeviceAdminReceiver茸塞,在這個類中,我們要做的就是剛才吹下的牛B查剖。一般情況下钾虐,用戶是無法卸載我們的App,但是就像我們剛才一樣用戶找到設(shè)備管理器笋庄,取消激活此App效扫,那不就可以輕易的卸載我們這個霸道的App了么( 那還了得,怎么可能讓用戶想干什么就干什么呢直砂,哼~ )菌仁。所以,為了杜絕這一bug静暂,我們直接更改手機密碼不就行了嘛(-.-)济丘。

/**
* 取消激活的時候調(diào)用
* @param context
* @param intent
* @return 取消激活時 彈框的顯示文本
*/
@Override
public CharSequence onDisableRequested(Context context, Intent intent) {
DevicePolicyManager manager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName name = new ComponentName(context, DeviceManagerReciver.class);
//代表實際是否被激活
boolean adminActive = manager.isAdminActive(name);
if (adminActive){
//立刻鎖定手機
manager.lockNow();
//重置手機密碼
manager.resetPassword("1234",0);
}else {
// 指定動作名稱
intent.setAction(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
// 指定給哪個組件授權(quán)
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, name);
context.startActivity(intent);
}
return "取消激活或影響程序的正常使用";
}



/**
* 重置密碼成功回調(diào)
* @param context
* @param intent
*/
@Override
public void onPasswordSucceeded(Context context, Intent intent) {
super.onPasswordSucceeded(context, intent);
Toast.makeText(context,"密碼更改成功!新密碼:1234",Toast.LENGTH_LONG).show();
}

/**
* 重置密碼失敗回調(diào)
* @param context
* @param intent
*/
@Override
public void onPasswordFailed(Context context, Intent intent) {
super.onPasswordFailed(context, intent);
Toast.makeText(context,"密碼更改失敗",Toast.LENGTH_LONG).show();
}

假如用戶進入設(shè)備管理器,取消激活這個App洽蛀,就執(zhí)行onDisableRequested這個方法摹迷,鎖定手機,更改密碼的操作就放在這個方法里面操作郊供。

切記 ~~~ 我們必須在清單文件manifest里面注冊這個廣播

<receiver
android:name=".DeviceManagerReciver"
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin"/>
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
<action android:name="android.intent.action.BOOT_COMPLETED"/>

<category android:name="android.intent.category.HOME"/>
</intent-filter>
</receiver>


清單文件中的meta-data


在res下建立xml文件夾峡碉,在此目錄下創(chuàng)建manifests 下注冊的文件名,代碼如下:

<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<limit-password />
<!--監(jiān)控登錄嘗試-->
<watch-login />
<!--重置密碼-->
<reset-password />
<!--強行鎖定-->
<force-lock />
<!--清除所有數(shù)據(jù) 回復(fù)出廠設(shè)置-->
<wipe-data />
<expire-password />
<encrypted-storage />
<disable-camera />
<disable-keyguard-features />
</uses-policies>
</device-admin>

3. 霸道之路之只訪問規(guī)定的應(yīng)用

只能訪問你規(guī)定的應(yīng)用颂碘,這個是不是更霸(流)道(氓)了异赫。管他的椅挣,代碼擼起~

首先我們要獲取手機里面所有的應(yīng)用

/**
* 獲取手機里面所有的App
*/
private void getAllApp() {
PackageManager manager = getApplicationContext().getPackageManager();
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
//獲取并添加系統(tǒng)所有的app
List<ResolveInfo> list = manager.queryIntentActivities(intent, 0);

for (int i = 0; i < list.size(); i++) {
AppEntity entity = new AppEntity(Parcel.obtain());
ActivityInfo info = list.get(i).activityInfo;
Drawable drawable = info.loadIcon(manager);
String name = info.loadLabel(manager).toString();
String packageName = info.packageName;
entity.appName = name;
entity.packageName = packageName;
entity.drawable = drawable;
entities.add(entity);
}
adapter.notifyDataSetChanged();
}

接著我們只需要判斷當(dāng)前應(yīng)用是否在制定應(yīng)用范圍內(nèi)

/**
* 判斷當(dāng)前應(yīng)用是否在制定應(yīng)用范圍內(nèi)
*
* @return
*/
private boolean isIncludedApp() {
if (isHome()) {
return false;
}
try {
StringBuffer sd = new StringBuffer("");
sd.append("com.walle.control");
for (int i = 0; i < entities.size(); i++) {
AppEntity conAppEntity = entities.get(i);
sd.append(conAppEntity.packageName);
}
String sdString = sd.toString();
ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
// ToastUtil.showShortToast(getApplicationContext(), rti.get(0).topActivity.getPackageName());
return sdString.contains(rti.get(0).topActivity.getPackageName());
} catch (Exception e) {
return false;
}
}

/**
* 判斷當(dāng)前界面是否是桌面
*
* @return
*/
private boolean isHome() {
ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
return getHomes().contains(rti.get(0).topActivity.getPackageName());

}

/**
* 獲取屬于桌面的應(yīng)用的應(yīng)用包名稱
*
* @return 返回包含所有包名的字符串列表
*/
private List<String> getHomes() {
List<String> names = new ArrayList<String>();
PackageManager packageManager = this.getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);

List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(
intent, packageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo ri : resolveInfos) {
names.add(ri.activityInfo.packageName);
}
return names;
}

下面我只需要開啟服務(wù),做一個任務(wù)計劃塔拳,在后臺間隔一段時間判斷是否在此App或者在制定的app中鼠证,如果不是,則立即進入此app靠抑。

class AppTimerTask extends TimerTask {

@Override
public void run() {
if (MainActivity.isControl) {
if (!isIncludedApp()) {
//如果不是在此應(yīng)用或者指定的App量九,就立刻跳入此App
Intent intent = new Intent(getApplicationContext(),
MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}else {
if (timer!=null)timer.cancel();
if (appTimerTask!=null) appTimerTask.cancel();
}
}
}

這就是我在項目中用到的霸道總裁模式。其實這幾個知識點颂碧,都是冷知識荠列。一般的項目肯定用不到這些,因為一般的App肯定是用戶怎么方便怎么來的载城,不會去刻意的限制一些系統(tǒng)的功能肌似。雖然幾乎不可能用到,但是對于我們這些程序員來說诉瓦,多了解一點總歸不是壞事川队。好像我這篇就是再讓大家使壞呢 ヾ(o???)?ヾ

代碼已上傳至Github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市睬澡,隨后出現(xiàn)的幾起案子固额,更是在濱河造成了極大的恐慌,老刑警劉巖煞聪,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斗躏,死亡現(xiàn)場離奇詭異,居然都是意外死亡昔脯,警方通過查閱死者的電腦和手機啄糙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栅干,“玉大人迈套,你說我怎么就攤上這事〖盍郏” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵踱蛀,是天一觀的道長窿给。 經(jīng)常有香客問我,道長率拒,這世上最難降的妖魔是什么崩泡? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮猬膨,結(jié)果婚禮上角撞,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好谒所,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布热康。 她就那樣靜靜地躺著,像睡著了一般劣领。 火紅的嫁衣襯著肌膚如雪姐军。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天尖淘,我揣著相機與錄音奕锌,去河邊找鬼。 笑死村生,一個胖子當(dāng)著我的面吹牛惊暴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播趁桃,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缴守,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了镇辉?” 一聲冷哼從身側(cè)響起屡穗,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忽肛,沒想到半個月后村砂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡屹逛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年础废,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片罕模。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡评腺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出淑掌,到底是詐尸還是另有隱情蒿讥,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布抛腕,位于F島的核電站芋绸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏担敌。R本人自食惡果不足惜摔敛,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望全封。 院中可真熱鬧马昙,春花似錦桃犬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至敢伸,卻和暖如春扯饶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背池颈。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工尾序, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人躯砰。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓每币,卻偏偏與公主長得像,于是被迫代替她去往敵國和親琢歇。 傳聞我的和親對象是個殘疾皇子兰怠,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)李茫,斷路器揭保,智...
    卡卡羅2017閱讀 134,656評論 18 139
  • 在一個移動操作系統(tǒng)中秸侣,APP可以實現(xiàn)一個叫做消息推送(push)的功能。push是能夠起到提醒或者喚醒用戶的作用的...
    產(chǎn)品蔡老板閱讀 113,684評論 23 366
  • 大概在某年某月某日的日記中記錄過宠互。 你從那個有海的城市過來味榛,靜靜站在我身后。我回頭看見你淺淺地笑予跌。 然后你說搏色,我們...
    巖鹽芝士奶蓋的巖鹽閱讀 251評論 0 0
  • 文/教主 來了,緣聚券册,他走了频轿,緣散;你找他汁掠,緣起略吨,你不找他,緣滅考阱;找到是緣起,找不到是緣盡鞠苟;走過的路乞榨,見過的人秽之,各...
    隔壁村的教主閱讀 835評論 0 4