版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/luliyuan/article/details/78269225


    文章主要参考《Android实现自定义状态栏》

    公司的项目目标是自己开发一个状态栏,显示时间日期,蓝牙无线等状态

    核心:statusBar是SystemUI的一部分,statusBar跟正常建立的Android app不同,它不能有主Activity,需要在服务中创建窗口画面。SystemUIService是SystemUI的入口处,是被系统启动,之后通过WindowsManager创建画面显示。

    1、AndroidManifest.xml文件

    1. package="com.android.systemui"
    2. <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />/*这个可能不需要*/
    3. <uses-permission android:name="android.permission.STATUS_BAR" />
    4. <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />/* 创建TYPE_STATUS_BAR类型窗体,需要此权限*/
    5. <service android:name="SystemUIService"
    6. android:exported="true"
    7. />
    8. /*不能设置启动Activity*/
    9. <!--<activity android:name=".MainActivity">-->
    10. <!--<intent-filter>-->
    11. <!--<action android:name="android.intent.action.MAIN" />-->
    12. <!--<category android:name="android.intent.category.DEFAULT" />-->
    13. <!--<category android:name="android.intent.category.LAUNCHER" />-->
    14. <!--</intent-filter>-->
    15. <!--</activity>-->

    2、 StatusIconView

    1. public class StatusIconView extends LinearLayout {
    2. //图标
    3. private ImageView mIcon;
    4. public StatusIconView(Context context) {
    5. super(context);
    6. }
    7. public StatusIconView(Context context, AttributeSet attrs) {
    8. this(context, attrs, 0);
    9. }
    10. public StatusIconView(Context context, AttributeSet attrs, int defStyle) {
    11. super(context, attrs, defStyle);
    12. init(context, attrs, defStyle);
    13. }
    14. private void init(Context context, AttributeSet attrs, int defStyle) {
    15. LayoutInflater inflater = (LayoutInflater) context
    16. .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    17. inflater.inflate(R.layout.status_icon_view, this);
    18. mIcon = (ImageView) findViewById(R.id.icon);
    19. }
    20. public final void setIcon(int resId) {
    21. mIcon.setImageResource(resId);
    22. }
    23. public final ImageView getIconView(){
    24. return mIcon;
    25. }
    26. }

    需要的xml文件status_icon_view

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. xmlns:tools="http://schemas.android.com/tools"
    4. android:layout_width="wrap_content"
    5. android:layout_height="wrap_content"
    6. android:orientation="horizontal" >
    7. <ImageView
    8. android:id="@+id/icon"
    9. android:layout_width="wrap_content"
    10. android:layout_height="@dimen/status_bar_icon_height" />
    11. <!--<TextView-->
    12. <!--android:id="@+id/title"-->
    13. <!--android:layout_width="@dimen/status_bar_icon_width"-->
    14. <!--android:layout_height="@dimen/status_bar_icon_height" />-->
    15. </LinearLayout>

    3、SystemUIService

    1. public class SystemUIService extends Service {
    2. private WindowManager wm = null;
    3. private WindowManager.LayoutParams statusBarParams = new WindowManager.LayoutParams();
    4. private LinearLayout statusBarLayout=null;
    5. private StatusBarViewHolder statusBarViewHolder = new StatusBarViewHolder();
    6. @Override
    7. public void onCreate() {
    8. super.onCreate();
    9. createStatusView();
    10. registerReceiver();
    11. }
    12. @Override
    13. public IBinder onBind(Intent intent) {
    14. return null;
    15. }
    16. /* 手机电池电量显示 */
    17. BroadcastReceiver phoneBatteryReceiver = new BroadcastReceiver(){
    18. public void onReceive(Context context, Intent intent) {
    19. if(intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)){
    20. int level = intent.getIntExtra("level", 0);
    21. int scale = intent.getIntExtra("scale", 100);
    22. int curPower = (level * 100 / scale);
    23. updateIcon(getBatteryImage(curPower), statusBarViewHolder.phoneBatteryIcon);
    24. }
    25. };
    26. };
    27. private void createStatusView(){
    28. Context context = getApplicationContext();
    29. statusBarLayout = new LinearLayout(context);
    30. //statusBarLayout.setGravity(Gravity.CENTER_VERTICAL);
    31. //statusBarLayout.setLayoutParams(new android.view.ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
    32. wm=(WindowManager)getApplicationContext().getSystemService(WINDOW_SERVICE);
    33. ((LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(R.layout.status_bar, statusBarLayout);
    34. findStatusBarViews();
    35. wm.addView(statusBarLayout, getStatusViewParams());
    36. }
    37. private WindowManager.LayoutParams getStatusViewParams(){
    38. statusBarParams = new WindowManager.LayoutParams(
    39. ViewGroup.LayoutParams.MATCH_PARENT,
    40. (int) getResources().getDimension(
    41. R.dimen.status_bar_height),
    42. WindowManager.LayoutParams.TYPE_STATUS_BAR,
    43. WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    44. | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
    45. | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
    46. | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
    47. | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
    48. PixelFormat.TRANSLUCENT);
    49. statusBarParams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
    50. statusBarParams.gravity = Gravity.TOP;
    51. statusBarParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
    52. statusBarParams.setTitle("StatusBar");
    53. statusBarParams.packageName = this.getPackageName();
    54. return statusBarParams;
    55. }
    56. private void findStatusBarViews() {
    57. statusBarViewHolder.datetimeTextView = (TextView) statusBarLayout.findViewById(R.id.datetime_textView);
    58. statusBarViewHolder.phoneUSBIcon = (StatusIconView)statusBarLayout.findViewById(R.id.usb_icon);
    59. statusBarViewHolder.phoneSDCardIcon = (StatusIconView)statusBarLayout.findViewById(R.id.sdcard_icon);
    60. statusBarViewHolder.phoneHotspotIcon = (StatusIconView)statusBarLayout.findViewById(R.id.hotspot_icon);
    61. statusBarViewHolder.phoneMobileIcon = (StatusIconView)statusBarLayout.findViewById(R.id.mobile_icon);
    62. statusBarViewHolder.phoneBluetoothIcon = (StatusIconView)statusBarLayout.findViewById(R.id.bluetooth_icon);
    63. statusBarViewHolder.phoneWifiIcon = (StatusIconView)statusBarLayout.findViewById(R.id.wifi_icon);
    64. statusBarViewHolder.phoneBatteryIcon = (StatusIconView)statusBarLayout.findViewById(R.id.battery_icon);
    65. statusBarViewHolder.phoneUSBIcon.setIcon(R.drawable.usb);
    66. statusBarViewHolder.phoneSDCardIcon.setIcon(R.drawable.sd);
    67. statusBarViewHolder.phoneBluetoothIcon.setIcon(R.drawable.btconnected);
    68. statusBarViewHolder.phoneWifiIcon.setIcon(R.drawable.wifi0);
    69. }
    70. private void updateIcon(int Icon, StatusIconView icon){
    71. icon.setIcon(Icon);
    72. }
    73. private int getBatteryImage(int battery) {
    74. int resId;
    75. if(battery > 0 && battery <= 10){
    76. resId = R.drawable.battery0;
    77. }else if(battery > 10 && battery <= 40){
    78. resId = R.drawable.battery1;
    79. }else if(battery > 40 && battery <= 60){
    80. resId = R.drawable.battery2;
    81. }else if(battery > 60 && battery <= 80){
    82. resId = R.drawable.battery3;
    83. }else if(battery > 80 && battery <= 100){resId = R.drawable.battery4;
    84. }else{
    85. resId = R.drawable.battery0;
    86. }
    87. return resId;
    88. }/**
    89. * 注册状态栏更新信息的广播
    90. */
    91. private void registerReceiver() {
    92. registerReceiver(phoneBatteryReceiver , new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    93. }
    94. /**
    95. * 状态栏的所有图标
    96. */
    97. private class StatusBarViewHolder{
    98. TextView datetimeTextView;
    99. StatusIconView phoneUSBIcon;
    100. StatusIconView phoneSDCardIcon;
    101. StatusIconView phoneHotspotIcon;
    102. StatusIconView phoneMobileIcon;
    103. StatusIconView phoneBluetoothIcon;
    104. StatusIconView phoneWifiIcon;
    105. StatusIconView phoneBatteryIcon;
    106. }
    107. @Override
    108. public void onDestroy(){
    109. unregisterReceiver();
    110. wm.removeView(statusBarLayout);
    111. super.onDestroy();
    112. }
    113. private void unregisterReceiver(){
    114. unregisterReceiver(phoneBatteryReceiver);
    115. }
    116. public String GetSysTime() {
    117. long sysTime = System.currentTimeMillis();
    118. String time = "";
    119. boolean is24Hour = DateFormat.is24HourFormat(getApplicationContext());
    120. /** @brief Get the same time as the system. */
    121. if(is24Hour) {
    122. time = (String) DateFormat.format("yyyy-MM-dd HH:mm:ss", sysTime);
    123. }
    124. else{
    125. time = (String) DateFormat.format("yyyy-MM-dd hh:mm:ss", sysTime);
    126. }
    127. return time;
    128. }

    需要的xml文件status_bar

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. android:orientation="horizontal"
    4. android:layout_width="match_parent"
    5. android:layout_height="@dimen/status_bar_height">
    6. <TextView
    7. android:id="@+id/datetime_textView"
    8. android:layout_width="0dp"
    9. android:layout_weight="1"
    10. android:layout_height="@dimen/status_bar_date_height"
    11. android:textColor="@android:color/holo_red_dark"
    12. android:layout_gravity="center"/>
    13. <LinearLayout
    14. android:layout_width="0dp"
    15. android:layout_weight="1"
    16. android:gravity="right"
    17. android:layout_height="@dimen/status_bar_icon_width">
    18. <com.android.systemui.StatusIconView
    19. android:id="@+id/usb_icon"
    20. android:layout_width="wrap_content"
    21. android:layout_height="@dimen/status_bar_icon_height"
    22. android:layout_gravity="center"/>
    23. <com.android.systemui.StatusIconView
    24. android:id="@+id/sdcard_icon"
    25. android:layout_width="wrap_content"
    26. android:layout_height="wrap_content"
    27. android:layout_gravity="center"/>
    28. <com.android.systemui.StatusIconView
    29. android:id="@+id/hotspot_icon"
    30. android:layout_width="wrap_content"
    31. android:layout_height="wrap_content"
    32. android:layout_gravity="center"/>
    33. <com.android.systemui.StatusIconView
    34. android:id="@+id/mobile_icon"
    35. android:layout_width="wrap_content"
    36. android:layout_height="wrap_content"
    37. android:layout_gravity="center"/>
    38. <com.android.systemui.StatusIconView
    39. android:id="@+id/bluetooth_icon"
    40. android:layout_width="wrap_content"
    41. android:layout_height="wrap_content"
    42. android:layout_gravity="center"/>
    43. <com.android.systemui.StatusIconView
    44. android:id="@+id/wifi_icon"
    45. android:layout_width="wrap_content"
    46. android:layout_height="wrap_content"
    47. android:layout_gravity="center"/>
    48. <com.android.systemui.StatusIconView
    49. android:id="@+id/battery_icon"
    50. android:layout_width="wrap_content"
    51. android:layout_height="wrap_content"
    52. android:layout_gravity="center"/>
    53. </LinearLayout>
    54. <!--<TextView-->
    55. <!--android:id="@+id/ssidInfo"-->
    56. <!--android:layout_width="match_parent"-->
    57. <!--android:layout_height="400dp"-->
    58. <!--android:lines="10"-->
    59. <!--android:textColor="@android:color/holo_red_dark"/>-->
    60. </LinearLayout>

    注意:以上工程一定要替换系统的SystemUI源码,编译后烧写内核才可以