ReactNative项目OpenHarmony三方库集成实战:react-native-device-info

欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net

📋 前言

获取设备信息是一项基础而重要的功能。无论是做用户统计分析、设备适配、还是实现设备绑定功能,都需要准确获取设备的各种信息。react-native-device-info 是 React Native 生态中最流行的设备信息获取库,提供了丰富的 API 来获取设备硬件、系统、应用等各种信息,让开发者能够轻松实现设备识别、统计分析等功能。

🎯 库简介

基本信息

  • 库名称 : react-native-device-info
  • 版本信息 :
    • 11.1.0 + @react-native-ohos/react-native-device-info: 支持 RN 0.72 版本
    • 14.0.5 + @react-native-ohos/react-native-device-info: 支持 RN 0.77 版本
  • 官方仓库: https://github.com/react-native-device-info/react-native-device-info
  • 鸿蒙仓库: https://github.com/react-native-oh-library/react-native-device-info
  • 主要功能 :
    • 📱 获取设备基本信息(品牌、型号、名称等)
    • 💾 获取应用信息(包名、版本、构建号等)
    • 🔋 获取电池信息(电量、充电状态等)
    • 📡 获取网络信息(运营商、IP地址等)
    • 💾 获取存储信息(总容量、可用空间等)
    • 🖥️ 获取系统信息(系统版本、API级别等)
    • 📐 获取屏幕信息(分辨率、字体缩放等)

为什么需要 Device Info?

功能需求 手动实现 react-native-device-info
获取设备型号 ⚠️ 需原生代码 ✅ 一行代码搞定
获取应用版本 ⚠️ 需原生代码 ✅ 跨平台统一 API
获取电池电量 ❌ 复杂原生实现 ✅ 简单调用
获取运营商信息 ❌ 需系统权限 ✅ 自动处理权限
设备唯一标识 ⚠️ 各平台差异大 ✅ 统一接口
HarmonyOS 支持 ❌ 无 ✅ 完整适配

支持的核心 API

API 分类 API 名称 说明 HarmonyOS 支持
应用信息 getBundleId() 获取包名
getVersion() 获取应用版本
getBuildNumber() 获取构建号
getApplicationName() 获取应用名称
getFirstInstallTime() 首次安装时间
设备信息 getBrand() 获取设备品牌
getModel() 获取设备型号
getDeviceName() 获取设备名称
getDeviceType() 获取设备类型
isTablet() 是否为平板
系统信息 getSystemName() 获取系统名称
getSystemVersion() 获取系统版本
getApiLevel() 获取 API 级别
电池信息 getBatteryLevel() 获取电池电量
isBatteryCharging() 是否正在充电
网络信息 getCarrier() 获取运营商
getIpAddress() 获取 IP 地址
存储信息 getTotalDiskCapacity() 获取总存储容量 ⚠️ 部分支持
getFreeDiskStorage() 获取可用存储空间 ⚠️ 部分支持
屏幕信息 getFontScale() 获取字体缩放比例
版本 是否支持 Autolink RN 版本 需要手动配置
~14.0.5 ❌ No 0.77 ✅ 需要完整配置
~11.1.1 ✅ Yes 0.72 ❌ 如果工程已接入 Autolink,无需手动配置
<= 11.1.0-0.0.8 ❌ No 0.72 ✅ 需要手动配置

⚠️ 重要提示

  • 如果使用 11.1.1 版本 且工程已接入 Autolink,可跳过手动配置步骤
  • 如果使用 14.0.x 版本,必须按照下文进行完整手动配置

兼容性验证

在以下环境验证通过:

  • RNOH : 0.72.90; SDK : HarmonyOS 6.0.0 Release SDK; IDE : DevEco Studio 6.0.2; ROM: 6.0.0

📦 安装步骤

1. 安装依赖

在项目根目录执行以下命令,本文基于 RN 0.72.90 版本开发:

bash 复制代码
# RN 0.72 版本
npm install @react-native-oh-tpl/react-native-device-info@11.1.0-0.0.8-rc.1

2. 配置并运行 Codegen

本库已经适配了 Codegen,在使用前需要主动执行生成三方库桥接代码,否则可能会出现如下报错:

复制代码
cannot find module '@rnoh/react-native-openharmony/generated/ts' or its corresponding type declarations.
2.1 在 package.json 中配置 codegen 脚本

打开项目根目录的 package.json,在 scripts 中添加 codegen 脚本:

