Android 之 网络通信(HTTP/TCP/UDP/JSON)

1.HTTP请求

OkHttp

OkHttpUtils 的全面使用指南,整合多个来源的最佳实践,涵盖依赖配置、基础请求、文件操作、高级功能及注意事项,帮助开发者快速上手并避免常见问题。

​一、依赖配置​

在项目的 build.gradle 中添加依赖:

Groovy 复制代码
dependencies {
    // 核心库(必选)
    implementation 'com.lzy.net:okhttputils:3.0.4'
    // 扩展库(按需添加)
    implementation 'com.lzy.net:okrx2:2.0.2'      // RxJava2 支持
    implementation 'com.lzy.net:okserver:2.0.5'    // 下载/上传管理
}

​二、基本使用

​1. GET 请求​
Groovy 复制代码
OkHttpUtils.get("https://api.example.com/data")
    .tag(this)                          // 设置请求标签(用于取消)
    .params("page", "1")                // 添加URL参数
    .headers("Authorization", "token123") // 添加请求头
    .execute(new StringCallback() {
        @Override
        public void onSuccess(Response<String> response) {
            // 请求成功处理
            String data = response.body();
        }

        @Override
        public void onError(Response<String> response) {
            // 请求失败处理
        }
    });
2. POST 请求(表单)
Groovy 复制代码
Map<String, String> params = new HashMap<>();
params.put("username", "admin");
params.put("password", "123456");

OkHttpUtils.post("https://api.example.com/login")
    .tag(this)
    .params(params)                     // 添加表单参数
    .execute(new JsonCallback<User>(User.class) { // 自动解析为JavaBean
        @Override
        public void onSuccess(Response<User> response) {
            User user = response.body();
        }
    });
​3. POST JSON 数据​
Groovy 复制代码
String json = new Gson().toJson(new User("admin", "123456"));
OkHttpUtils.post("https://api.example.com/login")
    .postJson(json)                     // 直接提交JSON字符串
    .execute(new StringCallback());
4. 文件上传​
Groovy 复制代码
File file = new File(Environment.getExternalStorageDirectory(), "test.jpg");
OkHttpUtils.post("https://api.example.com/upload")
    .addFile("file", file.getName(), file) // 参数名、文件名、文件对象
    .execute(new StringCallback() {
        @Override
        public void onSuccess(Response<String> response) {
            // 上传成功
        }
    });
5.文件下载
Groovy 复制代码
OkHttpUtils.get("https://example.com/file.zip")
    .execute(new FileCallback("/sdcard/download/", "file.zip") {
        @Override
        public void onSuccess(Response<File> response) {
            File file = response.body(); // 下载完成
        }

        @Override
        public void downloadProgress(long currentSize, long totalSize, float progress) {
            // 进度回调(UI线程)
            progressBar.setProgress((int) (100 * progress));
        }
    });
6.高级功能,全局配置
Groovy 复制代码
public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        OkHttpUtils.init(this);
        OkHttpUtils.getInstance()
            .setConnectTimeout(30_000)    // 连接超时
            .setReadTimeout(30_000)       // 读取超时
            .addCommonHeader("App-Version", BuildConfig.VERSION_NAME) // 公共请求头
            .setCertificates(getAssets().open("server.cer")); // HTTPS自签名证书[1](@ref)
    }
}
7.高级功能,配置拦截器
Groovy 复制代码
public class TokenInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request()
            .newBuilder()
            .header("token", "user_token")
            .build();
        return chain.proceed(request);
    }
}

// 配置拦截器
OkHttpClient client = OkHttpUtils.getInstance().getOkHttpClient()
    .newBuilder()
    .addInterceptor(new TokenInterceptor())
    .build();
OkHttpUtils.initClient(client);

Retrofit

​一、依赖配置

java 复制代码
dependencies {
    // Retrofit 核心库
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'  // [2,3,4](@ref)
    // Gson 转换器(JSON 解析)
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'  // [1,3,4](@ref)
    // OkHttp 底层支持(含日志拦截器)
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'  // [1,8](@ref)
}

