Framework StatusBar添加(wifi,bluetooth,gps,sound,rotate)控制面板

来源:互联网 发布:ubuntu卸载wine 编辑:程序博客网 时间:2024/04/30 04:57

Framework StatusBar添加(wifi,bluetooth,gps,sound,rotate)控制面板

 

学android已经数月了,最近跳槽了一家做手机的公司,一去就是改framework层里的代码,那个纠结啊。第一个项目就是改statusbar,添加控制面板开关。

因为项目公司里任何的资源都带不出来,就用我自己的手机截图示范,跟android原生statusbar对比,源码主要以wifi为示例。


我做的项目是添加WIFI,BLUETOOTH,GPS,SOUND,自动旋转,个人感觉自动旋转是最让人纠结的,因为无法监听到状态的广播,不过可以监听数据库里的变化。我主要以WIFI项目示范,其他的四个提下我的思路,欢迎大家探讨。

修改的图片文件位置:

 

 

view plainprint?
  1. platform\frameworks\base\packages\SystemUI\res\drawable-hdpi  

添加switch_wifi_on.png,switch_wifi_off.png,switch_ind_on.png,switch_ind_off.png,swith_bg

修改的layout文件位置:

view plainprint?
  1. platform\frameworks\base\packages\SystemUI\res\layout\status_bar_expanded.xml  
修改的string文件位置:

中文

view plainprint?
  1. platform\frameworks\base\packages\SystemUI\res\values-zh-rCN\strings.xml  
view plainprint?
  1.    
view plainprint?
  1. 英文  
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">platform\frameworks\base\packages\SystemUI\res\values\strings.xml  
view plainprint?
  1.    

代码文件位置:
view plainprint?
  1.    
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">platform\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\StatusBarService.java  
view plainprint?
  1.    
view plainprint?
  1. </pre>在status_bar_expanded.xml里添加5个开关的排列,添加在最顶层的android:background="@drawable/title_bar_portrait"的这个LinearLayout的上面,那样控制面板就会显示在最顶层了,大家看下源码就知道了,下面添加的是wifi的,添加其他的开关继续在里面添加即可。  
view plainprint?
  1.    
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">    <LinearLayout   
  2.         android:layout_width="match_parent"  
  3.         android:layout_height="wrap_content"  
  4.         android:background="@drawable/switch_bg">  
  5.         <LinearLayout   
  6.             android:layout_width="match_parent"  
  7.             android:layout_height="wrap_content"  
  8.             android:id="@+id/switch_wifi"  
  9.             >  
  10.             <ImageView android:layout_width="wrap_content"  
  11.                 android:layout_height="wrap_content"  
  12.                 android:id="@+id/switch_wifi_img"/>  
  13.             <TextView android:layout_width="wrap_content"  
  14.                 android:layout_height="wrap_content"  
  15.                 android:id="@+id/switch_wifi_text"/>  
  16.             <ImageView android:layout_width="fill_parent"  
  17.                 android:layout_height="wrap_content"  
  18.                 android:id="@+id/switch_ind_state"/>  
  19.         </LinearLayout>  
  20.     </LinearLayout>  

功能控制添加在StatusBarService.xml文件里:
view plainprint?
  1. 定义变量:  
view plainprint?
  1.    
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="java" name="code">    private WifiManager mWifiManager;  
  2.     private IntentFilter mWifiStateFilter;  
  3.       
  4.     LinearLayout mWifiState;  
  5.     ImageView mWifiImg;  
  6.     TextView mWifiText;  
  7.     ImageView mWifiInd;  
view plainprint?
  1.    
view plainprint?
  1. </pre>在private void makeStatusBarView(Context context)定义这些变量的值及要用的广播等。  
view plainprint?
  1.    
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">        mWifiState=(LinearLayout)expanded.findViewById(R.id.switch_wifi);  
  2.         mWifiState.setOnClickListener(mWifiChangeListener);  
  3.         mWifiImg=(ImageView)expanded.findViewById(R.id.switch_wifi_img);  
  4.         mWifiText=(TextView)expanded.findViewById(R.id.switch_wifi_text);  
  5.         mWifiInd=(ImageView)expanded.findViewById(R.id.switch_ind_state);  
  6.           
  7.         mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);  
  8.         mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);  
  9.         registerReceiver(mWifiStateReceiver, mWifiStateFilter);  


