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

Android客户端无法连接本地服务器问题排查求助

Android OkHttp GET请求无法到达本地服务器

我之前用Java开发的Windows客户端和服务器通过POST请求交互完全正常,但现在用Java开发Android客户端,借助OkHttp库实现GET请求时,请求根本无法到达本地服务器。

我已完成以下检查:

  • IP地址正确,已通过Windows客户端验证,格式为http://x.x.x.x:25565/home的IPv4地址
  • 端口已正确配置端口转发
  • 运行App的手机可正常联网,通过浏览器访问同一URL能获取预期数据
  • 已在Manifest.xml中为App正确配置INTERNET权限
  • 已使用线程在MainActivity中执行GET请求的准备与发送逻辑

服务器收到请求时会在控制台输出消息,但此次无任何输出,看起来App并未真正发送请求或请求未到达服务器。以下是相关代码及Manifest文件,恳请提供解决建议。


MainActivity代码

package com.example.provaserver;

import android.os.Bundle;

import com.google.android.material.bottomnavigation.BottomNavigationView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;

import com.example.provaserver.databinding.ActivityMainBinding;
import okhttp3.*;
import android.net.Uri;
import android.util.Log;
import android.widget.TextView;

import java.io.IOException;
import java.net.URLEncoder;


public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;
    OkHttpClient client = new OkHttpClient();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        BottomNavigationView navView = findViewById(R.id.nav_view);
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(binding.navView, navController);

        TextView textViewResponse = findViewById(R.id.textViewResponse);


        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Request request = new Request.Builder()
                            .url("http://x.x.x.x:25565/home")
                            .build();

                    Log.d("NetworkRequest", "Inizio richiesta GET");
                    Call call = client.newCall(request);
                    Response response = call.execute();
                    Log.d("MainActivity", "Richiesta inviata, in attesa della risposta...");
                    if (response.isSuccessful()) {
                        final String responseData = response.body().string();

                        // Aggiorna l'interfaccia utente sul thread principale
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                // Esempio: aggiorna un TextView con la risposta
                                textViewResponse.setText(responseData);
                            }
                        });
                    } else {
                        runOnUiThread(() -> {
                            textViewResponse.setText("Errore nella risposta");
                        });
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

Manifest文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ProvaServer"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

排查与解决建议

1. 解决Android 9+明文HTTP限制

从Android 9(API 28)开始,系统默认禁止明文HTTP请求(仅允许HTTPS),而浏览器不受此限制。如果你的服务器使用HTTP,需在Manifest的application标签中添加如下配置:

<application
    ...
    android:usesCleartextTraffic="true"
    ...>

这是此类问题最常见的触发原因。

2. 捕获详细异常日志

当前代码仅调用e.printStackTrace(),建议将异常信息打印到Logcat,便于定位具体错误:

catch (IOException e) {
    Log.e("NetworkError", "请求失败: " + e.getMessage(), e);
}

通过日志可直接看到是连接超时、DNS解析失败还是其他网络问题。

3. 配置OkHttpClient超时时间

默认OkHttpClient未设置超时参数,可能导致请求无响应却无报错。手动添加超时配置:

OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(10, TimeUnit.SECONDS)
        .readTimeout(10, TimeUnit.SECONDS)
        .writeTimeout(10, TimeUnit.SECONDS)
        .build();

超时后会抛出明确异常,帮助快速排查。

4. 确认请求线程稳定性

请求逻辑在onCreate中启动线程,若Activity在请求完成前被销毁(如快速切换页面),线程可能被中断。建议将请求逻辑移至ViewModel等生命周期更稳定的组件中,或给线程添加标识确保执行完成。

5. 用抓包工具验证请求

使用Charles或Wireshark抓取手机网络包,确认App是否真正发送了请求,以及请求的目标地址、请求头是否正确。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 16:49:52