二**、基本使用**

1.封装实现(核心类)
java 复制代码
public class RetrofitClient {
    private static final int TIMEOUT = 30; // 超时时间(秒)
    private static volatile Retrofit retrofit;

    // 构建全局唯一 Retrofit 实例
    public static Retrofit getInstance(String baseUrl) {
        if (retrofit == null) {
            synchronized (RetrofitClient.class) {
                if (retrofit == null) {
                    retrofit = new Retrofit.Builder()
                        .baseUrl(baseUrl)
                        .client(initOkHttpClient()) // 配置OkHttp
                        .addConverterFactory(GsonConverterFactory.create())
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava
                        .build();
                }
            }
        }
        return retrofit;
    }

    // 配置OkHttp(含日志拦截器+超时设置)
    private static OkHttpClient initOkHttpClient() {
        return new OkHttpClient.Builder()
            .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            .connectTimeout(TIMEOUT, TimeUnit.SECONDS)
            .readTimeout(TIMEOUT, TimeUnit.SECONDS)
            .writeTimeout(TIMEOUT, TimeUnit.SECONDS)
            .build();
    }
}

关键特性​​:

双检锁单例模式确保线程安全 
统一超时和日志拦截配置
支持 RxJava 响应式编程
2. API 服务接口定义​
java 复制代码
public interface ApiService {
    @GET("users/{id}")
    Observable<User> getUserById(@Path("id") int userId); // RxJava Observable

    @POST("login")
    @FormUrlEncoded
    Observable<LoginResponse> login(
        @Field("username") String username,
        @Field("password") String password
    );
}
3. 网络请求基类(封装通用逻辑)
java 复制代码
public abstract class BaseRepository {
    protected ApiService apiService;

    public BaseRepository() {
        apiService = RetrofitClient.getInstance("https://api.example.com/")
                                  .create(ApiService.class);
    }

    // 统一错误处理
    protected <T> Observable<T> handleRequest(Observable<T> observable) {
        return observable.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .onErrorResumeNext(throwable -> {
                // 统一转换网络错误
                if (throwable instanceof SocketTimeoutException) {
                    return Observable.error(new NetworkException("连接超时"));
                } else if (throwable instanceof ConnectException) {
                    return Observable.error(new NetworkException("服务器不可达"));
                }
                return Observable.error(throwable);
            });
    }
}
4.调用示例
java 复制代码
public class UserRepository extends BaseRepository {
    
    // 获取用户信息
    public Observable<User> getUser(int userId) {
        return handleRequest(apiService.getUserById(userId));
    }

    // 登录操作
    public Observable<LoginResponse> login(String username, String password) {
        return handleRequest(apiService.login(username, password));
    }
}
5. Activity 中调用
java 复制代码
public class MainActivity extends AppCompatActivity {
    private CompositeDisposable disposables = new CompositeDisposable();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        UserRepository userRepo = new UserRepository();
        
        // 请求用户数据
        disposables.add(userRepo.getUser(123)
            .subscribe(user -> {
                Log.d("MainActivity", "用户名称: " + user.getName());
            }, error -> {
                Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show();
            }));
        
        // 登录请求
        userRepo.login("admin", "123456")
            .subscribe(response -> {
                if (response.isSuccess()) {
                    startActivity(new Intent(this, HomeActivity.class));
                }
            });
    }

    @Override
    protected void onDestroy() {
        disposables.clear(); // 防止内存泄漏
        super.onDestroy();
    }
}
6.文件上传/下载
java 复制代码
@Multipart
@POST("upload")
Observable<ResponseBody> uploadFile(@Part MultipartBody.Part file);

// 调用示例:
File file = new File("/sdcard/photo.jpg");
RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);
apiService.uploadFile(body);

2.Json解析

Gson

基于Gson封装的工具类及使用示例,支持复杂数据结构(嵌套对象、泛型集合等),并包含详细注释和最佳实践