json 复制代码
{
  "scripts": {
    "codegen": "react-native codegen-harmony --cpp-output-path ./harmony/entry/src/main/cpp/generated --rnoh-module-path ./harmony/entry/oh_modules/@rnoh/react-native-openharmony"
  }
}

参数说明

参数 说明
--cpp-output-path 指定用于存储生成的 C++ 文件的输出目录,默认 ./harmony/entry/src/main/cpp/generated
--rnoh-module-path Native 工程内 RNOH SDK 模块的相对路径
--project-root-path Native 工程根目录的相对路径(可选)
2.2 执行 codegen 命令

⚠️ 注意:运行前请确保三方库已经正确安装!

bash 复制代码
npm run codegen

运行后,会在以下路径生成代码:

  • C++ 代码:./harmony/entry/src/main/cpp/generated/
  • ArkTS/TS 代码:./harmony/entry/oh_modules/@rnoh/react-native-openharmony/generated/
2.3 配置 CMakeLists.txt 引入生成的代码

打开 harmony/entry/src/main/cpp/CMakeLists.txt,添加:

c 复制代码
# 添加生成的 C++ 文件
+ file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")

add_library(rnoh_app SHARED
+   ${GENERATED_CPP_FILES}
    "./PackageProvider.cpp"
    "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
2.4 在 PackageProvider.cpp 中引入 RNOHGeneratedPackage

打开 harmony/entry/src/main/cpp/PackageProvider.cpp,添加:

cpp 复制代码
#include "RNOH/PackageProvider.h"
+ #include "generated/RNOHGeneratedPackage.h"

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
        std::make_shared<SamplePackage>(ctx),
        + std::make_shared<RNOHGeneratedPackage>(ctx),
    };
}

3. 验证安装

安装完成后,检查 package.json 文件:

json 复制代码
{
  "dependencies": {
    "@react-native-oh-tpl/react-native-device-info": "11.1.0-0.0.8-rc.1",
    // ... 其他依赖
  }
}

🔧 HarmonyOS 平台配置 ⭐

⚠️ 版本差异说明

  • 11.1.1 版本:支持 Autolink,如果工程已接入 Autolink,可跳过本章节
  • 14.0.x 版本:不支持 Autolink,需要完整配置

由于 HarmonyOS 部分版本不支持 AutoLink,需要手动配置原生端代码。本文提供 HAR 包引入源码引入 两种方式,可根据实际需求选择。

1. 在工程根目录的 oh-package.json5 添加 overrides 字段

打开 harmony/oh-package.json5,添加以下配置:

json5 复制代码
{
  // ... 其他配置
  "overrides": {
    "@rnoh/react-native-openharmony": "0.72.90"
  }
}

方式一:HAR 包引入(推荐)📦

HAR 包引入方式简单快捷,适合大多数场景。

💡 提示 :HAR 包位于三方库安装路径的 harmony 文件夹下。

2.1 在 entry/oh-package.json5 添加依赖

打开 harmony/entry/oh-package.json5,添加以下依赖:

json 复制代码
"dependencies": {
  "@rnoh/react-native-openharmony": "0.72.90",
  + "@react-native-oh-tpl/react-native-device-info": "file:../../node_modules/@react-native-oh-tpl/react-native-device-info/harmony/device_info.har"
}

2.2 同步依赖

点击 DevEco Studio 右上角的 sync 按钮,或者在终端执行:

bash 复制代码
cd harmony/entry
ohpm install

2.3 配置 CMakeLists.txt(如果安装的是oh-tpl下的,可以跳过cmake配置)

⚠️ 注意 :此步骤仅适用于 14.0.x 版本(RN 0.77)11.1.1 版本不需要此步骤

打开 harmony/entry/src/main/cpp/CMakeLists.txt,添加以下配置:

c 复制代码
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_STANDARD 17)
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../oh_modules/@rnoh/react-native-openharmony/src/main/cpp")
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(WITH_HITRACE_SYSTRACE 1)
add_compile_definitions(WITH_HITRACE_SYSTRACE)

add_subdirectory("${RNOH_CPP_DIR}" ./rn)
+ add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-device-info/src/main/cpp" ./device_info)

