1. Taller de Programación
de Dispositivos Móviles
José Miguel Rubio L.
Oficina 3-20
http://www.inf.ucv.cl/~jrubio
jose.rubio.l@ucv.cl
2. Parte 1
1.Programación de dispositivos móviles
2.Limitaciones de los dispositivos móviles
3.Sistemas operativos móviles
4.Desarrollo de aplicaciones móviles
5.Java 2 Mobile Edition
6.Configuración CDC
7.Configuración CLDC
8.Paquetes opcionales en J2ME
9.MIDP: MIDlets
10.MIDP: Interfaces Gráficas de Usuario
11.MIDP: Persistencia
12.MIDP: Conexión por red
13.Persistencia II: Ficheros
14.Para terminar
3. MIDP: Midlets
MIDP: MIDlets
●Una aplicación MIDP requiere la implementación
de un MIDlet, cuya estructura recuerda los Applets
y Servlets de J2SE
import javax.microedition.midlet.MIDlet;
public class EjemploMidlet extends MIDlet
{ public void startApp() {
// Arrancar aplicación
}
public void pauseApp()
{ // Parar aplicación }
public void destroyApp(boolean unconditional)
{ // Eliminar recursos
}
}
Sistemas operativos
móviles
4. MIDP: Midlets
De manera similar a un Applet, un MIDlet requiere
●
la implementación de tres operaciones de la clase
MIDlet:
●startApp(). Es llamada automáticamente cuando
la aplicación debe comenzar su ejecución.
●pauseApp(). El dispositivo puede solicitar la parada
temporal de la aplicación en cualquier momento.
La reanudación implicará una nueva llamada a
startApp() o la terminación definitiva mediante la
llamada a destroyApp().
●destroyApp(). Es invocada para solicitar la liberación
de los recursos del MIDlet y cualquier tarea
necesaria antes de su eliminación de memoria.
Sistemas operativos
móviles
5. MIDP: Midlets
●Un conjunto de MIDlets se distribuye en un fichero
.jar
●El MANIFEST del fichero jar es más complicado que
los que conocemos
●Primero se indica el nombre global del conjunto de
MIDlets del fichero jar, su versión, autor y las versio-
nes de CLDC y MIDP necesarias
●Después cada MIDlet se describe mediante un nom-
bre, el icono correspondiente y el nombre de la clase
que lo implementa
MIDlet-Name: EjemplosMIDP
MIDlet-Version: 1.0
MIDlet-Vendor: ajrueda
MicroEdition-Configuration: CLDC-1.1
MicroEdition-Profile: MIDP-2.0
MIDlet-1: Ejemplo,ejemplo.png,EjemploMidlet
Sistemas operativos
móviles
6. MIDP: Interfaces Gráficas
de Usuario
MIDP: Interfaces Gráficas de Usuario
● MIDP proporciona una forma sencilla de construir
interfaces de usuario adaptada a las limitaciones de
pantalla, potencia de cálculo y batería de los dispo-
sitivos móviles.
●En comparación con toolkits como Swing, la varie-
dad y número de componentes existentes es muy
pequeño.
●La interfaz se construye a base de distintas panta-
llas, en lugar de ventanas o diálogos.
●Las acciones del usuario definen la transición de
una pantalla a otra .
Sistemas operativos
móviles
7. MIDP: Interfaces Gráficas
de Usuario
●Es importante tener en cuenta el pequeño tamaño
la pantalla del dispositivo a la hora de diseñar la
interfaz.
●La mayoría de los dispositivos dispone de un par
de botones de acción cuyo efecto se puede progra-
mar para cada pantalla.
Sistemas operativos
móviles
8. MIDP: Interfaces Gráficas
de Usuario
●Para empezar hay que obtener el objeto Display
que permite manejar la pantalla del dispositivo.
●La operación estática getDisplay() de esta clase
devuelve el objeto
Display d = Display.getDisplay()
●A continuación podemos establecer la pantalla ac-
tual mediante:
d.setCurrent(Displayable pantalla)
●Una vez obtenido el display, el MIDlet sigue el
siguiente esquema de funcionamiento:
1.Crear una pantalla
2.Mostrarla mediante setCurrent()
3.Esperar las acciones del usuario
4.Elegir otra pantalla en función de estas acciones (volver a 1)
Sistemas operativos
móviles
9. MIDP: Interfaces Gráficas
de Usuario
●Las clases que implementan la interfaz Display
able son las siguientes:
TextBox List Alert Form
Sistemas operativos
Canvas móviles
10. ● Crear y activar una pantalla TextBox es muy sencillo:
TextBox t = new TextBox( Escribe un poema , , 500, TextField.ANY);
d.setCurrent(t);
●Un Alert es similar a un messageBox de Swing,
admitiendo distintos tipos.
●El tiempo de visualización del Alert es configurable
mediante setTimeout()
●Al llamar a setCurrent() es necesario indicar
el siguiente displayable a mostrar tras el Alert
Alert a = new Alert( Error , Error al salvar la información ,
null, AlertType.ERROR);
a.setTimeout(5000);
d.setCurrent(a, siguienteDisp);
móviles
11. MIDP: Interfaces Gráficas
de Usuario
El displayable Form permite definir una pantalla
●
con múltiples Item (o componentes):
● StringItem. Similar a un label de Swing.
●Spacer. Un espacio con un ancho y alto determinado. Útil para distribuir los
componentes.
● TextField. Un editor de texto con una etiqueta asociada.
● ImageItem. Una imagen con una etiqueta.
● DateField. Un editor que permite introducir una fecha/hora.
● Gauge. Sirve para representar de manera gráfica un valor entero.
●ChoiceGroup. Sirve para seleccionar valores de una lista predeterminada.
Puede ser múltiple, exclusiva o popup
● Cualquier Item definido por el usuario
móviles
12. MIDP: Interfaces Gráficas
de Usuario
● Los Form permiten crear interfaces mucho más ricas:
Form f = new Form("Ficha deportiva");
f.append(new TextField("Apellidos", null, 40, TextField.ANY));
f.append(new TextField("Nombre", null, 40, TextField.ANY));
f.append(new DateField("Fecha de nacimiento", DateField.DATE));
f.append(new TextField("E-mail", null, 20,
TextField.EMAILADDR));
String[] tipos = {"Profesor", "Alumno"};
f.append(cg = new ChoiceGroup("Tipo", ChoiceGroup.EXCLUSIVE, tipos, null));
d.setCurrent(f);
Sistemas operativos
móviles
13. ●Para asociar acciones a los botones del dispositivo
se utiliza la clase Command
●Las activación de un comando es capturada por
un CommandListener, cuya única operación es
commandAction()
class listenerTextBox implements CommandListener {
public commandAction(Command cm, Displayable ds) {
if (cm == cFin) {
// Procesar el comando
}
}
}
TextBox t = new TextBox( Escribe un poema , , 500, TextField.ANY);
t.addCommand(cFin = new Command( Fin , Command.OK, 0));
t.setListener(new listenerTextBox());
d.setCurrent(t);
14. Tarea:Siguiendo el ejemplo que hemos desarrollado en la asignatura, crear un
visor móvil de nuestra cuenta
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.*;
public class MidletCuenta extends MIDlet
{ private Cuenta c;
private Display d;
private TextField tCodigo;
private Command cEntrar, cSalir, cVolver, cMovimientos;
private Form fPeticionCodigo, fInfoCuenta;
private List lMovCuenta;
public MidletCuenta()
{ d = null;
}
void crearComandos() {
cEntrar = new Command("Entrar", Command.OK, 0); cSalir =
new Command("Salir", Command.EXIT, 1); cVolver = new
Command("Volver", Command.BACK, 0); cMovimientos = new
Command("ver Mov.", Command.SCREEN, 0); }
15. MIDP: Interfaces Gráficas
de Usuario
public void startApp()
{ if (d == null)
{ d = Display.getDisplay(this);
}
crearComandos();
crearFormPeticionCodigo();
d.setCurrent(fPeticionCodigo); }
void crearFormPeticionCodigo() {
fPeticionCodigo = new Form("Información de cuentas");
fPeticionCodigo.append(tCodigo = new TextField("Código de cuenta
", null, 10, TextField.NUMERIC));
fPeticionCodigo.addCommand(cEntrar);
fPeticionCodigo.addCommand(cSalir);
fPeticionCodigo.setCommandListener(new listenerPeticionCodigo());
tCodigo.setLayout(Item.LAYOUT_2 | Item.LAYOUT_CENTER); }
class listenerPeticionCodigo implements CommandListener {
public void commandAction(Command cm, Displayable s) { if
(cm == cEntrar) {
// Cargar la cuenta aquí
crearFormInformacionCuenta();
d.setCurrent(fInfoCuenta); } else
if (cm == cSalir) {
destroyApp(true);
notifyDestroyed();
}
}
}
Sistemas operativos
móviles
16. MIDP: Interfaces Gráficas
de Usuario
void crearFormInformacionCuenta() {
// Crear formulario de información dae la cuenta fInfoCuenta = new
Form("Información de cuenta"); fInfoCuenta.append(new
StringItem("Código:", Long.toString(c.leerNumero())));
fInfoCuenta.append(new StringItem("Titular:", c.leerTitular()));
fInfoCuenta.append(new StringItem("Interés:",
Float.toString(c.leerInteres()))); fInfoCuenta.append(new
StringItem("Saldo:", Float.toString(c.leerSaldo())));
fInfoCuenta.addCommand(cMovimientos);
fInfoCuenta.addCommand(cVolver);
fInfoCuenta.setCommandListener(new listenerInformacionCuenta());
// Crear lista de movimientos
lMovCuenta = new List("Ultimos movimientos",
List.IMPLICIT); Movimiento m;
int nMov, nm;
for (nMov = 10, nm = c.numMovimientosHistorico() - 1;
nMov > 0 && nm >= 0; nm--, nMov--) {
m = c.leerMovimientoHistorico(nm);
lMovCuenta.append(cadenaDate(m.fecha) + ' ' + m.tipo + '
' + m.importe + ' ' + m.saldo, null);
}
lMovCuenta.addCommand(cVolver);
lMovCuenta.setCommandListener(new listenerInformacionMovimientos());
}
Sistemas operativos
móviles
17. MIDP: Interfaces Gráficas
de Usuario
class listenerInformacionCuenta implements CommandListener
{ public void commandAction(Command cm, Displayable s) { if
(cm == cVolver) {
d.setCurrent(fPeticionCodigo);
}
else if (cm == cMovimientos)
{ d.setCurrent(lMovCuenta); }
}
}
class listenerInformacionMovimientos implements CommandListener {
public void commandAction(Command cm, Displayable s) {
if (cm == cVolver) {
d.setCurrent(fInfoCuenta);
}
}
}
Sistemas operativos
móviles
18. MIDP: Persistencia
MIDP: Persistencia
●La capacidad de almacenamiento persistente de un
dispositivo móvil puede ser muy limitada.
●El soporte de tarjetas de memoria, cada vez más
común, ha aumentado mucho las prestaciones (8Gb
en iPhone o Nokia N95) posibilitando una estructura
de ficheros similar a la de un computador convencio
nal.
●Sin embargo el perfil MIDP es conservador y pro-
porciona un soporte sencillo de persistencia a través
de registros de bloques de bytes.
Sistemas operativos
móviles
19. MIDP: Persistencia
Un MIDlet puede abrir un almacén de registros
●
con un nombre arbitrario mediante:
RecordStore RecordStore.openRecordStore(“nombre”, true);
● El segundo parámetro indica que el almacén
debe abrirse si no existe.
●A través de las operaciones del objeto Record
Store podremos manejar los registros.
●Normalmente un almacén no se comparte con
otros MIDlets, aunque puede habilitarse este acceso
.
●El almacén de registros se cierra mediante:
closeRecordStore()
Sistemas operativos
móviles
20. MIDP: Persistencia
●El acceso a los registros se realiza a través de
un identificador numérico, que es devuelto al aña-
dir un registro:
int addRecord(byte[] datos, int offset, int numBytes)
●Para recuperar un registro debemos indicar su
identificador:
int getRecord(int id, byte[] buffer, int offset)
● Modificar un registro ya existente:
void setRecord(int id, byte[] nuevosDatos, int offset, int numBytes)
● Eliminar un registro:
void deleteRecord(int id)
Sistemas operativos
móviles
21. MIDP: Persistencia
Es posible recorrer los registros de un almacén
●
creando una enumeración:
RecordStore rs = RecordStore.openRecordStores( ejemplo, true);
RecordEnumeration re = re.enumerateRecords(null, null, false);
while (re.hasNextElement()) {
byte[] datos = re.nextRecord(); // Operar con los datos
}
re.destroy();
rs.closeRecordStore();
●La operación enumerateRecords() admite la es-
pecificación de clases de filtrado y ordenación de
los registros del almacén.
Sistemas operativos
móviles
22. MIDP: Persistencia
Tarea:Crear un gestor de persistencia para las cuentas corrientes mediante
un almacén de registros.
import java.io.*;
import java.util.*;
import javax.microedition.rms.*;
public class DAOCuentaRS {
static DAOCuentaRS instancia = null;
public static DAOCuentaRS obtenerInstancia() throws RecordStoreException
{ if (instancia == null) {
instancia = new DAOCuentaRS();
}
return instancia;
}
private DAOCuentaRS() {}
public boolean existe(long numero) throws RecordStoreException, IOException
{ RecordStore rs = null;
try {
rs = RecordStore.openRecordStore("cuentas", true);
return (buscarRegistroCuenta(rs, numero) != -1); }
finally {
if (rs != null) rs.closeRecordStore();
}
}
Sistemas operativos
móviles
23. MIDP: Persistencia
public Cuenta cargar(long numero) throws RecordStoreException, IOException
{ RecordStore rs = null;
DataInputStream dis =
null; Cuenta c = null;
try {
rs = RecordStore.openRecordStore("cuentas", true);
int idReg = buscarRegistroCuenta(rs,
numero); if (idReg == -1) {
return null;
}
dis = new DataInputStream(new
ByteArrayInputStream(rs.getRecord(idReg))); c = new
Cuenta(dis.readLong(), dis.readUTF(), dis.readFloat()); c.saldo =
dis.readFloat();
int nMov = dis.readInt();
for (int nm = 0; nm < nMov; nm++) {
c.movimientos.addElement(new Movimiento(new Date(dis.readLong()),
dis.readChar(), dis.readFloat(), dis.readFloat())); }
}
finally {
if (dis != null) dis.close(); if (rs
!= null) rs.closeRecordStore(); }
return c;
}
Sistemas operativos
móviles
24. MIDP: Persistencia
public void salvar(Cuenta c) throws RecordStoreException, IOException
{ RecordStore rs = null;
ByteArrayOutputStream bos =
null; DataOutputStream dos =
null;
try {
rs = RecordStore.openRecordStore("cuentas", true); dos = new
DataOutputStream(bos = new ByteArrayOutputStream());
dos.writeLong(c.leerNumero()); dos.writeUTF(c.leerTitular());
dos.writeFloat(c.leerInteres()); dos.writeFloat(c.leerSaldo());
Movimiento m;
int nMov = c.numMovimientosHistorico(); dos.writeInt(nMov);
for (int nm = 0; nm < nMov; nm++)
{ m =
c.leerMovimientoHistorico(nm);
dos.writeLong(m.fecha.getTime()); dos.writeChar(m.tipo);
dos.writeFloat(m.importe); dos.writeFloat(m.saldo); }
int idReg = buscarRegistroCuenta(rs,
c.leerNumero()); if (idReg != -1) {
rs.setRecord(idReg, bos.toByteArray(), 0,
bos.size()); } else {
rs.addRecord(bos.toByteArray(), 0, bos.size());
}
}
finally {
if (dos != null) dos.close(); if (rs
!= null) rs.closeRecordStore(); }
}
Sistemas operativos
móviles
25. MIDP: Persistencia
private int buscarRegistroCuenta(RecordStore rs, long numero)
throws RecordStoreException, IOException {
RecordEnumeration re = null;
DataInputStream dis =
null; long recNum;
int id;
try {
re = rs.enumerateRecords(null, null,
false); while (re.hasNextElement()) {
id = re.nextRecordId();
dis = new DataInputStream(new
ByteArrayInputStream(rs.getRecord(id))); recNum = dis.readLong();
if (recNum == numero)
{ return id;
}
dis.close();
dis = null;
}
} finally {
if (dis != null) dis.close();
if (re != null) re.destroy();
}
return -1;
}
}
Sistemas operativos
móviles
26. MIDP: Persistencia
En el MIDlet debemos crear un atributo para referenciar el gestor de persis
-tencia, y realizar su inicialización en startApp()
public void startApp() {
if (d == null) {
d = Display.getDisplay(this);
}
if (dc == null) {
try {
dc = DAOCuentaRS.obtenerInstancia();
}
catch(Exception e) {
d.setCurrent(new Alert("Error",
"No es posible abrir el almacén de registros",
null, AlertType.ERROR));
destroyApp(true);
notifyDestroyed();
return;
}
}
// Crear las cuentas de ejemplo si no existen
crearCuentasEjemplo();
crearComandos();
crearFormPeticionCodigo();
d.setCurrent(fPeticionCodigo); }
Sistemas operativos
móviles
27. MIDP: Persistencia
class listenerPeticionCodigo implements CommandListener {
public void commandAction(Command cm, Displayable s) { if
(cm == cEntrar) {
try {
c = dc.cargar(Long.parseLong(tCodigo.getString()));
if (c == null) {
d.setCurrent(new Alert("Error", "Cuenta inexistente",
null, AlertType.ERROR), fPeticionCodigo); return;
}
} catch(Exception e) {
d.setCurrent(new Alert("Error", "Error de lectura de cuenta",
null, AlertType.ERROR), fPeticionCodigo);
return;
}
crearFormInformacionCuenta();
d.setCurrent(fInfoCuenta); } else
if (cm == cSalir) {
destroyApp(true);
notifyDestroyed();
}
}
}
Sistemas operativos
móviles
28. MIDP: Conexión por red
MIDP: Conexión por red
●MIDP es especialmente potente en lo que se refie-
re a la conexión por red mediante sockets, http y
otros protocolos
●La clase Connection representa una conexión ge-
nérica y es extendida a tres conexiones que admi-
ten E/S mediante streams: InputConnection, Output-
Connection y StreamConnection
●La clase StreamConnection es extendida a varias
clases que representan distintos tipos de conexiones:
CommConnection, HttpConnection, httpsConnection,
SocketConnection, etc.
Sistemas operativos
móviles
29. MIDP: Conexión por red
●La clase Connector es una factoría que a partir d
e un url devuelve la clase de conexión correspon-
diente: Connection Connector.open(String url)
HttpConnection con1;
con1 = (HttpConnection) Connector.open(http://www.google.es/search?hl=es&q=j2me);
SocketConnection con2;
con2 = (SocketConnection) Connector.open(socket://miservidor:79);
●La conexión debe cerrarse al final con close()
●A partir de la conexión podemos obtener un stream
de lectura o escritura
HttpConnection con1;
con1 = (HttpConnection) Connector.open(http://www.google.es/search?hl=es&q=j2me);
InputStream is = con1.openInputStream();
// Utilizar el stream
con1.close();
Sistemas operativos
móviles
30. MIDP: Conexión por red
Ejemplo:El siguiente gestor de persistencia obtiene los datos de la cuenta
desde un servidor web
import java.io.*;
import java.util.*;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
public class DAOCuentaNC {
static DAOCuentaNC instancia = null;
public static DAOCuentaNC obtenerInstancia()
{ if (instancia == null) {
instancia = new DAOCuentaNC();
}
return instancia;
}
private DAOCuentaNC()
{ }
public boolean existe(long numero)
{ try {
cargar(numero);
}
catch(Exception e)
{ return false;
}
return true;
}
Sistemas operativos
móviles
31. MIDP: Conexión por red
public Cuenta cargar(long numero) throws IOException
{ InputConnection ic = null;
DataInputStream dis =
null; Cuenta c = null;
try {
ic = (InputConnection) Connector.open(urlCuenta(numero)); dis =
ic.openDataInputStream();
c = new Cuenta(dis.readLong(), dis.readUTF(), dis.readFloat()); c.saldo
= dis.readFloat();
int nMov = dis.readInt();
for (int nm = 0; nm < nMov; nm++) {
c.movimientos.addElement(new Movimiento(new Date(dis.readLong()),
dis.readChar(), dis.readFloat(), dis.readFloat())); }
} catch(Exception e) { // No se
encuentra la cuenta return
null;
} finally {
if (ic != null) ic.close();
}
return c;
}
private String urlCuenta(long codigo) {
return "http://robin.ujaen.es/asignaturas/progav/cuentas/"
+ Long.toString(codigo) + ".cnt";
}
}
Sistemas operativos
móviles
32. Persistencia II: Ficheros
Persistencia II: Ficheros
●El File Connection and PIM API (JSR 75) define
un nuevo tipo de conexión denominado FileConnec-
tion que permite trabajar con ficheros de manera
similar a un computador convencional.
●Este API no está disponible en todos los disposi-
tivos.
●El acceso al sistema de ficheros requiere permisos
especiales si la aplicación no está certificada, para
evitar daños en el mismo.
Sistemas operativos
móviles
33. Persistencia II: Ficheros
El siguiente ejemplo lee una imagen guardada en el dispositivo
FileConnection fc;
InputStream is;
fc = (FileConnection) Connector.open( /Imagenes/flower.jpg , Connector.READ);
is = fc.openInputStream();
Image mi = Image.createImage(is); //
Utilizar la imagen
is.close();
●La clase FileConnection permite abrir un stream de
E/S al fichero pero también contiene operaciones
para la creación, renombrado y borrado de ficheros
y directorios.
Sistemas operativos
móviles
34. Persistencia II: Ficheros
●No obstante existe un problema importante: la e
structura del sistema de ficheros de cada disposit
ivo no es estándar
●Cada dispositivo contiene una raíz para cada un
o de los medios de almacenamiento: memoria int
erna (/root, /internal, /InternalMemory) y tarjetas d
e memoria (/SDCard1, /MemoryCard)
●Es posible enumerar las distintas raices existe
ntes mediante el registro del sistema de ficher
os:
Enumeration raicesSF =
FileSystemRegistry.listRoots(); while
(raicesSF.hasMoreElements()) {
raizSF = (String) raicesSF.nextElement();
// Hacer algo con la raiz encontrada }
Sistemas operativos
móviles
35. Persistencia II: Ficheros
Este gestor de persistencia utiliza el API JSR 75
import java.io.*;
import java.util.*;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
class FileConnectionAPIInexistente extends Exception {}
public class DAOCuentaFC {
static DAOCuentaFC instancia =
null; String raizSF;
public static DAOCuentaFC obtenerInstancia() throws FileConnectionAPIInexistente
{ if (instancia == null) {
String versionFCAPI = System.getProperty(
"microedition.io.file.FileConnection.version");
if (versionFCAPI == null) {
throw new FileConnectionAPIInexistente();
}
instancia = new DAOCuentaFC();
}
return instancia;
}
private DAOCuentaFC() {
obtenerRaizSistemaFicheros(); }
Sistemas operativos
móviles
36. Persistencia II: Ficheros
public boolean existe(long numero)
{ try {
cargar(numero);
}
catch(Exception e)
{ return false;
}
return true;
}
public Cuenta cargar(long numero) throws IOException
{ FileConnection fc = null;
DataInputStream dis =
null; Cuenta c = null;
try {
fc = (FileConnection) Connector.open(urlCuenta(numero),
Connector.READ); if (!fc.exists()) {
return null;
}
dis = fc.openDataInputStream();
c = new Cuenta(dis.readLong(), dis.readUTF(),
dis.readFloat()); c.saldo = dis.readFloat();
Sistemas operativos
móviles
37. Persistencia II: Ficheros
int nMov = dis.readInt();
for (int nm = 0; nm < nMov; nm++) {
c.movimientos.addElement(new Movimiento(new Date(dis.readLong()),
dis.readChar(), dis.readFloat(), dis.readFloat())); }
}
finally {
if (fc != null) fc.close();
}
return c;
}
public void salvar(Cuenta c) throws IOException
{ FileConnection fc = null;
DataOutputStream dos = null;
try {
fc = (FileConnection) Connector.open("file:///" +
raizSF + "cuentas", Connector.READ_WRITE);
if (!fc.exists()) {
fc.mkdir();
}
fc.close();
fc = (FileConnection)
Connector.open(urlCuenta(c.leerNumero()),
ifConnector.READ_WRITE);
(!fc.exists())
{ fc.create();
}
Sistemas operativos
móviles
39. Persistencia II: Ficheros
●Otro problema adicional son las restricciones de
seguridad existentes en algunos dispositivos, que
sólo permiten el acceso a determinados directorio
s públicos (/Imagenes, /Sonidos, etc.)
Sistemas operativos
móviles
40. Para terminar
Para terminar
●Hemos estudiado MIDP a nivel básico
●En función de las necesidades de la aplicación
móvil a implementar será necesario estudiar con
mayor profundidad algunos de los APIs que hem
os visto y otros nuevos
● PIM API JSR 75
● API MIDP para juegos
●
Mobile Media API JSR JSR 184
●
Wireless Messaging API JSR 13
5 ● Bluetooth API JSR 82 Sistemas operativos
móviles