Midlet mensajero

CLASE PRINCIPAL

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package midletMensajero;

// Importo las clases necesarias para trabajar.
import java.io.IOException;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.*;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

/**
 * Midlet que permite la gestión de una agenda y el envío de sms's a la misma.
 * @author glop
 */
public class MidletMensajero extends MIDlet implements CommandListener {
   
    Display pantalla; // Pantalla del midlet.
    private Command seleccionar; // Comando con la opción seleccionar del menú principal.
    private Command Mver; // Comando con que lanza el formulario de ver cliente.
    private Command Mnuevo; // Comando con que lanza el formulario de guardar cliente.
    private Command Mmodificar; // Comando con que lanza el formulario de modificar cliente.
    private Command Meliminar; // Comando elimina el cliente seleccionado.
    private Command Mvolver; // Comando que regresa al menú principal.
    private Command cGuardar; // Comando que guarda el cliente.
    private Command cModificar; // Comando que modifica el cliente.
    private Command MmodificarPublicidad; // Modifica la plantilla del mensaje publicitario.
    private Command cVolver; // Comando que regresa al lista de clientes.
    private Command siguiente; // Comando utilizado en la pantalla de presentación que da paso a la pantalla de instrucciones.
    private Command probar; // Comando utilizado en la pantalla de instrucciones que da paso a la pantalla del menú principal.
    private Command adios; // Comando utilizado en la pantalla de créditos que cierra la aplicación.
    private RecordStore almacen; // Almacen de registros de clientes.
    listaClientes listado; // Instancia del objeto listaClientes que hereda de List.
    private List menu; // Lista que forma el menú principal.
    TextField tnombre; // TextField nombre. Utiliza tanto en la adición de clientes como en la modificación.
    TextField ttelefono; // TextField teléfono. Utiliza tanto en la adición de clientes como en la modificación.
    TextBox sms; // TextBox sms. Utilizado en la modificación del mensaje publicitario.
    private RecordEnumeration enumerador; // Enumerador que recorre los registros del RecordStore.
    private Form contenedor; // Formulario con el que se forman las pantallas según la necesidad.
    mensaje smsObj; // Instancia del objeto mensaje que representa un hilo de ejecución.
    String nombreCliente,telefonoCliente,smsTexto; // Variables que almacenan los datos necesarios para envío de mensajes

   
    public MidletMensajero() throws IOException {
       
        pantalla = Display.getDisplay(this); // Se indica que coja nuestra pantalla coja la pantalla principal del midlet.
        smsTexto = "Enhorabuena ***** ha sido agraciado con un premio de 1000 euros";
        presentacion(); // Se llama al método presentación que lanza la pantalla con el mismo nombre.
    }
   
    // Método que lanza la pantalla de presentación.
     public void presentacion() throws IOException {
        contenedor = new Form(""); // Formulario sin título
        contenedor.append("Tarea 3 -- Midlet Mensajero"); // Se añade texto
        Image imag = Image.createImage("imagenes/java.png"); // Se crea una imagen
        ImageItem elemento= new ImageItem ("",  imag, ImageItem.LAYOUT_CENTER, ""); // La imagen se pasa a un ImageItem para
                                                                                    // definir algunos detalles
        contenedor.append(elemento); // Se añade el ImageItem
        contenedor.append("Gabriel López Marcos"); // Se añade texto
        // Se añaden los comandos que tendrá la pantalla
        siguiente = new Command("Siguiente",Command.OK,0);
        contenedor.addCommand(siguiente);
        contenedor.setCommandListener(this); // Se asigna el oyente
        pantalla.setCurrent(contenedor); // La pantalla activa es ésta.
    }
    
     // Método que lanza la pantalla de instrucciones.
     public void instrucciones() {
        contenedor = new Form("Instrucciones");
        contenedor.append("La aplicación consiste en una pequeña agenda de clientes.\n"
                + "- Tienes control completo sobre los clientes, tanto su adición como su modificación\n"
                + "- Es posible enviar mensajes publicitarios a la lista de clientes, siendo posible editar el mensaje enviado");
        probar = new Command("Probar",Command.OK,0);
        contenedor.addCommand(probar);
        contenedor.setCommandListener(this);
        pantalla.setCurrent(contenedor);
    }

