Encapsulamento de Requisições HTTP em Android com HttpURLConnection

Este artigo apresenta uma classe Java para Android que encapsula requisições HTTP, inspirada na biblioteca Axios, utilizanod a classe HttpURLConnection nativa do Android.

Modo de Uso

A biblioteca oferece métodos simplificados para realizar requisições GET e POST, com suporte a parâmetros e tratamento de respostsa através de um calllback.


// Instanciação e uso básico:
// axiosGH(url, callback) // Requisição GET por padrão
// axiosGH.get(url, callback)
// axiosGH.get(url, params, callback)
// axiosGH.post(url, callback)
// axiosGH.post(url, params, callback)

// Exemplo de requisição POST:
axiosGH.post(serverUrl + "/user/login", params, new AxiosGH.Callback() {
    @Override
    public void onSuccess(String response) {
      // Processar resposta de sucesso
        System.out.println(response);
    }
    @Override
    public void onFailed(String error) {
      // Processar falha na requisição
        System.out.println(error);
    }
});

Código Fonte


package com.guhun.server;

import android.annotation.SuppressLint;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import androidx.annotation.NonNull;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Classe de encapsulamento de requisições HTTP para Android, inspirada no Axios.
 * Utiliza HttpURLConnection internamente.
 */
public class AxiosGH {
    private String requestMethod;
    private boolean useCaches;
    private String serverUrl;
    private int connectTimeout;
    private String encode;

    /**
     * Construtor padrão. Inicializa as configurações.
     */
    public AxiosGH(){
        initializeDefaults();
    }

    /**
     * Construtor para requisições GET diretas.
     * @param url O endereço da URL para a requisição.
     * @param callback O objeto de callback para tratar a resposta.
     */
    public AxiosGH(String url, Callback callback){
        initializeDefaults();
        this.serverUrl = url;
        processRequest(null, callback);
    }

    /**
     * Executa uma requisição GET.
     * @param url O endereço da URL.
     * @param callback O callback para a resposta.
     */
    public void get(String url, Callback callback){
        this.serverUrl = url;
        processRequest(null, callback);
    }

    /**
     * Executa uma requisição GET com parâmetros em formato Map.
     * @param url O endereço da URL.
     * @param params Parâmetros da requisição como um Map.
     * @param callback O callback para a resposta.
     */
    public void get(String url, Map<String, Object> params, Callback callback){
        this.serverUrl = url;
        processRequest(params, callback);
    }

    /**
     * Executa uma requisição GET com parâmetros de um objeto Java.
     * @param url O endereço da URL.
     * @param params Objeto contendo os parâmetros da requisição.
     * @param callback O callback para a resposta.
     */
    public void get(String url, Object params, Callback callback) {
        this.serverUrl = url;
        processRequest(convertObjectToMap(params), callback);
    }

    /**
     * Executa uma requisição POST.
     * @param url O endereço da URL.
     * @param callback O callback para a resposta.
     */
    public void post(String url, Callback callback){
        this.requestMethod = "POST";
        this.serverUrl = url;
        processRequest(null, callback);
    }

    /**
     * Executa uma requisição POST com parâmetros em formato Map.
     * @param url O endereço da URL.
     * @param params Parâmetros da requisição como um Map.
     * @param callback O callback para a resposta.
     */
    public void post(String url, Map<String, Object> params, Callback callback){
        this.requestMethod = "POST";
        this.serverUrl = url;
        processRequest(params, callback);
    }

    /**
     * Executa uma requisição POST com parâmetros de um objeto Java.
     * @param url O endereço da URL.
     * @param params Objeto contendo os parâmetros da requisição.
     * @param callback O callback para a resposta.
     */
    public void post(String url, Object params, Callback callback) {
        this.requestMethod = "POST";
        this.serverUrl = url;
        processRequest(convertObjectToMap(params), callback);
    }

    /**
     * Define os valores padrão para as configurações da requisição.
     */
    private void initializeDefaults(){
        this.requestMethod = "GET";
        this.useCaches = false;
        this.connectTimeout = 3000;
        this.encode = "utf-8";
    }