add_library(rnoh_app SHARED
    "./PackageProvider.cpp"
    "${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
+ target_link_libraries(rnoh_app PUBLIC device_info)

2.4 修改 PackageProvider.cpp(如果安装的是oh-tpl下的,可以跳过)

⚠️ 注意 :此步骤仅适用于 14.0.x 版本(RN 0.77)11.1.1 版本不需要此步骤

打开 harmony/entry/src/main/cpp/PackageProvider.cpp,添加:

cpp 复制代码
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
+ #include "RNDeviceInfoPackage.h"

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
        std::make_shared<RNOHGeneratedPackage>(ctx),
        std::make_shared<SamplePackage>(ctx),
        + std::make_shared<RNDeviceInfoPackage>(ctx),
    };
}

2.5 在 ArkTs 侧引入 RNDeviceInfoPackage(这个不可跳过,注意你的是ohos还是oh-tpl,如果按照文章的依赖安装,直接复制)

⚠️ 注意 :此步骤仅适用于 14.0.x 版本(RN 0.77)11.1.1 版本不需要此步骤

打开 harmony/entry/src/main/ets/RNPackagesFactory.ts,添加:

typescript 复制代码
import type { RNPackageContext, RNPackage } from 'rnoh/ts';
+ import { RNDeviceInfoPackage } from '@react-native-oh-tpl/react-native-device-info/ts';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
    // ... 其他包
    + new RNDeviceInfoPackage(ctx),
  ];
}


🔐 权限配置

在 entry 目录下的 module.json5 中添加权限

打开 harmony/entry/src/main/module.json5,添加:

json5 复制代码
"requestPermissions": [
  {
    "name": "ohos.permission.GET_NETWORK_INFO"
  },
  {
    "name": "ohos.permission.GET_WIFI_INFO"
  },
  {
    "name": "ohos.permission.DISTRIBUTED_DATASYNC",
    "reason": "$string:DATA_SYNC",
    "usedScene": {
      "abilities": [
        "EntryAbility"
      ],
      "when": "always"
    }
  }
]

在 string.json 中添加权限说明

打开 harmony/entry/src/main/resources/base/element/string.json,添加:

json 复制代码
{
  "string": [
    {
      "name": "DATA_SYNC",
      "value": "用于获取设备信息"
    }
  ]
}

🔤 字体缩放配置(可选)

💡 提示 :如果需要使用 getFontScale() 接口,需要进行以下配置。

1. 新增 configuration.json 文件

harmony/AppScope/resources/base/profile 文件夹下新增 configuration.json 文件:

json 复制代码
{
  "configuration": {
    "fontSizeScale": "followSystem",
    "fontSizeMaxScale": "3.2"
  }
}

2. 在 app.json5 中配置

打开 harmony/AppScope/app.json5,添加配置:

json5 复制代码
{
  "app": {
    "bundleName": "com.example.test",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:app_icon",
    "label": "$string:app_name",
    "distributedNotificationEnabled": true,
    + "configuration": "$profile:configuration"
  }
}

同步并运行 🚀

3. 同步依赖

点击 DevEco Studio 右上角的 sync 按钮,或者在终端执行:

bash 复制代码
cd harmony/entry
ohpm install

然后编译、运行即可。

📖 API 详解

🔷 应用信息 API

1. getBundleId - 获取应用包名 📦
typescript 复制代码
import DeviceInfo from 'react-native-device-info';

const bundleId = DeviceInfo.getBundleId();
// 返回值示例: "com.example.myapp"
2. getVersion - 获取应用版本 📝
typescript 复制代码
const version = DeviceInfo.getVersion();
// 返回值示例: "1.0.0"
3. getBuildNumber - 获取构建号 🔢
typescript 复制代码
const buildNumber = DeviceInfo.getBuildNumber();
// 返回值示例: "100"
4. getApplicationName - 获取应用名称 📱
typescript 复制代码
const appName = DeviceInfo.getApplicationName();
// 返回值示例: "我的应用"
5. getFirstInstallTime - 获取首次安装时间 ⏰
typescript 复制代码
const firstInstallTime = await DeviceInfo.getFirstInstallTime();
// 返回值示例: 1609459200000 (时间戳)
6. getReadableVersion - 获取可读版本 📖
typescript 复制代码
const readableVersion = DeviceInfo.getReadableVersion();
// 返回值示例: "1.0.0.100" (版本号.构建号)

🔷 设备信息 API

