21 - Biblioteca Volley - Insertar una fila en una tabla (PHP y MySQL)

Problema

Implementar una aplicación que permita insertar una fila en una tabla de MySQL mediante PHP.

Tenemos la tabla en un servidor web llamada:

create table articulos (
    codigo int primary key AUTO_INCREMENT,
    descripcion varchar(50),
    precio float
);

Crearemos el proyecto 'Compose23'

Agregamos las dependencias de la biblioteca Volley:

dependencies {
        ...
        implementation 'com.android.volley:volley:1.2.0'
    }

Nuestra aplicación debe acceder a internet por lo que debemos pedir dicho permiso:

<uses-permission android:name="android.permission.INTERNET"/>

Debemos llamar a la URL:

https://scratchya.com.ar/videosandroidjava/volley/insertar.php

En el servidor tenemos la página:

insertar.php

<?php
header('Content-Type: application/json');
$datos = json_decode(file_get_contents("php://input"), true);
require("conexion.php");
$conexion = retornarConexion();

$respuesta = mysqli_query($conexion, "insert into articulos(descripcion,precio) values ('$datos[descripcion]',$datos[precio])");
if ($respuesta)
  echo '{"respuesta":"ok"}';
else
  echo '{"respuesta":"error de en la inserción"}';
 
 ?>

Y el archivo conexion.php

<?php
function retornarConexion() {
    $server="localhost";
    $usuario="xxxx";
    $clave="xxxx";
    $base="xxxx";
    $con=mysqli_connect($server,$usuario,$clave,$base) or die("problemas") ;
    mysqli_set_charset($con,'utf8'); 
    return $con;
}
?>

La interfaz visual que debemos implementar con Compose debe ser similar a:

biblioteca Volley Jetpack Compose

El código a implementar en Kotlin para obtener dicha funcionalidad es:

package com.tutorialesprogramacionya.compose23

import android.content.Context
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Button
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.KeyboardType
import com.android.volley.Request

import org.json.JSONObject

import com.android.volley.toolbox.JsonObjectRequest
import com.android.volley.toolbox.Volley


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ConsultaArticulo()
        }
    }
}

@Composable
fun ConsultaArticulo() {
    val contexto = LocalContext.current
    Column(
        modifier = Modifier.fillMaxSize()
    ) {
        var descripcion by remember { mutableStateOf("") }
        var precio by remember { mutableStateOf("") }
        var mensaje by remember { mutableStateOf("") }
        OutlinedTextField(
            value = descripcion,
            onValueChange = { descripcion = it },
            label = {
                Text("Descripción")
            },
            modifier = Modifier
                .fillMaxWidth()
                .padding(10.dp),
            singleLine = true
        )
        OutlinedTextField(
            value = precio,
            onValueChange = { precio = it },
            label = {
                Text("Precio")
            },
            modifier = Modifier
                .fillMaxWidth()
                .padding(10.dp),
            singleLine = true,
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
        )
        Button(
            onClick = {
                AltaArticulo(
                    descripcion = descripcion,
                    precio = precio,
                    contexto = contexto,
                    respuesta = {
                        if (it) {
                            mensaje = "se cargaron los datos"
                            descripcion=""
                            precio=""
                        }
                        else
                            mensaje="problemas en la carga"
                    }
                )
            },
            modifier = Modifier.padding(10.dp)
        ) {
            Text(text = "Agregar")
        }
        Text(text = "$mensaje")
    }
}

fun AltaArticulo(descripcion: String, precio: String, contexto: Context,respuesta: (Boolean) -> Unit) {
    val requestQueue = Volley.newRequestQueue(contexto)
    val url = "https://scratchya.com.ar/videosandroidjava/volley/insertar.php"
    val parametros=JSONObject()
    parametros.put("descripcion",descripcion)
    parametros.put("precio",precio)
    val requerimiento = JsonObjectRequest(Request.Method.POST,
        url,
        parametros,
        { response ->
            if (response.get("respuesta").toString().equals("ok"))
                respuesta(true)
            else
                respuesta(false)
        },
        { error ->
            respuesta(false)
        }
    )
    requestQueue.add(requerimiento)
}

Cuando se presiona el botón "Agregar", se ejecuta la función lambda donde llamamos a la función AltaArticulo, pasando la descripción, precio, contexto del Activity y una función lambda que recibirá si la carga se efectuó o no correctamente:

        Button(
            onClick = {
                AltaArticulo(
                    descripcion = descripcion,
                    precio = precio,
                    contexto = contexto,
                    respuesta = {
                        if (it) {
                            mensaje = "se cargaron los datos"
                            descripcion=""
                            precio=""
                        }
                        else
                            mensaje="problemas en la carga"
                    }
                )
            },
            modifier = Modifier.padding(10.dp)
        ) {
            Text(text = "Agregar")
        }

La función AltArticulo hace uso de la biblioteca Volley para hacer un requerimiento al servidor de tipo POST, esto significa que le enviaremos datos mediante la variable parámetros que se trata de un objeto de la clase JSONObject.

Mediante una función lambda recibimos la respuesta del servidor y verificamos se la carga se efectuó correctamente, en caso afirmativo llamamos mediante el parámetro respuesta pasando un true a la función lambda de la primer función:

fun AltaArticulo(descripcion: String, precio: String, contexto: Context,respuesta: (Boolean) -> Unit) {
    val requestQueue = Volley.newRequestQueue(contexto)
    val url = "https://scratchya.com.ar/videosandroidjava/volley/insertar.php"
    val parametros=JSONObject()
    parametros.put("descripcion",descripcion)
    parametros.put("precio",precio)
    val requerimiento = JsonObjectRequest(Request.Method.POST,
        url,
        parametros,
        { response ->
            if (response.get("respuesta").toString().equals("ok"))
                respuesta(true)
            else
                respuesta(false)
        },
        { error ->
            respuesta(false)
        }
    )
    requestQueue.add(requerimiento)
}

Este proyecto lo puede descargar en un zip desde este enlace: Compose23.zip