​一、依赖配置​

在项目的 build.gradle 中添加依赖:

Groovy 复制代码
dependencies {
    implementation 'com.google.code.gson:gson:2.10.1'
}

二**、**基本使用

1.工具类封装
Groovy 复制代码
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * Gson工具类(线程安全)
 * 功能:对象与JSON互转、泛型集合处理、格式化输出
 */
public class GsonUtils {
    // 单例模式 + 自定义配置(格式化/序列化空值)
    private static final Gson GSON = new GsonBuilder()
        .setPrettyPrinting()    // 格式化JSON(便于阅读)
        .serializeNulls()       // 序列化null值字段
        .create();

    /**
     * 对象转JSON字符串
     * @param object Java对象
     * @return JSON字符串
     */
    public static String toJson(Object object) {
        return GSON.toJson(object);
    }

    /**
     * JSON字符串转对象
     * @param json  JSON字符串
     * @param clazz 目标对象的Class
     * @param <T>   目标类型
     * @return 解析后的对象
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        return GSON.fromJson(json, clazz);
    }

    /**
     * JSON转List(支持泛型)
     * @param json  JSON字符串
     * @param clazz List元素的Class
     * @param <T>   元素类型
     * @return 解析后的List
     */
    public static <T> List<T> fromJsonToList(String json, Class<T> clazz) {
        Type type = TypeToken.getParameterized(List.class, clazz).getType();
        return GSON.fromJson(json, type);
    }

    /**
     * JSON转Map(支持泛型)
     * @param json JSON字符串
     * @return 解析后的Map
     */
    public static <K, V> Map<K, V> fromJsonToMap(String json) {
        Type type = new TypeToken<Map<K, V>>() {}.getType();
        return GSON.fromJson(json, type);
    }
}
2.使用示例(含复杂数据结构)
Groovy 复制代码
public class User {
    private String name;
    private int age;
    private Address address;          // 嵌套对象
    private List<String> hobbies;     // List字段
    private Map<String, String> metadata; // Map字段

    // 必须有无参构造方法(Gson反序列化需要)[2](@ref)
    public User() {}

    // Getter/Setter方法省略(实际开发中需补充)
}

public class Address {
    private String city;
    private String zipCode;
    
    public Address() {}
    // Getter/Setter省略
}
3. 序列化(对象 → JSON)
java 复制代码
// 构建复杂对象
Address address = new Address("New York", "10001");
List<String> hobbies = Arrays.asList("Reading", "Traveling");
Map<String, String> metadata = new HashMap<>();
metadata.put("role", "admin");
metadata.put("department", "IT");

User user = new User("John", 25, "john@example.com", address, hobbies, metadata);

// 转换为JSON(格式化输出)
String json = GsonUtils.toJson(user);
System.out.println(json);
4.输出结果​
java 复制代码
{
  "name": "John",
  "age": 25,
  "email": "john@example.com",
  "address": {
    "city": "New York",
    "zipCode": "10001"
  },
  "hobbies": ["Reading", "Traveling"],
  "metadata": {
    "role": "admin",
    "department": "IT"
  }
}
5. 反序列化(JSON → 对象)​
java 复制代码
// JSON字符串转对象
String json = "{\"name\":\"Alice\",\"age\":30,\"address\":{\"city\":\"Paris\"}}";
User user = GsonUtils.fromJson(json, User.class);
System.out.println(user.getAddress().getCity()); // 输出:Paris

// JSON转List(泛型支持)
String listJson = "[{\"name\":\"Bob\"}, {\"name\":\"Charlie\"}]";
List<User> userList = GsonUtils.fromJsonToList(listJson, User.class);
System.out.println(userList.size()); // 输出:2