     // Lanza un menú principal con las opciones de la aplicación.
    public void menu() {
        menu = new List("Opciones",List.IMPLICIT);
        menu.append("Explorar lista de clientes", null);
        menu.append("Modificar mensaje publicitario", null);
        menu.append("Enviar publicidad a clientes", null);
        menu.append("Salir de la aplicación", null);
        seleccionar = new Command("Seleccionar",Command.OK,0);
        menu.addCommand(seleccionar);
        menu.setCommandListener(this);
        pantalla.setCurrent(menu);
    }
   
    // Se listan todos los clientes y se añaden las opciones que se pueden realizar sobre ellos.
   public void listarClientes() throws RecordStoreException {
      
       listado = new listaClientes("Clientes"); // Se instancia un nuevo objeto de listaClientes.
       listado.listar();
       Mver = new Command("Ver",Command.OK,0);
       Mnuevo = new Command("Nuevo cliente",Command.OK,1);
       Mmodificar = new Command("Editar cliente",Command.OK,1);
       Meliminar = new Command("Borrar cliente",Command.OK,1);
       Mvolver = new Command("Volver",Command.OK,1);
       listado.addCommand(Mnuevo);
       if (listado.size() != 0) {
       listado.addCommand(Mver);
       listado.addCommand(Mmodificar);
       listado.addCommand(Meliminar);
       }
       listado.addCommand(Mvolver);
       listado.setCommandListener(this);
       pantalla.setCurrent(listado);
      
   }
   
    // Método que lanza la pantalla de visualización de cliente. Para ello tenemos que obtener dicho cliente y lo hacemos
    // recurriendo a la tabla hash.
    public void verCliente() {
       // Se almacena el índice seleccionado de la lista. Recordemos que este índice está relacionado con la tabla hash
       // paralela de registros y que ésta contiene los clientes y podremos trabajar con sus datos.
       int idSeleccionado = listado.getSelectedIndex();
       // Se pasa el idSeleecionado al almacén paralelo de clientes para que nos devuelve el cliente asociado.
       // Guardamos lo obtenido en un objeto con el que trabajaremos.
       Object chash = listado.almacen_hash.get(String.valueOf(idSeleccionado));
       String cliente; // Variable donde se almacena la parte de los datos, sin el índice, del cliente almacenado en el objeto.
       String nombre; // Variable donde se almacena el nombre del cliente a editar.
       String telefono; // Variable donde se almacena el teléfono del cliente a editar.
       int separador = chash.toString().indexOf("|"); // Se almacena la posición del primer separador.
       // Se almacena en un string el cliente. Recordemos que en la tabla hash paralela al RecordStore, almacenamos los
       // clientes con su id para poder trabajar con este datos. Es por ello que tengo que acceder sin ese dato.
       // En la tabla hash se almacena así : id|nombre|teléfono
       cliente = chash.toString().substring(separador+1);
       separador = cliente.indexOf("|"); // Obtengo la posición del separador en la parte de los datos del cliente.
       // Almaceno el nombre. Lo obtengo con substring desde la posición 0 de la variable cliente, hasta el próximo separador.
       nombre = cliente.substring(0,separador);
       telefono = cliente.substring(separador+1); // El teléfono lo obtengo con substring desde el separador hasta el final.
      
       // Ahora puedo construir el formulario.
       contenedor = new Form("Detalle de cliente");
       contenedor.append("Nombre :");
       contenedor.append(nombre);
       contenedor.append("Teléfono : ");
       contenedor.append(telefono);
       cVolver = new Command("Volver",Command.BACK,0);
       contenedor.addCommand(cVolver);
       contenedor.setCommandListener(this);
       pantalla.setCurrent(contenedor);
   }
   