view plainprint?
  1. 然后在其他位置添加广播,定义的5个状态的样式及点击切换等。  
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="java" name="code">    
  2.     private final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {  
  3.         @Override  
  4.         public void onReceive(Context context, Intent intent) {  
  5.             if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {  
  6.                 handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,  
  7.                             mWifiManager.getWifiState()));  
  8.             }  
  9.         }  
  10.     };  
  11.     private void handleWifiStateChanged(int wifiState) {  
  12.         switch(wifiState){  
  13.         case WifiManager.WIFI_STATE_DISABLED:  
  14.             mWifiImg.setBackgroundResource(R.drawable.switch_wifi_off);  
  15.             mWifiText.setText(R.string.switch_wifi_text_off);  
  16.             mWifiInd.setBackgroundResource(R.drawable.switch_ind_off);  
  17.             break;  
  18.         case WifiManager.WIFI_STATE_DISABLING:  
  19.             mWifiImg.setBackgroundResource(R.drawable.switch_wifi_on);  
  20.             mWifiText.setText(R.string.switch_wifi_text_closing);  
  21.             mWifiInd.setBackgroundResource(R.drawable.switch_ind_on);  
  22.             break;  
  23.         case WifiManager.WIFI_STATE_ENABLED:  
  24.             mWifiImg.setBackgroundResource(R.drawable.switch_wifi_on);  
  25.             mWifiText.setText(R.string.switch_wifi_text_on);  
  26.             mWifiInd.setBackgroundResource(R.drawable.switch_ind_on);  
  27.             break;  
  28.         case WifiManager.WIFI_STATE_ENABLING:  
  29.             mWifiImg.setBackgroundResource(R.drawable.switch_wifi_off);  
  30.             mWifiText.setText(R.string.switch_wifi_text_opening);  
  31.             mWifiInd.setBackgroundResource(R.drawable.switch_ind_off);  
  32.             break;  
  33.         case WifiManager.WIFI_STATE_UNKNOWN:  
  34.             mWifiImg.setBackgroundResource(R.drawable.switch_wifi_off);  
  35.             mWifiText.setText(R.string.switch_wifi_text_off);  
  36.             mWifiInd.setBackgroundResource(R.drawable.switch_wifi_off);  
  37.             break;  
  38.         }  
  39.     }  
  40.     private View.OnClickListener mWifiChangeListener = new View.OnClickListener() {  
  41.         public void onClick(View v) {  
  42.             if(mWifiManager.getWifiState()==WifiManager.WIFI_STATE_DISABLED){  
  43.                 mWifiManager.setWifiEnabled(true);  
  44.                 handleWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);  
  45.             }else{  
  46.                 mWifiManager.setWifiEnabled(false);  
  47.                 handleWifiStateChanged(WifiManager.WIFI_STATE_DISABLED);  
  48.             }  
  49.         }  
  50.     };  
view plainprint?
  1.    
view plainprint?
  1. </pre>在strings.xml文件里添加  
view plainprint?
  1.    
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">    <string name="switch_wifi_text_on">wifi</string>  
  2.     <string name="switch_wifi_text_off">wifi</string>  
  3.     <string name="switch_wifi_text_opening">opening</string>  
  4.     <string name="switch_wifi_text_closing">closing</string>  



就这样一个wifi的控制开关就完成了。因为是在家里写的,所以完整的代码无法打出来,就当给大家点提示吧。
view plainprint?
  1. wifi的源文件可以参考:<pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">   
view plainprint?
  1. platform\packages\apps\Settings\src\com\android\settings\wifi  
view plainprint?
  1.    
view plainprint?
  1. </pre>在widget里已经有一个范例了,大家可以参考里面的广播。  
view plainprint?
  1.    
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">platform\packages\apps\Settings\src\com\android\settings\widget\SettingsAppWidgetProvider.java  

