You are on page 1of 53

Programacinde dispositivosmviles

Tema6:Programacinde dispositivosmviles
1.Programacindedispositivosmviles 2.Limitacionesdelosdispositivosmviles 3.Sistemasoperativosmviles 4.Desarrollodeaplicacionesmviles 5.Java2MobileEdition 6.ConfiguracinCDC 7.ConfiguracinCLDC 8.PaquetesopcionalesenJ2ME 9.MIDP:MIDlets 10.MIDP:InterfacesGrficasdeUsuario 11.MIDP:Persistencia 12.MIDP:Conexinporred 13.PersistenciaII:Ficheros 14.Paraterminar

Programacinde dispositivosmviles

Programacindedispositivosmviles
Lageneralizacinenlosltimosaosdetelfonos mviles,smartphones,PDAs,etc.hageneradoun importantenecesidaddeaplicacionesparaestetipo dedispositivos Lasprestacionesdelosdispositivosmvilesse incrementandaada,posibilitandolaimplementacin deaplicacionesmuyinteresantes

AccesoaInternetyconectividadmedianteBluetooth Envodemensajescortos Aceleracin2Dy3D Reproduccindevideoysonido Cmaraintegrada InformacindelocalizacinGPS Sensoresdeorientacin etc.

Programacinde dispositivosmviles

Programacinde dispositivosmviles

Limitacionesdelosdispositivosmviles
Lanecesidaddeahorrarenergaobligaautilizar procesadoresconunacapacidaddecmputolimitada ybajafrecuenciadereloj Elusointensivodeclculos,grficos,sonido, conexionesinalmbricasetc.limitalavidadela bateria Lamemoriadisponibleesmuylimitadaen comparacinconladeunordenadorordinario Elalmacenamientodedatospersistentetambines muylimitado:memoriainterna+tarjetasSDosimilar

Limitacionesdelos dispositivosmviles

Programacinde dispositivosmviles

Sistemasoperativosmviles
Sonsistemasoperativosespecficosparaestetipode dispositivos,quetienenencuentalaslimitacionesque hemosvistoantes SymbianeselS.O.instaladoenmayornmerode dispositivosmvilesenlaactualidad,sobretodo telfonosmviles Dosplataformas:S60yUIQ

S60

UIQ

Sistemasoperativos mviles

Programacinde dispositivosmviles

WindowsMobile,conmayordifusinenelmercado dePDAs

PalmOS,utilizadoporelfabricantedePDAsPalm Inc.

Sistemasoperativos mviles

Programacinde dispositivosmviles

Android,esunS.O.paramvilespresentado recientementeporGoogle.UtilizaunkernelLinux

OtrosS.O.mviles:RIMBlackberryyotrosS.O. basadosenkernellinux

Sistemasoperativos mviles

Programacinde dispositivosmviles

Desarrollodeaplicacionesmviles
Grandisparidaddeplataformasdedesarrollo Symbian(S60yUIQ):C++conlibrerasnativas WindowsMobile:.NETCompactFramework,una versinlimitadade.NET PalmOS:C/C++,conlibrerasnativas Android:Javaconlibrerasnativas(noJ2ME) JavaMobileEdition(J2ME)paramltiples plataformas,especialmenteSymbian Otras:Python

Sistemasoperativos mviles

Java2MobileEdition

Java2MobileEdition
Lanicaopcinrealquepermiteundesarrollo multiplataformaparadispositivosmviles Tieneunaestructuraaltamentemodularpara adaptarsealascaractersticasdecadadispositivo

Sistemasoperativos mviles

Java2MobileEdition

Lasconfiguraciones(CDCyCDLC)definenel entornomnimonecesarioparalaejecucinde aplicacionesjavaenungrupoampliodedispositivos mviles(JVM/KVM+paquetesbsicos) Losperfilesdefinenpaquetesadicionalespara soportarfuncionalidadesbsicasimprescindiblesde cadafamiliadedispositivos Lospaquetesopcionalessirvenparacubrir funcionalidadesespecficas:Bluetooth,soporte3D, etc.

Sistemasoperativos mviles

ConfiguracinCDC

ConfiguracinCDC
CDC(ConnectedDeviceConfiguration).ParaPDAs deltimageneracinosmartphonesavanzados Requiereunamquinavirtualjavacompatiblecon J2SE1.4.2ylossiguientespaquetes:

