Armazenamento de dados através do RMS (Record Management System)

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (3)  (0)

Aprenda a construir um catálogo de endereços para o seu celular

Armazenamento de dados através do RMS (Record Management System)

Aprenda a construir um catálogo de endereços para o seu celular

 

Andrea Pivoto Patta

Introdução

Os dados manipulados pelas aplicações do mundo real são de suma importância. Por isto eles precisam ser armazenados em algum lugar para serem acessados quando necessário. Um exemplo disto, é um cadastro de dados pessoais, onde você armazena o nome, endereço e telefone de pessoas para serem acessados mais tarde. Como fazer isto em um dispositivo móvel? Simples, pois cada dispositivo móvel mantêm uma área dedicada de memória para armazenamento dos dados. Neste artigo, você vai começar a manipular com esta área utilizando a API RMS que o MIDP (Mobile Information Device Profile) disponibiliza. Inicialmente, será apresentado o modelo de armazenamento e como manipular com estes dados. Um exemplo de código é apresentado para você aprender os conceitos  e construir um catálogo de endereços para o seu celular.

O modelo de armazenamento de dados

O RMS suporta a criação e manipulação de vários registros para armazenamento de dados chamados de record store. Um record store é identificado pelo nome que consiste de no máximo 32 caracteres. Cada registro pode ter um ou mais outros registros.

O record store  é criado pelo MIDlet. MIDlets dentro de um mesmo MIDlet Suite podem compartilhar os registros. Portanto, um record store deve conter um nome único dentro do MIDlet Suite. O mesmo nome pode ser utilizado em diferentes MIDlets Suites.

Quando o MIDlet for removido do dispositivo, todos os record stores  criados no MIDlet também são removidos. Neste caso, obviamente todos os dados são perdidos. Por esta razão, o desenvolvedor deve considerar isto no projeto da aplicação incluindo mensagens de alerta ou confirmação para informar aos usuários a perda dos dados se a aplicação for removida. As aplicações devem também incluir um mecanismo de backup dos dados para outra localização.

As operações para manipulação do record store são:

 

Adicionar um registro

Deletar um registro

Alterar um registro

Recuperar um registro

Enumerar todos os registros

 

Os registros são identificados por um record ID, que é a chave primária. O record ID é do tipo inteiro (int). O primeiro registro adicionado recebe o ID 1 e os demais recebem o ID do último registro somado de 1. O RMS não suporta tipos característicos de banco de dados, tais como tabelas, linhas colunas etc.

Um registro é um array de bytes do tipo byte [ ]. Por causa disto, as aplicações devem converter seus dados para array de bytes ao escrever no registro e ao ler os dados a conversão inversa deve ser feita.

Exceções relacionadas ao acesso

O RMS define várias exceções relacionadas ao acesso aos dados. Todas elas pertencem ao pacote javax.microedition.rms. Veja a figura 1.

 

 

 pwm-25ago-rms_image001.jpg

Figura 1. Exceções do RMS

 

Ao desenvolver uma aplicação é importante tratar estas exceções.

A manipulação dos dados

Como mencionado anteriormente, conversões ao adicionar e recuperar os dados no registro precisam ser feitas devido ao armazenamento em array de bytes. O método addAddress do código de exemplo ilustra esta conversão. Uma função bastante utilizada nas aplicações é a recuperação de um determinado registro. Por exemplo, em um cadastro de dados pessoais o usuário pode querer entrar com o nome da pessoa e obter todos os dados armazenados da mesma, tais como, endereço, telefone, estado civil, sexo etc. O RMS disponibiliza duas maneiras para recuperar os dados de um registro específico.

Utilizar o record ID

Recuperar vários registros e procurar pelo qual você interessa através da enumeração

 

Na primeira opção, você precisa ter o identificador (ID) do registro. Portanto, você precisa guardá-lo de alguma forma. Isto não é conveniente e nem prático quando se tratar de um número muito grande de registros. A maneira mais fácil é usar a enumeração principalmente quando você não sabe os IDs que você quer e depois examinar cada registro para verificar qual você procura. A classe RecordStore define o método enumerateRecords que retorna alguns ou todos os registros de um record store, dependendo do que você passar como parâmetro. O método findAddress do código de exemplo ilustra o uso da enumeração para percorrer o record store.

 

