Android 系统充电动画

news2025/1/18 9:50:17
  • 效果
    在这里插入图片描述

Android获取电池充电状态是否为快充可参考.

Android_source/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

    private int lastBatteryStatus;
    private final BroadcastReceiver mBatteryChangedReceiver= new BroadcastReceiver(){
        @Override
        public void onReceive(Context context, Intent intent) {
            int status=intent.getIntExtra(BatteryManager.EXTRA_STATUS,BatteryManager.BATTERY_STATUS_UNKNOWN);
            BatteryManager batteryManager = context.getSystemService(BatteryManager.class);
            int level = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
            batteryStatus = com.android.settingslib.Utils.getBatteryStatus(context, intent);
            Log.d(TAG, "battery status="+status+" level="+level + "  batteryStatus = " + batteryStatus);
            if (status==BatteryManager.BATTERY_STATUS_CHARGING
                    && lastBatteryStatus!=status){
                  showWirelessChargingAnimation(level);
            }
            if (status==BatteryManager.BATTERY_STATUS_DISCHARGING
                    && lastBatteryStatus!=status){
                  hideWirelessChargingAnimation();
            }
            lastBatteryStatus=status;
        }
    };


    @Override
    public void showWirelessChargingAnimation(int batteryLevel) {
        if(!mKeyguardManager.isKeyguardLocked() && !isHome(mContext)){
            return;
        }
        if (mDozing || mKeyguardManager.isKeyguardLocked()) {
            // on ambient or lockscreen, hide notification panel
           wirelessChargingAnimation =  WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
                    batteryLevel, new WirelessChargingAnimation.Callback() {
                        @Override
                        public void onAnimationStarting() {
                            CrossFadeHelper.fadeOut(mNotificationPanelViewController.getView(), 1);
                        }

                        @Override
                        public void onAnimationEnded() {
                            CrossFadeHelper.fadeIn(mNotificationPanelViewController.getView());
                        }
                    }, mDozing, batteryStatus);
            wirelessChargingAnimation.show();
        } else {
            // workspace
            wirelessChargingAnimation =  WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
                    batteryLevel, null, false, batteryStatus);
            wirelessChargingAnimation.show();
        }
    }


    public void hideWirelessChargingAnimation(){
        try{
            if(wirelessChargingAnimation != null  && wirelessChargingAnimation.isShown()){
                wirelessChargingAnimation.hide();
            }
        }catch(RuntimeException e){
           
        }

    }

Android_source/frameworks/base/packages/SystemUI/src/com/android/systemui/charing/WirelessChargingAnimation.java

/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.charing;


import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.provider.Settings;
import android.os.Build;
import android.content.pm.ActivityInfo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.chargeanim.R;

/**
 * A WirelessChargingAnimation is a view containing view + animation for wireless charging.
 * @hide
 */
public class WirelessChargingAnimation {

    public static final long DURATION = 15133;
    private static final String TAG = "WirelessChargingView";

    private final WirelessChargingView mCurrentWirelessChargingView;
    private static WirelessChargingView mPreviousWirelessChargingView;

    public interface Callback {
        void onAnimationStarting();
        void onAnimationEnded();
    }


    /**
     * Constructs an empty WirelessChargingAnimation object.  If looper is null,
     * Looper.myLooper() is used.  Must set
     * {@link WirelessChargingAnimation#mCurrentWirelessChargingView}
     * before calling {@link #show} - can be done through {@link #makeWirelessChargingAnimation}.
     * @hide
     */
    public WirelessChargingAnimation(@NonNull Context context, @Nullable Looper looper, int
            batteryLevel, Callback callback, boolean isDozing, String batteryStatus) {
        mCurrentWirelessChargingView = new WirelessChargingView(context, looper,
                batteryLevel, callback, isDozing, batteryStatus);
    }

    /**
     * Creates a wireless charging animation object populated with next view.
     * @hide
     */
    public static WirelessChargingAnimation makeWirelessChargingAnimation(@NonNull Context context,
            @Nullable Looper looper, int batteryLevel, Callback callback, boolean isDozing, String batteryStatus) {
        return new WirelessChargingAnimation(context, looper, batteryLevel, callback, isDozing, batteryStatus);
    }

