如何使用Angular检测设备是否开启省电模式
Angular 检测设备省电模式实现方案
核心基于浏览器原生Battery Status API实现,搭配降级兼容逻辑覆盖不支持API的设备,封装为Angular服务即可实现状态响应式更新,自动切换视频/图片资源。
核心实现逻辑
- 优先调用
navigator.getBattery()接口获取电池管理实例,直接读取原生省电模式标记,同时监听充电状态、电量变化、省电模式开关三类事件,实时更新状态 - 对不支持Battery API的设备做降级判断:结合系统减少动效偏好、设备硬件配置(CPU核心数、内存大小)做兜底判定,避免功能失效
- 用Angular Signal存储状态,组件可直接绑定实现视图自动更新,无需手动触发变更检测
可复用服务代码
新建battery-detect.service.ts,代码如下:
import { Injectable, signal } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { fromEvent, merge, of, from } from 'rxjs'; import { map, catchError, switchMap } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class BatteryDetectService { // 存储省电模式状态,支持响应式更新 isPowerSaveMode = signal(false); // 检测当前环境是否支持Battery API private isBatteryApiSupported = typeof navigator !== 'undefined' && 'getBattery' in navigator; constructor() { if (!this.isBatteryApiSupported) { this.fallbackDetect(); return; } // 初始化电池状态监听 from(navigator.getBattery()).pipe( switchMap((battery: any) => { // 初始化状态赋值 this.updatePowerSaveStatus(battery); // 绑定所有状态变更事件 return merge( fromEvent(battery, 'chargingchange'), fromEvent(battery, 'levelchange'), fromEvent(battery, 'powersavingchange') ).pipe(map(() => battery)); }), map((battery: any) => this.updatePowerSaveStatus(battery)), catchError(() => { this.fallbackDetect(); return of(this.isPowerSaveMode()); }), takeUntilDestroyed() ).subscribe(); } /** * 从电池实例计算省电模式状态 */ private updatePowerSaveStatus(battery: any): boolean { let status = false; // 优先读取原生省电模式标记,判断准确率最高 if (typeof battery.powerSavingMode === 'boolean') { status = battery.powerSavingMode; } else { // 低版本API无原生标记时,兜底判断:非充电状态下电量≤20%视为省电场景 status = !battery.charging && battery.level <= 0.2; } this.isPowerSaveMode.set(status); return status; } /** * 降级检测逻辑,适配不支持Battery API的环境 */ private fallbackDetect() { // 匹配系统减少动效偏好:开启该选项的设备通常处于省电模式/低性能模式 const reduceMotionQuery = window.matchMedia('(prefers-reduced-motion: reduce)'); // 低配设备判定:CPU核心≤2/设备内存≤2G时默认按省电场景适配 const isLowEndDevice = navigator.hardwareConcurrency <= 2 || (navigator as any).deviceMemory <= 2; const setStatus = () => { this.isPowerSaveMode.set(reduceMotionQuery.matches || isLowEndDevice); }; setStatus(); // 监听系统动效偏好变化 reduceMotionQuery.addEventListener('change', setStatus); } }
组件内使用方式
在需要切换媒体资源的组件中直接注入服务,绑定模板即可自动切换:
import { Component } from '@angular/core'; import { BatteryDetectService } from './battery-detect.service'; import { NgIf } from '@angular/common'; @Component({ selector: 'app-biz-media', standalone: true, imports: [NgIf], template: ` <!-- 非省电模式加载视频 --> <video *ngIf="!batteryService.isPowerSaveMode()" src="assets/biz-video.mp4" autoplay muted loop playsinline ></video> <!-- 省电模式加载静态封面图 --> <img *ngIf="batteryService.isPowerSaveMode()" src="assets/biz-cover.jpg" alt="业务内容封面" > ` }) export class BizMediaComponent { constructor(public batteryService: BatteryDetectService) {} }
适配注意事项
- iOS Safari 16.4以下版本不支持Battery Status API,会自动走降级逻辑,不会抛出异常
- 部分安卓定制ROM的省电模式触发规则存在差异,原生
powerSavingMode字段为最高优先级判断依据,低电量兜底阈值可根据业务场景自行调整 - 自动检测存在小概率误判,可在页面增加轻量的手动切换入口,允许用户手动选择视频/图片展示模式,覆盖检测误差
内容的提问来源于stack exchange,提问作者Shrikant
相关产品推荐
相关产品推荐

