AndroidQ(10.0) 手机锁屏炫酷充电动画————html方案

简介: AndroidQ(10.0) 手机锁屏炫酷充电动画————html方案

效果图


0YDu9g.gif

知识储备


1、WebView加载html,并通过JS传值


在网上随便搜索找到了这个炫酷的充电动画,可惜是css实现的,想在Android中使用那只能

通过 WebView 来加载了,要传递当前系统电量需要在Java和JS中传值,具体可参考下面的文章

Android如何使用HTML做界面——WebView控件

Android:你要的WebView与 JS 交互方式 都在这里了


2、SystemUI 中使用 WebView 控件排错


开始在普通工程中使用WebView是没有问题的,但移植到SystemUI中运行的时候出现错误


AndroidRuntime: Caused by: java.lang.UnsupportedOperationException: For security reasons, WebView is not


allowed in privileged processes


解决办法,添加 hookWebView() 方法 解决 WebView 报错 Binary XML file line #7 Error inflating class android.webkit.WebView


具体实现


1、将html文件拷贝至assets文件夹


lottie和html充电动画相关资源.zip


2、新建 layout_charge.xml 布局文件

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/transparent">
    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </WebView>
    <FrameLayout
        android:id="@+id/clickView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</FrameLayout>

3、新建 ChargeActivity.java 文件

package com.android.systemui.power;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import com.android.systemui.R;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ChargeActivity extends Activity {
    private WebView mWebView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        hookWebView();
        setContentView(R.layout.layout_charge);
        mWebView = (WebView) findViewById(R.id.webView);
        FrameLayout mClickView = (FrameLayout) findViewById(R.id.clickView);
        mWebView.setVisibility(View.INVISIBLE);
        WebSettings webSettings = mWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        webSettings.setDomStorageEnabled(true);
        mWebView.loadUrl("file:///android_asset/charging.html");
        mWebView.setWebViewClient(new WebViewClient(){
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                mWebView.setVisibility(View.VISIBLE);
                mHandler.sendEmptyMessage(MSG_BATTERY);
            }
        });
        mClickView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                closeAnim();
            }
        });
        registerReceiver();
    }
    public static void hookWebView(){
        int sdkInt = Build.VERSION.SDK_INT;
        try {
            Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
            Field field = factoryClass.getDeclaredField("sProviderInstance");
            field.setAccessible(true);
            Object sProviderInstance = field.get(null);
            if (sProviderInstance != null) {
                Log.i("hook","sProviderInstance isn't null");
                return;
            }
            Method getProviderClassMethod;
            if (sdkInt > 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
            } else if (sdkInt == 22) {
                getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
            } else {
                Log.i("hook","Don't need to Hook WebView");
                return;
            }
            getProviderClassMethod.setAccessible(true);
            Class<?> factoryProviderClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
            Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
            Constructor<?> delegateConstructor = delegateClass.getDeclaredConstructor();
            delegateConstructor.setAccessible(true);
            if(sdkInt < 26){
                Constructor<?> providerConstructor = factoryProviderClass.getConstructor(delegateClass);
                if (providerConstructor != null) {
                    providerConstructor.setAccessible(true);
                    sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance());
                }
            } else {
                Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD");
                chromiumMethodName.setAccessible(true);
                String chromiumMethodNameStr = (String)chromiumMethodName.get(null);
                if (chromiumMethodNameStr == null) {
                    chromiumMethodNameStr = "create";
                }
                Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass);
                if (staticFactory!=null){
                    sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance());
                }
            }
            if (sProviderInstance != null){
                field.set("sProviderInstance", sProviderInstance);
                Log.i("hook","Hook success!");
            } else {
                Log.i("hook","Hook failed!");
            }
        } catch (Throwable e) {
            Log.w("hook",e);
            e.printStackTrace();
        }
    }
    private void closeAnim(){
        mHandler.removeMessages(MSG_BATTERY);
        finish();
    }
    private void registerReceiver() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
        registerReceiver(receiver, filter);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }
    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Intent.ACTION_POWER_DISCONNECTED.equals(action)){
                closeAnim();
            }
        }
    };
    private int MSG_BATTERY = 100;
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == MSG_BATTERY){
                changeBatteryText();
                mHandler.sendEmptyMessageDelayed(MSG_BATTERY, 15000);
            }
        }
    };
    private int getBatteryLevel() {
        BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
        return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
    }
    private void changeBatteryText() {
        mWebView.post(new Runnable() {
            @Override
            public void run() {
                String mbettery = getBatteryLevel() + "%";
                Log.e("ccz", "mbettery=" + mbettery);
                mWebView.evaluateJavascript("javascript:callJSWithArgs('" + mbettery + "')", new ValueCallback<String>() {
                    @Override
                    public void onReceiveValue(String value) {
                        //Toast.makeText(getApplication(), " "+value, Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
}


优化体验


因为本文章只是提供充电动画思路,细节考虑不到位,采用Activity方式加载layout,

切换时会有明显拉起动画,可以通过Window addView 方式将 layout 添加到SystemUI中,

有需求的可自己去实现


参考文章


android 高仿华为充电动画

css3安卓充电动画效果

目录
相关文章
|
4天前
|
前端开发 JavaScript API
Webview+Python:用HTML打造跨平台桌面应用的创新方案
本文系统介绍了使用PyWebView库结合HTML/CSS/JavaScript开发跨平台桌面应用的方法。相比传统方案(如PyQt、Tkinter),PyWebView具备开发效率高、界面美观、资源占用低等优势。文章从技术原理、环境搭建、核心功能实现到性能优化与实战案例全面展开,涵盖窗口管理、双向通信、系统集成等功能,并通过“智能文件管理器”案例展示实际应用。适合希望快速构建跨平台桌面应用的Python开发者参考学习。
41 1
|
3月前
可爱狗狗的404动画HTML源码
可爱狗狗的404动画HTML源码
192 17
|
3月前
创意滑板动画404错误提示HTML源码
创意滑板动画404错误提示页面HTML源码
157 0
创意滑板动画404错误提示HTML源码
|
3月前
html5+svg太空人404动画模板源码
html5+svg太空人404动画模板源码
59 17
|
3月前
css3 svg制作404页面动画效果HTML源码
css3 svg制作404页面动画效果HTML源码
84 34
|
3月前
|
移动开发 前端开发 HTML5
Html5 Canvas绘制圆形仪表盘动画源码
Html5 Canvas绘制圆形仪表盘动画特效是一款基于HTML5 Canvas绘制的圆形百分比仪表盘动画特效。
33 1
|
3月前
|
移动开发 HTML5
HTML5 SVG实现可爱的小鸟卡通动画3D特效
HTML5 SVG实现可爱的小鸟卡通动画
88 29
|
3月前
html实现的文字发散动画效果代码
html实现的文字发散动画效果代码
84 30
|
3月前
|
移动开发 前端开发 HTML5
基于HTML5+Canvas绘制的鼠标跟随三角形碎片光标动画代码
基于HTML5+Canvas绘制的鼠标跟随三角形碎片光标动画特效代码,很有意思,一团三角形碎片跟随鼠标的移动,不冗长、不笨重,反而有一种很轻盈的感觉,非常不错
75 29
|
3月前
|
移动开发 HTML5
HTML5实现的手机验证抽奖领券效果源码
这是一款基于HTML5实现的手机验证抽奖领券效果源码。在输入框输入手机号码即可点击下方的按钮来进行抽奖游戏,中奖后还会弹出提示信息,是一款比较经典的抽奖游戏源码
95 9

热门文章

最新文章