java.lang java.lang.ref java.lang.reflect java.math java.text java.io javax.microedition.io

java.util java.util.zip java.util.jar java.net java.security java.security.cer

Sistemasoperativos mviles

ConfiguracinCDC

LosdispositivosqueutilizanelCDCadmitentres perfiles:FoundationProfile,PersonalBasisProfiley PersonalProfile ElFoundationProfile proporcionasoportebsicode redyE/S ElPersonalBasisProfilecontienetodaslasclasesdel FoundationProfilemssoportelimitadodeJavabeans yAWT ElPersonalProfileincluyelosdosperfilesanteriores mssoportecompletodeAWTyJavabeans UnaaplicacinJ2SEimplementadacuidadosamente puedeserejecutableenlaconfiguracinCDC

Sistemasoperativos mviles

ConfiguracinCLDC

ConfiguracinCLDC
CLDC(ConnectedLimitedDeviceConfiguration). Paradispositivosconpotenciadeclculo,memoria, baterayaccesoaredlimitados Incluyeunamquinavirtualjavareducida(KVM)ylos siguientespaquetes:

Sloincluyelasclasesbsicas EEDDs:Vector,HashtableyStack

Sistemasoperativos mviles

java.lang(reducida) java.lang.ref(reducida) java.util(reducida) java.io(reducida) java.microedition.io

ConfiguracinCDLC

MobileInformationDeviceProfile(MIDP)eselperfil mscomnconCLDC MIDPpermitelaimplementacindeaplicacionescon lasiguientefuncionalidad:

LamayoradelosmvilesactualessoportanCLDC +MIDP.Muchoxitoporlaimplementacindejuegos LaprogramacinMIDPparaconfiguracinCLDC requierelainstalacindelSunJavaWirelessToolkit NetbeansproporcionasoportemedianteelMobility Pack

Interfazdeusuariosencilla,adaptadaamviles APIespecializadoparajuegos Persistenciabsica Conexinporred Sonido

Sistemasoperativos mviles

Paquetesopcionales enJ2ME

PaquetesopcionalesenJ2ME
Permitenextenderlafuncionalidadbsicadelos perfilesparaaprovechartodaslasposibilidadesdel dispositivo WirelessMessagingAPI(WMA)JSR120,JSR205. EnvodemensajesSMS. MobileMediaAPI(MMAPI)JSR135.Soportede audioyvideo,tantoreproduccincomocaptura LocationAPIJSR179.Localizacingeogrficadel dispositivo,medianteGPSuotrosmecanismos

Sistemasoperativos mviles

Paquetesopcionales enJ2ME

PersonalInformationManagementandFile ConnectionAPIJSR75.Accesoalalistadecontactos deltelfonomvilyalsistemadeficheros SecurityandTrustServicesAPIJSR177. Tratamientodeinformacinprivada,ejecucinsegura, identificacinyautentificacinetc. Mobile3DGraphicsJSR184.Soportedegrficos3D J2MEWebServicesAPI(WSA)JSR172.Soportede servicioswebendispositivosmviles BluetoothAPIJSR82 J2MERMIJSR66.Llamadaaoperacionesde objetosremotos

Sistemasoperativos mviles

MIDP:Midlets

MIDP:MIDlets
UnaaplicacinMIDPrequierelaimplementacinde unMIDlet,cuyaestructurarecuerdalosAppletsy ServletsdeJ2SE

