Android系统开放App程序监听Home键的权限
来源:互联网 发布:男士头发护理 知乎 编辑:程序博客网 时间:2024/05/29 11:22
项目的安全需要:
要求客户APP在申请了特定ENABLE_HOME权限后,允许监听home键并对HOME键的系统功能进行屏蔽;
修改基于RK平台Android 5.1.1系统
经过对系统代码的分析,按照用户按下HOME键的流程整理如下:
系统服务进程中:
1、framework/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
函数:interceptKeyBeforeQueueing 本次并未修改,不展开
函数:interceptKeyBeforeDispatching
if (keyCode == KeyEvent.KEYCODE_HOME) { // If we have released the home key, and didn't do anything else // while it was pressed, then it is time to go home! if (!down) {//处理HOME键up(放开)的动作; mHomePressed = false;//这部分是我加入的如果应用截取了home键,直接退出,主要通过加入的标志mHomeIgnoreflag来判断,后面会做介绍 //add by liaozongping @20161111 for HOME key ignore! if( mHomeIgnoreflag == true ){ mHomeIgnoreflag = false; return 0; } //added end cancelPreloadRecentApps(); if (mHomeConsumed) { mHomeConsumed = false; return -1; } if (canceled) { Log.i(TAG, "Ignoring HOME; event canceled."); return -1; } // If an incoming call is ringing, HOME is totally disabled. // (The user is already on the InCallUI at this point, // and his ONLY options are to answer or reject the call.) TelecomManager telecomManager = getTelecommService(); if (telecomManager != null && telecomManager.isRinging()) { Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); return -1; } // Delay handling home if a double-tap is possible. if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case mHomeDoubleTapPending = true; mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, ViewConfiguration.getDoubleTapTimeout()); return -1; } //add by liaozongping @20161111 for HOME key ignore! mHomeIgnoreflag = false;//此处系统处理home键up的实际操作,也就是退回到桌面的动作 handleShortPressOnHome(); return -1; } //这下面处理的是HOME键down(按下)的动作,实际的短按系统没有做什么处理动作 //add by liaozongping @20161111 for HOME key ignore! mHomeIgnoreflag = false;//跟解说一样,这里是判断,如果是锁屏串口,那么就把按键给锁屏的APP或者是不需要操作的类型,就丢弃 // If a system window has focus, then it doesn't make sense // right now to interact with applications. WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; if (attrs != null) { final int type = attrs.type; if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { // the "app" is keyguard, so give it the key return 0; } final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; for (int i=0; i<typeCount; i++) { if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { // don't do anything, but also don't pass it to the app return -1; } } } // Remember that home is pressed and handle special actions. if (repeatCount == 0) { mHomePressed = true; if (mHomeDoubleTapPending) { mHomeDoubleTapPending = false; mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); handleDoubleTapOnHome(); } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { preloadRecentApps();//我的流程中,正常是的短按流程会走到这里,原始是return -1,然后系统就不会将HOME按键传递给APP,这里我们需要传递给APP,使得APP使用onKeyDown函数能够捕获到KEYCODE_HOME按键; //add by liaozongping @20161111 for HOME key ignore! return 0; } } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { if (!keyguardOn) { handleLongPressOnHome(); } } //add by liaozongping @20161111 for HOME key ignore! else {//这里只是保险起见,事实应该没什么用 // give app the key return 0; } //added end return -1;
经过此文件的修改,在APP中正常的onKeyDown中已经能够捕获到KEYCODE_HOME的按键了!但是无论返回true还是false,APP中依然会退回到桌面;
这里注册一个广播接收器,用于获取KEYCODE_HOME按键down的用户处理状态,如果被APP捕获并处理了,就不再执行up的动作(即handleShortPressOnHome();)
//add by liaozongping @20161111 for HOME key ignore! HomeIgnoreReceiver mHomeIgnoreReceiver; private boolean mHomeIgnoreflag; //added end /* * 接收home键屏蔽广播 */ class HomeIgnoreReceiver extends BroadcastReceiver{ public void onReceive(Context context, Intent intent) { Log.d(TAG, "KeyCode_HOME Ignore!!!"); mHomeIgnoreflag = true; } }
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs)
函数中注册相应的广播接收器(也可以另外找合适的地方进行注册):
//add by liaozongping @20161111 for HOME key ignore! IntentFilter homeKeyFilter = new IntentFilter(); homeKeyFilter.addAction("keyevent.ignorehome"); mHomeIgnoreReceiver = new HomeIgnoreReceiver();//这里对于抓取home键的广播进行权限限制,只有具备android.permission.XXXXX.XXX权限的应用能够截取HOME键的操作; context.registerReceiver( mHomeIgnoreReceiver, homeKeyFilter, "android.permission.XXXXX.XXX", null); //added end
接下,要对APP的onKeyDown处理结果获取并发送广播,经过查找发现framework中最终调用APP的onKeyDown函数的地方是:
frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@Override public boolean dispatchKeyEvent(KeyEvent event) { final int keyCode = event.getKeyCode(); final int action = event.getAction(); final boolean isDown = action == KeyEvent.ACTION_DOWN; if (isDown && (event.getRepeatCount() == 0)) { // First handle chording of panel key: if a panel key is held // but not released, try to execute a shortcut in it. if ((mPanelChordingKey > 0) && (mPanelChordingKey != keyCode)) { boolean handled = dispatchKeyShortcutEvent(event); if (handled) { return true; } } // If a panel is open, perform a shortcut on it without the // chorded panel key if ((mPreparedPanel != null) && mPreparedPanel.isOpen) { if (performPanelShortcut(mPreparedPanel, keyCode, event, 0)) { return true; } } } if (!isDestroyed()) { final Callback cb = getCallback();//没有经过其他处理,并没有销毁的窗口,最终会到这里调用callback,调用到APP重写的onKeyDown,此处handled即为onKeyDown的返回值 final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event) : super.dispatchKeyEvent(event); LOGD("keycallback handled=" + handled); if (handled) {//当APP截取到KeyCODE_HOME按键,返回true后,我们需要通知系统按键服务进程,此次操作被APP捕获了,不要再执行退回到桌面的操作//PS:之所以这里需要使用广播,//1、是因为这里是属于用户APP的进程范围,而KEYCODE_HOME的down和up是独立的event,并且前一个文件中的event处理是在系统按键进程中进行处理,所以只能使用广播//2、客户定义了接口要在onKeyDown中进行捕获,那么只能够将down的捕获情况通过广播传递给按键处理进程,让该进程放弃下一次KEYCODE_HOME的up event的处理 //add by liaozongping @20161111 for HOME key ignore! if(event.getKeyCode() == KeyEvent.KEYCODE_HOME && event.getAction() == KeyEvent.ACTION_DOWN ){ Intent intent = new Intent(); intent.setAction("keyevent.ignorehome"); mContext.sendBroadcast(intent); } //added end return true; } } return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event) : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event); }
至此,整个的功能已经完成;
最后,在系统中加入刚才使用的自定义的系统权限:
frameworks/base/core/res/AndroidManifest.xml文件中加入:
2926 <!-- add by liaozongping for app to get HOME key event!-->
2927 <permission android:name="android.permission.XXXXX.XXX"
2928 android:protectionLevel="dangerous" />
附参考链接:http://www.cnblogs.com/android-blogs/p/5684622.html
- Android系统开放App程序监听Home键的权限
- Android开发-监听系统的 home键
- Android系统中home键的监听
- 关于Android系统开放所有App运用的权限
- Android程序监听Home键
- Android程序监听Home键
- APP全局监听系统Home键
- 监听android的Home键
- android Home键的监听
- 监听android的home键
- android Home键的监听
- android判断app置于后台监听home键
- android监听home键
- android 监听HOME键
- Android 监听Home键
- android Home键监听
- Android 监听Home键
- Android 监听home键
- light beach, pink water and vernal shining sun
- unity3D游戏开发七之创建基本游戏场景四
- android:DataBind
- Elasticsearch
- 2016年新运维:论《普通运维人员就是秋后的蚂蚱》
- Android系统开放App程序监听Home键的权限
- Android中JNI的简单认识
- activemq 三种消息监听器
- 使用java代码输出图片指定的*字塔
- 如何在各个版本的VC及64位下使用CPUID指令
- USB学习2
- 一个小脚本---拷贝编译完成的镜像
- 为mysql数据库建立索引
- 译文:使用MVC5的Entity Framework 6入门(九)——为ASP.NET MVC应用程序使用异步及存储过程