目录
📂 前言
AR 眼镜系统版本
充电动画
1. 🔱 技术方案
1.1 方案介绍
1.2 实现方案
关机充电动画
亮屏/锁屏充电动画
2. 💠 关机充电动画
2.1 关机充电动画核心处理类与路径
2.2 实现细节
步骤一:1)定制 ui.c 文件,适配分辨率
步骤一:2)定制 ui.c 文件,定制动画 UI
步骤二:新增定制的动画 UI 相关png图片
3. ⚛️ 亮屏/锁屏充电动画
3.1 亮屏/锁屏充电动画时序图
3.2 实现细节
步骤一:注册广播 Action 监听充电接通/断开/充满电等状态
步骤二:开发充电接通/断开/充满电的系统弹窗,显示对应动画
4. ✅ 小结
📂 前言
AR 眼镜系统版本
W517 Android9。
充电动画
Android 充电动画分为:关机充电动画 与 亮屏/锁屏充电动画,而且据了解 Android 原生系统只提供了关机充电动画,并未提供亮屏/锁屏充电动画,所以对于关机情况下需要定制,亮屏/锁屏情况下需要增加。
1. 🔱 技术方案
1.1 方案介绍
技术方案概述:对于关机充电动画,是通过 minui 开发的,主要定制 ui.c 文件以及 /images/*.png 图片;对于亮屏/锁屏充电动画,主要通过监听系统充电连接、断开和充满电的广播去实现。
1.2 实现方案
关机充电动画
-
定制 ui.c 文件,适配分辨率,定制动画 UI;
-
新增定制的动画 UI 相关png图片。
亮屏/锁屏充电动画
-
注册 ACTION_POWER_CONNECTED、ACTION_POWER_DISCONNECTED、ACTION_BATTERY_OKAY 等广播 Action 监听充电接通/断开/充满电等状态;
-
开发充电接通/断开/充满电的系统弹窗,显示对应动画。
2. 💠 关机充电动画
2.1 关机充电动画核心处理类与路径
-
关机充电动画 UI 处理类:w517\vendor\sprd\proprietories-source\charge\ui.c
-
关机充电动画图片存放路径:w517\vendor\sprd\proprietories-source\charge\images\
-
AR 眼镜上的充电动画图片存放路径:/vendor/etc/res/images/
2.2 实现细节
步骤一:1)定制 ui.c 文件,适配分辨率
步骤一:2)定制 ui.c 文件,定制动画 UI
步骤二:新增定制的动画 UI 相关png图片
3. ⚛️ 亮屏/锁屏充电动画
3.1 亮屏/锁屏充电动画时序图
3.2 实现细节
步骤一:注册广播 Action 监听充电接通/断开/充满电等状态
class BatteryListener(context: Context) {
private val TAG = BatteryListener::class.java.simpleName
private val mContext: Context
private val mReceiver: BatteryBroadcastReceiver
private val mBatteryChargeWindow: BatteryChargeWindow
init {
mContext = context
mReceiver = BatteryBroadcastReceiver()
mBatteryChargeWindow = BatteryChargeWindow()
}
fun register() {
Log.e(TAG, "register: ")
val filter = IntentFilter()
// filter.addAction(Intent.ACTION_BATTERY_CHANGED) // 电量发生改变
filter.addAction(Intent.ACTION_BATTERY_LOW) // 电量低
filter.addAction(Intent.ACTION_BATTERY_OKAY) // 电量充满
filter.addAction(Intent.ACTION_POWER_CONNECTED) // 接通电源
filter.addAction(Intent.ACTION_POWER_DISCONNECTED) // 拔出电源
mContext.registerReceiver(mReceiver, filter)
mBatteryChargeWindow.init(mContext)
}
fun unregister() {
Log.e(TAG, "unregister: ")
mContext.unregisterReceiver(mReceiver)
}
private inner class BatteryBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.e(TAG, "onReceive: ${intent.action}")
when (intent.action) {
// Intent.ACTION_BATTERY_CHANGED -> {
//
// }
Intent.ACTION_BATTERY_LOW -> {
}
Intent.ACTION_BATTERY_OKAY -> {
mBatteryChargeWindow.finishCharge()
}
Intent.ACTION_POWER_CONNECTED -> {
SoundPoolTools.play(
context, SoundPoolTools.MUSIC, R.raw.notification_power_connected
)
mBatteryChargeWindow.startCharge()
}
Intent.ACTION_POWER_DISCONNECTED -> {
}
}
}
}
}
步骤二:开发充电接通/断开/充满电的系统弹窗,显示对应动画
class BatteryChargeWindow {
private lateinit var mContext: Context
private lateinit var mWindowManager: WindowManager
private lateinit var mBatteryChargeView: View
private lateinit var mChargingAnimation: LottieAnimationView
private lateinit var mFinishedChargingAnimation: LottieAnimationView
private lateinit var mBattery: AGGTextView
private var mLayoutParams: WindowManager.LayoutParams? = null
private var mIsBarWindowAdded = false
private val mUiHandler = Handler(Looper.getMainLooper())
fun init(context: Context) {
mContext = context.applicationContext
mWindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
initLayoutParams()
initView()
}
fun startCharge() {
initLayoutParams()
addBarWindow()
mChargingAnimation.visibility = View.VISIBLE
mChargingAnimation.playAnimation()
mBattery.text = getBatteryLevel()
mUiHandler.postDelayed({
mChargingAnimation.cancelAnimation()
mChargingAnimation.visibility = View.GONE
removeBarWindow()
}, BATTERY_CHARGE_TIME_OUT)
}
@SuppressLint("SetTextI18n")
fun finishCharge() {
initLayoutParams()
addBarWindow()
mFinishedChargingAnimation.visibility = View.VISIBLE
mFinishedChargingAnimation.playAnimation()
mBattery.text = "100%"
mUiHandler.postDelayed({
mFinishedChargingAnimation.cancelAnimation()
mFinishedChargingAnimation.visibility = View.GONE
removeBarWindow()
}, BATTERY_CHARGE_TIME_OUT)
}
private fun initLayoutParams() {
mLayoutParams = WindowManager.LayoutParams().apply {
type = WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL
val density = mContext.resources.displayMetrics.density
width = (640 * density).toInt()
height = (640 * density).toInt()
flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
format = PixelFormat.RGBA_8888 // 去除默认时有的黑色背景,设置为全透明
gravity = Gravity.CENTER
title = Constants.AGG_SYSUI_BATTERY_CHARGE
x = 0
y = 0
dofIndex = 1 // 默认为1。 为0,则表示窗口为0DOF模式;为1,则表示窗口为3DOF模式;为2,则表示窗口为6DOF模式。
setTranslationZ(Constants.TRANSLATION_Z_150CM)
setRotationXAroundOrigin(-XrEnvironment.getInstance().headPose.roll)
setRotationYAroundOrigin(-XrEnvironment.getInstance().headPose.yaw)
setRotationZAroundOrigin(-XrEnvironment.getInstance().headPose.pitch)
}
}
private fun initView() {
mBatteryChargeView =
LayoutInflater.from(mContext).inflate(R.layout.battery_charge_layout, null, false)
mChargingAnimation = mBatteryChargeView.findViewById(R.id.charging)
mFinishedChargingAnimation = mBatteryChargeView.findViewById(R.id.finishedCharging)
mBattery = mBatteryChargeView.findViewById(R.id.battery)
}
private fun addBarWindow() {
mUiHandler.post {
synchronized(this) {
if (!mIsBarWindowAdded) {
try {
mWindowManager.addView(mBatteryChargeView, mLayoutParams)
} catch (e: Exception) {
e.printStackTrace()
}
mIsBarWindowAdded = true
}
}
}
}
private fun removeBarWindow() {
mUiHandler.post {
synchronized(this) {
if (mIsBarWindowAdded) {
try {
mWindowManager.removeViewImmediate(mBatteryChargeView)
} catch (e: Exception) {
e.printStackTrace()
}
mIsBarWindowAdded = false
}
}
}
}
/**
* 获取剩余电池容量占总容量的整数百分比
*/
private fun getBatteryLevel(): String {
val batteryManager = mContext.getSystemService(BATTERY_SERVICE) as BatteryManager
return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
.toString() + "%"
}
}
4. ✅ 小结
对于充电动画定制,本文只是一个基础实现方案,更多业务细节请参考产品逻辑去实现。
另外,由于本人能力有限,如有错误,敬请批评指正,谢谢。