7. getBrand - 获取设备品牌 🏷️
typescript 复制代码
const brand = DeviceInfo.getBrand();
// HarmonyOS 返回值示例: "HUAWEI"
// iOS 返回值示例: "Apple"
// Android 返回值示例: "Xiaomi"
8. getModel - 获取设备型号 📱
typescript 复制代码
const model = DeviceInfo.getModel();
// 返回值示例: "Mate 60 Pro"
9. getDeviceName - 获取设备名称 📛
typescript 复制代码
const deviceName = await DeviceInfo.getDeviceName();
// 返回值示例: "我的手机"
10. getDeviceType - 获取设备类型 📱💻📺
typescript 复制代码
const deviceType = DeviceInfo.getDeviceType();
// 返回值: "Handset" | "Tablet" | "Tv" | "Desktop" | "GamingConsole" | "unknown"
11. isTablet - 判断是否为平板 📱
typescript 复制代码
const isTablet = DeviceInfo.isTablet();
// 返回值: true | false

🔷 系统信息 API

12. getSystemName - 获取系统名称 🖥️
typescript 复制代码
const systemName = DeviceInfo.getSystemName();
// HarmonyOS 返回值示例: "HarmonyOS"
// iOS 返回值示例: "iOS"
// Android 返回值示例: "Android"
13. getSystemVersion - 获取系统版本 📊
typescript 复制代码
const systemVersion = DeviceInfo.getSystemVersion();
// HarmonyOS 返回值示例: "6.0.0"
// iOS 返回值示例: "17.0"
// Android 返回值示例: "14"
14. getApiLevel - 获取 API 级别 🔢
typescript 复制代码
const apiLevel = await DeviceInfo.getApiLevel();
// HarmonyOS 返回值示例: 12
// Android 返回值示例: 34

🔷 电池信息 API

15. getBatteryLevel - 获取电池电量 🔋
typescript 复制代码
const batteryLevel = await DeviceInfo.getBatteryLevel();
// 返回值: 0 到 1 之间的浮点数
// 示例: 0.85 表示 85% 电量
16. isBatteryCharging - 是否正在充电 ⚡
typescript 复制代码
const isCharging = await DeviceInfo.isBatteryCharging();
// 返回值: true | false

应用场景

typescript 复制代码
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, ProgressBarAndroid } from 'react-native';
import DeviceInfo from 'react-native-device-info';

function BatteryDemo() {
  const [batteryInfo, setBatteryInfo] = useState({
    level: 0,
    isCharging: false,
  });

  useEffect(() => {
    const fetchBatteryInfo = async () => {
      const level = await DeviceInfo.getBatteryLevel();
      const isCharging = await DeviceInfo.isBatteryCharging();

      setBatteryInfo({
        level,
        isCharging,
      });
    };

    fetchBatteryInfo();

    // 定时刷新电池信息
    const interval = setInterval(fetchBatteryInfo, 30000);
    return () => clearInterval(interval);
  }, []);

  const getBatteryColor = () => {
    if (batteryInfo.level > 0.5) return '#4CAF50';
    if (batteryInfo.level > 0.2) return '#FF9800';
    return '#F44336';
  };

  const getBatteryIcon = () => {
    if (batteryInfo.isCharging) return '⚡';
    if (batteryInfo.level > 0.8) return '🔋';
    if (batteryInfo.level > 0.5) return '🔋';
    if (batteryInfo.level > 0.2) return '🪫';
    return '🪫';
  };

  return (
    <View style={styles.container}>
      <Text style={styles.icon}>{getBatteryIcon()}</Text>
      <Text style={styles.percentage}>
        {Math.round(batteryInfo.level * 100)}%
      </Text>
      <View style={styles.progressBarContainer}>
        <View
          style={[
            styles.progressBar,
            {
              width: `${batteryInfo.level * 100}%`,
              backgroundColor: getBatteryColor(),
            },
          ]}
        />
      </View>
      {batteryInfo.isCharging && (
        <Text style={styles.charging}>正在充电中...</Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f5f5f5',
    padding: 20,
  },
  icon: {
    fontSize: 60,
    marginBottom: 16,
  },
  percentage: {
    fontSize: 48,
    fontWeight: 'bold',
    color: '#333',
    marginBottom: 16,
  },
  progressBarContainer: {
    width: '100%',
    height: 20,
    backgroundColor: '#e0e0e0',
    borderRadius: 10,
    overflow: 'hidden',
  },
  progressBar: {
    height: '100%',
    borderRadius: 10,
  },
  charging: {
    marginTop: 16,
    fontSize: 16,
    color: '#4CAF50',
  },
});

export default BatteryDemo;

🔷 网络信息 API

17. getCarrier - 获取运营商 📡
typescript 复制代码
const carrier = await DeviceInfo.getCarrier();
// 返回值示例: "中国移动", "中国联通", "中国电信"
18. getIpAddress - 获取 IP 地址 🌐
typescript 复制代码
const ipAddress = await DeviceInfo.getIpAddress();
// 返回值示例: "192.168.1.100"

🔷 存储信息 API

19. getTotalDiskCapacity - 获取总存储容量 💾
typescript 复制代码
const totalCapacity = await DeviceInfo.getTotalDiskCapacity();
// 返回值: 字节数
// 需要转换为 GB: (totalCapacity / 1024 / 1024 / 1024).toFixed(2)
20. getFreeDiskStorage - 获取可用存储空间 📁
typescript 复制代码
const freeStorage = await DeviceInfo.getFreeDiskStorage();
// 返回值: 字节数

🔷 屏幕信息 API

21. getFontScale - 获取字体缩放比例 📐
typescript 复制代码
const fontScale = await DeviceInfo.getFontScale();
// 返回值示例: 1.0 (正常), 1.5 (大字体), 2.0 (超大字体)

⚠️ 注意 :使用此接口需要配置 configuration.json 文件,详见上文"字体缩放配置"章节。


📊 完整示例:设备信息面板

typescript 复制代码
import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
  StyleSheet,
  ScrollView,
  SafeAreaView,
  RefreshControl,
} from 'react-native';
import DeviceInfo from 'react-native-device-info';

