Created
May 30, 2018 23:34
-
-
Save Guilherme-HRamos/a56f96f3983a538847f9136c1932e94c to your computer and use it in GitHub Desktop.
Comunicação com a API que uso na Minerva
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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