// JSON转Map
String mapJson = "{\"key1\":\"value1\", \"key2\":\"value2\"}";
Map<String, String> map = GsonUtils.fromJsonToMap(mapJson);
System.out.println(map.get("key2")); // 输出:value2
6.日常使用
java 复制代码
1.定制工具类

 public final class JSONUtils {
 //解析jsonobject,以{}开头和结尾
	public static <T> T parseJSON(String jsonStr, Class<T> t) {
		Gson gson = new Gson();
		T bean = gson.fromJson(jsonStr, t);
		return bean;
	}

	/**
	 * //jsonarry,以[]开头和结尾
	 * @param response
	 * @param type
	 *           Type type = new TypeToken< ArrayList<实体类名>>() {  }.getType();
	//							 *          
	 * @return
	 */
	public static <T> T parseJSONArray(String response, Type type) {
		Gson gson = new Gson();
		T data = gson.fromJson(response, type);
		return data;
	}
	//把map转为String,很少用
	public static <T> String mapToJson(Map<String, T> map) {
		Gson gson = new Gson();
		String jsonStr = gson.toJson(map);
		return jsonStr;
	}

}



2.Java Bean

public class Man {


    /**
     * name : 张三
     * age : 18
     */

    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

2.准备字符串数据

{"error_code":10005,"reason":"应用未审核超时,请提交认证"}

3.解析字符串数据
 
  Man man = JSONUtils.parseJSON(ST, Man.class);
  //获得错误码
  int error_code = man.getError_code();
  //错误原因
   String reason = man.getReason();
 

4.准备数组数据
[
    {
        "name": "张三",
        "age": 18
    },
    {
        "name": "李四",
        "age": 19
    }
]




5.解析数组数据


 Type type = new TypeToken<ArrayList<Man>>() {  }.getType();
 //获得了一个Man(类名)的集合
                ArrayList<Man> first  = JSONUtils.parseJSONArray(st, type);
                 //获得第一个人的年龄
                int age = first.get(0).getAge();
                Log.e("888", ""+age);
                打印下是18岁哦!

注意导包导这个,不然会出错
import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;
 

Jackson

​一、依赖配置​

在项目的 build.gradle 中添加依赖:

Groovy 复制代码
//jackson-databind:核心库(自动包含jackson-core和jackson-annotations)
//jackson-datatype-jsr310:支持LocalDateTime等Java 8日期类型

dependencies {
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'
    implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2'
}

二**、**基本使用

1.工具类封装
java 复制代码
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

public class JacksonUtil {
    private static final ObjectMapper mapper = new ObjectMapper();

    static {
        // 基础配置
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略未知字段[6](@ref)
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略null字段[7](@ref)
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); // 统一日期格式
        
        // 注册Java 8日期模块
        mapper.registerModule(new JavaTimeModule()); 
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 禁用时间戳格式[7](@ref)
    }

    // 对象 → JSON字符串
    public static String toJson(Object obj) {
        try {
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON序列化失败", e);
        }
    }

    // JSON字符串 → 对象
    public static <T> T toObject(String json, Class<T> clazz) {
        try {
            return mapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON反序列化失败", e);
        }
    }

    // JSON字符串 → 复杂集合(如List<User>)
    public static <T> List<T> toList(String json, Class<T> elementClass) {
        try {
            return mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, elementClass));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("JSON转List失败", e);
        }
    }

    // JSON字符串 → 嵌套结构(如Map<String, List<Order>>)
    public static <T> T toComplexObject(String json, TypeReference<T> typeRef) {
        try {
            return mapper.readValue(json, typeRef);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("复杂结构转换失败", e);
        }
    }
}
2.基础对象转换​
java 复制代码
// 定义实体类
public class User {
    private String name;
    private Integer age;
    private LocalDateTime createTime;
    // Getter/Setter省略
}

// 序列化对象 → JSON
User user = new User("张三", 25, LocalDateTime.now());
String json = JacksonUtil.toJson(user); 
// 输出: {"name":"张三","age":25,"createTime":"2025-08-03 14:30:00"} [3](@ref)