interface DeviceData {
  // 应用信息
  bundleId: string;
  version: string;
  buildNumber: string;
  appName: string;
  firstInstallTime: number;
  // 设备信息
  brand: string;
  model: string;
  deviceName: string;
  deviceType: string;
  isTablet: boolean;
  // 系统信息
  systemName: string;
  systemVersion: string;
  apiLevel: number;
  // 电池信息
  batteryLevel: number;
  isCharging: boolean;
  // 网络信息
  carrier: string;
  ipAddress: string;
  // 存储信息
  totalStorage: number;
  freeStorage: number;
  // 屏幕信息
  fontScale: number;
}

function DeviceInfoPanel() {
  const [deviceData, setDeviceData] = useState<DeviceData | null>(null);
  const [refreshing, setRefreshing] = useState(false);

  const fetchAllDeviceInfo = async () => {
    const data: DeviceData = {
      // 应用信息
      bundleId: DeviceInfo.getBundleId(),
      version: DeviceInfo.getVersion(),
      buildNumber: DeviceInfo.getBuildNumber(),
      appName: DeviceInfo.getApplicationName(),
      firstInstallTime: await DeviceInfo.getFirstInstallTime(),
      // 设备信息
      brand: DeviceInfo.getBrand(),
      model: DeviceInfo.getModel(),
      deviceName: await DeviceInfo.getDeviceName(),
      deviceType: DeviceInfo.getDeviceType(),
      isTablet: DeviceInfo.isTablet(),
      // 系统信息
      systemName: DeviceInfo.getSystemName(),
      systemVersion: DeviceInfo.getSystemVersion(),
      apiLevel: await DeviceInfo.getApiLevel(),
      // 电池信息
      batteryLevel: await DeviceInfo.getBatteryLevel(),
      isCharging: await DeviceInfo.isBatteryCharging(),
      // 网络信息
      carrier: await DeviceInfo.getCarrier(),
      ipAddress: await DeviceInfo.getIpAddress(),
      // 存储信息
      totalStorage: await DeviceInfo.getTotalDiskCapacity(),
      freeStorage: await DeviceInfo.getFreeDiskStorage(),
      // 屏幕信息
      fontScale: await DeviceInfo.getFontScale(),
    };

    setDeviceData(data);
  };

  useEffect(() => {
    fetchAllDeviceInfo();
  }, []);

  const onRefresh = async () => {
    setRefreshing(true);
    await fetchAllDeviceInfo();
    setRefreshing(false);
  };

  const formatBytes = (bytes: number) => {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  };

  const formatTime = (timestamp: number) => {
    const date = new Date(timestamp);
    return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
  };

  if (!deviceData) {
    return (
      <View style={styles.loading}>
        <Text>加载中...</Text>
      </View>
    );
  }

  return (
    <SafeAreaView style={styles.container}>
      <ScrollView
        refreshControl={
          <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
        }
      >
        <Text style={styles.header}>📱 设备信息面板</Text>

        {/* 应用信息 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>📦 应用信息</Text>
          <InfoRow label="包名" value={deviceData.bundleId} />
          <InfoRow label="版本" value={deviceData.version} />
          <InfoRow label="构建号" value={deviceData.buildNumber} />
          <InfoRow label="应用名" value={deviceData.appName} />
          <InfoRow
            label="首次安装"
            value={formatTime(deviceData.firstInstallTime)}
          />
        </View>

        {/* 设备信息 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>📱 设备信息</Text>
          <InfoRow label="品牌" value={deviceData.brand} />
          <InfoRow label="型号" value={deviceData.model} />
          <InfoRow label="设备名称" value={deviceData.deviceName} />
          <InfoRow label="设备类型" value={deviceData.deviceType} />
          <InfoRow
            label="是否平板"
            value={deviceData.isTablet ? '是' : '否'}
          />
        </View>

        {/* 系统信息 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>🖥️ 系统信息</Text>
          <InfoRow label="系统名称" value={deviceData.systemName} />
          <InfoRow label="系统版本" value={deviceData.systemVersion} />
          <InfoRow label="API级别" value={String(deviceData.apiLevel)} />
        </View>

        {/* 电池信息 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>🔋 电池信息</Text>
          <InfoRow
            label="电量"
            value={`${Math.round(deviceData.batteryLevel * 100)}%`}
          />
          <InfoRow
            label="充电状态"
            value={deviceData.isCharging ? '充电中 ⚡' : '未充电'}
          />
        </View>

        {/* 网络信息 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>📡 网络信息</Text>
          <InfoRow label="运营商" value={deviceData.carrier || '未知'} />
          <InfoRow label="IP地址" value={deviceData.ipAddress || '未知'} />
        </View>

        {/* 存储信息 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>💾 存储信息</Text>
          <InfoRow label="总容量" value={formatBytes(deviceData.totalStorage)} />
          <InfoRow label="可用空间" value={formatBytes(deviceData.freeStorage)} />
          <InfoRow
            label="已使用"
            value={formatBytes(
              deviceData.totalStorage - deviceData.freeStorage
            )}
          />
        </View>

        {/* 屏幕信息 */}
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>📐 屏幕信息</Text>
          <InfoRow label="字体缩放" value={`${deviceData.fontScale.toFixed(1)}x`} />
        </View>
      </ScrollView>
    </SafeAreaView>
  );
}