Algumas vezes você pode querer selecionar um subconjunto de registros e não somente um registro específico. Neste caso, você pode utilizar a enumeração para recuperar os registros que satisfaçam algum critério. O primeiro argumento do método enumerateRecords especifica o filtro que é um objeto de RecordFilter. RecordFilter é uma classe que implementa a interface RecordFilter para identificar critérios utilizados no filtro.

 

O segundo argumento do método enumerateRecords é utilizado para comparar registros para determinar a sua ordem. Você poderá utilizá-lo quando quiser ordenar os registros seguindo algum critério, por exemplo, recuperar todos os nomes das pessoas em ordem alfabética.

Record listeners

As aplicações podem recebem notificações quando um registro é adicionado, removido ou alterado. Para isto, você utiliza a classe RecordStore que permite adicionar e remover listeners utilizando os métodos addRecordListener e removeRecordListener. No exemplo apresentado, não utilizamos esta funcionalidade, mas você poderá incluí-la se quiser. O importante é saber que existe e se você precisar há uma maneira de receber estas notificações.

A performance

O desempenho ao acessar o record store é bastante lento, o que não deixa de ser um problema. Os desenvolvedores devem considerar isto ao escolher as alternativas de armazenamento dos dados para a sua aplicação. Uma alternativa viável para aplicações com muitos dados é utilizar um banco de dados em um servidor e acessá-lo através da conexão utilizando o protocolo HTTP (Hiper Text Transfer Protocol). Neste caso, o uso do RMS é viável para aplicações que não manipulam grande quantidade de dados e o desempenho não é tão importante. Um exemplo típico destas aplicações é o catálogo de endereços ilustrado no exemplo.

A seguir o código que implementa o catálogo de endereços utilizando o RMS.

 

 

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.IOException;

 

import javax.microedition.lcdui.Alert;

import javax.microedition.lcdui.AlertType;

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.StringItem;

import javax.microedition.lcdui.TextField;

import javax.microedition.midlet.MIDlet;

import javax.microedition.midlet.MIDletStateChangeException;

import javax.microedition.rms.InvalidRecordIDException;

import javax.microedition.rms.RecordEnumeration;

import javax.microedition.rms.RecordStore;

import javax.microedition.rms.RecordStoreException;

import javax.microedition.rms.RecordStoreFullException;

import javax.microedition.rms.RecordStoreNotFoundException;

import javax.microedition.rms.RecordStoreNotOpenException;

 

 

public class AddressCatalog extends MIDlet implements CommandListener {

       private Display display;

       private Form mainForm;

       private TextField tbName; 

       private TextField tbAddress;

       private TextField tbQuestion;

       private Command cmdExit;   // Botão para sair do MIDlet

       private Command cmdSave;   // Botão para salvar no record store

       private Command cmdFind;   // Botão para encontrar um endereço

       private Command cmdRem;    // Botão para remover um nome do cadastro

       private Command cmdAdd;    // Botão para adicionar o endereço

       private StringItem strOpt;

       private Command cmdFindOK;

       private Command cmdFindBack;

       private Command cmdBack;

       private Command cmdRemOK;

       private Command cmdRemBack;

       private RecordStore rs;   // Objeto para manipulação do Record Store

      

       public AddressCatalog () throws RecordStoreNotFoundException,
          RecordStoreFullException, RecordStoreException {

             // Abre o Record Store chamado "AddressCatalog"

             rs = RecordStore.openRecordStore("AddressCatalog", true);

       }

 

       protected void startApp() throws MIDletStateChangeException {

             // Tela principal

             mainScreen();

       }

       private void mainScreen() {

             // Desenha a tela principal

             mainForm = new Form ("Catálogo de endereços");

             strOpt = new StringItem ("Escolha a opção no Menu", null);

            

             cmdAdd = new Command ("Adicionar",Command.SCREEN,1);

             cmdFind = new Command ("Encontrar", Command.SCREEN,1);

             cmdRem = new Command ("Remover", Command.SCREEN,1);

             cmdExit = new Command ("Sair",Command.SCREEN,1);

            

             mainForm.append(strOpt);

             mainForm.addCommand(cmdAdd);

             mainForm.addCommand(cmdFind);

             mainForm.addCommand(cmdRem);

             mainForm.addCommand(cmdExit);

             mainForm.setCommandListener(this);

 

             display = Display.getDisplay(this);

             display.setCurrent(mainForm);

       }

 

       protected void pauseApp() { }

 