       // Método que lanza una pantalla con un formulario que contiene dos textfields para introducir un nuevo cliente.
   public void nuevoCliente() throws RecordStoreException {
       contenedor = new Form("Nuevo Cliente");
       // Se añade el TextField nombre con 25 caracteres de capacidad. Se pueden introducir todo tipo de caracteres.
       tnombre= new TextField ("Nombre: ", null, 25, TextField.ANY);
       // Se añade el TextField teléfono con 25 caracteres de capacidad. Se pueden introducir únicamente números.
       ttelefono= new TextField ("Teléfono: ", null, 25, TextField.PHONENUMBER);
       contenedor.append(tnombre);
       contenedor.append(ttelefono);
       cVolver = new Command("Volver",Command.BACK,0);
       cGuardar = new Command("Guardar",Command.BACK,1);
       contenedor.addCommand(cVolver);
       contenedor.addCommand(cGuardar);
       contenedor.setCommandListener(this);
       pantalla.setCurrent(contenedor);
   }
  
  
   // Método que lanza un formulario con los datos de clientes para editar. Es necesario rellenar dichos datos
   // accediendo a la tabla hash asociado e introducirlos en el formulario.
   public void modificarCliente() throws RecordStoreException {
      
       // Se almacena el índice seleccionado de la lista. Recordemos que este índice está relacionado con la tabla hash
       // paralela de registros y que ésta contiene los clientes y podremos trabajar con sus datos.
       int idSeleccionado = listado.getSelectedIndex();
       // Se pasa el idSeleecionado al almacén paralelo de clientes para que nos devuelve el cliente asociado.
       // Guardamos lo obtenido en un objeto con el que trabajaremos.
       Object chash = listado.almacen_hash.get(String.valueOf(idSeleccionado));
       String cliente; // Variable donde se almacena la parte de los datos, sin el índice, del cliente almacenado en el objeto.
       String nombre; // Variable donde se almacena el nombre del cliente a editar.
       String telefono; // Variable donde se almacena el teléfono del cliente a editar.
       int separador = chash.toString().indexOf("|"); // Se almacena la posición del primer separador.
       // Se almacena en un string el cliente. Recordemos que en la tabla hash paralela al RecordStore, almacenamos los
       // clientes con su id para poder trabajar con este datos. Es por ello que tengo que acceder sin ese dato.
       // En la tabla hash se almacena así : id|nombre|teléfono
       cliente = chash.toString().substring(separador+1);
       separador = cliente.indexOf("|"); // Obtengo la posición del separador en la parte de los datos del cliente.
       // Almaceno el nombre. Lo obtengo con substring desde la posición 0 de la variable cliente, hasta el próximo separador.
       nombre = cliente.substring(0,separador);
       telefono = cliente.substring(separador+1); // El teléfono lo obtengo con substring desde el separador hasta el final.
      
       // Ahora puedo construir el formulario.
       contenedor = new Form("Editar cliente");
       tnombre= new TextField ("Nombre: ", nombre, 25, TextField.ANY);
       ttelefono= new TextField ("Teléfono: ", telefono, 25, TextField.PHONENUMBER);
       contenedor.append(tnombre);
       contenedor.append(ttelefono);
       cVolver = new Command("Volver",Command.BACK,0);
       cModificar = new Command("Modificar",Command.BACK,1);
       contenedor.addCommand(cVolver);
       contenedor.addCommand(cModificar);
       contenedor.setCommandListener(this);
       pantalla.setCurrent(contenedor);
      
   }
  
   
    public void startApp() {
        pantalla.setCurrent(contenedor);
    }
   
    public void pauseApp() {
    }
   
    public void destroyApp(boolean unconditional) {
    }

    // Control de comandos.
    public void commandAction(Command c, Displayable d) {
       
        try {
           
            if (c == siguiente) {
            instrucciones();
            }
            if (c == probar) {
            menu();
            }
            if (c == Mnuevo) {
            nuevoCliente();
            }
           
        if (c == seleccionar) {
            int opcion = menu.getSelectedIndex();
            switch(opcion) {
                case 0:
                  listarClientes();
                    break;
                case 1:
                    editarMensaje();
                    break;
                case 2:
                    if (listado.almacen_hash.size()!=0) {
                    envioPublicidad();
                }
                       
                    break;
                case 3:
                    creditos();
            }
        }
        if (c == adios) {
        destroyApp (true);
        notifyDestroyed ();
                    }
       
        if (c == Mmodificar) {
            modificarCliente();
        }
        if (c == Mver) {
            verCliente();
        }
        if (c == cGuardar) {

            if (!"".equals(tnombre.getString()) && !"".equals(ttelefono.getString())) {
            listado.guardar(tnombre, ttelefono);
            listarClientes();
            }
           
        }
        if (c == cModificar) {
            if (!"".equals(tnombre.getString()) && !"".equals(ttelefono.getString())) {
            listado.modificar(tnombre, ttelefono);
            listarClientes();
            }
        }
        if (c == Meliminar) {
            listado.eliminar();
            listarClientes();
        }
        if (c == Mvolver) {
            pantalla.setCurrent(menu);
        }
        if (c == cVolver) {
            pantalla.setCurrent(listado);
        }
        if (c == MmodificarPublicidad) {
            smsTexto = sms.getString();
            pantalla.setCurrent(menu);
        }
       
       
        } catch (Exception ex) {
           
        }
    }
   
   
  // Método que lanza la pantalla de edición del mensaje publicitario.
   public void editarMensaje() {
       // La pantalla la forma un TextBox con el texto del mensaje listo para ser editado.
       sms = new TextBox("",smsTexto,255,TextField.ANY);
       MmodificarPublicidad = new Command("Modificar",Command.OK,0);
       Mvolver = new Command("Volver",Command.BACK,1);
       sms.addCommand(MmodificarPublicidad);
       sms.addCommand(Mvolver);
       sms.setCommandListener(this);
       pantalla.setCurrent(sms);
   }
  
