近日做了一个需求,要求设备录音中的时候,状态栏显示一个动态图标,提醒用户处于录音中状态,录音结束则动态图标停止显示。
软件版本:android8.1
硬件平台:展讯
最开始UI提供了一个三个图层的icon,结果设置进去发现背景图层一直存在,相当丑陋,后来了解到状态栏图标都是一些矢量xml文件,需要svg矢量图转为xml格式(Android studio就可以转,具体可百度),于是将svg格式转化成了矢量xml,结果发现设置进去,依然有背景图层,后来修改了xml中一个参数,关于透明度的,android:fillAlpha 这个值改为0,图标就透明了。
素材OK了,下边直接粘贴代码改动:
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index fbd24643a..5baf20615 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -53,6 +53,7 @@ <item><xliff:g id="id">@string/status_bar_data_connection</xliff:g></item> <item><xliff:g id="id">@string/status_bar_phone_evdo_signal</xliff:g></item> <item><xliff:g id="id">@string/status_bar_phone_signal</xliff:g></item>+ <item><xliff:g id="id">@string/status_bar_record</xliff:g></item> <item><xliff:g id="id">@string/status_bar_battery</xliff:g></item> <item><xliff:g id="id">@string/status_bar_alarm_clock</xliff:g></item> <item><xliff:g id="id">@string/status_bar_secure</xliff:g></item> @@ -61,6 +62,7 @@ <string translatable="false" name="status_bar_rotate">rotate</string> <string translatable="false" name="status_bar_headset">headset</string>+ <string translatable="false" name="status_bar_record">record</string> <string translatable="false" name="status_bar_data_saver">data_saver</string> <string translatable="false" name="status_bar_managed_profile">managed_profile</string> <string translatable="false" name="status_bar_ime">ime</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f9f48adbe..861263dfb 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2583,6 +2583,7 @@ <java-symbol type="string" name="status_bar_rotate" />
<java-symbol type="string" name="status_bar_headset" />+ <java-symbol type="string" name="status_bar_record" /> <java-symbol type="string" name="status_bar_data_saver" /> <java-symbol type="string" name="status_bar_managed_profile" /> <java-symbol type="string" name="status_bar_ime" /> diff --git a/packages/SystemUI/res/drawable-hdpi/record_icon.xml b/packages/SystemUI/res/drawable-hdpi/record_icon.xml new file mode 100755 index 000000000..213223782 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/record_icon.xml @@ -0,0 +1,4 @@+<vector android:height="24dp" android:viewportHeight="20" + android:viewportWidth="20" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="#FF000000" android:pathData="M10.3,12.5c1.9,0 3.4,-1.5 3.4,-3.3V6.3c0,-1.9 -1.5,-3.3 -3.4,-3.3S6.9,4.5 6.9,6.3v2.8C6.9,11 8.4,12.5 10.3,12.5zM15.6,8.4c0,-0.3 -0.3,-0.6 -0.7,-0.6s-0.6,0.3 -0.6,0.6c0,0.1 0,0.1 0,0.2v0.5c0,2.2 -1.8,4 -4.1,4c-2.2,0 -4.1,-1.8 -4.1,-4V8.5c0,0 0,-0.1 0,-0.1c0,-0.3 -0.3,-0.6 -0.6,-0.6C5.3,7.8 5,8.1 5,8.4v0.9c0,2.7 2,4.8 4.6,5.2v1.2H7.8c-0.4,0 -0.7,0.3 -0.7,0.7c0,0.4 0.3,0.6 0.7,0.6h4.8c0.4,0 0.6,-0.3 0.6,-0.6c0,-0.3 -0.3,-0.7 -0.6,-0.7h-1.8v-1.2c2.7,-0.3 4.7,-2.5 4.7,-5.2V8.4z"/> +</vector>
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -44,6 +44,7 @@ import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager;+import android.os.Message; import android.provider.Settings; import android.provider.Settings.Global; import android.service.notification.StatusBarNotification; @@ -112,6 +113,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, private final String mSlotManagedProfile; private final String mSlotRotate; private final String mSlotHeadset;+ private final String mSlotRecord; private final String mSlotDataSaver; private final String mSlotLocation; @@ -153,6 +155,13 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, private BluetoothController mBluetooth; + private static final int MSG_RECORDING = 400; + private static final int MSG_RECORD_HIDE = 600; + private static final int MSG_STOP_RECORDING = 800; + private static boolean recordState = false; + private static boolean recordingNow = false;
+ private final static String IFLYTEK_RECORD_STATE = "IFLYTEK_RECORD_STATE"; + public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController) { mContext = context; mIconController = iconController; @@ -181,6 +190,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, com.android.internal.R.string.status_bar_managed_profile); mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate); mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);+ mSlotRecord = context.getString(com.android.internal.R.string.status_bar_record); mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver); mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location); @@ -194,6 +204,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);+ filter.addAction(IFLYTEK_RECORD_STATE); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); // listen for user / profile change. @@ -272,6 +283,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, } public void destroy() {+ removeRecordMsg(); mRotationLockController.removeCallback(this); mBluetooth.removeCallback(this);
mProvisionedController.removeCallback(this); @@ -735,6 +747,55 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, } } + private Handler mRecordHandler = new Handler() { + public void handleMessage(android.os.Message msg) { + switch (msg.what) { + case MSG_RECORDING: + mIconController.setIcon(mSlotRecord, R.drawable.record_icon, null); + mIconController.setIconVisibility(mSlotRecord, true); + Message msgDisplay = Message.obtain(); + msgDisplay.what = MSG_RECORD_HIDE; + mRecordHandler.sendMessageDelayed(msgDisplay, 800); + break; + case MSG_RECORD_HIDE: + mIconController.setIconVisibility(mSlotRecord, false); + Message msgHide = Message.obtain(); + msgHide.what = MSG_RECORDING; + mRecordHandler.sendMessageDelayed(msgHide, 800); + break;+ case MSG_STOP_RECORDING: + mRecordHandler.removeMessages(MSG_RECORDING); + mRecordHandler.removeMessages(MSG_RECORD_HIDE); + break; + } + }; + };
+ + private void removeRecordMsg() { + mRecordHandler.removeMessages(MSG_RECORDING); + mRecordHandler.removeMessages(MSG_RECORD_HIDE); + } + + private void updateIflytekRecordState(Intent intent) { + recordState = intent.getIntExtra("state", 0) != 0; + if (recordState) { + if (!recordingNow) {+ recordingNow = true; + mIconController.setIcon(mSlotRecord, R.drawable.record_icon, null); + mIconController.setIconVisibility(mSlotRecord, true); + Message msgStart = Message.obtain(); + msgStart.what = MSG_RECORDING; + mRecordHandler.sendMessage(msgStart); + } + } else { + recordingNow = false; + mIconController.setIconVisibility(mSlotRecord, false); + Message msgStop = Message.obtain(); + msgStop.what = MSG_STOP_RECORDING; + mRecordHandler.sendMessage(msgStop); + } + } + private void updateHeadsetPlug(Intent intent) { boolean connected = intent.getIntExtra("state", 0) != 0;
boolean hasMic = intent.getIntExtra("microphone", 0) != 0; @@ -782,6 +843,8 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks, updateManagedProfile(); } else if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) { updateHeadsetPlug(intent);+ } else if (action.equals(IFLYTEK_RECORD_STATE)) { + updateIflytekRecordState(intent); } } };
大概的实现逻辑做个说明,进入录音中后,相关app会发送自定义广播,附带录音状态字段,收到广播后,调整图标的显示和隐藏,其中闪烁的效果是用了延迟的msg,用handler实现的。
自己可以通过adb命令模拟广播事件,进行简单测试。
比如发送模拟录音开始的广播 adb shell am broadcast -a IFLYTEK_RECORD_STATE --ei state 1
停止录音广播 adb shell am broadcast -a IFLYTEK_RECORD_STATE --ei state 0
欢迎留言讨论~~~~如果有更简便的闪烁图标方法的话!