       protected void destroyApp(boolean arg0) throws MIDletStateChangeException{ }

 

       //Método responsável por verificar o comando e chamar o método apropriado

       public void commandAction(Command cmd, Displayable disp) {

             // Comando Sair

             if (cmd == cmdExit){

                    try {

                           destroyApp(true);

                    } catch (MIDletStateChangeException e) {

                           e.printStackTrace();

                    }

                    notifyDestroyed();

             } // Commando Adicionar

               else if (cmd == cmdAdd) {

                    addAddress();

             } // Comando Salvar

               else if (cmd == cmdSave) {

                    try {

                           saveOpt(tbName.getString(), tbAddress.getString());

                    } catch (RecordStoreException e) {

                           e.printStackTrace();

                    }

             } // Comando Encontrar

               else if (cmd == cmdFind) {

                    findOpt();

             } // Commando Remover

               else if (cmd == cmdRem) {

                    remOpt();

               }

               // Comando OK da opção Encontrar

               else if (cmd == cmdFindOK) {

                    try {

                           findAddress(tbQuestion.getString());

                    } catch (RecordStoreException e) {

                           // TODO Auto-generated catch block

                           e.printStackTrace();

                    } catch (IOException e) {

                           // TODO Auto-generated catch block

                           e.printStackTrace();

                    }

             } // Comando Voltar

             else if (cmd == cmdFindBack || cmd == cmdRemBack || cmd == cmdBack)
             {

                    mainScreen();

             } // Comando OK da opção Listar

                else if (cmd == cmdRemOK) {

                    try {

                           remAddress();

                    } catch (IOException e1) {

                                  // TODO Auto-generated catch block

                                  e1.printStackTrace();

                    } catch (RecordStoreException e) {

                           // TODO Auto-generated catch block

                           e.printStackTrace();

                    }

       }

       }

 

       // Método responsável pela entrada de dados da opção Listar

       private void remOpt() {

             Form form = new Form ("Remove endereço");

             tbName = new TextField ("Entre com o nome", "", 30,TextField.ANY);

             cmdRemOK = new Command("OK",Command.SCREEN,1);

             cmdRemBack = new Command("Voltar",Command.SCREEN,1);

             form.append(tbName);

             form.addCommand(cmdRemOK);

             form.addCommand(cmdRemBack);

             form.setCommandListener(this);

             display.setCurrent(form);

       }

 

       // Método responsável por remover um endereço do catálogo

       private void remAddress() throws RecordStoreException, IOException {

             RecordEnumeration re = null; 

             boolean findAddress = false;

 

             // Recupera os registros usando enumeração

             try {

                    re = rs.enumerateRecords(null, null, false);

              } catch (RecordStoreNotOpenException e1) {

                    // TODO Auto-generated catch block

                    e1.printStackTrace();

             }

 

             // Procura pelo registro

             if (re.numRecords() > 0) {

                    ByteArrayInputStream bais = null;

                    DataInputStream dis = null;

                    String nameRMS = null;

                   

                    // Procura pelo endereço enquanto houver registros no RMS

                    byte [] record = re.nextRecord();

                    int id = 0;

                   

                    while (re.hasNextElement()) {

                           System.out.println (id);

                           bais = new ByteArrayInputStream (record);

                           dis = new DataInputStream(bais);

                           nameRMS = dis.readUTF();

                           String name = tbName.getString();

                           if (name.compareTo(nameRMS)== 0) { // Encontrou

                                  findAddress = true;

                                  // Recupera o ID corrente

                                  record = re.nextRecord();

                                  id = re.previousRecordId();

                                  // Remove o endereço pelo ID

                                  rs.deleteRecord(id);

                                  showMessage ("Sucesso!");

                                  break;

                           }

                           record = re.nextRecord();

                    }

                    if (!findAddress) {

                           showMessage ("Endereço não cadastrado");

                    }

             } else {

                    showMessage ("Endereço não cadastrado");

             }

       }

 

       // Método responsável pela entrada de dados para adição no catálogo

       private void addAddress() {

             Form form = new Form ("Adiciona endereços");

             tbName = new TextField ("Nome", "", 30,TextField.ANY);

             tbAddress = new TextField ("Endereço", "",50,TextField.ANY);

             cmdSave = new Command ("Salvar",Command.SCREEN,1);

             form.append(tbName);

             form.append(tbAddress);

             form.addCommand(cmdExit);

             form.addCommand(cmdSave);

             form.setCommandListener(this);

 

             display = Display.getDisplay(this);

             display.setCurrent(form);

       }

 

