Aplicación Android (curso 21-22)
App que se comunica con el API Rest creado en Laravel
Aplicación Android
¿Esquema de la red?
ApiRestClient.java
public class ApiRestClient {
private static ApiService API_SERVICE;
public static final String BASE_URL = "https://todo.alumno.me/";
public static synchronized ApiService getInstance() {
if (API_SERVICE == null) {
OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(5, TimeUnit.SECONDS);
Gson gson = new GsonBuilder()
.setDateFormat("dd-MM-yyyy")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpBuilder.build())
.build();
API_SERVICE = retrofit.create(ApiService.class);
}
return API_SERVICE;
}
}
ApiService.java
public interface ApiService {
@FormUrlEncoded
@POST("api/register")
Call<RegisterResponse> register(
@Field("name") String name,
@Field("email") String email,
@Field("password") String password,
@Field("confirm_password") String confirmPassword);
//@POST("api/register")
//Call<RegisterResponse>register(@Body User user);
@FormUrlEncoded
@POST("api/login")
Call<LoginResponse> login(
@Field("email") String email,
@Field("password") String password);
//@POST("api/login")
//Call<LoginResponse>login(@Body User user);
}
ApiTokenRestClient.java
public class ApiTokenRestClient {
private static ApiTokenService API_SERVICE;
public static final String BASE_URL = "https://todo.alumno.me/";
public static synchronized ApiTokenService getInstance(final String token) {
if (API_SERVICE == null) {
Interceptor interceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Accept", "application/json")
.addHeader("authorization", "Bearer " + token)
.build();
return chain.proceed(newRequest);
}
};
OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(5, TimeUnit.SECONDS)
.addInterceptor(interceptor);
Gson gson = new GsonBuilder()
.setDateFormat("dd-MM-yyyy")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(okHttpBuilder.build())
.build();
API_SERVICE = retrofit.create(ApiTokenService.class);
}
return API_SERVICE;
}
public static void deleteInstance() {
API_SERVICE = null;
}
}
ApiTokenService
public interface ApiTokenService {
@POST("api/logout")
Call<LogoutResponse> logout(
//@Header("Authorization") String token
);
@GET("api/tasks")
Call<GetTasksResponse> getTasks(
//@Header("Authorization") String token
);
@POST("api/tasks")
Call<AddResponse> createTask(
//@Header("Authorization") String token,
@Body Task task);
@PUT("api/tasks/{id}")
Call<AddResponse> updateTask(
//@Header("Authorization") String token,
@Body Task task,
@Path("id") int id);
@DELETE("api/tasks/{id}")
Call<DeleteResponse> deleteTask(
//@Header("Authorization") String token,
@Path("id") int id);
@POST("api/email")
Call<EmailResponse> sendEmail(@Body Email email);
}
SharedPreferencesManager
public class SharedPreferencesManager {
//public static final String APP = "MyApp";
//public static final String EMAIL = "email";
//public static final String PASSWORD = "password";
//public static final String TOKEN = "token";
SharedPreferences sp;
SharedPreferences.Editor spEditor;
public SharedPreferencesManager(Context context){
sp = context.getSharedPreferences(MainActivity.APP, Context.MODE_PRIVATE);
spEditor = sp.edit();
}
public void save (String email, String password){
spEditor.putString(MainActivity.EMAIL, email);
spEditor.putString(MainActivity.PASSWORD, password);
spEditor.apply();
}
public void save (String email, String password, String token){
spEditor.putString(MainActivity.EMAIL, email);
spEditor.putString(MainActivity.PASSWORD, password);
spEditor.putString(MainActivity.TOKEN, token);
spEditor.apply();
}
public void saveEmail(String key, String value){
spEditor.putString(key, value);
spEditor.apply();
}
public String getEmail(){
return sp.getString(MainActivity.EMAIL, "");
}
public void savePassword(String key, String value){
spEditor.putString(key, value);
spEditor.apply();
}
public String getPassword(){
return sp.getString(MainActivity.PASSWORD, "");
}
public void saveToken(String key, String value){
spEditor.putString(key, value);
spEditor.apply();
}
public String getToken(){
return sp.getString(MainActivity.TOKEN, "");
}
}
Login en el MainActivity
private void loginByServer() {
progressDialog = new ProgressDialog(this);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Login ...");
progressDialog.setCancelable(false);
progressDialog.show();
binding.login.setEnabled(false);
String email = binding.email.getText().toString();
String password = binding.password.getText().toString();
Call<LoginResponse> call = ApiRestClient.getInstance().login(email, password);
//User user = new User(name, email, password);
call.enqueue(new Callback<LoginResponse>() {
@Override
public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
StringBuilder message = new StringBuilder();
progressDialog.dismiss();
binding.login.setEnabled(true);
//onRegisterSuccess();
LoginResponse loginResponse = response.body();
if (response.isSuccessful()) {
if (loginResponse.getSuccess()) {
Log.d("onResponse", "" + response.body());
//showMessage(response.body().getToken());
//guardar token en shared preferences
preferences.save(binding.email.getText().toString(), binding.password.getText().toString(), loginResponse.getData().getToken());
startActivity(new Intent(getApplicationContext(), PanelActivity.class));
finish();
} else {
showMessage("Error in login: " + loginResponse.getMessage());
}
} else {
message.append("Error in login: ");
if (response.body() != null)
message.append("\nBody\n" + response.body());
if (response.errorBody() != null)
try {
message.append("\nError\n" + response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
showMessage(message.toString());
}
}
@Override
public void onFailure(Call<LoginResponse> call, Throwable t) {
progressDialog.dismiss();
binding.login.setEnabled(true);
String message = "Failure in the communication\n";
if (t != null) {
Log.d("onFailure", t.getMessage());
message += t.getMessage();
}
showMessage(message);
binding.register.setEnabled(true);
}
});
}
Registro en RegisterActivity
private void sendToServer(String name, String email, String password, String confirmPassord) {
progressDialog = new ProgressDialog(this);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Creating Account ...");
progressDialog.setCancelable(false);
progressDialog.show();
binding.register.setEnabled(false);
Call<RegisterResponse> call = ApiRestClient.getInstance().register(name, email, password, confirmPassord);
//User user = new User(name, email, password);
call.enqueue(new Callback<RegisterResponse>() {
@Override
public void onResponse(Call<RegisterResponse> call, Response<RegisterResponse> response) {
progressDialog.dismiss();
//onRegisterSuccess();
binding.register.setEnabled(true);
if (response.isSuccessful()) {
RegisterResponse registerResponse = response.body();
if (registerResponse.getSuccess()) {
//Log.d("onResponse", "" + registerResponse.getData().getToken());
//enviar al Login para entrar después de validar el email
binding.register.setEnabled(true);
Intent resultIntent = new Intent();
resultIntent.putExtra("email", email);
resultIntent.putExtra("password", password);
//guardar el token en shared preferences
resultIntent.putExtra("token", registerResponse.getData().getToken());
setResult(RESULT_OK, resultIntent);
finish();
} else {
showMessage("Error in registration " + registerResponse.getMessage());
}
} else {
StringBuilder message = new StringBuilder();
message.append("Download error: " + response.code());
if (response.body() != null)
message.append("\n" + response.body());
if (response.errorBody() != null)
try {
message.append("\n" + response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
showMessage(message.toString());
}
}
@Override
public void onFailure(Call<RegisterResponse> call, Throwable t) {
progressDialog.dismiss();
String message = "Failure in the communication\n";
if (t != null) {
Log.d("onFailure", t.getMessage());
message += t.getMessage();
}
showMessage(message);
binding.register.setEnabled(true);
}
});
}
Adapter en TodoAdapter
public class TodoAdapter extends RecyclerView.Adapter<TodoAdapter.MyViewHolder> {
private ArrayList<Task> tasks;
public TodoAdapter(){
this.tasks = new ArrayList<>();
}
// Provide a direct reference to each of the views within a data item
// Used to cache the views within the item layout for fast access
public class MyViewHolder extends RecyclerView.ViewHolder {
private ItemViewBinding binding;//Name of the item_contact.xml in camel case + "Binding"
public MyViewHolder(ItemViewBinding b) {
super(b.getRoot());
binding = b;
}
}
@Override
public TodoAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
return new MyViewHolder(ItemViewBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
}
// Involves populating data into the item through holder
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// Get the data model based on position
Task task = tasks.get(position);
holder.binding.description.setText(task.getDescription());
}
@Override
public int getItemCount() {
return tasks.size();
}
public int getId(int position){
return this.tasks.get(position).getId();
}
public void setTasks(ArrayList<Task> tasks) {
this.tasks = tasks;
notifyDataSetChanged();
}
public Task getAt(int position){
Task task;
task = this.tasks.get(position);
return task;
}
public void add(Task task) {
this.tasks.add(task);
notifyItemInserted(tasks.size() - 1);
notifyItemRangeChanged(0, tasks.size() - 1);
}
public void modifyAt(Task task, int position) {
this.tasks.set(position, task);
notifyItemChanged(position);
}
public void removeAt(int position) {
this.tasks.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(0, tasks.size() - 1);
}
}
Respuesta para convertir el JSON
public class GetTasksResponse {
@SerializedName("success")
@Expose
private Boolean success;
@SerializedName("data")
@Expose
private ArrayList<Task> data = null;
@SerializedName("message")
@Expose
private String message;
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public ArrayList<Task> getData() {
return data;
}
public void setData(ArrayList<Task> data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
GetTasksData
public class GetTasksData {
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("description")
@Expose
private String description;
@SerializedName("created_at")
@Expose
private String createdAt;
@SerializedName("updated_at")
@Expose
private String updatedAt;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public String getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(String updatedAt) {
this.updatedAt = updatedAt;
}
}
DowloadTasks() en PanelActivity
private void downloadTasks() {
progreso = new ProgressDialog(this);
progreso.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progreso.setMessage("Connecting . . .");
progreso.setCancelable(false);
progreso.show();
//Call<ArrayList<Site>> call = ApiRestClient.getInstance().getSites("Bearer " + preferences.getToken());
Call<GetTasksResponse> call = ApiTokenRestClient.getInstance(preferences.getToken()).getTasks();
call.enqueue(new Callback<GetTasksResponse>() {
@Override
public void onResponse(Call<GetTasksResponse> call, Response<GetTasksResponse> response) {
progreso.dismiss();
if (response.isSuccessful()) {
GetTasksResponse getTasksResponse = response.body();
if (getTasksResponse.getSuccess()) {
adapter.setTasks(getTasksResponse.getData());
showMessage("Tasks downloaded ok");
} else {
showMessage("Error downloading the tasks: " + getTasksResponse.getMessage());
}
} else {
StringBuilder message = new StringBuilder();
message.append("Download error: " + response.code());
if (response.body() != null)
message.append("\n" + response.body());
if (response.errorBody() != null)
try {
message.append("\n" + response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
showMessage(message.toString());
}
}
@Override
public void onFailure(Call<GetTasksResponse> call, Throwable t) {
progreso.dismiss();
String message = "Failure in the communication\n";
if (t != null)
message += t.getMessage();
showMessage(message);
}
});
}
Añadir una nueva tarea en AddActivity
private void connection(Task task) {
progreso = new ProgressDialog(this);
progreso.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progreso.setMessage("Connecting . . .");
progreso.setCancelable(false);
progreso.show();
//Call<Site> call = ApiRestClient.getInstance().createSite("Bearer " + preferences.getToken(), s);
Call<AddResponse> call = ApiTokenRestClient.getInstance(preferences.getToken()).createTask(task);
call.enqueue(this);
}
@Override
public void onResponse(Call<AddResponse> call, Response<AddResponse> response) {
progreso.dismiss();
if (response.isSuccessful()) {
AddResponse addResponse = response.body();
if (addResponse.getSuccess()) {
Intent i = new Intent();
Bundle bundle = new Bundle();
bundle.putInt("id", addResponse.getData().getId());
bundle.putString("description", addResponse.getData().getDescription());
i.putExtras(bundle);
setResult(OK, i);
finish();
showMessage("Task created ok");
} else {
String message = "Error creating the task";
if (!addResponse.getMessage().isEmpty()) {
message += ": " + addResponse.getMessage();
}
showMessage(message);
}
} else {
StringBuilder message = new StringBuilder();
message.append("Download error: ");
if (response.body() != null)
message.append("\n" + response.body());
if (response.errorBody() != null)
try {
message.append("\n" + response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
showMessage(message.toString());
}
}
@Override
public void onFailure(Call<AddResponse> call, Throwable t) {
progreso.dismiss();
if (t != null)
showMessage("Failure in the communication\n" + t.getMessage());
}
Actualizar una tarea
Eventos click y longClick
//manage click
binding.recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this, binding.recyclerView, new ClickListener() {
@Override
public void onClick(View view, final int position) {
showMessage("Single Click on task with id: " + adapter.getAt(position).getId());
modify(adapter.getAt(position));
positionClicked = position;
}
@Override
public void onLongClick(View view, int position) {
showMessage("Long press on position :" + position);
confirm(adapter.getAt(position).getId(), adapter.getAt(position).getDescription(), position);
}
}));
Lanzar UpdateActivity
private void modify(Task task) {
Intent i = new Intent(this, UpdateActivity.class);
i.putExtra("task", task);
startActivityForResult(i, UPDATE_CODE);
}
conectarse al API en UpdateActivity
private void connection(Task task) {
showMessage(task.getId() + "");
progreso = new ProgressDialog(this);
progreso.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progreso.setMessage("Connecting . . .");
progreso.setCancelable(false);
progreso.show();
//Call<Site> call = ApiRestClient.getInstance().createSite("Bearer " + preferences.getToken(), s);
Call<AddResponse> call = ApiTokenRestClient.getInstance(preferences.getToken()).updateTask(task, task.getId());
call.enqueue(this);
}
@Override
public void onResponse(Call<AddResponse> call, Response<AddResponse> response) {
progreso.dismiss();
if (response.isSuccessful()) {
AddResponse addResponse = response.body();
if (addResponse.getSuccess()) {
Intent i = new Intent();
Bundle bundle = new Bundle();
bundle.putInt("id", addResponse.getData().getId());
bundle.putString("description", addResponse.getData().getDescription());
i.putExtras(bundle);
setResult(OK, i);
finish();
showMessage("Task updated ok: " + addResponse.getData().getDescription());
} else {
String message = "Error updating the task";
if (!addResponse.getMessage().isEmpty()) {
message += ": " + addResponse.getMessage();
}
showMessage(message);
}
} else {
StringBuilder message = new StringBuilder();
message.append("Download error: ");
Log.e("Error:", response.errorBody().toString());
if (response.body() != null)
message.append("\n" + response.body());
if (response.errorBody() != null)
try {
message.append("\n" + response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
showMessage(message.toString());
}
}
@Override
public void onFailure(Call<AddResponse> call, Throwable t) {
progreso.dismiss();
if (t != null)
showMessage("Failure in the communication\n" + t.getMessage());
}
Eliminar una tarea en PanelActivity
private void confirm(final int idTask, String description, final int position) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(description + "\nDo you want to delete?")
.setTitle("Delete")
.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
connection(position);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
builder.show();
}
conexión al API en PanelActivity para eliminar una tarea
private void connection(final int position) {
//Call<ResponseBody> call = ApiRestClient.getInstance().deleteSite("Bearer " + preferences.getToken(), adapter.getId(position));
Call<DeleteResponse> call = ApiTokenRestClient.getInstance(preferences.getToken()).deleteTask(adapter.getId(position));
progreso.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progreso.setMessage("Connecting . . .");
progreso.setCancelable(false);
progreso.show();
call.enqueue(new Callback<DeleteResponse>() {
@Override
public void onResponse(Call<DeleteResponse> call, Response<DeleteResponse> response) {
progreso.dismiss();
if (response.isSuccessful()) {
DeleteResponse deleteResponse = response.body();
if (deleteResponse.getSuccess()) {
adapter.removeAt(position);
showMessage("Task deleted OK");
} else
showMessage("Error deleting the task");
} else {
StringBuilder message = new StringBuilder();
message.append("Error deleting a site: " + response.code());
if (response.body() != null)
message.append("\n" + response.body());
if (response.errorBody() != null)
try {
message.append("\n" + response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
showMessage(message.toString());
}
}
@Override
public void onFailure(Call<DeleteResponse> call, Throwable t) {
progreso.dismiss();
if (t != null)
showMessage("Failure in the communication\n" + t.getMessage());
}
});
}
Enviar un email en EmailActivity
private void connection(Email e) {
progreso = new ProgressDialog(this);
progreso.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progreso.setMessage("Connecting . . .");
progreso.setCancelable(false);
progreso.show();
Call<EmailResponse> call = ApiTokenRestClient.getInstance(preferences.getToken()).sendEmail(e);
call.enqueue(this);
}
@Override
public void onResponse(Call<EmailResponse> call, Response<EmailResponse> response) {
progreso.dismiss();
if (response.isSuccessful()) {
EmailResponse emailResponse = response.body();
if (emailResponse.getSuccess()) {
//Intent i = new Intent();
//setResult(OK, i);
showMessage("Email sent ok: " + emailResponse.getMessage());
finish();
} else {
String message = "Email not sent";
if (!emailResponse.getMessage().isEmpty()) {
message += ": " + emailResponse.getMessage();
}
showMessage(message);
}
} else {
StringBuilder message = new StringBuilder();
message.append("Error sending the mail: " + response.code());
if (response.body() != null)
message.append("\n" + response.body());
if (response.errorBody() != null)
try {
message.append("\n" + response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
showMessage(message.toString());
}
}
@Override
public void onFailure(Call<EmailResponse> call, Throwable t) {
String message = "Failure sending the email\n";
if (t != null)
message += t.getMessage();
showMessage(message);
}
Mejoras
- Usar el patrón MVVM en el diseño de la aplicación
- Enviar un email de verificación al registrarse un usuario y comprobar en el login si el usuario está verificado
- Añadir más campos a la tarea (título, fecha límite, observaciones, . . . )
- Devolver los códigos de estado adecuados en los errores (no solo el 404)


Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.