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

在一家手机公司工作,负责修改framework层代码,首个任务是增强statusbar,添加WiFi、蓝牙、GPS、声音和旋转控制。以WiFi开关为例,展示了如何在没有状态广播的情况下监听自动旋转,并分享了其他功能的实现思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

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

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


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

修改的图片文件位置:

 

 

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文件位置:

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

中文

platform\frameworks\base\packages\SystemUI\res\values-zh-rCN\strings.xml
 
英文
platform\frameworks\base\packages\SystemUI\res\values\strings.xml
 

代码文件位置:

 


platform\frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\StatusBarService.java
 
在status_bar_expanded.xml里添加5个开关的排列,添加在最顶层的android:background="@drawable/title_bar_portrait"的这个LinearLayout的上面,那样控制面板就会显示在最顶层了,大家看下源码就知道了,下面添加的是wifi的,添加其他的开关继续在里面添加即可。
 
	<LinearLayout 
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:background="@drawable/switch_bg">
		<LinearLayout 
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:id="@+id/switch_wifi"
			>
			<ImageView android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:id="@+id/switch_wifi_img"/>
			<TextView android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:id="@+id/switch_wifi_text"/>
			<ImageView android:layout_width="fill_parent"
				android:layout_height="wrap_content"
				android:id="@+id/switch_ind_state"/>
		</LinearLayout>
	</LinearLayout>

功能控制添加在StatusBarService.xml文件里:

定义变量:
 
    private WifiManager mWifiManager;
    private IntentFilter mWifiStateFilter;
    
    LinearLayout mWifiState;
    ImageView mWifiImg;
    TextView mWifiText;
    ImageView mWifiInd;
 
在private void makeStatusBarView(Context context)定义这些变量的值及要用的广播等。
 
        mWifiState=(LinearLayout)expanded.findViewById(R.id.switch_wifi);
        mWifiState.setOnClickListener(mWifiChangeListener);
        mWifiImg=(ImageView)expanded.findViewById(R.id.switch_wifi_img);
        mWifiText=(TextView)expanded.findViewById(R.id.switch_wifi_text);
        mWifiInd=(ImageView)expanded.findViewById(R.id.switch_ind_state);
        
        mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
        mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
        registerReceiver(mWifiStateReceiver, mWifiStateFilter);



然后在其他位置添加广播,定义的5个状态的样式及点击切换等。
  
    private final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
                handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                            mWifiManager.getWifiState()));
            }
        }
    };
    private void handleWifiStateChanged(int wifiState) {
        switch(wifiState){
        case WifiManager.WIFI_STATE_DISABLED:
        	mWifiImg.setBackgroundResource(R.drawable.switch_wifi_off);
        	mWifiText.setText(R.string.switch_wifi_text_off);
        	mWifiInd.setBackgroundResource(R.drawable.switch_ind_off);
        	break;
        case WifiManager.WIFI_STATE_DISABLING:
        	mWifiImg.setBackgroundResource(R.drawable.switch_wifi_on);
        	mWifiText.setText(R.string.switch_wifi_text_closing);
        	mWifiInd.setBackgroundResource(R.drawable.switch_ind_on);
        	break;
        case WifiManager.WIFI_STATE_ENABLED:
        	mWifiImg.setBackgroundResource(R.drawable.switch_wifi_on);
        	mWifiText.setText(R.string.switch_wifi_text_on);
        	mWifiInd.setBackgroundResource(R.drawable.switch_ind_on);
        	break;
        case WifiManager.WIFI_STATE_ENABLING:
        	mWifiImg.setBackgroundResource(R.drawable.switch_wifi_off);
        	mWifiText.setText(R.string.switch_wifi_text_opening);
        	mWifiInd.setBackgroundResource(R.drawable.switch_ind_off);
        	break;
        case WifiManager.WIFI_STATE_UNKNOWN:
        	mWifiImg.setBackgroundResource(R.drawable.switch_wifi_off);
        	mWifiText.setText(R.string.switch_wifi_text_off);
        	mWifiInd.setBackgroundResource(R.drawable.switch_wifi_off);
        	break;
        }
    }
    private View.OnClickListener mWifiChangeListener = new View.OnClickListener() {
        public void onClick(View v) {
            if(mWifiManager.getWifiState()==WifiManager.WIFI_STATE_DISABLED){
            	mWifiManager.setWifiEnabled(true);
            	handleWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
            }else{
            	mWifiManager.setWifiEnabled(false);
            	handleWifiStateChanged(WifiManager.WIFI_STATE_DISABLED);
            }
        }
    };
 
在strings.xml文件里添加
 
	<string name="switch_wifi_text_on">wifi</string>
	<string name="switch_wifi_text_off">wifi</string>
	<string name="switch_wifi_text_opening">opening</string>
	<string name="switch_wifi_text_closing">closing</string>



就这样一个wifi的控制开关就完成了。因为是在家里写的,所以完整的代码无法打出来,就当给大家点提示吧。

wifi的源文件可以参考:
 
platform\packages\apps\Settings\src\com\android\settings\wifi
 
在widget里已经有一个范例了,大家可以参考里面的广播。
 