import javax.microedition.midlet.MIDlet; public class EjemploMidlet extends MIDlet { public void startApp() { // Arrancar aplicacin } public void pauseApp() { // Parar aplicacin } public void destroyApp(boolean unconditional) { // Eliminar recursos } }

Sistemasoperativos mviles

MIDP:Midlets

DemanerasimilaraunApplet,unMIDletrequierela implementacindetresoperacionesdelaclase MIDlet: startApp().Esllamadaautomticamentecuandola aplicacindebecomenzarsuejecucin pauseApp().Eldispositivopuedesolicitarlaparada temporaldelaaplicacinencualquiermomento.La reanudacinimplicarunanuevallamadaa startApp()olaterminacindefinitivamediantela llamadaadestroyApp() destroyApp().Esinvocadaparasolicitarla liberacindelosrecursosdelMIDletycualquier tareanecesariaantesdesueliminacindememoria

Sistemasoperativos mviles

MIDP:Midlets

UnconjuntodeMIDletssedistribuyeenunficherojar ElMANIFESTdelficherojaresmscomplicadoque losqueconocemos Primeroseindicaelnombreglobaldelconjuntode MIDletsdelficherojar,suversin,authorylas versionesdeCLDCyMIDPnecesarias DespuscadaMIDletsedescribemedianteun nombre,eliconocorrespondienteyelnombredela clasequeloimplementa

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
Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

MIDP:InterfacesGrficasdeUsuario
MIDPproporcionaunaformasencilladeconstruir interfacesdeusuarioadaptadaalaslimitacionesde pantalla,potenciadeclculoybateradelos dispositivosmviles EncomparacincontoolkitscomoSwing,lavariedad ynmerodecomponentesexistentesesmuypequeo Lainterfazseconstruyeabasededistintaspantallas, enlugardeventanasodilogos Lasaccionesdelusuariodefinenlatransicindeuna pantallaaotra

Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

Esimportantetenerencuentaelpequeotamaode lapantalladeldispositivoalahoradedisearla interfaz Lamayoradelosdispositivosdisponedeunparde botonesdeaccincuyoefectosepuedeprogramar paracadapantalla

Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

ParaempezarhayqueobtenerelobjetoDisplayque permitemanejarlapantalladeldispositivo LaoperacinestticagetDisplay()deestaclase devuelveelobjeto Displayd=Display.getDisplay() Acontinuacinpodemosestablecerlapantallaactual mediante: d.setCurrent(Displayablepantalla) Unavezobtenidoeldisplay,elMIDletsigueel siguienteesquemadefuncionamiento:

1. Crearunapantalla 2. MostrarlamediantesetCurrent() 3. Esperarlasaccionesdelusuario 4. Elegirotrapantallaenfuncindeestasacciones(volvera1)

Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

LasclasesqueimplementanlainterfazDisplayable sonlassiguientes:

TextBox

List

Alert

Form

Canvas

Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

CrearyactivarunapantallaTextBoxesmuysencillo:
TextBox t = new TextBox( Escribe un poema , d.setCurrent(t); , 500, TextField.ANY);

UnAlertessimilaraunmessageBoxdeSwing, admitiendodistintostipos. EltiempodevisualizacindelAlertesconfigurable mediantesetTimeout() AlllamarasetCurrent()esnecesarioindicarel siguientedisplayableamostrartraselAlert

Alert a = new Alert( Error , null, AlertType.ERROR); a.setTimeout(5000);

Error al salvar la informacin ,

d.setCurrent(a, siguienteDisp);

Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

EldisplayableFormpermitedefinirunapantallacon mltiplesItem(ocomponentes):

StringItem.SimilaraunlabeldeSwing Spacer.Unespacioconunanchoyaltodeterminado.tilparadistribuirlos componentes TextField.Uneditordetextoconunaetiquetaasociada ImageItem.Unaimagenconunaetiqueta DateField.Uneditorquepermiteintroducirunafecha/hora Gauge.Sirvepararepresentardemaneragrficaunvalorentero ChoiceGroup.Sirveparaseleccionarvaloresdeunalistapredeterminada.Puede sermltiple,exclusivaopopup CualquierItemdefinidoporelusuario

Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

LosFormpermitencrearinterfacesmuchomsricas:
Form f = new f.append(new f.append(new f.append(new f.append(new Form("Ficha deportiva"); TextField("Apellidos", null, 40, TextField.ANY)); TextField("Nombre", null, 40, TextField.ANY)); DateField("Fecha de nacimiento", DateField.DATE)); TextField("E-mail", null, 20, TextField.EMAILADDR));

String[] tipos = {"Profesor", "Alumno"}; f.append(cg = new ChoiceGroup("Tipo", ChoiceGroup.EXCLUSIVE, tipos, null)); d.setCurrent(f);

Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

Paraasociaraccionesalosbotonesdeldispositivose utilizalaclaseCommand Lasactivacindeuncomandoescapturadaporun CommandListener,cuyanicaoperacines 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);


Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

Siguiendoelejemploquehemosdesarrolladoenlaasignatura,vamosacrearun visormvildenuestracuenta
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); }

Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