    /**
     * Show the view for the specified duration.
     */
    public void show() {
        if (mCurrentWirelessChargingView == null ||
                mCurrentWirelessChargingView.mNextView == null) {
            throw new RuntimeException("setView must have been called");
        }

        if (mPreviousWirelessChargingView != null) {
            mPreviousWirelessChargingView.hide(0);
        }

        mPreviousWirelessChargingView = mCurrentWirelessChargingView;
        mCurrentWirelessChargingView.show();
//        mCurrentWirelessChargingView.hide(DURATION);
    }


    public void hide(){
        if (mCurrentWirelessChargingView == null ||
                mCurrentWirelessChargingView.mNextView == null) {
            throw new RuntimeException("setView must have been called");
        }

        if (mPreviousWirelessChargingView != null) {
            mPreviousWirelessChargingView.hide(0);
        }
    }

    private static class WirelessChargingView {
        private static final int SHOW = 0;
        private static final int HIDE = 1;

        private final WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
        private final Handler mHandler;

        private int mGravity;
        private View mView;
        private View mNextView;
        private WindowManager mWM;
        private Callback mCallback;
        private Context mContext;

        public WirelessChargingView(Context context, @Nullable Looper looper, int batteryLevel,
                Callback callback, boolean isDozing, String batteryStatus) {
            mContext = context;
            mCallback = callback;
            mNextView = LayoutInflater.from(context).inflate(R.layout.activity_main , null, false);
            BubbleView syberBubbleView = mNextView.findViewById(R.id.syber_bubble_view);
            syberBubbleView.setBatteryLevel(batteryLevel);
//            syberBubbleView.setBatteryStatus(batteryStatus);
            syberBubbleView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    Log.d(TAG, "onTouch: " + motionEvent.getAction());
                    return true;
                }
            });
            mGravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER;

            final WindowManager.LayoutParams params = mParams;
            params.height = WindowManager.LayoutParams.MATCH_PARENT;
            params.width = WindowManager.LayoutParams.MATCH_PARENT;
            params.format = PixelFormat.TRANSLUCENT;
            params.type = WindowManager.LayoutParams.TYPE_WALLPAPER ;

            params.setTitle("Charging Animation");

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                params.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
                params.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
            }
            params.dimAmount = .3f;

            if (looper == null) {
                // Use Looper.myLooper() if looper is not specified.
                looper = Looper.myLooper();
                if (looper == null) {
                    throw new RuntimeException(
                            "Can't display wireless animation on a thread that has not called "
                                    + "Looper.prepare()");
                }
            }

            mHandler = new Handler(looper, null) {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case SHOW: {
                            handleShow();
                            break;
                        }
                        case HIDE: {
                            handleHide();
                            // Don't do this in handleHide() because it is also invoked by
                            // handleShow()
                            mNextView = null;
                            break;
                        }
                    }
                }
            };
        }

        public void show() {
           Log.d(TAG, "SHOW: " + this);
            mHandler.obtainMessage(SHOW).sendToTarget();
        }

        public void hide(long duration) {
            mHandler.removeMessages(HIDE);

           Log.d(TAG, "HIDE: " + this);
            mHandler.sendMessageDelayed(Message.obtain(mHandler, HIDE), duration);
        }

        private void handleShow() {
//            Settings.System.putInt(mContext.getContentResolver(), "show_battery_ui", 1);
           {
                Log.d(TAG, "HANDLE SHOW: " + this + " mView=" + mView + " mNextView="
                        + mNextView);
            }

            if (mView != mNextView) {
                // remove the old view if necessary
                handleHide();
                mView = mNextView;
                Context context = mView.getContext().getApplicationContext();
                String packageName = mView.getContext().getOpPackageName();
                if (context == null) {
                    context = mView.getContext();
                }
                mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
                mParams.packageName = packageName;
//                mParams.hideTimeoutMilliseconds = DURATION;

                if (mView.getParent() != null) {
                   Log.d(TAG, "REMOVE! " + mView + " in " + this);
                    mWM.removeView(mView);
                }
               Log.d(TAG, "ADD! " + mView + " in " + this);

                try {
                    if (mCallback != null) {
                        mCallback.onAnimationStarting();
                    }
                    int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                            | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                            | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
                            | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                            | WindowManager.LayoutParams.FLAG_FULLSCREEN;
                    mParams.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
                    mView.setSystemUiVisibility(visibility);
                    mView.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Log.d("sgq", "onTouch:    handleHide();" );
                           handleHide();
                        }
                      });
                    mWM.addView(mView, mParams);
                } catch (WindowManager.BadTokenException e) {
                    Log.d(TAG, "Unable to add wireless charging view. " + e);
                }
            }
        }

        private void handleHide() {
            if (mView != null) {
                if (mView.getParent() != null) {
                    if (mCallback != null) {
                        mCallback.onAnimationEnded();
                    }
                    mWM.removeViewImmediate(mView);
                }

                mView = null;
            }
        }
    }
}

资源文件可参考充电动画Demo.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1622714.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ComfyUI学习旅程

一、模型文件(Checkpoint) 首先它很大,这些文件是你从huggingface或者civitai下载而来的, 所以这些大文件如 .ckpt 或 .safetensors ,实际上包含了什么内容呢? 它包含了包含了三种不同模型的权重&#x…

【STM32F4】STM32CUMX相关环境配置

一、环境配置 我们需要以下两个软件 (一)keil5 最正统,最经典的嵌入式MCU开发环境。 该环境的配置可以看看之前的文章 所需文件如下: 当时配置的是STC8H的环境,现在基于此,重新给STM32配置环境。能让STC…

docker的默认路径存储不足

docker的默认路径存储不足 添加磁盘 [rootlocalhost ~]# fdisk -l磁盘 /dev/sda:42.9 GB, 42949672960 字节,83886080 个扇区 Units 扇区 of 1 * 512 512 bytes 扇区大小(逻辑/物理):512 字节 / 512 字节 I/O 大小(最小/最佳)&#xff1a…

【网络安全】网络安全协议和防火墙

目录 1、网络层的安全协议:IPsec 协议族 (1)IP 安全数据报格式 (2)互联网密钥交换 IKE (Internet Key Exchange) 协议 2、运输层的安全协议:TLS 协议 3、系统安全:防火墙与入侵检测 1、网络…

CJSON工具类

4.4.3.CJSON工具类 OpenResty提供了一个cjson的模块用来处理JSON的序列化和反序列化。 官方地址: https://github.com/openresty/lua-cjson/ 1)引入cjson模块: local cjson require "cjson"2)序列化: …

pwn--realloc [CISCN 2019东南]PWN5

首先学习一下realloc这个函数,以下是文心一言的解释: realloc是C语言库函数之一,用于重新分配内存空间。它的主要功能是调整一块内存空间的大小。当需要增加内存空间时,realloc会分配一个新的更大的内存块,然后将原内…

19 使用MapReduce编程统计超市1月商品被购买的次数

首先将1月份的订单数据上传到HDFS上&#xff0c;订单数据格式 ID Goods两个数据字段构成 将订单数据保存在order.txt中&#xff0c;&#xff08;上传前记得启动集群&#xff09;。 打开Idea创建项目 修改pom.xml&#xff0c;添加依赖 <dependencies><dependency>…

多客圈子交友系统 uniapp+thinkphp6适配小程序/H5/app/api全开源,多款插件自选,支持个性定制!

网上交友的优点包括&#xff1a; 1. 方便&#xff1a;网上交友可以随时随地进行&#xff0c;不受时间和空间的限制&#xff0c;方便且高效。 2. 匿名性&#xff1a;网上交友可以实现匿名性&#xff0c;用户可以匿名地搜索、聊天或交换信息&#xff0c;保护个人隐私和安全。 3.…

Linux——进程基本概念中篇

Linux——进程基本概念中篇 文章目录 Linux——进程基本概念中篇一、通过系统调用创建进程——fork1.1 fork的理解1.2 fork的返回值 二、进程状态2.1 运行状态2.2 睡眠状态和休眠状态2.3 停止状态和死亡状态2.4 僵尸进程2.5 孤儿进程2.6 前台和后台进程 三、进程优先级3.1 查看…

redis中的集群模式

主从复制、主从同步(解决高并发读的问题) 主从同步原理&#xff1a; 1.全量同步 slave&#xff08;从节点&#xff09;每次请求数据同步会带两个参数&#xff1a;replid和offset。 replid&#xff1a;第一次请求同步时&#xff0c;replid和master的replid不一样&#xff0c;这…

使用FPGA实现逐级进位加法器

介绍 逐级进位加法器就是将上一位的输出作为下一位的进位输入&#xff0c;依次这样相加。下面以一个8位逐级进位加法器给大家展示。 我增加了电路结构&#xff0c;应该很容易理解吧。 下面我也列举了一位加法器&#xff0c;可以看下。 电路结构 设计文件 1位加法器 librar…

Python-VBA函数之旅-iter函数

目录 一、iter函数的常见应用场景&#xff1a; 二、iter函数使用注意事项&#xff1a; 三、如何用好iter函数&#xff1f; 1、iter函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;神奇夜光杯-CSDN博客 …

《深入Linux设备驱动程序内核机制》学习笔记-第4章

前言 本文是《深入Linux设备驱动程序内核机制》的读书笔记&#xff0c;本文因为是读书笔记所以抄写引用了该书中的大量内容&#xff0c;写读书笔记的目的是在写作的过程中加深对书中内容的理解。 建议读者直接阅读《深入Linux设备驱动程序内核机制》&#xff0c;这本书是Linu…

word导出或另存为pdf图片不清晰问题解决方案

问题描述&#xff1a; 使用word 2019导出pdf时图片不清晰&#xff0c;即使我已经在“选项 → \to →高级 → \to →图片大小和质量 → \to →不压缩文件中的图像 ”选项卡中关闭掉了图片压缩依然无效。 解决方案&#xff1a; 利用word foxit pdf 软件打印的方案转pdf。 &…

SpringBoot3 + Kotlin + mybatis-plus + Swagger3后端开发样例

前言&#xff1a; Kotlin 是一种在 JVM&#xff08;Java 虚拟机&#xff09;、Android 和浏览器端运行的静态类型编程语言。以下是关于 Kotlin 的总结介绍&#xff1a; 1、语言特性&#xff1a; 简洁性&#xff1a;Kotlin 旨在提供简洁且安全的代码&#xff0c;同时保持与 Jav…

学校开展第二届教学名师沙龙

四川城市职业学院讯 4月23日下午&#xff0c;党委教师工作部&#xff08;质量部&#xff09;、教师发展中心组织开展了以“大力弘扬教育家精神&#xff0c;建设高质量高水平教师队伍”为主题的第二届教学名师经验分享沙龙活动。全校12名入选学校教学名师&#xff08;名辅导员…

vue3+Echarts+Nodejs实现动态数据可视化

最近在做毕设的后台管理系统&#xff0c;刚好需要做数据动态可视化的功能&#xff0c;就来记录一下具体的实现方式吧&#xff01; 在开始之前就不阐述用vue创建项目的具体步骤了&#xff0c;主要详细讲解一下vue3、echarts和nodejs三者之间是如何实现数据的动态显示的&#xf…

kafka大数据采集技术实验(未完待续)

Kafka环境搭建 下载地址&#xff1a;https://link.zhihu.com/?targethttps%3A//kafka.apache.org/downloads解压启动zookeeper bin/zookeeper-server-start.sh config/zookeeper.properties需要注意的是 : " c o n f i g / z o o k e e p e r . p r o p e r t i e s &q…

探秘三维地形瓦片服务:流畅展现全球地貌的秘密揭秘

想象一下&#xff0c;如果我们能将全球地形一次性清晰地呈现在我们的电脑屏幕上&#xff0c;那将是怎样的场景&#xff1f;即使拥有比大多数人性能更强悍的电脑&#xff0c;也会忍不住说一句&#xff1a;“卧槽&#xff0c;卡死了”&#xff01;那么&#xff0c;要在电脑中流畅…

linux驱动-CCF-0基础

1. 时钟设备 晶振&#xff1a;提供基础时钟源的&#xff08;可分为有源晶振、无源晶振两种&#xff09;&#xff1b; PLL: 用于倍频的锁相环&#xff1b; mux: 用于多路时钟源选择&#xff1b; Divider: 用于分频的&#xff1b; gate: 用于时钟使能的与门电路等 注册函数…