       // Método responsável por encontrar o endereço a partir do nome

       private void findAddress(String name) throws RecordStoreException, 
         IOException {

             RecordEnumeration re = null; 

             boolean findAddress = false;

 

             // Recupera os registros usando enumeração

             try {

                    re = rs.enumerateRecords(null, null, false);

             } catch (RecordStoreNotOpenException e1) {

                    // TODO Auto-generated catch block

                    e1.printStackTrace();

             }

 

             // Procura pelo registro

             if (re.numRecords() > 0) {

                    ByteArrayInputStream bais = null;

                    DataInputStream dis = null;

                    String nameRMS = null;

 

               //Procura pelo endereço enquanto houver registros no record store

                    byte [] record = re.nextRecord();

                    while (re.hasNextElement()) {

                           bais = new ByteArrayInputStream (record);

                           dis = new DataInputStream(bais);

                           nameRMS = dis.readUTF();

                           if (name.compareTo(nameRMS)== 0) { // Encontrou

                                  findAddress = true;

                                  System.out.println(nameRMS);

                                  showAddress(dis.readUTF());

                                  break;

                           }

                           record = re.nextRecord();

                    }

                    if (!findAddress)

                           showMessage ("Endereço não cadastrado");

             } else {

                    showMessage ("Endereço não cadastrado");

             }

       }

 

       // Método responsável por mostrar o endereço encontrado

       private void showAddress(String addressRMS) {

             StringItem strAddress;

             Form form = new Form("Mostrar endereço");

             cmdBack = new Command("Voltar",Command.SCREEN,1);

            

             strAddress = new StringItem("Endereço:", addressRMS);

             form.append(strAddress);

             form.addCommand(cmdBack);

             form.setCommandListener(this);

             display.setCurrent(form);

       }

 

       // Método responsável pela entrada de dados para procura

       private void findOpt() {

             Form form = new Form("Achar endereço");

             cmdFindOK = new Command("OK",Command.SCREEN,2);

             cmdFindBack = new Command("Voltar",Command.SCREEN,2);

            

             tbQuestion = new TextField("Entre com o nome", "", 30, 
             TextField.ANY);

             form.append(tbQuestion);

             form.addCommand(cmdFindOK);

             form.addCommand(cmdFindBack);

             form.setCommandListener(this);

             display.setCurrent(form);

       }

 

   //Método responsável por adicionar os dados (nome e endereço) no record store

       private void saveOpt(String name, String address) throws 
         RecordStoreException {

             ByteArrayOutputStream baos = new ByteArrayOutputStream();

             DataOutputStream dos = new DataOutputStream(baos);

            

             try {

                    dos.writeUTF(name);

                    dos.writeUTF(address);

             } catch (IOException e) {

                    e.printStackTrace();

             }

 

             // Adiciona os dados convertendo-os para array de bytes

             rs.addRecord(baos.toByteArray(), 0, baos.toByteArray().length);

             showMessage ("Sucesso !");

       }

 

       // Método responsável por apresentar mensagens na tela

       private void showMessage(String msg) {

             Alert alert = new Alert("Mensagem", msg, null, 
                AlertType.CONFIRMATION);

             display.setCurrent(alert,mainForm);

       }

}

 

Conclusão

 

O armazenamento dos dados é de suma importância para uma aplicação do mundo real. Existem várias maneiras de armazenar os dados. Entre elas está o RMS disponibilizado pelo MIDP que permite armazenar os dados em record store que guardam os dados em array de bytes.  Os registros  podem ser compartilhados entre os MIDlets de um mesmo MIDlet Suite e são identificados pelo nome.

A aplicação deve utilizar mecanismos de conversão dos tipos de dados específicos para array de bytes e vice-versa ao escrever e ler os dados respectivamente. O record store pode ser acessado pelo seu ID ou através de enumeration que é  a melhor opção para recuperar registros. Utilizando enumeração você recupera todos os registros de um record store e registros que satisfaçam critérios que você especificar. Outra facilidade disponibilizada pela enumeração é recuperar dados de uma forma ordenada. Embora a performance em utilizar o RMS seja um problema, este sistema poderá ser utilizado em pequenas aplicações que armazenam poucos dados cujo desempenho não seja tão importante.

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?