// 反序列化 JSON → 对象
User parsedUser = JacksonUtil.toObject(json, User.class);
System.out.println(parsedUser.getName()); // 输出: 张三
3.集合处理
java 复制代码
// List序列化
List<User> userList = Arrays.asList(
    new User("李四", 30, null),
    new User("王五", 28, LocalDateTime.now())
);
String listJson = JacksonUtil.toJson(userList);
// 输出: [{"name":"李四","age":30},{"name":"王五","age":28,"createTime":"2025-08-03 14:35:00"}]

// List反序列化
List<User> parsedList = JacksonUtil.toList(listJson, User.class);
4. 工具类方法总结

fastjson

​一、依赖配置​

在项目的 build.gradle 中添加依赖:

Groovy 复制代码
//jackson-databind:核心库(自动包含jackson-core和jackson-annotations)
//jackson-datatype-jsr310:支持LocalDateTime等Java 8日期类型

dependencies {
    implementation 'com.alibaba:fastjson:2.0.39'
}

二**、**基本使用

1.工具类封装
java 复制代码
import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.filter.Filter;
import java.util.List;

public class FastJsonUtil {
    private static final ParserConfig SAFE_PARSER_CONFIG;

    static {
        // 安全配置:启用安全模式,禁止反序列化任意类 [7](@ref)
        SAFE_PARSER_CONFIG = new ParserConfig();
        SAFE_PARSER_CONFIG.setSafeMode(true);
        
        // 可选:设置白名单(仅允许指定包下的类)[7](@ref)
        SAFE_PARSER_CONFIG.addAccept("com.yourpackage.model.");
    }

    // 对象 → JSON 字符串(默认配置)
    public static String toJson(Object obj) {
        return JSON.toJSONString(obj);
    }

    // 对象 → JSON 字符串(自定义配置)
    public static String toJson(Object obj, JSONWriter.Feature... features) {
        return JSON.toJSONString(obj, features);
    }

    // JSON 字符串 → 对象(安全模式)
    public static <T> T toBean(String json, Class<T> clazz) {
        return JSON.parseObject(json, clazz, SAFE_PARSER_CONFIG);
    }

    // JSON 字符串 → 泛型集合(如 List<User>)
    public static <T> List<T> toList(String json, Class<T> clazz) {
        return JSON.parseArray(json, clazz, SAFE_PARSER_CONFIG);
    }

    // JSON 字符串 → 复杂嵌套结构(如 Map<String, List>)
    public static <T> T toComplexType(String json, TypeReference<T> typeRef) {
        return JSON.parseObject(json, typeRef, SAFE_PARSER_CONFIG);
    }
}
2. ​​基础对象转换
java 复制代码
// 定义实体类
public class User {
    @JSONField(name = "user_name") // 自定义字段名 [6,7](@ref)
    private String name;
    
    @JSONField(serialize = false) // 忽略序列化 [6](@ref)
    private String password;
    
    @JSONField(format = "yyyy-MM-dd") // 日期格式化 [7](@ref)
    private Date birthDate;
    
    // Getter/Setter 省略
}

// 序列化对象 → JSON
User user = new User("张三", "123456", new Date());
String json = FastJsonUtil.toJson(user); 
// 输出:{"user_name":"张三","birthDate":"2025-08-03"}

// 反序列化 JSON → 对象
User parsedUser = FastJsonUtil.toBean(json, User.class);
System.out.println(parsedUser.getName()); // 输出:张三
3. ​​集合处理​
java 复制代码
// List 序列化与反序列化
List<User> userList = Arrays.asList(
    new User("李四", null, null),
    new User("王五", "abc", new Date())
);
String listJson = FastJsonUtil.toJson(userList, JSONWriter.Feature.PrettyFormat);

List<User> parsedList = FastJsonUtil.toList(listJson, User.class);

3.TCP通信

netty

​一、依赖配置

build.gradle中配置最新Netty依赖:

复制代码
dependencies {
    implementation 'io.netty:netty-all:4.1.97.Final' // 截至2025年8月最新稳定版[4,6](@ref)
}

二**、基本使用**

1. 封装工具类

