FBI Warning:歡迎轉載,但請標明出處:http://blog.csdn.net/codezjx/article/details/45542137,未經本人同意請勿用於商業用途,感謝支持!
Recent鍵及狀態欄下拉的屏蔽
Back鍵和Home鍵的屏蔽可以看我這篇貼:
http://blog.csdn.net/codezjx/article/details/45485975
Home鍵與Recent鍵的點擊事件是在framework層進行處理的,因此onKeyDown與dispatchKeyEvent都捕獲不到點擊事件。
查看StatusBarManager.java源碼,目前只能通過其void disable(int what) {…}設置,並可傳入值:
public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME;
public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT;
public static final int DISABLE_BACK = View.STATUS_BAR_DISABLE_BACK;
public static final int DISABLE_NONE = 0x00000000;
等等… 具體值可以查view的源碼,因爲都是@hide的
首先想到了反射機制來進行調用:(或者使用移除了@hide的API 庫classes.jar)
public static final String STATUS_BAR_SERVICE = “statusbar”;
public static final String CLASS_STATUS_BAR_MANAGER = “android.app.StatusBarManager”;
public static final String METHOD_DISABLE = “disable”;
try {
Object service = getSystemService(STATUS_BAR_SERVICE);
Class <?> statusBarManager = Class.forName(CLASS_STATUS_BAR_MANAGER);
Method disable = statusBarManager.getMethod(METHOD_DISABLE, int.class);
disable.invoke (service, 0x01000000); //爲View.STATUS_BAR_DISABLE_RECENT的值
} catch (Exception e) {
e.printStackTrace();
}
會報出以下錯誤提示:
Neither user 10076 nor current process has android.permission.STATUS_BAR.
提示缺少權限,Manifest添加之,提示:Permission is only granted to system apps
總結:通過這種方法屏蔽狀態欄下拉,必須得有系統簽名,WTF。。。
後續:參考了一些鎖屏軟件,如小米百變鎖屏、GO鎖屏等,他們在鎖屏的時候也沒有屏蔽掉Recent鍵和狀態欄下拉。而是在點擊按鍵後迅速將彈出的Dialog和Window收回去,其實這也可以看作另一種應急解決方法。繼續回去看StatusBarManager.java源碼:發現了另外一個方法,public void collapse() {…}和public void expand() {…},其中collapse爲收縮的方法,expand爲展開方法,而且調用這兩個方法不需要系統簽名。用上面的反射方法繼續調用之:
注意:點擊Recent鍵彈出dialog會回調onWindowFocusChanged(),因此可在該方法中調用:
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(!hasFocus) {
……
Method collapse = statusBarManager.getMethod(METHOD_COLLAPSE);
collapse.invoke(service);
……
}
}
加入權限:
<uses-permission android:name=”android.permission.EXPAND_STATUS_BAR”/></span>
後面又發現了另一種方法,更加簡便,同樣是點擊後迅速消失(還可以隱藏長按電源的彈出框):
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));</span>
可以通過View焦點丟失的情況下去觸發,發送該廣播,如:
class MyView extends View {
public MyView(Context pContext) {
super(pContext);
}
@Override
public void onWindowFocusChanged(boolean pHasWindowFocus) {
super.onWindowFocusChanged(pHasWindowFocus);
if (!pHasWindowFocus) {
mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
}
}
}
狀態欄的隱藏:
方法一:
隱藏:(但點擊menu會恢復,然後又自動隱藏)
getWindow().getDecorView().setSystemUiVisibility(Window.FEATURE_ACTION_BAR_OVERLAY);
顯示:
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
(用這個type可以將按鈕變成小圓點:View.SYSTEM_UI_FLAG_LOW_PROFILE)
WindowManager.LayoutParams params = window.getAttributes();
params.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE;
window.setAttributes(params);
方法二:
隱藏:進入\system\目錄,編輯build.prop,在最後一行添加qemu.hw.mainkeys=1,保存重啓即可。
顯示:改成qemu.hw.mainkeys=0,保存重啓即可。
方法三:
參考一個叫GMD Hide Bar的軟件。反編譯了他的源碼,他是用命令行直接幹掉SystemUI這個進程來達到隱藏目的的。大家可以嘗試直接在DDMS中關閉:com.android.systemui這個進程,狀態欄直接消失,不過一段時間後又會自動運行。因此需要運行後臺線程不斷執行關閉操作,比較耗資源,且需要root權限。
隱藏:
int k = getPid();
if (k > 0)
ProcessUtil.execAsRoot(“kill -s CONT ” + k);
顯示:
ProcessUtil.execAsApp(“am startservice -n com.android.systemui/.SystemUIService”);