Android如何添加系统长按键功能

   这章主要说明,在Android4.0上添加一个长按键发送消息打开系统通知面板功能,中间涉及到按键的响应的添加,Broadcast的注册和监听,以及SystemUI的修改。。

   按键分为长按或者短按,KeyEvent.FLAG_LONG_PRESS标志按键处于长按状态,而KeyEvent的getFlags能够获取当前按键的状态。在/PhoneWindowManager.java(拦截消息的处理类)中interceptKeyBeforeDispatching找到按键处理【以菜单键为例】。

1.添加按键的响应配置:   /frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

   [1]定义消息名称:

    static final String NOTIFICATION_ACTION = "com.android.action.OPEN_NOTIFICATION";
   [2]按键消息处理:

     菜单键为 KeyEvent.KEYCODE_MENU,先查看是否已经有了该按键的配置,若没有直接添加以下代码:

} else if (keyCode == KeyEvent.KEYCODE_MENU) {
   	        //liusl--add--open notification panel--on ipanel Remote Control
	        Slog.i(TAG,"----down"+down+" Flags"+event.getFlags());
	        if (down&&(event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0){ 	       
		    Intent intent = new Intent(); 
                    intent.setAction(NOTIFICATION_ACTION); 
                    intent.putExtra("msg", "MSG_OPEN_NOTIFICATION_PANEL");
                    mContext.sendBroadcast(intent);//发送消息 
                    return -1;
                }

2.在SystemUI中定义一个消息接受类并注册消息:         

    \frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\tablet\TabletStatusBar.java

    [1]注册消息:

       在makeStatusBarView()中添加Broadcast的注册和监听:

       NotificationReceiver hNotificationReceiver;//全局变量

        hNotificationReceiver = new NotificationReceiver(mContext);
        hNotificationReceiver.registerReceiver();

    [2]自定义消息接收类:
public class NotificationReceiver extends BroadcastReceiver {
          private final String TAG = "StatusBar.NotificationReceiver";
          private final String NOTIFICATION_ACTION = "com.android.action.OPEN_NOTIFICATION";
          Context mContext;
          public NotificationReceiver(Context context) {
                mContext = context;
          }

          @Override
          public void onReceive(Context context, Intent intent) {//重写onReceive方法
                String msg = intent.getStringExtra("msg");
                if(msg.equals("MSG_OPEN_NOTIFICATION_PANEL")) {
                       displayNotificationPanel();//打开通知面板
                }
          }

          public void registerReceiver() {//动态注册消息监听器
              final IntentFilter filter = new IntentFilter();
              filter.addAction(NOTIFICATION_ACTION);
              final Intent val = mContext.registerReceiver(this, filter);
          }
}

3.通知面板的打开:

\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\tablet\TabletStatusBar.java

public void displayNotificationPanel() {
     setTitle();
     animateExpand();
     visibilityChanged(true);
}

注:

    本文主要实现在PhoneWindowManager中添加一个长按菜单键的事件响应,发送一个MSG_OPEN_NOTIFICATION_PANEL打开通知面板的消息出去。在SystemUI中动态注册一个自定义的BroadcastReceiver,当接收到MSG_OPEN_NOTIFICATION_PANEL消息时,将打开通知面板的窗口。

-------------------------------------------------------------------

BroadcastReceiver的调用过程:

    首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action、Category)装入一个Intent对象,然后通过调用 Context.sendBroadcast()、sendOrderBroadcast()或sendStickyBroadcast()方法,把 Intent对象以广播方式发送出去。

    当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent相匹配,若匹配则就会调用BroadcastReceiver的onReceive()方法。所以当我们定义一个BroadcastReceiver的时候,都需要实现onReceive()方法。

注册BroadcastReceiver有两种方式:

    1.静态的在AndroidManifest.xml中用<receiver>标签生命注册,并在标签内用<intent- filter>标签设置过滤器。

    2.动态的在代码中先定义并设置好一个 IntentFilter 对象,然后在需要注册的地方调Context.registerReceiver()方法,如果取消时就调用 Context.unregisterReceiver()方法。如果用动态方式注册的BroadcastReceiver的Context对象被销毁时,BroadcastReceiver也就自动取消注册了。(特别注意,有些可能需要后台监听的,如短信消息,SystemUI是一个系统的apk,会一直处于后台运行,context不会销毁,所以可以采用动态注册的方式。


你可能感兴趣的:(android,SystemUI,系统按键)