How to Add Virtual Keys on Status Bar

How to add virtual keys on status bar?
--------------------------------------(for the version before Froyo) 

 


There are 6 .png for touch up and touch down of 3 buttons
Put 72 dpi and 48 dpi which can be found in Google native source code into
frameworks/base/core/res/res/drawable-hdpi
frameworks/base/core/res/res/drawable-mdpi
respectively (P.S. it has xhdpi for supporting tablet device in Gingerbread)
(in Gingerbread the directory has been changed to frameworks/base/packages/SystemUI/res/... )
and add 3 ImageView in frameworks/base/core/res/res/layout/status_bar.xml
status_search, status_back, and status_menu
<ImageView android:id="@+id/status_search"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="top"
  android:paddingTop="1dip"
  android:src="@drawable/search"/>
 <ImageView android:id="@+id/status_back"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="top"
  android:paddingTop="1dip"
  android:src="@drawable/back"/>
 <ImageView android:id="@+id/status_menu"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_gravity="top"
  android:paddingTop="1dip"
  android:src="@@drawable/menu"/>
in frameworks/base/core/res/res/value/dimens.xml
you can simply change the height of status bar by assigning
<!-- Height of the status bar -->
    <dimen name="status_bar_height">34dip</dimen>
in frameworks/base/services/java/com/android/server/status/StatusBarView.java
(in Gingerbread the directory has been changed to frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/... )
add
//ImageView for virtual key
    ImageView mSearchIcon;
    ImageView mBackIcon;
    ImageView mMenuIcon;
//KeyEevent set
    public static final int RESV_KEY_SEARCH = KeyEvent.KEYCODE_SEARCH;
    public static final int RESV_KEY_BACK = KeyEvent.KEYCODE_BACK;
    public static final int RESV_KEY_MENU = KeyEvent.KEYCODE_MENU;
//Handle touch event
    int mResvKeyState = -1;
    int mResvKeyCode = -1;
in protected void onFinishInflate() {}
add
//ImageView for virtual key
 mSearchIcon = (ImageView)findViewById(R.id.status_search);
 mBackIcon = (ImageView)findViewById(R.id.status_back);
 mMenuIcon = (ImageView)findViewById(R.id.status_menu);
in public boolean onTouchEvent(MotionEvent event) {}
add
//Added
 if(mResvKeyState == -1){
  switch(getResvKeyArea(event)){
  case RESV_KEY_SEARCH:
  case RESV_KEY_BACK:
  case RESV_KEY_MENU:
  {
   mResvKeyState = event.getAction();
   mResvKeyCode = getResvKeyArea(event);
   updateResvKeyIcon(mResvKeyState, mResvKeyCode);
   }
  break;
  default:
  {
   if(event.getAction() != MotionEvent.ACTION_DOWN)
    mService.interceptTouchEvent(event);
  }
  break;
  } 
 }
 else{
  mResvKeyState = event.getAction();
  if(mResvKeyState == MotionEvent.ACTION_MOVE){
   if(mResvKeyCode != getResvKeyArea(event)){
   updateResvKeyIcon(MotionEvent.ACTION_UP, mResvKeyCode);
   mResvKeyCode = -1;
   mResvKeyState = -1;
   }
  }
  else if (mResvKeyState == MotionEvent.ACTION_UP){
   updateResvKeyIcon(mResvKeyState, mResvKeyCode);
   Intent intent = new Intent(Intent.ACTION_ICONKEY_CHANGED);   
   intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);   
   intent.putExtra("keycode",   mResvKeyCode);   
   mService.sendIntent(intent);  
   mResvKeyCode = -1;
   mResvKeyState = -1;
  }
  else{
   Slog.d(TAG, "error");
  }
Add 2 private functions
 //Private methods
    private int getResvKeyArea(MotionEvent event){
 if((event.getX() >= mSearchIcon.getLeft() && event.getX() <= mSearchIcon.getRight())
 && (event.getY() <= this.getHeight())){
  return RESV_KEY_SEARCH;
 }
 else if((event.getX() >= mBackIcon.getLeft() && event.getX() <= mBackIcon.getRight())
 && (event.getY() <= this.getHeight())){
  return RESV_KEY_BACK;
 }
 else if((event.getX() >= mMenuIcon.getLeft() && event.getX() <= mMenuIcon.getRight())
 && (event.getY() <= this.getHeight())){
  return RESV_KEY_MENU;
 }
 else
  return -1;
    }
    //Private methods added
    private int updateResvKeyIcon(int state, int key){
 if(key == RESV_KEY_SEARCH){
  if(state == MotionEvent.ACTION_UP){
  mSearchIcon.setImageResource(com.android.internal.R.drawable.search);
  }
  else if(state == MotionEvent.ACTION_DOWN){
  mSearchIcon.setImageResource(com.android.internal.R.drawable.search_pressed);
  }
 }
 else if(key == RESV_KEY_BACK){
  if(state == MotionEvent.ACTION_UP){
  mBackIcon.setImageResource(com.android.internal.R.drawable.back);
  }
  else if(state == MotionEvent.ACTION_DOWN){
  mBackIcon.setImageResource(com.android.internal.R.drawable.back_pressed);
  }
 }
 else if(key == RESV_KEY_MENU){
  if(state == MotionEvent.ACTION_UP){
  mMenuIcon.setImageResource(com.android.internal.R.drawable.menu);
  }
  else if(state == MotionEvent.ACTION_DOWN){
  mMenuIcon.setImageResource(com.android.internal.R.drawable.menu_pressed);
  }
 }
 return 0;
    }
Change public boolean onInterceptTouchEvent(MotionEvent event) {} to
@Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if(event.getX() < mSearchIcon.getLeft()){        
  return mService.interceptTouchEvent(event)
                 ? true : super.onInterceptTouchEvent(event);
 }
 return false;
    }
in  frameworks/base/core/java/android/content/intent.java
add our new intent 
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)   
public static final String ACTION_ICONKEY_CHANGED = "android.intent.action.ICONKEY_CHANGED"; 
in  frameworks/base/services/java/com/android/server/status/StatusBarService.java
add
//function added
    void sendIntent(Intent intent){   
     mContext.sendBroadcast(intent);   
    }
in  frameworks/base/services/java/com/android/server/status/StatusBaPolicy.java
find the field where to add registration for intents and add
//Action added
   filter.addAction(Intent.ACTION_ICONKEY_CHANGED);
       mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
in private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {}
add
//added
     else if (action.equals(Intent.ACTION_ICONKEY_CHANGED)) {   
     updateIconKeyAction(intent);
     }
add our private function
 //added
 private final void updateIconKeyAction(Intent intent){   
   int keycode = intent.getIntExtra("keycode", -1);   
   if(keycode != -1){   
     long now = SystemClock.suptimeMillis();   
      try {   
        KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0);   
        KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0);   
        (IWindowManager.Stub.asInterface(ServiceManager.getService("window"))).injectKeyEvent(down, false);   
        (IWindowManager.Stub.asInterface(ServiceManager.getService("window"))).injectKeyEvent(up, false);  
      }
     catch (RemoteException e) {    
      } 
   }   
 }
Done
Remember to make update-api to update frameworks/base/api/current.xml and see if our intent is already added
<field name="ACTION_ICONKEY_CHANGED"
 type="java.lang.String"
 transient="false"
 volatile="false"
 value="&quot;android.intent.action.ICONKEY_CHANGED&quot;"
 static="true"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
Result

 

 


 

發佈了14 篇原創文章 · 獲贊 5 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章