Terminado

Desarrollo parcial app para propietarios de mascotas en React Native

Publicado el 31 Octubre, 2020 en Programación y Tecnología

Sobre este proyecto

Abierto

Desarrollo parcial de app para propietarios de mascotas, que puedan logearse e ingresar sus mascotas.

Login: (imagen login)
Permite loggear con email+contraseña, google, facebook.
a.Crear cuenta (imagen login_crear_cuenta)
b.en espera verificación cuenta vía click en link email (solo para loggeo email+contraseña) (imagen login_crear_cuenta_verificacion)
c.obtener ubicación del usuario

Main:
Menu lateral (imagen menu_principal, no guiarse por los textos, es solo para ver el formato), titulo de la app. Se presentan algunos mensajes que permiten
realizar acciones:
a.crear nueva mascota si no hay ninguna
b.seleccionar lat,lgn vía google maps si no estuviese ya establecido

Menu lateral:
a.Mi perfil
b.Mis mascotas
c.Logout

Mi perfil:
Se muestra la foto del usuario (, se permite cambio de foto (solo para loggeo email+contraseña))
+ nombre + ubicación + dirección. Edición de ubicación vía google maps / dirección

Mis mascotas:
Se muestran las mascotas cargadas con su foto.



Posibilidad de ver una mascota particular
o agregar nuevas mascotas.

Mascota particular:
se ve una mascota, con su foto, nombre y fecha de nacimiento, sexo.
Permite modificar, eliminar.

Nueva mascota:
Permite ingresar nuevas mascotas con su foto, nombre y fecha de nacimiento.

Especificaciones:

Login, creación de usuarios
URL: /api/user_create_account.php
Método: POST
Body: Objeto conteniendo el usuario:
{
    "device_name": "Google Android SDK built for x86",
    "email": "usuari48pp3@hotmail.com",
    "nombre": "usuario3",
    "password": "1234",
    "unique_id": "9e751f7a-8ad9-477f-9b0d-c504d5c8b2fk"
}

La creación de usuarios debe incluir el nombre de la plataforma donde se ejecuta, de ser
posible, y debe generar un id único en el dispositivo. Código de ejemplo en java:

public static String Generateguid() {
    uuid uuid = uuid.randomUUID();
    return uuid.toString();
}

Login, chequeo de usuarios que crearon cuenta vía email+contraseña, para determinar
si hicieron clic en el email de confirmación de cuenta que recibieron
URL: /api/user_check_account.php?id_propietario=101
Método: GET
Parámetro: id_propietario
Respuesta: 1 para válido, 0 para inválido.

Login, logeo de usuario email+contraseña
URL: /api/user_login_account.php
Método: POST
Body:
{
    "email": "nuevousuario1000@hotmail.com",
    "password": "1234"
}
Respuesta:
Un objeto conteniendo un miembro de enumeración [INVALID_ACCOUNT_PASSWORD,
ACCOUNT_WAITING_FOR_EMAIL_CHECK, VALID] y un objeto propietario.
{
    "Response": "VALID",
    "propietario": {
        "id": "98",
        "nombre": "nuevousuario105",
        "identificacion_regional": null,
        "direccion": null,
        "id_region": null,
        "nombre_region": null,
        "latlng": null,
        "telefono": null,
        "email": "nuevousuario107@hotmail.com",
        "notas": null,
        "tipo_login": "EMAIL",
        "valid": "1",
        "access_token": "b3b2986922293fb9d9f86cfa21c5e4a2751aed702a7cfc0748577e7d435d07bd",
        "photo_url": null
    }
}

Mascotas, creación de mascotas:
URL: /api/insert_mascota.php
Método: POST
Body:
Un array conteniendo un objeto mascota, un objeto que indica quién es el
propietario y un ubjeto que contiene la foto
[
    {
        "nombre": "Nueva mascota",
        "nacimiento": "2020-09-14 00:00:00"
    },
    {
        "id_propietario": 27
    },
    [
        {
            "file_extension": ".jpg",
            "guid": "1bfc013c-2a46-415d-9e73-df0e3020224a",
            "upload_finished": 1
        },
        {
            "file_extension": ".jpg",
            "guid": "0051615f-056f-4c34-96e4-7fefb3c17c3b",
            "postfix": "_thumb",
            "upload_finished": 1
        }
    ]
]
La foto se debe comprimir a jpeg en el dispositivo. Luego codificar los bytes
a String en base 64.