java 复制代码
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class NettyClient {
    private static final int RECONNECT_DELAY = 3; // 重连间隔(秒)
    private EventLoopGroup workerGroup;
    private Channel channel;
    private final String host;
    private final int port;
    private NettyListener listener;

    public NettyClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    // 初始化连接
    public void connect() {
        workerGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(workerGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new StringDecoder());   // 字符串解码
                            pipeline.addLast(new StringEncoder());   // 字符串编码
                            pipeline.addLast(new ClientHandler(listener)); // 业务处理器
                        }
                    });
            
            // 异步连接
            ChannelFuture future = bootstrap.connect(host, port).addListener((ChannelFutureListener) f -> {
                if (!f.isSuccess()) scheduleReconnect(); // 连接失败触发重连
            });
            channel = future.sync().channel();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    // 消息发送
    public void sendMessage(String msg) {
        if (channel != null && channel.isActive()) {
            channel.writeAndFlush(msg);
        }
    }

    // 重连机制
    private void scheduleReconnect() {
        workerGroup.schedule(this::connect, RECONNECT_DELAY, TimeUnit.SECONDS);
    }

    // 释放资源
    public void shutdown() {
        if (channel != null) channel.close();
        if (workerGroup != null) {
            Future<?> future = workerGroup.shutdownGracefully();
            future.syncUninterruptibly();
        }
    }

    // 设置消息监听器
    public void setListener(NettyListener listener) {
        this.listener = listener;
    }

    // 内部处理器
    private static class ClientHandler extends SimpleChannelInboundHandler<String> {
        private final NettyListener listener;

        ClientHandler(NettyListener listener) {
            this.listener = listener;
        }

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) {
            if (listener != null) listener.onMessageReceived(msg); // 消息回调
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx) {
            if (listener != null) listener.onConnectionStatusChanged(true); // 连接建立
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) {
            if (listener != null) listener.onConnectionStatusChanged(false); // 连接断开
        }
    }

    // 状态监听接口
    public interface NettyListener {
        void onMessageReceived(String message);
        void onConnectionStatusChanged(boolean isConnected);
    }
}

2. Activity调用示例

java 复制代码
public class MainActivity extends AppCompatActivity implements NettyClient.NettyListener {
    private NettyClient nettyClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 初始化Netty客户端
        nettyClient = new NettyClient("192.168.1.100", 8080);
        nettyClient.setListener(this);
        new Thread(() -> nettyClient.connect()).start(); // 在子线程启动连接

        // 发送消息示例
        findViewById(R.id.btn_send).setOnClickListener(v -> {
            String msg = "Hello Server!";
            nettyClient.sendMessage(msg);
        });
    }

    // 实现监听回调
    @Override
    public void onMessageReceived(final String message) {
        runOnUiThread(() -> {
            TextView tv = findViewById(R.id.tv_response);
            tv.setText("收到: " + message); // 主线程更新UI
        });
    }

    @Override
    public void onConnectionStatusChanged(final boolean isConnected) {
        runOnUiThread(() -> {
            String status = isConnected ? "已连接" : "连接断开";
            Toast.makeText(this, "状态: " + status, Toast.LENGTH_SHORT).show();
        });
    }

    @Override
    protected void onDestroy() {
        nettyClient.shutdown(); // 释放资源防止内存泄漏
        super.onDestroy();
    }
}

4.心跳保活

java 复制代码
在ClientHandler中添加:
// 每30秒发送心跳
ctx.executor().scheduleAtFixedRate(() -> 
    ctx.writeAndFlush("HEARTBEAT"), 0, 30, TimeUnit.SECONDS
);

4.UDP通信

netty

​一、依赖配置

build.gradle中配置最新Netty依赖:

复制代码
dependencies {
    implementation 'io.netty:netty-all:4.1.97.Final' // 截至2025年8月最新稳定版[4,6](@ref)
}

二**、基本使用**

​1. UDP工具类封装

java 复制代码
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Netty UDP 客户端工具类
 * 功能:消息发送、接收回调、资源释放
 */
