Android 系统充电动画

发布于:2024-04-29 ⋅ 阅读:(29) ⋅ 点赞:(0)
  • 效果
    在这里插入图片描述

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.