Código en java que puede servir de guía:

    public static String imageToString(Bitmap bitmap) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
        byte[] imgBytes = byteArrayOutputStream.toByteArray();
        return Base64.encodeToString(imgBytes, Base64.DEFAULT);
    }

Mascotas, get de las mascotas del propietario:
URL: /api/get_mascotas.php?id_propietario=101

Especificaciones para la subida de imágenes:

En la clase que se renderice para mostrar el ingreso de una nueva mascota, añadir una lista
global:

    //cada archivo a ser subido tendra un guid unico, en cada getFileGuid se iran almacenando
    //en esta lista
    private ArrayList<Upload_file> files_guids = new ArrayList<>();

Clase Upload_file:

public class Upload_file {
    private String guid;
    private String file_base64;
    private String file_extension;
    private Boolean upload_finished;
    private String postfix;

    public Upload_file() {
    }
    public Upload_file(String guid) {
        this.guid = guid;
    }
    public Upload_file(String guid, String file_base64, String file_extension) {
        this.guid = guid;
        this.file_base64 = file_base64;
        this.file_extension = file_extension;
    }

    public String getGuid() {
        return guid;
    }
    public void setGuid(String guid) {
        this.guid = guid;
    }
    public String getFile_base64() {
        return file_base64;
    }
    public void setFile_base64(String file_base64) {
        this.file_base64 = file_base64;
    }
    public String getFile_extension() {
        return file_extension;
    }
    public void setFile_extension(String file_extension) {
        this.file_extension = file_extension;
    }
    public Boolean getUpload_finished() {
        return upload_finished;
    }
    public void setUpload_finished(Boolean upload_finished) {
        this.upload_finished = upload_finished;
    }
    public String getPostfix() {
        return postfix;
    }
    public void setPostfix(String postfix) {
        this.postfix = postfix;
    }

}

Al tomar foto o elegir imagen de galeria:

1-Escalar la imagen al 20% de su tamaño original, y comprimir
  con una razón del 80% de calidad en jpg:

    public static Bitmap CompressBitmap(Bitmap bitmap) {
        Bitmap resized = Bitmap.createScaledBitmap(bitmap,(int)(bitmap.getWidth()*0.2), (int)(bitmap.getHeight()*0.2), false);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        resized.compress(Bitmap.CompressFormat.JPEG, 80, out);
        Bitmap jpgCoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
        return jpgCoded;
    }

2-Crear una segunda imagen escalando la anterior de 64 x 64 px