view plainprint?
  1. public void onReceive(Context context, Intent intent) {  
  2.         super.onReceive(context, intent);  
  3.         String action = intent.getAction();  
  4.         if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {  
  5.             sWifiState.onActualStateChange(context, intent);  
  6.         } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {  
  7.             sBluetoothState.onActualStateChange(context, intent);  
  8.         } else if (LocationManager.PROVIDERS_CHANGED_ACTION.equals(action)) {  
  9.             sGpsState.onActualStateChange(context, intent);  
  10.         } else if (SyncStorageEngine.SYNC_CONNECTION_SETTING_CHANGED_INTENT.getAction()  
  11.                 .equals(action)) {  
  12.             sSyncState.onActualStateChange(context, intent);  
  13.         } else if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) {  
  14.             Uri data = intent.getData();  
  15.             int buttonId = Integer.parseInt(data.getSchemeSpecificPart());  
  16.             if (buttonId == BUTTON_WIFI) {  
  17.                 sWifiState.toggleState(context);  
  18.             } else if (buttonId == BUTTON_BRIGHTNESS) {  
  19.                 toggleBrightness(context);  
  20.             } else if (buttonId == BUTTON_SYNC) {  
  21.                 sSyncState.toggleState(context);  
  22.             } else if (buttonId == BUTTON_GPS) {  
  23.                 sGpsState.toggleState(context);  
  24.             } else if (buttonId == BUTTON_BLUETOOTH) {  
  25.                 sBluetoothState.toggleState(context);  
  26.             }  
  27.         } else {  
  28.             // Don't fall-through to updating the widget.  The Intent  
  29.             // was something unrelated or that our super class took  
  30.             // care of.  
  31.             return;  
  32.         }  
  33.   
  34.         // State changes fall through  
  35.         updateWidget(context);  
  36.     }  
view plainprint?
  1.    

view plainprint?
  1. </pre><pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">bluetooth也是一样的注册广播,监听变化。  
view plainprint?
  1.    
view plainprint?
  1. BluetoothAdapter,主要是这个类的相关应用。  
view plainprint?
  1.    
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="java" name="code">    private void handleStateChanged(int state) {  
  2.         switch (state) {  
  3.             case BluetoothAdapter.STATE_TURNING_ON:  
  4.                 mCheckBox.setSummary(R.string.wifi_starting);  
  5.                 mCheckBox.setEnabled(false);  
  6.                 break;  
  7.             case BluetoothAdapter.STATE_ON:  
  8.                 mCheckBox.setChecked(true);  
  9.                 mCheckBox.setSummary(null);  
  10.                 mCheckBox.setEnabled(true);  
  11.                 break;  
  12.             case BluetoothAdapter.STATE_TURNING_OFF:  
  13.                 mCheckBox.setSummary(R.string.wifi_stopping);  
  14.                 mCheckBox.setEnabled(false);  
  15.                 break;  
  16.             case BluetoothAdapter.STATE_OFF:  
  17.                 mCheckBox.setChecked(false);  
  18.                 mCheckBox.setSummary(mOriginalSummary);  
  19.                 mCheckBox.setEnabled(true);  
  20.                 break;  
  21.             default:  
  22.                 mCheckBox.setChecked(false);  
  23.                 mCheckBox.setSummary(R.string.wifi_error);  
  24.                 mCheckBox.setEnabled(true);  
  25.         }  
  26.     }  

view plainprint?
  1. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {  
  2.     @Override  
  3.     public void onReceive(Context context, Intent intent) {  
  4.         handleBluetoothStateChanged(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, mBluetoothAdapter.getState()););  
  5.     }  
  6. };  
view plainprint?
  1.    


view plainprint?
  1. </pre><pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">GPS则是监听数据库里的开关变化  
view plainprint?
  1. 参考写法:  
view plainprint?
  1. <span style="font-family:monospace;BACKGROUND-COLOR: rgb(240,240,240); WHITE-SPACE: pre"></span>   