public void startApp() { if (d == null) { d = Display.getDisplay(this); } crearComandos(); crearFormPeticionCodigo(); d.setCurrent(fPeticionCodigo); } void crearFormPeticionCodigo() { fPeticionCodigo = new Form("Informacin de cuentas"); fPeticionCodigo.append(tCodigo = new TextField("Cdigo 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(); } } }
Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

void crearFormInformacionCuenta() { // Crear formulario de informacin dae la cuenta fInfoCuenta = new Form("Informacin de cuenta"); fInfoCuenta.append(new StringItem("Cdigo:", Long.toString(c.leerNumero()))); fInfoCuenta.append(new StringItem("Titular:", c.leerTitular())); fInfoCuenta.append(new StringItem("Inters:", 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()); }
Sistemasoperativos mviles

MIDP:InterfacesGrficas deUsuario

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); } } }

Sistemasoperativos mviles

MIDP:Persistencia

MIDP:Persistencia
Lacapacidaddealmacenamientopersistentedeun dispositivomvilpuedesermuylimitada Elsoportedetarjetasdememoria,cadavezms comn,haaumentadomucholasprestaciones(8Gb eniPhoneoNokiaN95)posibilitandounaestructura deficherossimilaraladeunordernadorconvencional SinembargoelperfilMIDPesconservadory proporcionaunsoportesencillodepersistenciaa travsderegistrosdebloquesdebytes

Sistemasoperativos mviles

MIDP:Persistencia

UnMIDletpuedeabrirunalmacnderegistrosconun nombrearbitrariomediante:

Elsegundoparmetroindicaqueelalmacndebe abrirsesinoexiste AtravsdelasoperacionesdelobjetoRecordStore podremosmanejarlosregistros Normalmenteunalmacnnosecomparteconotros MIDlets,aunquepuedehabilitarseesteacceso Elalmacnderegistrossecierramediante:

RecordStoreRecordStore.openRecordStore(nombre,true);

closeRecordStore()

Sistemasoperativos mviles

MIDP:Persistencia

Elaccesoalosregistrosserealizaatravsdeun identificadornumrico,queesdevueltoalaadirun registro:

Pararecuperarunregistrodebemosindicarsu identificador:

intaddRecord(byte[]datos,intoffset,intnumBytes)

Modificarunregistroyaexistente: Eliminarunregistro:

intgetRecord(intid,byte[]buffer,intoffset)

voidsetRecord(intid,byte[]nuevosDatos,intoffset,intnumBytes) voiddeleteRecord(intid)

Sistemasoperativos mviles

MIDP:Persistencia

Esposiblerecorrerlosregistrosdeunalmacn creandounaenumeracin:

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();

LaoperacinenumerateRecords()admitela especificacindeclasesdefiltradoyordenacinde losregistrosdelalmacn

Sistemasoperativos mviles

MIDP:Persistencia

Vamosacrearungestordepersistenciaparalascuentascorrientesmedianteun almacnderegistros
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(); } }
Sistemasoperativos mviles

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; }
Sistemasoperativos mviles

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(); } }
Sistemasoperativos mviles

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; } }

Sistemasoperativos mviles

MIDP:Persistencia

EnelMIDletdebemoscrearunatributoparareferenciarelgestordepersistencia, yrealizarsuinicializacinenstartApp()
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 almacn de registros", null, AlertType.ERROR)); destroyApp(true); notifyDestroyed(); return; } } // Crear las cuentas de ejemplo si no existen crearCuentasEjemplo(); crearComandos(); crearFormPeticionCodigo(); d.setCurrent(fPeticionCodigo); }
Sistemasoperativos mviles

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(); } } }

Sistemasoperativos mviles

MIDP:Conexinporred

MIDP:Conexinporred
MIDPesespecialmentepotenteenloqueserefierea laconexinporredmediantesockets,httpyotros protocolos LaclaseConnectionrepresentaunaconexin genricayesextendidaatresconexionesque admitenE/Smediantestreams:InputConnection, OutputConnectionyStreamConnection LaclaseStreamConnectionesextendidaavarias clasesquerepresentandistintostiposdeconexiones: CommConnection,HttpConnection,httpsConnection, SocketConnection,etc.

Sistemasoperativos mviles

