10.0.2.2

在Android Emulator中,localhost 指的是模拟器本身的回环地址,而不是开发机器的回环地址。因此,如果你在模拟器中使用 localhost,它会尝试连接到模拟器自身的服务,而不是开发机器上的服务。这就是为什么你需要使用开发机器的局域网IP地址(例如 10.213.121.155)来访问本地运行的Spring Boot应用。

为什么不能直接使用 localhost?

模拟器回环地址:

localhost 或 127.0.0.1 在模拟器中指向的是模拟器本身。

如果你的Spring Boot应用运行在开发机器上,模拟器无法通过 localhost 访问到开发机器上的服务。

开发机器局域网IP:

使用开发机器的局域网IP地址(例如 10.213.121.155)可以确保模拟器通过网络连接到开发机器上的服务。

使用 10.0.2.2 的情况

如果你使用的是Android Emulator,还有一个特殊的IP地址 10.0.2.2,它可以用来访问开发机器上的服务。这个地址是Android Emulator提供的一个别名,用于指向开发机器的回环地址(127.0.0.1)。

使用 10.0.2.2 的示例

如果你选择使用 10.0.2.2,你可以将 BASE_URL 修改为:

package com.android.webttest.Config;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiClient {
    private static final String BASE_URL = "http://10.0.2.2:8080/api/"; // 使用10.0.2.2
    private static Retrofit retrofit = null;

    public static Retrofit getClient() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

确保网络权限

确保在你的 AndroidManifest.xml 文件中添加网络权限:

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

package com.android.webttest.activity;

import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.android.webttest.Api.Service.Checkcode;
import com.android.webttest.Config.ApiClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 创建Checkcode接口实例
        Checkcode checkcodeService = ApiClient.getClient().create(Checkcode.class);

        // 调用getCheckcode方法
        Call<String> call = checkcodeService.getCheckcode();
        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                if (response.isSuccessful()) {
                    String checkcode = response.body();
                    Log.d("MainActivity", "Checkcode received: " + checkcode);
                    // 例如,将验证码显示在TextView中
                    TextView checkcodeTextView = findViewById(R.id.checkcodeTextView);
                    checkcodeTextView.setText(checkcode);
                } else {
                    Log.d("MainActivity", "Failed to get checkcode: " + response.code());
                }
            }

            @Override
            public void onFailure(Call<String> call, Throwable t) {
                Log.d("MainActivity", "Failed to get checkcode: " + t.getMessage());
            }
        });
    }
}

Failed to get checkcode: CLEARTEXT communication to 10.0.2.2 not permitted by network security policy为什么

错误信息 Failed to get checkcode: CLEARTEXT communication to 10.0.2.2 not permitted by network security policy 表明应用尝试通过 HTTP(明文通信)访问网络资源,但被 Android 的网络安全策略阻止。

原因

Android 的网络安全策略

从 Android 9.0(API 级别 28)开始,默认情况下,应用不允许使用明文(HTTP)进行网络通信。所有网络请求必须使用 HTTPS。

如果需要使用 HTTP,必须显式配置应用的网络安全策略。

IP 地址 10.0.2.2

10.0.2.2 是 Android 模拟器中的特殊 IP 地址,指向主机机器(开发者的电脑)。通常用于调试或本地 API 测试。

由于它是 HTTP 而非 HTTPS,因此被默认的安全策略阻止。

解决方案

方法 1:在 AndroidManifest.xml 中允许明文通信

如果测试环境仅限于本地调试,可以通过修改 AndroidManifest.xml 文件来允许明文通信。

在 <application> 标签中添加以下属性:

 android:usesCleartextTraffic="true"

   <application
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:roundIcon="@mipmap/ic_launcher_round"
       android:supportsRtl="true"
       android:theme="@style/Theme.WebTTest"
       android:usesCleartextTraffic="true"> <!-- 允许明文通信 -->
   </application>