   // Método que permite el envío de los mensajes a la lista.
   // En el RecordStore los datos se guardan así: nombre|teléfono
   public void envioPublicidad() throws RecordStoreException {
      
       try {
           almacen = RecordStore.openRecordStore("clientes", true); // Abrimos el almacén de registros.
           enumerador = almacen.enumerateRecords(null, null, true); // Se los pasamos al enumerador.
           while(enumerador.hasNextElement()) { // Mientras haya elementos ...
               byte[] b = enumerador.nextRecord(); // Pasamos el registros a un array de bytes para trabajar con los datos.
               String cliente = new String(b); // Convertimos el array a string.
               int separador = cliente.toString().indexOf("|"); // Obtenemos la posición del separador.
               nombreCliente = cliente.toString().substring(0,separador); // Obtenemos el nombre del cliente.
               telefonoCliente = cliente.toString().substring(separador+1); // Obtenemos el teléfono del cliente.
               // Nueva instancia de mensajes con los datos de los clientes y el texto publicitario.
               // Iniciaremos tantos hilos como clientes existan en el almacén. Los hilos trabajarán sincronizados.
               smsObj = new mensaje(nombreCliente,telefonoCliente,smsTexto);
               smsObj.start(); // Se inicia el hilo
           }
           resultadoEnvios(); // Al término de las operaciones, se lanza la pantalla de resultados para informar.
       } catch (Exception ex) {
          
       } finally { // Al finalizar ...
          if (enumerador!=null) {
              enumerador.destroy(); // Cerramos el enumerador.
          }
          if (almacen!=null) {
              almacen.closeRecordStore(); // Cerramos el RecordStore.
          }
       }
      
   }
  
   // Método que lanza una pantalla de resultados de operaciones.
   public void resultadoEnvios() {
       Alert alerta = new Alert("Resultado de los envíos");
       alerta.setString("El envío de mensajes ha finalizado ... \n"
               + "Se han enviado un total de : " + listado.size() + " mensajes");
       Mvolver = new Command("Volver",Command.BACK,0);
       alerta.addCommand(Mvolver);
       alerta.setCommandListener(this);
       pantalla.setCurrent(alerta);
   }
  
 
      // Método que lanza una pantalla de créditos.
       public void creditos() {
        contenedor = new Form ("Créditos");
        contenedor.append("Tarea realizada por:\n"
                + "Gabriel López Marcos\n"
                + "para DAM\n"
                + "10/Agosto/2013");
        adios = new Command("Adiós",Command.OK,0);
        contenedor.addCommand(adios);
        contenedor.setCommandListener(this);
        pantalla.setCurrent(contenedor);
    }
      
}

CLASE LISTA DE CLIENTES

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package midletMensajero;

// Importo las clases necesarias para trabajar.
import java.util.Hashtable;
import javax.microedition.lcdui.List;
import javax.microedition.lcdui.TextField;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

/**
 * Clase donde se efectúan las acciones sobre la lista de clientes. Hereda de List.
 * @author glop
 */
public class listaClientes extends List {
   
    RecordStore almacen; // Almacén de registros.
    RecordEnumeration enumerador; // Enumerador de registros. Utilizado para recorrer el RecordStore.
    Hashtable almacen_hash; // Tabla hash que guarda una lista paralela de clientes.
   
    // Construímos el objeto listaClientes que hereda de List.
    public listaClientes(String nombre) {
        super(nombre,List.IMPLICIT); // Se construye una lista de tipo implícito.
        almacen_hash = new Hashtable(); // Se construye una tabla hash como almacen paralelo de clientes.
    }
   
