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());
    }
});
相关推荐
御水流红叶36 分钟前
安卓加固脱壳
android·开发语言·python
xq95272 小时前
android webview和 js 各种用法交互
android
北有花开4 小时前
Android方法耗时监控插件:基于ASM字节码插桩的性能分析工具
android
whysqwhw4 小时前
React Native应用中实现原生组件与JavaScript组件的复杂交互
android
whysqwhw4 小时前
React Native 中调用 Android 自定义控件
android
往事如烟隔多年4 小时前
一加Ace5无法连接ColorOS助手解决(安卓设备ADB模式无法连接)
android·adb·手机·coloros
00后程序员张4 小时前
iOS软件性能监控实战指南 开发到上线的完整流程解析
android·ios·小程序·https·uni-app·iphone·webview
2401_837088504 小时前
Axios介绍
android·okhttp
一杯凉白开4 小时前
Compose实现点击防抖,给Modifier添加扩展函数(含扩展函数的原理)
android