Skip to content

Instantly share code, notes, and snippets.

@Guilherme-HRamos
Created May 30, 2018 23:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Guilherme-HRamos/a56f96f3983a538847f9136c1932e94c to your computer and use it in GitHub Desktop.
Save Guilherme-HRamos/a56f96f3983a538847f9136c1932e94c to your computer and use it in GitHub Desktop.
Comunicação com a API que uso na Minerva
/**
* Minerva Aplicativos™.
* Classe criada por Guilherme Ramos em 2018
* Contato: +55 (16) 98134-5755
* www.aplicativosminerva.com
*/
public abstract class ApiRestBase {
static final String ERROR_401 = "Usuário não autorizado. Faça o login novamente";
static final String ERROR_DEFAULT = "Houve um erro. Mensagem: ";
protected static final String OFFLINE_ERROR_MESSAGE = "Não foi possível estabelecer conexão com a internet";
protected static final String ERROR_TIMED_OUT = "Não foi possível obter os dados do servidor. Cheque sua conexão ou tente novamente mais tarde";
protected static final String DEFAULT_UNSUCCESSFUL_ERROR = "Houve um erro no servidor. Por favor, tente novamente mais tarde";
/**
* Criando Endpoint para o retrofit
* @param model modelo de resposta
* @param header headers necessários para enviar
* @return interface endpoint onde estão armazenadas as requisições
*/
protected abstract Endpoints buildEndpointClass(Class model, OkHttpClient header);
/**
* Criando Endpoint para o retrofit
* @param model modelo de resposta
* @return interface endpoint onde estão armazenadas as requisições
*/
protected abstract Endpoints buildEndpointClass(Class model);
/**
* Configurando e iniciando a chamada na API
*/
protected abstract void onStart();
/**
* Fazendo a chamada
*/
protected abstract <T> void onRequest(Call<T> chamada);
/**
* Obtendo o corpo (body) da resposta da chamada
*/
protected abstract <T> void onSuccessful(Response<T> resposta);
/**
* Tentando obter o erro da chamada
*/
protected abstract <T> void onFailureConnection(Response<T> resposta);
/**
* Tentando obter o erro da chamada
*/
protected abstract <T> void onFailureConnection(Call<T> call, Throwable t);
}
import android.content.Context;
import android.support.annotation.Nullable;
import com.aplicativosminerva.projeto_exemplo.api.Endpoints;
import com.aplicativosminerva.projeto_exemplo.commom.base.api_base.ApiCallback;
import com.aplicativosminerva.projeto_exemplo.commom.base.api_base.ApiCallbackOffline;
import com.aplicativosminerva.projeto_exemplo.commom.base.api_base.MinervaApiRestBase;
import java.lang.reflect.Type;
import retrofit2.Call;
import retrofit2.Response;
/**
* Minerva Aplicativos™.
* Classe criada por Guilherme Ramos em 2018
* Contato: +55 (16) 98134-5755
* www.aplicativosminerva.com
*/
public class ExampleRequest extends MinervaApiRestBase {
private final static String tag = "example";
private ApiCallback<Void> callback;
protected Examplerequest(@Nullable Context context) {
super(context, tag);
}
/**
* Caso o uso seja online
* @param callback callback
*/
public void onRequestExample(ApiCallback<Void> callback) {
this.callback = callback;
onPrepare();
}
/**
* Caso o uso seja offline
* @param callback callback
*/
public void onRequestExample(ApiCallbackOffline<Void> callback) {
this.callback = callback;
onPrepare(callback, Void.class);
}
@Override
protected void onStart() {
super.onStart();
Endpoints endpoints = buildEndpointClass(Void.class);
Call<?> call = endpoints.onRequest();
onRequest(call);
}
@Override
protected <T> void onSuccessful(Response<T> resposta) {
super.onSuccessful(resposta);
Void result = (Void) resposta.body();
if (result != null)
callback.onSuccess(result);
else
callback.onFailure("null");
}
@Override
protected void onFailure(String message) {
callback.onFailure(message);
}
@Override
protected void isUserOffline() {
callback.onFailure(OFFLINE_ERROR_MESSAGE);
}
}
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.aplicativosminerva.projeto_exemplo.api.Endpoints;
import com.aplicativosminerva.projeto_exemplo.api.models.local.LoginCredentials;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.HashMap;
import java.util.List;
import br.vince.easysave.EasySave;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
/**
* Minerva Aplicativos™.
* Classe criada por Guilherme Ramos em 2018
* Contato: +55 (16) 98134-5755
* www.aplicativosminerva.com
*/
public abstract class MinervaApiRestBase extends ApiRestBase {
private final String TAG = "MINERVA API REST BASE";
private final Context context;
private final String key;
private int TIMED_OUT = 0;
/**
* booleano que indicará se o app está online ou offline
*/
protected final boolean isOnline;
/**
* Base das conexões que serão feitas com o webservice. Aqui estão os métodos base para que o
* app consiga fazer tratamento offline, online, erros, e etc., tentando ser tudo de forma
* automática
* @param context contexto usado apenas para salvar e reaver os dados offline
* @param key chave na qual será identificado o objeto a ser salvo ou reavisto offline pelo app
*/
protected MinervaApiRestBase(@Nullable Context context, @Nullable String key) {
this.context = context;
this.key = key;
isOnline = isConnected();
}
/**
* método a ser chamado quando o usuário estiver offline. Pode ser usado para, por exemplo,
* mostrar uma mensagem de falha de conexão. Usado em
* {@link MinervaApiRestBase#onPrepare()}
*/
protected abstract void isUserOffline();
/**
* Chamado para fazer as verificações do app (internet, dados offline e etc.). É o primeiro
* método que deve ser chamado para iniciar o trabalho com o webservice, ou seja, no construtor
* @param callbackOffline callback para caso o app esteja offline
* @param cType classe que será reavista caso o app esteja offline
* @param <T> tipo da classe a ser reavista (objeto de retorno do webservice)
*/
protected final <T> void onPrepare(ApiCallbackOffline<T> callbackOffline, Class<T> cType) {
if (isConnected())
onStart();
else {
callbackOffline.onOfflineData(retrieveDataForTag(cType));
isUserOffline();
}
}
/**
* Chamado para fazer as verificações do app (internet, dados offline e etc.). É o primeiro
* método que deve ser chamado para iniciar o trabalho com o webservice, ou seja, no construtor.
* Este método não salva e nem obtém dados offline, apenas avisa.
*/
protected final void onPrepare() {
if (isConnected())
onStart();
else {
isUserOffline();
}
}
/**
* Usado para construir a classe de Endpoint a ser usada.
* @param model modelo de resposta
* @param header headers necessários para enviar
* @return classe Endpoint
*/
@Override
protected final Endpoints buildEndpointClass(Class model, OkHttpClient header) {
Retrofit retrofit;
Gson gson = new GsonBuilder().registerTypeAdapter(model, new Seriazable(model)).create();
retrofit = RetrofitController.startRetrofitGsonAndHeader(gson, header);
return retrofit.create(Endpoints.class);
}
/**
* Usado para construit a classe de Endpoint a ser usada, e que não necessita de headers
* @param model modelo de resposta
* @return classe Endpoints
*/
@Override
protected final Endpoints buildEndpointClass(Class model) {
Retrofit retrofit;
Gson gson = new GsonBuilder().registerTypeAdapter(model, new Seriazable(model)).create();
retrofit = RetrofitController.startRetrofitGson(gson);
return retrofit.create(Endpoints.class);
}
/**
* Usado para iniciar a configuração da conexão com o webservice. Modo de uso:
* <pre> {@code
* Endpoints endpoints = buildEndpointClass(Classe_de_retorno.class, @optional Header_se_houver);
Call<?> call = endpoints.nome_do_endpoint();
onRequest(call);
* } </pre>
*/
@Override
protected void onStart() {
Log.d(TAG, "Connecting Server");
}
/**
* Resposta, caso houver sucesso na conexão com a api. Modo de uso:
*
* <pre>{@code
*
* Objeto result = (Objeto) response.body();
if (result != null)
callback.onSuccess(result);
else
callback.onFailure("null");
* }</pre>
* @param response resposta obtida do servidor
* @param <T> tipo da classe de resposta
*/
@Override
protected <T> void onSuccessful(Response<T> response) {
if (context != null && key != null) {
Log.d(TAG, key + " -> Conexão realizada com sucesso!");
saveDataForTag(response);
} else {
Log.d(TAG, "Conexão realizada com sucesso!");
}
}
@Override
protected final <T> void onRequest(Call<T> chamada) {
Log.d(TAG, "criando conexão");
chamada.enqueue(new Callback<T>() {
@Override
public void onResponse(@NonNull Call<T> call, @NonNull Response<T> response) {
Log.d(TAG, "-----> code: " + response.code());
Log.d(TAG, "-----> message: " + response.message());
switch (response.code()) {
case 200:
case 201:
case 204:
onSuccessful(response);
break;
case 401:
onFailureConnectionUserMessage(ERROR_401);
onFailureConnection(response);
break;
default:
onFailureConnection(response);
onFailureConnectionUserMessage(ERROR_DEFAULT + response.message());
}
}
@Override
public void onFailure(@NonNull Call<T> call, @NonNull Throwable t) {
onFailureConnection(call, t);
}
});
}
/**
* Obtenção de erro baseado para o {@link MinervaApiRestBase#onRequest(retrofit2.Call)}
* quando não é erro da biblioteca
*/
@Override
protected final <T> void onFailureConnection(Response<T> resposta) {
Log.d(TAG, "Falha na conexão: " + resposta.message());
onFailureConnection(null, new Throwable("" + resposta.message()));
}
/**
* Obtenção de erro baseado para o {@link MinervaApiRestBase#onRequest(retrofit2.Call)}
* quando o erro é da biblioteca
*/
@Override
protected final <T> void onFailureConnection(Call<T> call, Throwable t) {
Log.d(TAG, "Gatilho de erro (throw): ", t);
onFailureConnectionUserMessage(t.getMessage());
}
/**
* Montagem das frases de erro do app
* @param message mensagem de erro vindo do servidor ou da biblioteca
*/
private void onFailureConnectionUserMessage(String message) {
switch (message) {
case "timed out" :
onTimedOut();
break;
}
}
private void onTimedOut() {
if (TIMED_OUT < 3) {
Log.d(TAG, "Erro de tempo excedido. Tentando novamente. Tentativas: " + TIMED_OUT);
TIMED_OUT += 1;
onStart();
} else {
Log.e(TAG, "Failure: timed out :(");
onFailure(ERROR_TIMED_OUT);
}
}
/**
* Método chamado quando há uma falha de conexão, recebendo a mensagem
* que o servidor devolve
*
* @param message Mensagem de falha de conexão
*/
protected void onFailure(String message) {
}
/**
* Criação de header
*
* @param loginCredentials credenciais salvas no app
* @return header
*/
protected final OkHttpClient onBuildHeader(final LoginCredentials loginCredentials) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(chain -> {
Request request = chain.request();
request = request.newBuilder()
.build();
Headers moreHeaders = request.headers().newBuilder()
.add("token", loginCredentials.getToken())
.add("email", loginCredentials.getEmail())
.add("Accept", "application/json")
.add("Content-Type", "application/json")
.build();
request = request.newBuilder().headers(moreHeaders).build();
return chain.proceed(request);
});
return httpClient.build();
}
/**
* Criação de header
*
* @param headers HashMap com os header personalizados. (chave, valor)
* @return header
*/
protected final OkHttpClient onBuildHeader(final HashMap<String, String> headers) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(chain -> {
Request request = chain.request();
request = request.newBuilder()
.build();
Headers.Builder builder = request.headers().newBuilder();
for (String s : headers.keySet()) {
builder.add(s, headers.get(s));
}
Headers moreHeaders = builder.build();
request = request.newBuilder().headers(moreHeaders).build();
return chain.proceed(request);
});
return httpClient.build();
}
/**
* Impressão do objeto em forma de JSON
*
* @param object a ser impresso
*/
protected final void requestLogFor(Object object) {
if (object == null) {
Log.w("/* COMMUNICATION BASE /*", "the object value == null. Check if this is right");
return;
}
Log.d("/* COMMUNICATION BASE /*", new Gson().toJson(object));
}
/**
* Criação do body da requisição, a partir de um objeto
*
* @param o objeto a ser passado como body
* @return request body
*/
protected final RequestBody onBuildBody(Object o) {
return RequestBody.create(MediaType.parse("application/json"), new Gson().toJson(o));
}
private boolean isConnected() {
if (context == null)
return false;
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = null;
if (connectivityManager != null) {
activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
}
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
private <T> T retrieveDataForTag(Class<T> cType) {
Log.d(TAG, "Obtendo dados: " + key);
return new EasySave(context).retrieveModel(key, cType);
}
private void saveDataForTag(Object object) {
Log.d(TAG, "Salvando dados: " + key);
new EasySave(context).saveModel(key, object);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment