近日做了一个需求,要求设备录音中的时候,状态栏显示一个动态图标,提醒用户处于录音中状态,录音结束则动态图标停止显示。
软件版本: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 @@
+
@@ -61,6 +62,7 @@
+
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 @@
+
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 @@
+
+
+
--- 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
欢迎留言讨论~~~~如果有更简便的闪烁图标方法的话!