You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何解决Xamarin Android应用中获取网站IP地址无返回且无报错的问题

解决Xamarin Android中Dns.GetHostAddressesAsync无响应的问题

我之前在Xamarin Android项目里也碰到过一模一样的情况,那段DNS解析代码在后端跑的好好的,到了移动端就彻底没动静,连个错误都不抛,简直让人抓狂!结合我的踩坑经验,给你几个排查和解决的方向:

1. 先检查Android权限配置

Xamarin Android默认不会自动授予INTERNET权限,这是最容易被忽略的点:

  • 打开你的Android项目下的Properties/AndroidManifest.xml
  • 确保里面添加了互联网权限:
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 可选,但有助于排查网络状态 -->
    
  • 如果你是针对Android 11及以上版本,INTERNET属于正常权限,不需要动态申请,但要确保配置没有被其他设置覆盖。

2. 排查异步调用的死锁问题

Xamarin Android的UI线程是单线程上下文,如果你在同步方法里直接调用await Dns.GetHostAddressesAsync(比如在OnCreate里直接写同步代码调用异步方法),很容易造成死锁。解决方法:

  • 确保你的调用方法本身是异步的,比如把Activity的方法改成async void(仅限事件处理方法)或者async Task
    protected override async void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        // ...其他初始化代码
        try
        {
            string url = "https://www.google.com/";
            Uri myUri = new Uri(url);
            var addresses = await Dns.GetHostAddressesAsync(myUri.Host).ConfigureAwait(false);
            var result = addresses?[0] + " from Android application";
            // 回到UI线程更新界面
            RunOnUiThread(() => {
                // 比如把结果显示到TextView
                yourTextView.Text = result;
            });
        }
        catch (Exception ex)
        {
            RunOnUiThread(() => {
                yourTextView.Text = $"错误:{ex.Message}";
            });
        }
    }
    
  • 加上ConfigureAwait(false)可以避免强制回到UI线程上下文,减少死锁的概率。

3. 捕获所有异常,找到隐藏的错误

你说代码既不返回也不报错,很大可能是异常被吞掉了。一定要把代码包裹在try-catch块里,并且捕获所有异常(包括深层的内部异常):

try
{
    string url = "https://www.google.com/";
    Uri myUri = new Uri(url);
    var addresses = await Dns.GetHostAddressesAsync(myUri.Host);
    return addresses?[0] + " from Android application";
}
catch (Exception ex)
{
    // 打印完整异常信息到调试日志,方便排查
    System.Diagnostics.Debug.WriteLine($"DNS解析错误详情:{ex.ToString()}");
    // 也可以用Toast提示用户
    Toast.MakeText(this, $"解析失败:{ex.Message}", ToastLength.Long).Show();
    return $"Error: {ex.Message}";
}

通过调试日志你就能看到具体是权限问题、网络问题还是API兼容性问题。

4. 替换为Android原生DNS解析API

如果Dns.GetHostAddressesAsync在Xamarin里确实有兼容性问题,可以直接调用Android原生的Java API来做DNS解析,稳定性会更好:

using Java.Net;
using System.Threading.Tasks;

// 封装原生DNS解析方法
public async Task<string> GetHostIpAsync(string host)
{
    try
    {
        InetAddress address = await InetAddress.GetByNameAsync(host);
        return address.HostAddress + " from Android application";
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine($"原生DNS解析错误:{ex.ToString()}");
        return $"Error: {ex.Message}";
    }
}

// 调用方式
var result = await GetHostIpAsync(myUri.Host);

这个方法绕过了.NET的Dns类,直接用Android系统的DNS服务,在移动端的兼容性会好很多。

5. 检查设备网络环境

有时候问题出在设备本身:

  • 测试设备有没有联网?是不是处于飞行模式或者连接了无法访问外网的WiFi?
  • 有没有使用代理?代理设置可能会干扰DNS解析。
  • 尝试切换到移动数据网络测试,排除WiFi的问题。

按照上面的步骤一步步排查,应该能找到问题所在。我当时就是因为漏加了INTERNET权限,折腾了半天,后来加上就正常了😂

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

火山引擎 最新活动