view plainprint?
  1. platform\packages\apps\Settings\src\com\android\settings\widget\SettingsAppWidgetProvider.java  
view plainprint?
  1.    
view plainprint?
  1. </pre><pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code"><pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="java" name="code"> private static final class GpsStateTracker extends StateTracker {  
  2.         public int getButtonId() { return R.id.img_gps; }  
  3.         public int getIndicatorId() { return R.id.ind_gps; }  
  4.         public int getButtonImageId(boolean on) {  
  5.             return on ? R.drawable.ic_appwidget_settings_gps_on  
  6.                     : R.drawable.ic_appwidget_settings_gps_off;  
  7.         }  
  8.   
  9.         @Override  
  10.         public int getActualState(Context context) {  
  11.             ContentResolver resolver = context.getContentResolver();  
  12.             boolean on = Settings.Secure.isLocationProviderEnabled(  
  13.                 resolver, LocationManager.GPS_PROVIDER);  
  14.             return on ? STATE_ENABLED : STATE_DISABLED;  
  15.         }  
  16.   
  17.         @Override  
  18.         public void onActualStateChange(Context context, Intent unused) {  
  19.             // Note: the broadcast location providers changed intent  
  20.             // doesn't include an extras bundles saying what the new value is.  
  21.             setCurrentState(context, getActualState(context));  
  22.         }  
  23.   
  24.         @Override  
  25.         public void requestStateChange(final Context context, final boolean desiredState) {  
  26.             final ContentResolver resolver = context.getContentResolver();  
  27.             new AsyncTask<Void, Void, Boolean>() {  
  28.                 @Override  
  29.                 protected Boolean doInBackground(Void... args) {  
  30.                     Settings.Secure.setLocationProviderEnabled(  
  31.                         resolver,  
  32.                         LocationManager.GPS_PROVIDER,  
  33.                         desiredState);  
  34.                     return desiredState;  
  35.                 }  
  36.   
  37.                 @Override  
  38.                 protected void onPostExecute(Boolean result) {  
  39.                     setCurrentState(  
  40.                         context,  
  41.                         result ? STATE_ENABLED : STATE_DISABLED);  
  42.                     updateWidget(context);  
  43.                 }  
  44.             }.execute();  
  45.         }  
  46.     }  


view plainprint?
  1. sound则是参考  
view plainprint?
  1.    
view plainprint?
  1. platform\packages\apps\Settings\src\com\android\settings\SoundSettings.java  
view plainprint?
  1. </pre><pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="java" name="code">   
view plainprint?
  1. private BroadcastReceiver mReceiver = new BroadcastReceiver() {  
  2.     @Override  
  3.     public void onReceive(Context context, Intent intent) {  
  4.         if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {  
  5.             updateState(false);  
  6.         }  
  7.     }  
  8. };  
view plainprint?
  1.   
view plainprint?
  1. IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);  
  2. registerReceiver(mReceiver, filter);  
view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">  
view plainprint?
  1. </pre><pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">  
view plainprint?
  1. 自动选择则是参考:  
view plainprint?
  1.    
view plainprint?
  1. platform\packages\apps\Settings\src\com\android\settings\DisplaySettings.java  
view plainprint?
  1. </pre><pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code"><pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="java" name="code">    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {  
  2.         if (preference == mAccelerometer) {  

view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="java" name="code">//设置数据库里自动选择的开关,1为开,0为关  

view plainprint?
  1. <pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="java" name="code">            Settings.System.putInt(getContentResolver(),  
  2.                     Settings.System.ACCELEROMETER_ROTATION,  
  3.                     mAccelerometer.isChecked() ? 1 : 0);  
  4.         }  
  5.         return true;  
  6.     }  

写一个类继承于ContentResolver,用于监听数据库里的变化,然后即可。

以上代码皆可在android源码里找到相关资源,欢迎大家互相讨论。

view plainprint?
  1. </pre><pre style="BACKGROUND-COLOR: rgb(240,240,240); MARGIN: 4px 0px" class="html" name="code">  
view plainprint?
  1. </pre><br /><p></p><p></p><p></p> 

原创粉丝点击