手机锁屏时充电动画
需求:插入手机充电线后,手机锁屏状态时,亮屏并显示充电动画效果
设计思想:
SystemUI监听充电线的插入和拔出
插入充电线时,启动一个Service,加载充电动画,动画布局中的电量使用TextView显示,动画使用lottie播放
关键步骤与技术点
充电连接与断开广播
Intent.ACTION_POWER_CONNECTED:充电连接广播
Intent.ACTION_POWER_DISCONNECTED:充电断开广播
是否是锁屏状态:
KeyguardManager mKeyguardManager =
(KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
boolean lockState = mKeyguardManager.inKeyguardRestrictedInputMode();
if (lockState ) {
//锁屏
} else {
//未锁屏
}
充电动画时json文件,不是帧动画的图片,所以采用lottie开源库播放动画
Android Studio导入lottie库的方式网上有很多,但是源码的方式没有。
本次使用的lottie版本是2.7.0,再往上的版本就要使用androidx的库了。
本文描述SystemUI导入lottie方法
SystemUI导入lottie方法
下载lottie-2.7.0.aar
使用Android Studio的方式导入lottie库,把lottie-2.7.0.aar下载到本地,放入项目的libs目录下
Android.mk修改
#预编译lottie库
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := lottie-2.7.0:libs/lottie-2.7.0.aar
#其它库的的预编译
include $(BUILD_MULTI_PREBUILT)
#导入lottie库
LOCAL_STATIC_JAVA_AAR_LIBRARIES := lottie-2.7.0
#合并打包库的资源文件时需要,并且记住是一个包名对应一个–extra-packges
LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages com.airbnb.lottie
–extra-packages xxxxxxxxx #其它需要aapt的库的包名
#把aar中的资源文件解压出来放入res-lottie目录进行资源编译,否则编译时会提示找不到资源,运行时会报错
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res-lottie
在AndroidManifest中增加如下的代码,否则会报aar中的manifest与主manifest中的minSdk不一样的错误。没有的话,有的环境能够编译通过,有的编译不通过
充电动画布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/float_id"
style="@android:style/Theme.Holo.Light.NoActionBar.Fullscreen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0000">
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottie_likeanim"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
<ImageView
android:id="@+id/charge_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginStart="854px"
android:layout_marginBottom="659px"
android:src="@drawable/icon_notify_battery_charging"
tools:background="#000" />
<TextView
android:id="@+id/percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginStart="13px"
android:layout_marginBottom="621px"
android:layout_toEndOf="@id/charge_mode"
android:fontFamily="sans-serif"
android:textColor="#FFF"
android:textSize="100px" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginStart="8px"
android:layout_marginBottom="621px"
android:layout_toEndOf="@+id/percent"
android:fontFamily="sans-serif"
android:text="%"
android:textColor="#FFF"
android:textSize="70px" />
</RelativeLayout>
上述xml布局是主体布局,通过WindowManger添加的窗口显示。再Window上加载xml的关键代码如下
wmParams = new LayoutParams();
mWindowManager = (WindowManager) getApplication().getSystemService(WINDOW_SERVICE);
wmParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
wmParams.type = LayoutParams.TYPE_NAVIGATION_BAR_PANEL; //显示在锁屏之上,并且能够接收事件
wmParams.format = PixelFormat.RGBA_8888;
wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_SHOW_WHEN_LOCKED |
LayoutParams.FLAG_LAYOUT_NO_LIMITS | LayoutParams.FLAG_FULLSCREEN;
wmParams.gravity = Gravity.START | Gravity.TOP;
int statusBarHeight = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
wmParams.x = 0;
wmParams.y = -statusBarHeight;
wmParams.width = 1080;
wmParams.height = 1920;
mRootView = LayoutInflater.from(getApplicationContext()).inflate(R.layout.anim, null, false);
mWindowManager.addView(mRootView, wmParams);
使用lottie播放json动画
通过LottieAnimationView控件播放json动画,关键代码如下
lavChargingAnimView = mRootView.findViewById(R.id.lottie_likeanim);
if (lavChargingAnimView != null) {
animData = "animdata_high.json"
lavChargingAnimView.setAnimation(animData);
lavChargingAnimView.loop(true);
lavChargingAnimView.playAnimation();
}