    /**
     * Gerencia a criação da thread e o tratamento da mensagem de retorno.
     * @param params Parâmetros da requisição.
     * @param callback O callback para a resposta.
     */
    private void processRequest(Map<String, Object> params, Callback callback){
        @SuppressLint("HandlerLeak")
        final Handler uiHandler = new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                if (msg.obj != null) {
                    callback.onSuccess((String) msg.obj);
                } else {
                    callback.onFailed("Erro desconhecido");
                }
            }
        };

        new Thread(() -> {
            try {
                String responseData = executeHttpRequest(params);
                Message message = new Message();
                message.obj = responseData;
                uiHandler.sendMessage(message);
            } catch (Exception e) {
                e.printStackTrace();
                callback.onFailed("Exceção: " + e.getMessage());
            }
        }).start();
    }

    /**
     * Executa a requisição HTTP real.
     * @param params Parâmetros da requisição.
     * @return A resposta da requisição como String.
     * @throws Exception Em caso de erro na comunicação.
     */
    private String executeHttpRequest(Map<String, Object> params) throws Exception {
        String requestBody = null;
        if(params != null){
             requestBody = formatRequestData(params, encode).toString();
        }

        // Adiciona parâmetros à URL se for requisição GET
        if(requestMethod.equals("GET") && requestBody != null){
            serverUrl += '?' + requestBody;
        }

        URL url = new URL(serverUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        connection.setRequestMethod(requestMethod);
        connection.setConnectTimeout(connectTimeout);

        if(requestMethod.equals("POST")){
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(useCaches);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Content-Length", String.valueOf(requestBody != null ? requestBody.getBytes().length : 0));

            if (requestBody != null) {
                try (OutputStream outputStream = connection.getOutputStream()) {
                    outputStream.write(requestBody.getBytes());
                }
            }
        }

        int responseCode = connection.getResponseCode();
        if(responseCode == HttpURLConnection.HTTP_OK) {
            try (InputStream inputStream = connection.getInputStream();
                 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    byteArrayOutputStream.write(buffer, 0, bytesRead);
                }
                return new String(byteArrayOutputStream.toByteArray(), encode);
            }
        } else {
            throw new IOException("Código de resposta do servidor: " + responseCode);
        }
    }

    /**
     * Formata os parâmetros para serem enviados no corpo da requisição ou na URL.
     * @param params Mapa de parâmetros.
     * @param encoding Codificação a ser usada.
     * @return Um StringBuffer com os parâmetros formatados.
     */
    private static StringBuffer formatRequestData(Map<String, Object> params, String encoding) {
        StringBuffer stringBuffer = new StringBuffer();
        for(Map.Entry<String, Object> entry : params.entrySet()) {
            stringBuffer.append(entry.getKey())
                    .append("=")
                    .append(Uri.encode(String.valueOf(entry.getValue()), encoding))
                    .append("&");
        }
        // Remove o último '&' se houver parâmetros
        if (stringBuffer.length() > 0) {
            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        }
        return stringBuffer;
    }

    /**
     * Interface de callback para tratamento de sucesso e falha.
     */
    public interface Callback{
        void onSuccess(String res);
        void onFailed(String err);
    }

    /**
    * Converte um objeto Java em um Map, acessando seus campos via reflexão.
    * @param obj O objeto a ser convertido.
    * @return Um Map representando os campos do objeto.
    */
    public static Map<String, Object> convertObjectToMap(Object obj) {
        Map<String, Object> map = new HashMap<>();
        if (obj == null) return map;

        Class<?> clazz = obj.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true); // Permite acesso a campos privados
            String fieldName = field.getName();
            Object value = null;
            try {
                value = field.get(obj);
            } catch (IllegalAccessException e) {
                // Logar o erro ou tratar de forma apropriada
                e.printStackTrace();
            }
            map.put(fieldName, value);
        }
        return map;
    }

    // --- Métodos Setters para Configuração ---

    /**
     * Define o método da requisição (GET, POST, etc.).
     * @param requestMethod O método HTTP.
     */
    public void setRequestMethod(String requestMethod) {
        this.requestMethod = requestMethod;
    }

    /**
     * Define se o cache deve ser utilizado.
     * @param useCaches true para habilitar cache, false caso contrário.
     */
    public void setUseCaches(boolean useCaches) {
        this.useCaches = useCaches;
    }

    /**
     * Define a URL base para as requisições.
     * @param serverUrl A URL do servidor.
     */
    public void setServerUrl(String serverUrl) {
        this.serverUrl = serverUrl;
    }

    /**
     * Define o tempo limite de conexão em milissegundos.
     * @param connectTimeout O tempo limite.
     */
    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    /**
     * Define a codificação de caracteres a ser utilizada.
     * @param encode A codificação (ex: "utf-8").
     */
    public void setEncode(String encode) {
        this.encode = encode;
    }
}

Tags: android HttpURLConnection Networking java

Publicado em 7-29 23:19