public class UdpClient {
    private final Bootstrap bootstrap;
    private final NioEventLoopGroup group;
    private Channel channel;
    private final ExecutorService threadPool;
    private UdpListener listener;

    public UdpClient() {
        group = new NioEventLoopGroup();
        bootstrap = new Bootstrap();
        threadPool = Executors.newSingleThreadExecutor();
        
        bootstrap.group(group)
            .channel(NioDatagramChannel.class)
            .option(ChannelOption.SO_BROADCAST, true) // 支持广播
            .handler(new ChannelInitializer<NioDatagramChannel>() {
                @Override
                protected void initChannel(NioDatagramChannel ch) {
                    ch.pipeline().addLast(new SimpleChannelInboundHandler<DatagramPacket>() {
                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) {
                            // 主线程回调 → 子线程处理
                            threadPool.execute(() -> {
                                String msg = packet.content().toString(CharsetUtil.UTF_8);
                                if (listener != null) {
                                    listener.onMessageReceived(msg);
                                }
                            });
                        }
                    });
                }
            });
    }

    /**
     * 绑定本地端口(Android需动态申请端口)
     * @param port 本地端口(0表示随机端口)
     */
    public void bind(int port) {
        threadPool.execute(() -> {
            try {
                ChannelFuture future = bootstrap.bind(port).sync();
                channel = future.channel();
                if (listener != null) listener.onBindSuccess(port);
            } catch (Exception e) {
                if (listener != null) listener.onError(e);
            }
        });
    }

    /**
     * 发送消息
     * @param targetIp   目标IP
     * @param targetPort 目标端口
     * @param message    消息内容
     */
    public void send(String targetIp, int targetPort, String message) {
        if (channel == null || !channel.isActive()) return;
        
        threadPool.execute(() -> {
            try {
                ByteBuf buf = Unpooled.copiedBuffer(message, CharsetUtil.UTF_8);
                InetSocketAddress target = new InetSocketAddress(targetIp, targetPort);
                channel.writeAndFlush(new DatagramPacket(buf, target));
            } catch (Exception e) {
                if (listener != null) listener.onError(e);
            }
        });
    }

    /**
     * 释放资源
     */
    public void shutdown() {
        if (channel != null) channel.close();
        group.shutdownGracefully();
        threadPool.shutdown();
    }

    /**
     * 设置事件监听
     */
    public void setListener(UdpListener listener) {
        this.listener = listener;
    }

    public interface UdpListener {
        void onBindSuccess(int localPort); // 绑定成功
        void onMessageReceived(String msg); // 收到消息
        void onError(Throwable cause);      // 发生异常
    }
}

​2. Activity调用示例​

java 复制代码
public class MainActivity extends AppCompatActivity implements UdpClient.UdpListener {
    private UdpClient udpClient;
    private TextView tvStatus;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvStatus = findViewById(R.id.tv_status);

        // 1. 初始化UDP客户端
        udpClient = new UdpClient();
        udpClient.setListener(this);
        udpClient.bind(0); // 绑定随机端口

