You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Android或Flutter应用配置自定义IPv4 DNS?

Android 原生实现方案

要实现仅当前应用内所有流量使用自定义DNS(如1.1.1.1),核心是让所有网络请求绕过系统DNS服务,使用指定DNS服务器完成域名解析。以下是针对常用网络库的具体实现:

1. Retrofit/OkHttp 配置

Retrofit基于OkHttp实现网络请求,只需为OkHttpClient配置自定义DNS解析器即可:

步骤1:添加DNS解析依赖

在app/build.gradle中添加第三方DNS解析库(简化自定义解析逻辑):

implementation 'dnsjava:dnsjava:3.5.2'

步骤2:实现自定义DNS解析器

import org.xbill.DNS.Lookup;
import org.xbill.DNS.Record;
import org.xbill.DNS.SimpleResolver;
import org.xbill.DNS.Type;
import okhttp3.Dns;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

public class CustomDns implements Dns {
    private final String dnsServer;

    public CustomDns(String dnsServer) {
        this.dnsServer = dnsServer;
    }

    @Override
    public List<InetAddress> lookup(String hostname) throws UnknownHostException {
        List<InetAddress> addresses = new ArrayList<>();
        try {
            // 使用指定DNS服务器解析域名A记录
            Lookup lookup = new Lookup(hostname, Type.A);
            lookup.setResolver(new SimpleResolver(dnsServer));
            Record[] records = lookup.run();
            
            if (records != null) {
                for (Record record : records) {
                    org.xbill.DNS.A aRecord = (org.xbill.DNS.A) record;
                    addresses.add(aRecord.getAddress());
                }
            }
        } catch (Exception e) {
            // 解析失败时降级到系统DNS
            addresses.addAll(Dns.SYSTEM.lookup(hostname));
        }

        if (addresses.isEmpty()) {
            throw new UnknownHostException("Failed to resolve hostname: " + hostname);
        }
        return addresses;
    }
}

步骤3:配置OkHttpClient与Retrofit

// 初始化带自定义DNS的OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .dns(new CustomDns("1.1.1.1"))
        .build();

// 绑定到Retrofit
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://your-api-domain.com/")
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

2. Glide 图片加载配置

Glide支持替换底层网络栈为OkHttp,复用上述自定义DNS配置:

步骤1:添加Glide-OkHttp集成依赖

implementation 'com.github.bumptech.glide:okhttp3-integration:4.16.0'

步骤2:自定义GlideModule配置

import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;
import com.bumptech.glide.Registry;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import okhttp3.OkHttpClient;
import android.content.Context;

@GlideModule
public class CustomGlideConfigModule extends AppGlideModule {
    @Override
    public void registerComponents(Context context, com.bumptech.glide.Glide glide, Registry registry) {
        // 使用带自定义DNS的OkHttpClient替换Glide默认网络栈
        OkHttpClient client = new OkHttpClient.Builder()
                .dns(new CustomDns("1.1.1.1"))
                .build();
        registry.replace(GlideUrl.class, java.io.InputStream.class, new OkHttpUrlLoader.Factory(client));
    }
}

3. Firebase 服务配置

Firebase多数模块允许自定义底层HttpClient,以Firestore和Realtime Database为例:

Firestore

import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreSettings;
import okhttp3.OkHttpClient;

// 配置带自定义DNS的HttpClient
OkHttpClient firestoreClient = new OkHttpClient.Builder()
        .dns(new CustomDns("1.1.1.1"))
        .build();

// 应用到Firestore
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
        .setHttpClient(firestoreClient)
        .build();
FirebaseFirestore.getInstance().setFirestoreSettings(settings);

Realtime Database

import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import okhttp3.OkHttpClient;

OkHttpClient dbClient = new OkHttpClient.Builder()
        .dns(new CustomDns("1.1.1.1"))
        .build();

DatabaseReference dbRef = FirebaseDatabase.getInstance().getReference();
dbRef.getDatabase().setHttpClient(dbClient);

Flutter 实现方案

Flutter中需针对不同网络请求库配置自定义DNS,核心是替换默认HttpClient的解析逻辑:

1. Dio 库配置

Dio是Flutter常用网络库,支持直接自定义DNS解析:

步骤1:添加依赖

在pubspec.yaml中添加:

dependencies:
  dio: ^5.4.0
  dns_lookup: ^2.0.0

步骤2:配置自定义DNS

import 'package:dio/dio.dart';
import 'package:dio/adapter.dart';
import 'package:dns_lookup/dns_lookup.dart';
import 'dart:io';

Future<List<InternetAddress>> _customDnsLookup(String host) async {
  final dns = DnsLookup();
  // 设置自定义DNS服务器
  dns.setDnsServer(InternetAddress('1.1.1.1'));
  // 解析域名A记录
  final records = await dns.lookup(host, RecordType.A);
  return records.map((record) => InternetAddress(record.address)).toList();
}

void setupDio() {
  Dio dio = Dio();
  (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
    // 替换默认DNS解析逻辑
    client.dns = _customDnsLookup;
    return client;
  };
}

2. http 库配置

原生http库可通过自定义HttpClient实现:

import 'package:http/http.dart' as http;
import 'package:dns_lookup/dns_lookup.dart';
import 'dart:io';

Future<http.Response> fetchWithCustomDns(String url) async {
  final client = HttpClient();
  client.dns = (host) async {
    final dns = DnsLookup();
    dns.setDnsServer(InternetAddress('1.1.1.1'));
    final records = await dns.lookup(host, RecordType.A);
    return records.map((r) => InternetAddress(r.address)).toList();
  };

  final uri = Uri.parse(url);
  final request = await client.getUrl(uri);
  final response = await request.close();
  return http.Response.fromStream(response);
}

3. Firebase 与图片加载库配置

Firebase Firestore

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:dns_lookup/dns_lookup.dart';
import 'dart:io';

void setupFirestore() {
  final client = HttpClient();
  client.dns = (host) async {
    final dns = DnsLookup();
    dns.setDnsServer(InternetAddress('1.1.1.1'));
    final records = await dns.lookup(host, RecordType.A);
    return records.map((r) => InternetAddress(r.address)).toList();
  };

  FirebaseFirestore.instance.settings = Settings(
    httpClient: client,
  );
}

CachedNetworkImage

import 'package:cached_network_image/cached_network_image.dart';
import 'package:dns_lookup/dns_lookup.dart';
import 'dart:io';

final _customHttpClient = HttpClient()
  ..dns = (host) async {
    final dns = DnsLookup();
    dns.setDnsServer(InternetAddress('1.1.1.1'));
    final records = await dns.lookup(host, RecordType.A);
    return records.map((r) => InternetAddress(r.address)).toList();
  };

// 使用示例
CachedNetworkImage(
  imageUrl: 'https://example.com/image.jpg',
  httpClient: _customHttpClient,
)

通用注意事项

  • 解析失败降级:务必添加系统DNS fallback逻辑,避免自定义DNS不可达时导致所有请求失败。
  • 第三方库兼容性:部分小众库可能不支持自定义HttpClient,需优先选择提供配置入口的库,或通过封装网络请求统一管理。
  • 性能优化:可添加DNS解析结果缓存,减少重复解析请求。

内容的提问来源于stack exchange,提问作者Mobin jafari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 20:15:42