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

在这里插入图片描述

前言

在做 P2P 应用、日志记录或地域限制功能时,经常需要知道用户的真实公网 IP。虽然可以自己写个后端 API 返回 request.ip,或者爬取 icanhazip.com,但这些方法要么麻烦,要么不稳定。

dart_ipify 封装了著名的 ipify.org 公共 API,它不仅提供 IPv4/IPv6 查询,还能返回 ISP(运营商)和地理位置信息(需 API Key)。最重要的是,它极其简单稳定,永久免费(基础查询)。

一、概念介绍/原理解析

1.1 基础概念

  • Public IP: 路由器在互联网上的唯一出口地址(区别于 192.168.x.x 内网 IP)。
  • Geolocation: 根据 IP 反查地理位置(国家、城市、经纬度)。
  • Ipify: 一个高性能的 IP 地址 API 服务,基于 AWS Lambda 构建,无请求限制。

HTTP 请求 (GET)

返回 IP (如 1.2.3.4)

渲染 UI

Flutter 应用

Ipify 服务

显示公网 IP

1.2 进阶概念

它支持 HTTPS 加密传输,确保 IP 信息不被中间人篡改。同时也提供了对 geo-ipify 的支持,适合需要精确位置的场景。

二、核心 API/组件详解

2.1 依赖安装

dependencies:
  dart_ipify: ^1.0.0

2.2 基础用法

获取纯文本 IP 地址(免费,无 Key)。

import 'package:dart_ipify/dart_ipify.dart';

void main() async {
  // 1.IPv4
  final ipv4 = await Ipify.ipv4();
  print(ipv4); // "98.207.254.136"

  // 2. IPv6 (如果网络支持)
  // final ipv6 = await Ipify.ipv64(); 
}

2.3 地理位置查询

注册 获取 API Key。

final geo = await Ipify.geo('YOUR_API_KEY');
print(geo.location.city); // "Mountain View"
print(geo.isp); // "Google LLC"

在这里插入图片描述

三、常见应用场景

3.1 场景 1:自动切换服务器区域

根据用户 IP 所在的国家(如 US, CN),自动选择最近的 CDN 节点或游戏服务器。

final location = await Ipify.geo(key);
if (location.location.country == 'CN') {
  Config.setBaseUrl('https://cn.api.com');
} else {
  Config.setBaseUrl('https://us.api.com');
}

在这里插入图片描述

3.2 场景 2:安全风控

检测用户是否频繁更换 IP,或者处于异常地理位置(如账号常在上海,突然在尼日利亚登录)。

if (lastIp != currentIp && distance(lastLoc, currentLoc) > 1000km) {
  triggerSecurityCheck();
}

在这里插入图片描述

3.3 场景 3:调试工具

在 App 的“关于”或“调试模式”页面,显示当前网络出口 IP,方便测试人员排查问题。

ListTile(
  title: Text('Public IP'),
  subtitle: FutureBuilder(
    future: Ipify.ipv4(),
    builder: (ctx, snap) => Text(snap.data ?? 'Loading...'),
  ),
);

在这里插入图片描述

四、OpenHarmony 平台适配

4.1 网络权限

查询 IP 需要访问互联网,务必在 config.json / module.json5 中声明 ohos.permission.INTERNET

4.2 稳定性

Ipify 服务在海外,国内访问速度偶尔波动。建议在 OpenHarmony 侧做一层超时处理(Timeout)或增加重试机制,避免阻塞主流程。

五、完整示例代码

本示例展示在鸿蒙设备上查询本机公网 IP 及地理位置信息。

import 'package:flutter/material.dart';
import 'package:dart_ipify/dart_ipify.dart';

void main() {
  runApp(const MaterialApp(home: IpPage()));
}

class IpPage extends StatefulWidget {
  const IpPage({super.key});

  
  State<IpPage> createState() => _IpPageState();
}

class _IpPageState extends State<IpPage> {
  String _ip = '';
  String _location = '';
  bool _loading = false;

  Future<void> _fetchIp() async {
    setState(() {
      _loading = true;
      _ip = '';
      _location = '';
    });

    try {
      // 1. 获取 IP (免费)
      final ip = await Ipify.ipv4();
      _ip = ip;
      
      // 2. 获取地理位置 (需要 Key,这里演示用)
      // 如果没有 Key,可以跳过此步骤
      // final geo = await Ipify.geo('YOUR_API_KEY');
      // _location = '${geo.location.city}, ${geo.location.country}';
      _location = '需要 API Key 才能显示详细位置'; 

    } catch (e) {
      _ip = '查询失败';
      print(e);
    } finally {
      if (mounted) setState(() => _loading = false);
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('我的 IP 地址')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (_loading) const CircularProgressIndicator(),
            if (!_loading) ...[
              const Text('Public IPv4', style: TextStyle(color: Colors.grey)),
              Text(
                _ip.isEmpty ? '点击按钮查询' : _ip,
                style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold, color: Colors.blue),
              ),
              const SizedBox(height: 10),
              const Text('Location', style: TextStyle(color: Colors.grey)),
              Text(_location, style: const TextStyle(fontSize: 16)),
            ],
            const SizedBox(height: 40),
            ElevatedButton.icon(
              onPressed: _fetchIp,
              icon: const Icon(Icons.refresh),
              label: const Text('查询'),
            ),
          ],
        ),
      ),
    );
  }
}

六、总结

dart_ipify 解决了“我是谁,我在哪”的问题。虽然功能单一,但在特定场景下(如检测代理、区域限制)极其好用。

最佳实践

  1. 缓存:IP 地址通常不会频繁变动(除非重启路由器或切换网络),获取一次后应缓存在内存或本地,避免每次打开 App 都请求。
  2. Privacy:注意隐私合规,未经用户同意,不要滥用位置信息用于追踪。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