Arquitectura de Sistemas Computacionais Práticas 2004-2005 Prof. Dr. Paulo Sampaio [email protected] Departamento de Matemática e Engenharias UNIVERSIDADE DA MADEIRA O ambiente J2ME MIDlets Bluetooth 1 Pacotes CLDC Short for Connected Limited Device Configuration. CLDC is the J2ME configuration for smaller handheld devices that are usually battery operated and low in memory with limited processing power and low bandwidth. Most often the CLDC uses the K virtual machine, which is suitable for devices with 16/32-bit RISC/CISC microprocessors/controllers, and with as little as 160 K of total memory available -- 128 K of which is for the storage of the actual virtual machine and libraries themselves. CLDC reference implementation and KVM runs on Windows 98/NT, Solaris, and Palm platforms. Developers can access binary releases of the CLDC, or they can get the full release by signing legal forms from Sun. Pacotes CLDC CLDC 1.1 contém os seguintes pacotes: java.io, classes para gerir entradas e saídas através de data streams java.lang, classes fundamentais à linguagem Java java.lang.ref, suporte para referências fracas java.util, colecção de classes utilitárias, incluindo as classes para gestão de datas/tempos java.microedition.io, classes para a GCF (Generic Connection Framework) As três primeiras classes são subconjuntos das classes J2SE! 2 MIDP MIDP (Mobile Information Device Profile) cobre os seguintes aspectos: Gestão do ciclo de vida das aplicações, definido no pacote javax.microedition.midlet Interface com o Utilizador e Eventos, definidos no pacote javax.microedition.lcdui Conectividade em Rede, definida no pacote javax.microedition.io Armazenamento de dados no dispositivo, definido pelo pacote javax.microedition.rms MIDP também tem pacotes para desenvolvimento de jogos, som, certificados para autenticar informação... MIDlet definição de uma classe pública que estende a classe abstracta javax.microedition.midlet.MIDlet. semelhantes aos servlets Métodos da classe MIDlet Qualquer MIDlet implementa três métodos de gestão do ciclo de vida: startApp(): inicializa os objectos e define o display pauseApp(): pausa as threads activas, armazena os dados destroyApp(): liberta ou fecha recursos, armazena dados para uso futuro Os métodos acima são chamados pelo gestor da aplicação (Application Manager) para iniciar, suspender ou destruir o MIDlet O Application Manager vem pré-instalado em qualquer dispositivo MIDP 3 Ciclo de Vida dos MIDlets Ciclo de Vida dos MIDlets Uma instância é criada chamando o construtor do MIDlet. O MIDlet fica no estado Paused. De seguida, passa para o estado Active após o Application Manager chamar startApp() Quando o MIDlet está activo, o manager pode suspender a sua execução chamando pauseApp(). Isto coloca o MIDlet no estado Paused. Um MIDlet pode colocar-se automaticamente em Paused chamando notifyPaused() O manager pode terminar o MIDlet chamando destroyApp(). Assim, o MIDlet é destruído, esperando pacientemente pela garbage collection. Um MIDlet pode destruir-se automaticamente chamando notifyDestroyed() 4 Application Manager Um Application Manager (Gestor de Aplicação) instala e corre o MIDlet que controla o comportamento do MIDlet. Tem de ser capaz de: transferir um suite de MIDlets a partir de qualquer localização, possivelmente através de uma ligação Bluetooth instalar a suite de MIDlets no dispositivo MIDP realizar a gestão das versões lançar o MIDlet a partir de uma suite remover uma suite de MIDlets instalada previamente Definições Ficheiro Java ARchive (JAR) Ficheiro usado para empacotar as classes Java num arquivo comprimido para permitir uma distribuição mais eficiente MIDlet Suite 2 ou mais MIDlets empacotados num ficheiro JAR Estes MIDlets podem partilhar os recursos em tempo de execução JAR manifest É a parte da MIDlet suite que define os atributos dos MIDlets Java Application Descriptor (JAD) Ficheiro texto que contém os atributos dos MIDlets. Uma vez que o JAR manifest é parte do ficheiro JAR da MIDlet suite, o JAR completo tem de ser transferido para o dispositivo, a fim de descobrir se há espaço disponível no dispositivo para a suite. Para evitar o download, o JAD é criado e usado pelo manager para isso 5 Passos no desenvolvimento de MIDlets Escrever o MIDlet Compilar o código fonte Empacotar num ficheiro JAR Criar ficheiro JAD Publicar o MIDlet (JAD e JAR) Instalar o MIDlet no dispositivo ou emulador Estrutura básica de um MIDlet import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Displayable; import javax.microedition.midlet.MIDlet; public class meuMidlet extends MIDlet implements CommandListener { public void startApp() { } public void pauseApp() { } public void destroyApp() { } public void commandAction(Command c, Displayable d) { } } 6 Resmas de MIDlets Palettes e Gigabytes de MIDlets: http://developers.sun.com/techtopics/mobility/reference/codesamples/index.h tml Bluetooth Tecnologia rádio de baixo custo e alcance curto, destinada a substituir os fios de dados que ligam os aparelhos Constituída por: tecnologia rádio, pilha de software e “profiles” A Pilha de Protocolo (Protocol Stack): Controlador •Tipicamente implementado em Hardware On-Host Stack •Usado pela aplicações e serviços •Camada de topo (Bluetooth Host Software Protocol Stack) 7 Bluetooth Protocol Stack Bluetooth Protocol Stack 8 Bluetooth Protocol Stack Host Controller Interface (HCI) Realiza a interface com o controlador de hardware do host Logical Link Control and Adaptation Layer (L2CAP) Gere a segmentação dos pacotes, multiplexagem dos protocolos e fornece informação sobre a qualidade do serviço Service Discovery Protocols (SDP) As aplicações usam esta camada para descobrir os serviços Bluetooth que estejam disponíveis RFCOMM Fornece comportamento em série sobre Bluetooth É o mesmo que usar uma porta série standard (COM)! Object Exchange Protocol Bluetooth Profiles Capacidades neutras em relação aos vendedores Para garantir a interoperabilidade e consistência entre os dispositivos Generic Access Profile (GAP) Define o uso das camadas baixo nível do protocol stack Service Discovery and Adaptation Profile (SDAP) Específica à aplicação: define a disponibilidade e aspectos IU da descoberta de serviços e o uso do L2CAP Serial Port Profile (SPP) Define os requisitos e capacidades do RFCOMM, L2CAP e SDP, para emulação do cabo série Dial-Up Networking Profile (DUNP), Generic Object Exchange Profile (GOEP), Object Push Profile (OPP), ... 9 Usando Bluetooth, passo 1 Passo 1: Descoberta do dispositivo Bluetooth O dispositivo A envia pacotes de inquérito (inquiry) O dispositivo B responde com Frequency Hop Synchronization (FHS), que contém informação sobre a classe do dispositivo Descoberta de Dispositivos 10 Usando Bluetooth, passo 2 Passo 2: Ligação à base de dados de descoberta de serviços Ligação de Banda Base (ACL) é estabelecida Ligação L2CAP (Logical Link and Adaptation Protocol) é estabelecida sobre o canal ACL Ligação de Service Discovery Protocol (SDP) sobre o canal L2CAP Dispositivo A recebe informação sobre Dial-UP Networking (DUN) enviada pela Base de Dados de descoberta de serviços do Disp.B Dispositivo A desliga-se. Usando Bluetooth, passo 3 Passo 3: Ligação a um serviço Bluetooth Ligação ACL está activa Dispositivo A usa Link Management Protocol (LMP) para configurar a ligação Ligação L2CAP usando o protocolo RFCOMM é estabelecida para a emulação do cabo série RS-232 Ligação DUN é estabelecida usando a ligação RFCOMM 11 Usando as API’s Java para Bluetooth (JSR-82) import javax.bluetooth.DiscoveryListener; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.CommandListener; import javax.microedition.lcdui.Displayable; import javax.microedition.midlet.MIDlet; public class yourMidlet extends MIDlet implements CommandListener, DiscoveryListener { public void startApp() { } public void pauseApp() { } public void destroyApp() { } public void commandAction(Command c, Displayable d) { } Usando as API’s Java para Bluetooth (JSR-82) public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) { } public void inquiryCompleted(int param) { } public void serviceSearchCompleted(int param, int param1) { } public void servicesDiscovered(int param, ServiceRecord[] serviceRecord) { } } 12 Exemplo Simples O MIDlet HelloClient localiza o MIDlet HelloServer e envia o texto “Hello World” ao servidor que mostra esse texto no seu écran. É um exemplo two-in-one! Declaração do pacote e imports necessários a todas as classes deste exemplo: package HelloWorld; import java.io.*; import javax.microedition.io.*; import javax.microedition.lcdui.*; import javax.microedition.midlet.*; import javax.bluetooth.*; BluetoothMIDlet public class BluetoothMIDlet extends MIDlet implements Runnable, CommandListener { public BluetoothMIDlet() {} public void startApp() throws MIDletStateChangedException { new Thread(this).start(); // cria nova thread } public void pauseApp() {} public void destroyApp(boolean unconditional) {} public void run() {} public void commandAction(Command c, Displayable d) { notifyDestroyed(); // destrói este MIDlet } } 13 HelloClient public class HelloClient extends BluetoothMIDlet { public void run() { // Cria Form e adiciona comando Exit Form f = new Form("Client"); f.addCommand(new Command("Exit",Command.EXIT,1)); f.setCommandListener(this); Display.getDisplay(this).setCurrent(f); // mostra o Form no écran actual • try { // busca string de ligação e liga ao servidor LocalDevice local = LocalDevice.getLocalDevice(); DiscoveryAgent agent = local.getDiscoveryAgent(); String connString = agent.selectService( new UUID("86b4d249fb8844d6a756ec265dd1f6a3",false), ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); HelloClient if (connString != null) { try { // Liga ao servidor e envia "Hello World" StreamConnection conn = (StreamConnection)Connector.open(connString); OutputStream out = conn.openOutputStream(); out.write("Hello World".getBytes()); out.close(); conn.close(); f.append("Mensagem enviada correctamente."); } catch (IOException e) { f.append("IOException: " + e.getMessage()); } else { f.append("Não localizou o serviço."); } catch (BluetoothStateException e) { f.append("BluetoothStateException: "); f.append(e.getMessage()); } } } 14 HelloServer public class HelloServer extends BluetoothMIDlet { public void run() { // Cria Form e adiciona comando Exit Form f = new Form("Client"); f.addCommand(new Command("Exit",Command.EXIT,1)); f.setCommandListener(this); Display.getDisplay(this).setCurrent(f); try { // Tornar o dispositivo local passível de ser descoberto pelo cliente! LocalDevice local = LocalDevice.getLocalDevice(); if (!local.setDiscoverable(DiscoveryAgent.GIAC)) { f.append("Falhou a mudança para modo discoverable!"); return; } // Cria um objecto de ligação ao servidor para aceitar ligações do cliente StreamConnectionNotifier notifier = (StreamConnectionNotifier)Conector.open("btspp://localhost:" + "86b4d249fb8844d6a756ec265dd1f6a3"); HelloServer // Aceita uma ligação do cliente StreamConnection conn = notifier.acceptAndOpen(); // Abre o input para ler os dados InputStream in = conn.openInputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream(); // Ler os dados enviados pelo cliente até ao fim do stream int data; while ((data = in.read()) != -1) { out.write(data); } // Adiciona o texto enviado pelo cliente ao Form do servidor f.append(out.toString()); // Fecha todos os recursos abertos in.close(); conn.close(); notifier.close(); } catch (IOException e) { f.append("IOException: " + e.getMessage()); } } } 15