Android平台Java代码动态修改hosts文件方案咨询(ChatGPT方案无效)
Android 动态修改 Hosts 文件的可行方案
一、Root 设备下的直接修改方案
Android 的 hosts 文件位于 /system/etc/hosts,默认处于只读状态,必须获取 Root 权限并将系统分区挂载为可读写模式才能修改。
操作步骤及代码示例
- 获取 Root 权限并挂载系统分区
通过执行 Shell 命令完成挂载操作,Java 中可通过Runtime调用:
Process process = Runtime.getRuntime().exec("su"); DataOutputStream os = new DataOutputStream(process.getOutputStream()); // 将/system分区挂载为可读写 os.writeBytes("mount -o remount,rw /system\n"); os.flush();
- 写入新 Hosts 条目
建议先读取原有 hosts 内容,追加新条目后再写入,避免覆盖系统默认配置:
// 读取原hosts内容 BufferedReader reader = new BufferedReader(new FileReader("/system/etc/hosts")); StringBuilder content = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { content.append(line).append("\n"); } reader.close(); // 追加自定义条目(示例:将example.com指向192.168.1.100) content.append("192.168.1.100 example.com\n"); // 写入修改后的内容 FileWriter writer = new FileWriter("/system/etc/hosts"); writer.write(content.toString()); writer.flush(); writer.close();
- 恢复系统分区为只读(推荐)
修改完成后将分区改回只读状态,保障系统稳定性:
os.writeBytes("mount -o remount,ro /system\n"); os.flush(); os.writeBytes("exit\n"); os.flush(); process.waitFor();
注意事项
- Android 10+ 部分设备采用 A/B 分区或只读系统(Read-Only System),直接修改
/system/etc/hosts可能失效,需借助 Magisk 等工具通过模块挂载镜像覆盖原文件。 - 执行 Shell 命令时需捕获权限异常,未获取 Root 权限会抛出
SecurityException。
二、非 Root 设备下的替代方案(推荐)
无 Root 权限时无法直接修改系统 hosts 文件,可通过 VpnService 拦截 DNS 请求 实现等效效果,这是 Google 官方允许的合法方案。
实现思路
- 继承
android.net.VpnService实现自定义 VPN 服务; - 配置路由规则,拦截所有 UDP 53 端口的 DNS 请求;
- 自定义解析逻辑:匹配目标域名时返回指定 IP,否则转发至公共 DNS 服务器。
核心代码示例
public class HostsVpnService extends VpnService { private ParcelFileDescriptor vpnInterface; @Override public int onStartCommand(Intent intent, int flags, int startId) { Builder builder = new Builder(); builder.addAddress("10.0.0.2", 32); builder.addRoute("0.0.0.0", 0); builder.addDnsServer("8.8.8.8"); // 备用公共DNS // 拦截所有应用的DNS请求 builder.addAllowedApplication("*"); vpnInterface = builder.establish(); // 启动线程处理DNS解析逻辑 new Thread(() -> handleDnsRequests(vpnInterface)).start(); return START_STICKY; } private void handleDnsRequests(ParcelFileDescriptor vpnInterface) { // 此处实现DNS数据包解析、域名匹配及自定义IP返回逻辑 // 可借助dnsjava等第三方库简化开发 } @Override public void onDestroy() { if (vpnInterface != null) { try { vpnInterface.close(); } catch (IOException e) { e.printStackTrace(); } } super.onDestroy(); } }
注意事项
- 需在
AndroidManifest.xml中声明权限:
并注册 VPN 服务:<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /><service android:name=".HostsVpnService" android:permission="android.permission.BIND_VPN_SERVICE"> <intent-filter> <action android:name="android.net.VpnService" /> </intent-filter> </service> - 用户需手动授权 VPN 权限,这是系统强制的安全机制。
常见问题排查
- Root 后修改无效:执行
mount命令检查/system分区是否成功挂载为可读写;Android 10+ 设备需确认是否为只读系统,改用 Magisk 模块方案。 - VPN 方式无效:确认 VPN 服务已启动并获得用户授权,检查 DNS 解析逻辑是否正确处理数据包。
内容的提问来源于stack exchange,提问作者Gabriele Callegari
相关产品推荐
相关产品推荐