        // 2. 发送消息示例
        findViewById(R.id.btn_send).setOnClickListener(v -> {
            String ip = "192.168.1.100"; // 目标服务器IP
            int port = 8080;            // 目标服务器端口
            String msg = "Hello UDP!";
            udpClient.send(ip, port, msg);
        });
    }

    // 3. 实现监听回调
    @Override
    public void onBindSuccess(final int localPort) {
        runOnUiThread(() -> tvStatus.setText("本地端口: " + localPort));
    }

    @Override
    public void onMessageReceived(final String msg) {
        runOnUiThread(() -> Toast.makeText(this, "收到: " + msg, Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onError(final Throwable cause) {
        runOnUiThread(() -> tvStatus.setText("错误: " + cause.getMessage()));
    }

    @Override
    protected void onDestroy() {
        udpClient.shutdown(); // 释放资源
        super.onDestroy();
    }
}

3.注意权限

XML 复制代码
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

4.注意

Android 9+ 默认禁用UDP广播,需在代码中开启:

java 复制代码
bootstrap.option(ChannelOption.SO_BROADCAST, true);

**5.**WebService

ksoap2-android

​一、依赖配置

build.gradle中配置最新Netty依赖:

Groovy 复制代码
implementation 'com.google.code.ksoap2-android:ksoap2-android:3.6.4'

二**、基本使用**

1. 封装工具类

java 复制代码
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SoapClientUtil {
    private static final String DEFAULT_NAMESPACE = "http://example.com/";
    private static final String DEFAULT_URL = "http://example.com/soap-endpoint";
    private static final int THREAD_POOL_SIZE = 5;
    private static ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

    // 异步请求(推荐)
    public static void callAsync(String methodName, Map<String, Object> params, 
                                boolean isDotNet, SoapCallback callback) {
        threadPool.submit(() -> {
            try {
                Object result = callSync(methodName, params, isDotNet);
                callback.onSuccess(result);
            } catch (Exception e) {
                callback.onError(e);
            }
        });
    }

    // 同步请求
    public static Object callSync(String methodName, Map<String, Object> params, 
                                 boolean isDotNet) throws Exception {
        SoapObject request = new SoapObject(DEFAULT_NAMESPACE, methodName);
        
        // 添加请求参数
        if (params != null) {
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                request.addProperty(entry.getKey(), entry.getValue());
            }
        }

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.setOutputSoapObject(request);
        envelope.dotNet = isDotNet; // 适配 .NET 平台

        HttpTransportSE transport = new HttpTransportSE(DEFAULT_URL);
        transport.debug = true; // 开启调试日志
        
        try {
            transport.call(DEFAULT_NAMESPACE + methodName, envelope);
            return envelope.getResponse(); // 返回原始响应(可转为 SoapObject/String)
        } catch (Exception e) {
            throw new RuntimeException("SOAP请求失败: " + e.getMessage());
        }
    }

    // 回调接口
    public interface SoapCallback {
        void onSuccess(Object result);
        void onError(Exception e);
    }
}

2. Activity调用示例

java 复制代码
// 初始化参数
String methodName = "getWeather";
Map<String, Object> params = new HashMap<>();
params.put("cityName", "Beijing");
boolean isDotNet = true; // .NET 服务需设为 true

// 发起异步请求
SoapClientUtil.callAsync(methodName, params, isDotNet, new SoapClientUtil.SoapCallback() {
    @Override
    public void onSuccess(Object result) {
        if (result instanceof SoapObject) {
            SoapObject response = (SoapObject) result;
            String temperature = response.getPropertyAsString("temperature");
            String weather = response.getPropertyAsString("weather");
            Log.d("SOAP", "北京天气: " + weather + ",温度: " + temperature);
        }
    }

    @Override
    public void onError(Exception e) {
        Log.e("SOAP", "请求失败: " + e.getMessage());
    }
});
相关推荐
LING14 分钟前
RN容器启动优化实践
android·react native
恋猫de小郭3 小时前
Flutter 发布官方 Skills ,Flutter 在 AI 领域再添一助力
android·前端·flutter
Kapaseker8 小时前
一杯美式搞懂 Any、Unit、Nothing
android·kotlin
黄林晴8 小时前
你的 Android App 还没接 AI?Gemini API 接入全攻略
android
恋猫de小郭18 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
冬奇Lab19 小时前
PowerManagerService(上):电源状态与WakeLock管理
android·源码阅读
BoomHe1 天前
Now in Android 架构模式全面分析
android·android jetpack
二流小码农1 天前
鸿蒙开发:上传一张参考图片便可实现页面功能
android·ios·harmonyos
鹏程十八少1 天前
4.Android 30分钟手写一个简单版shadow, 从零理解shadow插件化零反射插件化原理
android·前端·面试
Kapaseker1 天前
一杯美式搞定 Kotlin 空安全
android·kotlin