platform\packages\apps\Settings\src\com\android\settings\widget\SettingsAppWidgetProvider.java

public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        String action = intent.getAction();
        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
            sWifiState.onActualStateChange(context, intent);
        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
            sBluetoothState.onActualStateChange(context, intent);
        } else if (LocationManager.PROVIDERS_CHANGED_ACTION.equals(action)) {
            sGpsState.onActualStateChange(context, intent);
        } else if (SyncStorageEngine.SYNC_CONNECTION_SETTING_CHANGED_INTENT.getAction()
                .equals(action)) {
            sSyncState.onActualStateChange(context, intent);
        } else if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) {
            Uri data = intent.getData();
            int buttonId = Integer.parseInt(data.getSchemeSpecificPart());
            if (buttonId == BUTTON_WIFI) {
                sWifiState.toggleState(context);
            } else if (buttonId == BUTTON_BRIGHTNESS) {
                toggleBrightness(context);
            } else if (buttonId == BUTTON_SYNC) {
                sSyncState.toggleState(context);
            } else if (buttonId == BUTTON_GPS) {
                sGpsState.toggleState(context);
            } else if (buttonId == BUTTON_BLUETOOTH) {
                sBluetoothState.toggleState(context);
            }
        } else {
            // Don't fall-through to updating the widget.  The Intent
            // was something unrelated or that our super class took
            // care of.
            return;
        }

        // State changes fall through
        updateWidget(context);
    }
 


bluetooth也是一样的注册广播,监听变化。
 
BluetoothAdapter,主要是这个类的相关应用。
 
    private void handleStateChanged(int state) {
        switch (state) {
            case BluetoothAdapter.STATE_TURNING_ON:
                mCheckBox.setSummary(R.string.wifi_starting);
                mCheckBox.setEnabled(false);
                break;
            case BluetoothAdapter.STATE_ON:
                mCheckBox.setChecked(true);
                mCheckBox.setSummary(null);
                mCheckBox.setEnabled(true);
                break;
            case BluetoothAdapter.STATE_TURNING_OFF:
                mCheckBox.setSummary(R.string.wifi_stopping);
                mCheckBox.setEnabled(false);
                break;
            case BluetoothAdapter.STATE_OFF:
                mCheckBox.setChecked(false);
                mCheckBox.setSummary(mOriginalSummary);
                mCheckBox.setEnabled(true);
                break;
            default:
                mCheckBox.setChecked(false);
                mCheckBox.setSummary(R.string.wifi_error);
                mCheckBox.setEnabled(true);
        }
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            handleBluetoothStateChanged(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, mBluetoothAdapter.getState()););
        }
    };
 



GPS则是监听数据库里的开关变化
参考写法:
 
platform\packages\apps\Settings\src\com\android\settings\widget\SettingsAppWidgetProvider.java
 
 private static final class GpsStateTracker extends StateTracker {
        public int getButtonId() { return R.id.img_gps; }
        public int getIndicatorId() { return R.id.ind_gps; }
        public int getButtonImageId(boolean on) {
            return on ? R.drawable.ic_appwidget_settings_gps_on
                    : R.drawable.ic_appwidget_settings_gps_off;
        }

        @Override
        public int getActualState(Context context) {
            ContentResolver resolver = context.getContentResolver();
            boolean on = Settings.Secure.isLocationProviderEnabled(
                resolver, LocationManager.GPS_PROVIDER);
            return on ? STATE_ENABLED : STATE_DISABLED;
        }

        @Override
        public void onActualStateChange(Context context, Intent unused) {
            // Note: the broadcast location providers changed intent
            // doesn't include an extras bundles saying what the new value is.
            setCurrentState(context, getActualState(context));
        }

        @Override
        public void requestStateChange(final Context context, final boolean desiredState) {
            final ContentResolver resolver = context.getContentResolver();
            new AsyncTask<Void, Void, Boolean>() {
                @Override
                protected Boolean doInBackground(Void... args) {
                    Settings.Secure.setLocationProviderEnabled(
                        resolver,
                        LocationManager.GPS_PROVIDER,
                        desiredState);
                    return desiredState;
                }

                @Override
                protected void onPostExecute(Boolean result) {
                    setCurrentState(
                        context,
                        result ? STATE_ENABLED : STATE_DISABLED);
                    updateWidget(context);
                }
            }.execute();
        }
    }



sound则是参考
 
platform\packages\apps\Settings\src\com\android\settings\SoundSettings.java
 
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
                updateState(false);
            }
        }
    };

        IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
        registerReceiver(mReceiver, filter);


自动选择则是参考:
 
platform\packages\apps\Settings\src\com\android\settings\DisplaySettings.java
    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
        if (preference == mAccelerometer) {

//设置数据库里自动选择的开关,1为开,0为关


            Settings.System.putInt(getContentResolver(),
                    Settings.System.ACCELEROMETER_ROTATION,
                    mAccelerometer.isChecked() ? 1 : 0);
        }
        return true;
    }

写一个类继承于ContentResolver,用于监听数据库里的变化,然后即可。
以上代码皆可在android源码里找到相关资源,欢迎大家互相讨论。









评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值