MIDP:Conexinporred

LaclaseConnectoresunafactoraqueapartirdeun urldevuelvelaclasedeconexincorrespondiente:

ConnectionConnector.open(Stringurl)

HttpConnection con1; con1 = (HttpConnection) Connector.open( http://www.google.es/search?hl=es&q=j2me ); SocketConnection con2; con2 = (SocketConnection) Connector.open( socket://miservidor:79 );

Laconexindebecerrarsealfinalconclose() Apartirdelaconexinpodemosobtenerunstream delecturaoescritura

HttpConnection con1; con1 = (HttpConnection) Connector.open( http://www.google.es/search?hl=es&q=j2me ); InputStream is = con1.openInputStream(); // Utilizar el stream con1.close();

Sistemasoperativos mviles

MIDP:Conexinporred

Elsiguientegestordepersistenciaobtienelosdatosdelacuentadesdeun servidorweb
import import import import java.io.*; java.util.*; javax.microedition.io.*; 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; }

Sistemasoperativos mviles

MIDP:Conexinporred

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"; } }
Sistemasoperativos mviles

PersistenciaII:Ficheros

PersistenciaII:Ficheros
ElFileConnectionandPIMAPI(JSR75)defineun nuevotipodeconexindenominadoFileConnection quepermitetrabajarconficherosdemanerasimilara unordenadorconvencional EsteAPInoestdisponibleentodoslosdispositivos Elaccesoalsistemadeficherosrequierepermisos especialessilaaplicacinnoestcertificada,para evitardaosenelmismo

Sistemasoperativos mviles

PersistenciaII:Ficheros

Elsiguienteejemploleeunaimagenguardadaeneldispositivo
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();

LaclaseFileConnectionpermiteabrirunstreamde E/Salficheroperotambincontieneoperacionespara lacreacin,renombradoyborradodeficherosy directorios

Sistemasoperativos mviles

PersistenciaII:Ficheros

Noobstanteexisteunproblemaimportante:la estructuradelsistemadeficherosdecadadispositivo noesestndar Cadadispositivocontieneunarazparacadaunode losmediosdealmacenamiento:memoriainterna (/root,/internal,/InternalMemory)ytarjetasde memoria(/SDCard1,/MemoryCard) Esposibleenumerarlasdistintasraicesexistentes medianteelregistrodelsistemadeficheros:

Enumeration raicesSF = FileSystemRegistry.listRoots(); while (raicesSF.hasMoreElements()) { raizSF = (String) raicesSF.nextElement(); // Hacer algo con la raiz encontrada }

Sistemasoperativos mviles

PersistenciaII:Ficheros

EstegestordepersistenciautilizaelAPIJSR75
import import import import java.io.*; java.util.*; javax.microedition.io.*; 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(); }

Sistemasoperativos mviles

PersistenciaII: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();

Sistemasoperativos mviles

PersistenciaII: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()), Connector.READ_WRITE); if (!fc.exists()) { fc.create(); }
Sistemasoperativos mviles

PersistenciaII:Ficheros

dos = fc.openDataOutputStream(); 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); } } finally { if (fc != null) fc.close(); } } private String urlCuenta(long codigo) { return "file:///" + raizSF + "cuentas/" + Long.toString(codigo) + ".cnt"; } private void obtenerRaizSistemaFicheros() { Enumeration raicesSF = FileSystemRegistry.listRoots(); if (raicesSF.hasMoreElements()) { raizSF = (String) raicesSF.nextElement(); } } }
Sistemasoperativos mviles

PersistenciaII:Ficheros

Otroproblemaadicionalsonlasrestriccionesde seguridadexistentesenalgunosdispositivos,queslo permitenelaccesoadeterminadosdirectorios pblicos(/Imagenes,/Sonidos,etc.)

Sistemasoperativos mviles

Paraterminar

Paraterminar
HemosestudiadoMIDPanivelbsico Enfuncindelasnecesidadesdelaaplicacinmvil aimplementarsernecesarioestudiarconmayor profundidadalgunosdelosAPIsquehemosvistoy otrosnuevos PIMAPIJSR75 APIMIDPparajuegos MobileMediaAPIJSRJSR184 WirelessMessagingAPIJSR135 BluetoothAPIJSR82

Sistemasoperativos mviles