学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源码里找到相关资源,欢迎大家互相讨论。

更多相关文章

  1. Android(安卓)开发者 for Flutter (2)如何布局? XML layout 文件跑
  2. android android 在list view中插入一条广告
  3. Android(安卓)引导页动态添加圆点指示器
  4. android 上面一个listview下面一个button,让button一直处于listv
  5. Android5.0 下拉通知栏快捷开关的添加(必看)
  6. Android(安卓)网络状态监听那些事
  7. Android中Dialog对话框的调用及监听
  8. Android(安卓)使用AsyncTask 后监听异步加载完毕的动作-(by terry
  9. Android实现https网络通信之添加指定信任证书/信任所有证书

随机推荐

  1. 通过WifiManager可以实现对wifi进行操作,
  2. 【android之锚定视图】
  3. Android(安卓)自定义底部导航栏
  4. android弹出式菜单(效果爆炸)
  5. Android文本框实现搜索和清空效果
  6. Android(安卓)apk反编译java代码
  7. Android(安卓)中文API (69) ―― Bluetooth
  8. XUI 一个简洁而优雅的Android原生UI框架,
  9. Android通过OMA获得ESE的CPLC
  10. android WebView拦截请求详解