    // Lista todos los clientes y los pasa a una tabla hash paralela para trabajar con los datos.
    public void listar() throws RecordStoreException {
        super.deleteAll(); // Cada vez que se llama a este método, se limpian los resultados de la lista.
        try {
        almacen = RecordStore.openRecordStore("clientes", true); // Se crea un almacén de registros o se abre si ya existía.
        enumerador = null;
        enumerador = almacen.enumerateRecords(null, null, true); // Se pasa al enumerador la lista de clientes.
       
        while(enumerador.hasNextElement()) { // Se recorre la lista de clientes.
            int indice = enumerador.nextRecordId(); // Se almacena el id de cliente.
            byte[] cl = almacen.getRecord(indice); // Se pasa el cliente a un array de bytes.
            String cliente = new String(cl); // El cliente se almacena en una variable String.
            int separador = cliente.indexOf("|"); // Posición del separador: nombre|teléfono.
            String nombre = cliente.substring(0,separador); // Se almacena el nombre del cliente.
            String telefono = cliente.substring(separador + 1); // Se almacena el teléfono del cliente.
            super.append(nombre + " " + telefono, null); // Se añade el cliente completo a la lista.
            // Se almacena el número de registros que tiene la tabla hash. Se almacena como String para poderlo utilizar
            // para añadir un nuevo registro a la tabla hash que solo admite objetos como keys.
            String nregistros = String.valueOf(almacen_hash.size());
            // Se añade un nuevo registros a la tabla hash. Se asocia la posición que ocupa en la lista como key, con
            // el cliente completo incluido el índice. Así es fácil de trabajar con sus datos.
            almacen_hash.put(nregistros, indice + "|" + nombre + "|" + telefono);
        }
        } catch (Exception ex) {
            System.out.println("Se ha producido un error al listar los clientes :" + ex);
        } finally {
            if (enumerador!=null) {
            enumerador.destroy();} // Se cierra el enumerador.
            if  (almacen!=null) {
            almacen.closeRecordStore();} // Se cierra el almacen.
        }
       
    }
   
    // Método que guarda un nuevo registro en el RecordStore. Cuando acabe, se actualizará la lista y se añadirá
    // el registro a la tabla hash.
    // Se le pasan por parámetros los textfields de la pantalla de añadir clientes.
    public void guardar(TextField nombre, TextField telefono) throws RecordStoreException {
       
        try {
            almacen = RecordStore.openRecordStore("clientes", true);
            // Se almacena el cliente en una variable String con el formato adecuado.
            String cliente = nombre.getString() + "|" + telefono.getString();
            byte[] cl = cliente.getBytes(); // Se pasa el cliente a un array de bytes.
            almacen.addRecord(cl, 0, cl.length); // Se guarda el cliente en el RecordStore.
        } catch (Exception ex) {
            System.out.println("Ha ocurrido un error al intentar guardar un registro : " + ex);
        } finally {
            almacen.closeRecordStore(); // Se cierra el RecordStore.
        }
    }
   
    // Se modifica un cliente con los valores de los textfields que se le pasan por parámetros.
    // Cuando acabe, se actualizará la tabla hash asociada.
    public void modificar(TextField nombre, TextField telefono) throws RecordStoreException {
       
        try {
            int idSeleccionado = super.getSelectedIndex(); // Se almacena el índice de la lista seleccionado.
            almacen = RecordStore.openRecordStore("clientes", true); // Se abre el RecordStore.
            // Se obtiene el cliente de tabla hash paralela pasándole por parámetro el índice seleccionado.
            // Lo almacenamos en un objeto
            Object chash = almacen_hash.get(String.valueOf(idSeleccionado));
            // Se obtiene la posición del separador. En el cliente se almacena así: nombre|teléfono
            // en la tabla hash, sin embargo, se almacena así: id|nombre|teléfono
            // Se almacena así para trabajar con los datos de cliente y poder acceder a sus índices dentro del RecordStore.
            int separador = chash.toString().indexOf("|");
            String indice = chash.toString().substring(0,separador); // Se obtiene el índice del cliente.
            int indiceCliente = Integer.parseInt(indice); // Valor númerico del índice de cliente.
            // Se almacena en un String el cliente modificado con los datos recogidos por parámetros.
            String clienteModificado = nombre.getString() + "|" + telefono.getString();
            // Se pasa el cliente modificado a un array de bytes. El único formato adecuado para guardar datos en RecordStore.
            byte[] cl = clienteModificado.getBytes();
            almacen.setRecord(indiceCliente, cl, 0, cl.length);
           
        } catch (Exception ex) {
            System.out.println("Ha ocurrido u error al intentar modificar el registro : " + ex);
        } finally {
            almacen.closeRecordStore(); // Se cierra el RecordStore.
        }
    }
   