3-Subir ambas imagenes, teniendo en cuenta que la segunda se adjunta con el postfijo "_thumb"

    public void uploadImages() {
        Upload_file file = getImageGuid();
        Upload_file file_thumb = getImageGuid();
        file_thumb.setPostfix("_thumb");

        if (DoctorVetApp.DEBUGGING) {
            Log.i(TAG, "Starting upload: " + file);
            Log.i(TAG, "Starting upload: " + file_thumb);
        }

        DoctorVetApp.getInstance().uploadFile(file.getGuid(), file.getFile_extension(), HelperClass.imageToString(dataFragment.takePictureSupportObject.getImage()), new DoctorVetApp.VolleyCallback() {
            @Override
            public void onSuccess(Boolean result) {
                if (DoctorVetApp.DEBUGGING)
                    Log.i(TAG, "upload: " + file + " result: " + result.toString());

                if (result) {
                    file.setUpload_finished(true);
                }
            }
        });
        DoctorVetApp.getInstance().uploadFile(file_thumb.getGuid(), file.getFile_extension(), HelperClass.imageToString(dataFragment.takePictureSupportObject.getImage_thumb()), new DoctorVetApp.VolleyCallback() {
            @Override
            public void onSuccess(Boolean result) {
                if (DoctorVetApp.DEBUGGING)
                    Log.i(TAG, "upload: " + file_thumb + " result: " + result.toString());

                if (result) {
                    file_thumb.setUpload_finished(true);
                }
            }
        });
    }

    protected Upload_file getImageGuid(){
        Upload_file file = new Upload_file();
    file.setGuid(HelperClass.generateGUID());
    file.setFile_extension(".jpg");
        files_guids.add(file); //la lista global de subida de archivos
        return file;
    }

    public void uploadFile(String guid, String extension, String file_to_string_base64, @Nullable final VolleyCallback callback) {
        //primero el upload_prepare
        URL upload_prepareUrl = NetworkUtils.buildUploadPrepareImageUrl();
        String guidJsonObject = MySqlGson.getGson().toJson(new Upload_file(guid));
        StringRequest stringRequest = new StringRequest(Request.Method.POST, upload_prepareUrl.toString(),
                response -> {
                    try {
                        Integer success = Integer.parseInt(response);
                        if (success == 1) {
                            if (DoctorVetApp.DEBUGGING) Log.i(tag, "prepare upload: " + guid + " response true");

                            url uploadurl = networkutils.buildUploadImageUrl();
                            String fileGuidJsonObject =  MySqlGson.getGson().toJson(new Upload_file(guid, file_to_string_base64, extension));
                            StringRequest stringRequest2 = new StringRequest(Request.Method.POST, uploadUrl.toString(),
                                    response1 -> {
                                        try {
                                            Integer success2 = Integer.parseInt(response1);
                                            if (success2 == 1) {
                                                if (DoctorVetApp.DEBUGGING) Log.i(TAG, "Imagen subida " + guid);
                                                if (callback != null)
                                                    callback.onSuccess(true);
                                            } else {
                                                if (DoctorVetApp.DEBUGGING) Log.i(TAG, "Imagen NO subida " + guid);
                                                if (callback != null)
                                                    callback.onSuccess(false);
                                            }
                                        } catch (Exception ex) {
                                            handle_error(ex, ctx, tag, true);
                                        }
                                    },
                                    error -> {
                                        handle_volley_error(error, ctx, tag, false);
                                        if (callback != null)
                                            callback.onSuccess(false);
                                    }
                            )
                            {
                                @Override
                                public byte[] getBody() {
                                    return fileGuidJsonObject.getBytes();
                                }
                            };
                            addToRequestQueque(stringRequest2);

                            if (callback != null)
                                callback.onSuccess(true);
                        } else {
                            if (DoctorVetApp.DEBUGGING) Log.i(TAG, "prepare upload: " + guid + " response false");
                            if (callback != null)
                                callback.onSuccess(false);
                        }
                    } catch (Exception ex) {
                        handle_error(ex, ctx, tag, true);
                    }
                },
                error -> {
                    handle_volley_error(error, ctx, tag, true);
                    if (callback != null)
                        callback.onSuccess(false);
                }
        )
        {
            @Override
            public byte[] getBody() {
                return guidJsonObject.getBytes();
            }
        };
        addToRequestQueque(stringRequest);
    }


4-Por último, al registrar la mascota, se debe enviar la lista global
  de subida de archivos como un array de objetos. Asegurarse de nunca
  parsear las imagenes al miembro file_base64 en este último paso ya que
  si no, estaríamos subiendo las imágenes dos veces.

Categoría Programación y Tecnología
Subcategoría Programación de Apps. Android, iOS y otros
¿Cuál es el alcance del proyecto? Cambio mediano
¿Es un proyecto o una posición? Un proyecto
Actualmente tengo Tengo las especificaciones
Disponibilidad requerida Según se necesite
Plataformas requeridas iPhone, Android
Necesito Crear una app
Tipo de app Otro
Necesita backend No
Procesador de pago No

Plazo de Entrega: No definido

Habilidades necesarias