function InfoRow({ label, value }: { label: string; value: string }) {
  return (
    <View style={styles.infoRow}>
      <Text style={styles.label}>{label}</Text>
      <Text style={styles.value}>{value}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  loading: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  header: {
    fontSize: 24,
    fontWeight: 'bold',
    textAlign: 'center',
    padding: 16,
    backgroundColor: '#667eea',
    color: '#fff',
  },
  section: {
    backgroundColor: '#fff',
    margin: 8,
    padding: 16,
    borderRadius: 12,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 12,
    color: '#333',
  },
  infoRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingVertical: 8,
    borderBottomWidth: 1,
    borderBottomColor: '#f0f0f0',
  },
  label: {
    fontSize: 14,
    color: '#666',
  },
  value: {
    fontSize: 14,
    fontWeight: '500',
    color: '#333',
  },
});

export default DeviceInfoPanel;

⚠️ 遗留问题

问题 描述 状态
getAndroidId HarmonyOS 不支持此 API ❌ 不支持
getDeviceId HarmonyOS 不支持此 API ❌ 不支持
getFreeDiskStorage 部分设备可能返回不准确 ⚠️ 部分支持
getFingerprint HarmonyOS 不支持此 API ❌ 不支持

相关推荐
庄小焱1 小时前
React——React基础语法(2)
前端·javascript·react.js
终端鹿1 小时前
Vue3 核心 API 深度解析:ref / reactive / computed / watch
前端·javascript·vue.js
大雷神1 小时前
HarmonyOS APP<玩转React>开源教程十五:首页完整实现
react.js·开源·harmonyos
console.log('npc')2 小时前
partial在react接口定义中是什么意思
前端·javascript·typescript
SuperEugene2 小时前
前端 utils 工具函数规范:拆分 / 命名 / 复用全指南,避开全局污染等高频坑|编码语法规范篇
开发语言·前端·javascript
Amumu121382 小时前
Js:内置对象
开发语言·前端·javascript
我命由我123452 小时前
Element Plus 2.2.27 的单选框 Radio 组件,选中一个选项后,全部选项都变为选中状态
开发语言·前端·javascript·html·ecmascript·html5·js
weixin_443478513 小时前
flutter组件学习之卡片与列表
javascript·学习·flutter
moreen3 小时前
Koa3.1.2 迁移, 持续更新中
javascript