    public void eliminar() throws RecordStoreException {
       
        try {
            int idSeleccionado = super.getSelectedIndex(); // Se almacena el índice de la lista seleccionado.
            almacen = RecordStore.openRecordStore("clientes", true); // Se abre el RecordStore.
            // Se obtiene el cliente de tabla hash paralela pasándole por parámetro el índice seleccionado.
            // Lo almacenamos en un objeto
            Object chash = almacen_hash.get(String.valueOf(idSeleccionado));
            // Se obtiene la posición del separador. En el cliente se almacena así: nombre|teléfono
            // en la tabla hash, sin embargo, se almacena así: id|nombre|teléfono
            // Se almacena así para trabajar con los datos de cliente y poder acceder a sus índices dentro del RecordStore.
            int separador = chash.toString().indexOf("|");
            String indice = chash.toString().substring(0,separador); // Se obtiene el índice del cliente.
            int indiceCliente = Integer.parseInt(indice); // Valor númerico del índice de cliente.
            almacen.deleteRecord(indiceCliente); // Se elimina por índice de cliente.
        } catch (Exception ex) {
            System.out.println("Se ha producido un error al intentar eliminar el cliente : " + ex);
        } finally {
            almacen.closeRecordStore(); // Se cierra el RecordStore.
        }
    }
  
}


CLASE HILO MENSAJES

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package midletMensajero;

// Importo las clases necesarias para trabajar.
import java.io.IOException;
import javax.microedition.io.Connector;
import javax.wireless.messaging.MessageConnection;
import javax.wireless.messaging.TextMessage;

/**
 * Clase que controla los envíos de sms. Hereda de Thread.
 * @author glop
 */
public class mensaje extends Thread {
   
    int ocupado=0; // Variable que indice si el hilo está ocupado. 0 libre, 1 ocupado.
    String nombre; // Variable que almacena el nombre del destinatarios.
    String telefono; // Variable que almacena el teléfono del destinatario.
    String texto; // Variable que almacena el texto del mensaje.
    MessageConnection conexion; // Variable que establece la conexión.
    TextMessage mensaje; // Variable que implementa el mensaje.
   
    public mensaje(String nomb,String tlf,String text) { // Se contruye el objeto con los datos
        this.nombre=nomb;
        this.telefono=tlf;
        this.texto = text;
    }
   
    // Método sincronizado que permite el envío de mensajes.
    public synchronized void enviar() throws IOException {
       
        try {
           
        // Si el hilo está ocupado, espera. De este modo nunca se produce un bloque en la aplicación.
        while(ocupado==1) {
                wait();
        }
       
        ocupado=1; // Indicamos que un hilo está ocupado enviando el mensaje.
        conexion= (MessageConnection) Connector.open("sms://+34"+this.telefono); // Establecemos la conexión.
        mensaje= (TextMessage) conexion.newMessage(MessageConnection.TEXT_MESSAGE); // Creamos el mensaje.
       
        String textoMensaje = this.texto; // Se almacena el mensaje en una variable para trabajar con su texto.
        // En esta estructura controlamos que el mensaje tenga asteriscos (caracteres que utilizamos para referirnos a
        // los clientes) si los hay, los cambiamos por el nombre del cliente; Si no los hay, el mensaje queda tal cual.
        if (textoMensaje.indexOf("*")!=-1) {
        char caracter='*'; // Caracter que buscamos.
        int primera=0;
        String aux1 = textoMensaje.substring(0,textoMensaje.lastIndexOf(caracter)); // Parte del mensaje hasta los asteriscos.
        primera = aux1.indexOf("*"); // Primera asterisco.
        aux1 = aux1.substring(0, primera); // Cogemos sólo la parte donde no hay asteriscos.
        String aux2 = textoMensaje.substring(textoMensaje.lastIndexOf(caracter)+1); // La segunda parte del mensaje.
        aux1 +=this.nombre; // Añadimos el nombre a la primera parte.
        textoMensaje = aux1 + aux2;  // Formamos el mensaje completo. 
        }
        mensaje.setPayloadText(textoMensaje); // Añadimos el texto del mensaje.
        conexion.send(mensaje); // Enviamos el mensaje
        } catch (Exception ex) {
  
        } finally { // Ejecutamos aquí las últimas acciones.
        ocupado=0; // Indicamos que hemos acabado.
        notify(); // Lo notificamos a los demás hilos.
        conexion.close(); // Cerramos la conexión.        
        }
       
    }
   
    // Método que se ejecuta en el hilo al iniciarlo.
    public void run() {
        try {
            enviar(); // Llamamos al método enviar.
        } catch (IOException ex) {
           
        }
    }
}