APIs Java ME recentemente desaprovados no Motorola i876

O novo aparelho Motorola i876 inclui vários câmbios ao entorno Java ME. Isso inclui algumas APIs que foram desaprovadas e não serão incluídas mais pelo fato de serem redundantes ou porque já existem APIs padrão Java (conhecidos como JSRs) com mais funcionalidade.

As APIs desaprovadas, e as APIs que as substituem no i876 são as seguintes:

API Desaprovada Nova API
MidiPlayer API JSR 135 - Mobile Media API
VoiceNotes JSR 135 - Mobile Media API
Crypto API JSR 77 - Security and Trust Services API (SATSA)
Lightweight Windowing Toolkit (LWT) Não substituído
Math CLDC 1.1
3D API JSR 184 - Mobile 3d Graphics API for J2ME
File I/O JSR 75 - PDA Optional Packages for the J2ME Platform
DateBook API JSR 75 - PDA Optional Packages for the J2ME Platform
PhoneBook API JSR 75 - PDA Optional Packages for the J2ME Platform

Se os seus aplicativos existentes usam algumas de essas APIs, será necessário fazer algumas modificações ao seu código. A continuação, oferecemos algumas recomendações sobre como adequar os seus aplicativos para que eles funcionem corretamente.

MidiPlayer API

O pacote com.motorola.midi foi completamente eliminado, e é substituído com o JSR 135 Mobile Media API, que é o padrão para multimídia no Java ME. O JSR 135 permite maior portabilidade do código a diferentes aparelhos, e a utilização do mesmo código para reproduzir áudio em formatos MIDI, WAV, MP3 e outros, com maior funcionalidade.

VoiceNotes API

O pacote com.mot.iden.voicenote foi completamente eliminado e é substituído pelo JSR 135 Mobile Media API, que é o padrão para multimídia no Java ME. O JSR 135 permite maior portabilidade do código a diferentes aparelhos, e a utilização do mesmo código para registrar áudio em vários formatos.

Para registrar áudio com o JSR 135 nos mesmos formatos VSELP, AMBE o AMR usados pelo VoiceNotes API, somente é preciso passar o URI file:///./nombre.vnf no parâmetro passado ao Player.createPlayer(). Ele faz registrar um arquivo no formato Voice Notes (que por padrão é em formato AMBE registrado com um bitrate de 2400).

Crypto API

O pacote com.motorola.iden.crypto foi completamente eliminado e é substituído pelo JSR 177 - Security and Trust Services API (SATSA). SATSA é o padrão em MIDP para o manejo de criptografia, e oferece uma interface muito mais poderosa da que oferece o Crypto API para administrar criptografia, segurança, assinaturas digitais, e outros.

Lightweight Windowing Toolkit (LWT)

O Lightweight Windowing Toolkit (LWT) que era incluído para oferecer funções de GUI avançadas em aparelhos MIDP 1.0 é eliminado por completo. A metodologia em MIDP 2.0 de construção de formulários e/o de Canvases oferece funcionalidade equivalente sem introduzir uma API particular somente aos aparelhos iDEN.

Math API

O pacote com.mot.iden.math foi incluído nos primeiros aparelhos MIDP 1.0 de faz muitos anos para permitir cálculos de ponto de flutuação. Desde a introdução do java.lang.Float em CLDC 1.1 faz vários anos, este pacote tornou-se redundante, e porém é eliminado por completo no i876.

3D API

O pacote com.motorola.iden.micro3d é desaprovado e é substituído pelo JSR 184 Mobile 3D Graphics API. Este API é disponível em todos os aparelhos iDEN com écran grande (176x220), e nos aparelhos i290 e i335.

File I/O

O cambio do File I/O ao uso de JSR 75 é o de mais impacto, porque afeita a todos os aplicativos que guardam dados no aparelho usando arquivos (em vez de RMS) e que se desenvolveram para os primeiros aparelhos iDEN com Java ME.

Modo antigo:

//para salvar o arquivo na memória do aparelho
(StreamConnection) Connector.open("file://archivo");

//para salvar um arquivo seguro
(StreamConnection) Connector.open("sfile://archivo;PASSWORD=1234")

Modo novo:

//para salvar o arquivo na memória do aparelho
(FileConnection) Connector.open("file:///./archivo");

//para salvar um arquivo seguro na memória do aparelho
(FileConnection) Connector.open("sfile:///./archivo;PASSWORD=1234);

//para salvar um arquivo no cartão de memória MicroSD
(FileConnection) Connector.open("file:///Storage Card/archivo");

//para salvar um arquivo seguro no cartão de memória MicroSD
(FileConnection) Connector.open("sfile:///Storage Card/archivo;PASSWORD=1234");

DateBook e PhoneBook API

O pacote com.motorola.iden.udm.* foi completamente eliminado e é substituído pelo JSR 75 PIM API, o que permite maior portabilidade do código a diferentes aparelhos.

Modo antigo para o uso da agenda:

try
        {
            /* Abrir a agenda para ver o modificar. */
            calendars = UDM.openDateBook(UDM.READ_WRITE);
            Enumeration e; 
            for ( e = calendars.elements(); e.hasMoreElements(); )
            {
                dateEvent = (DateBookEvent)e.nextElement()
                int[] type;
                type = dateEvent.getFields();
 
                /* Obter detalhes do evento. */
                StringItem userName = new StringItem("Tema"
                    dateEvent.getString(DateBookEvent.SUMMARY));
                      }
                         /* Criar um evento */
                        long currentTime = 0;
                        dateEvent = calendars.createDateBookEvent();
                        dateEvent.setString(DateBookEvent.SUMMARY
                                "Evento");
                        currentTime = System.currentTimeMillis()+ 60*60000;
                        dateEvent.setDate(DateBookEvent.START, currentTime);
                        dateEvent.setDate(DateBookEvent.END,  currentTime + 600000);          
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    } 

Métodología nova para usar a agenda com PIM:

  try {
          /* Abrir a agenda para ver o modificar. */
   
        EventList listaDeEventos =
                (EventList)PIM.getInstance().openPIMList(PIM.EVENT_LIST, PIM.READ_WRITE);
       
        Enumeration e = listaDeEventos.items();
       
        // Ler todos os campos de um evento e adicionar o resume si ele existe
                while (e.hasMoreElements() );
                {
                        Event evento = (Event)e.nextElement();
                        campos[] = evento.getFields()
                        StringBuffer valores = new StringBuffer();
                        for (int numeroCampo = 0; numeroCampo < campos.length; numeroCampo++) {
                                int dataType = listaDeEventos.getFieldDataType(campos[numeroCampo]); //revisamos o tipo de dados que contem o campo
                                int numIndices = listaDeEventos.countValues(campos[numeroCampo]); //cada campo pode ter mais de um valor, representado por um índice
                                if (dataType == PIMItem.STRING) //caso o campo contem texto
                                {      
                                  for (int indice=0; indice < numIndices; indice++) {
                                         valores.append(evento.getFieldLabel(campos[numeroCampo])).append(" ").append(numeroCampo).append(": ").append(evento.getString(campos[numeroCampo], indice);
                               }
                                }
                                else if (dataType == PIMItem.DATE) //caso o campo contem uma data
                                {
                                  for (int indice=0; indice < numIndices; indice++) {   
                               Date fecha = new Date(evento.getDate(campos[numeroCampo], indice));
                                         valores.append(evento.getFieldLabel(campos[numeroCampo])).append(" ").append(numeroCampo).append(": ").append(fecha);
                               }                               
                                }
                                else if (dataType == PIMItem.INT) //caso contem um valor numérico
                                {
                                  for (int indice=0; indice < numIndices; indice++) {   
                                         valores.append(evento.getFieldLabel(campos[numeroCampo])).append(" ").append(numeroCampo).append(": ").append(evento.getInt(campos[numeroCampo], indice);
                               }                               
                                }
                                else if (dataType == PIMItem.BOOLEAN) //caso o campo contem um valor lógico
                                {
                                  for (int indice=0; indice < numIndices; indice++) {   
                                         valores.append(evento.getFieldLabel(campos[numeroCampo])).append(" ").append(numeroCampo).append(": ").append(evento.getBoolean(campos[numeroCampo], indice);
                               }                               
                                }
               
                                //modificar o primeiro valor do campo de resume. É necessário revisar se o campo que se deseja modificar existe,
                                //porque não todas as implementações do JSR incluem todos os campos
                                if (listaDeEventos.isSupportedField(Event.SUMMARY)) { 
                                        evento.setString(Event.SUMMARY,0,Event.ATTR_NONE,"Modificado durante a passada #" + numeroCampo);
                                        Date ahora = new Date();
                                        evento.setDate(Event.REVISION,0,Event.ATTR_NONE,ahora.getTime()); //para indicar que foi modificado o Evento
                                }
                                evento.commit(); //para guardar o valor em memória persistente
                        }
                }       
               
                //criar um novo evento de uma hora para o 20 de outubro do 2008 às 13h locais com o pessoal de manutenção
                //com uma notificação com 30 minutos de anterioridade
               
                Event eventoNuevo = listaDeEventos.createEvent();

                /* É necessário revisar que o campo que se pede existe, pois não é seguro que um campo em particular
                *  existe em alguma implementação particular da JSR. Os campos que existem para Event em aparelhos Motorola
                *  são os seguintes:
                *  LOCATION (PIMItem.STRING) = lugar do evento
                *  NOTE (PIMItem.STRING)= notas o comentários
                *  SUMMARY (PIMItem.STRING) = resume do evento
                *  UID (PIMItem.STRING) = número único do evento
                *  END (PIMItem.DATE) = data e hora de fim
                *  START (PIMItem.DATE) = data e hora de inicio
                *  REVISION (PIMItem.DATE) = data e hora da última modificação (útil para sincronizar com outra agenda em caso necessário)
                *  ALARM (PIMItem.INT) = número de segundos antes da data de inicio onde se deve gerar uma alarma
                *  CLASS (PIMItem.INT) = pode ser Event.CLASS_PUBLIC, Event.CLASS_PRIVATE, o Event.CLASS_CONFIDENTIAL)
                */

               
                Calendar horario = Calendar.getInstance();
                horario.set( Calendar.MONTH, Calendar.OCTOBER );
                horario.set( Calendar.DAY_OF_MONTH, 20 );
                horario.set( Calendar.YEAR, 2008 );
                horario.set( Calendar.HOUR_OF_DAY, 13 );
                horario.set( Calendar.MINUTE, 00 );
                horario.set( Calendar.SECOND, 00 );
                horario.set( Calendar.MILLISECOND, 0 );
                Date horaInicio = horario.getTime();
               
                horario.set( Calendar.MONTH, Calendar.OCTOBER );
                horario.set( Calendar.DAY_OF_MONTH, 20 );
                horario.set( Calendar.YEAR, 2008 );
                horario.set( Calendar.HOUR_OF_DAY, 14 );
                horario.set( Calendar.MINUTE, 00 );
                horario.set( Calendar.SECOND, 00 );
                horario.set( Calendar.MILLISECOND, 0 );
                Date horaFin = horario.getTime();
                Date horaRevision = new Date();  
               
                if (listaDeEventos.isSupportedField(Event.SUMMARY))
                  eventoNuevo.addString(Event.SUMMARY, PIMItem.ATTR_NONE, "Reunião com manutenção");
                if (listaDeEventos.isSupportedField(Event.START))
                  eventoNuevo.addDate(Event.START, PIMItem.ATTR_NONE, horaInicio.getTime());
                if (listaDeEventos.isSupportedField(Event.END))
                  eventoNuevo.addDate(Event.END, PIMItem.ATTR_NONE, horaFin.getTime());
                if (listaDeEventos.isSupportedField(Event.ALARM))
                  eventoNuevo.addInt(Event.ALARM, PIMItem.ATTR_NONE, horaInicio.getTime() - (30 * 60)); //30 intervalos de 60 segundos
                if (listaDeEventos.isSupportedField(Event.NOTE))
                  eventoNuevo.addString(Event.NOTE, PIMItem.ATTR_NONE, "Convocatória por Carlos");
                if (listaDeEventos.isSupportedField(Event.REVISION))
                  eventoNuevo.addString(Event.REVISION, PIMItem.ATTR_NONE, horaRevision.getTime());
         
         eventoNuevo.commit();
  }
  catch (UnsupportedFieldException e) {
  //este erro não deveria ocorrer se usamos o isSupportedField() antes de modificar ou adicionar campos, mais é boa prática o incluir
                ...
  }
  catch (FieldFullException e) {
  //é gerado quando não tem mais lugar para adicionar índices adicionais ao campo
                ...
  }
  catch (FieldEmptyException e){
  //se gera ao dar acesso a um campo que não tem dados preenchidos
  }
  catch (PIMException e){
  //Qualquer outro erro dentro das classes do pacote PIM.
              /*a razão do erro pode ser uma de várias:
              *
              * PIMException.FEATURE_NOT_SUPPORTED -- a funcionalidade não existe na implementação do JSR
              * PIMException.GENERAL_ERROR -- um error genérico
              * PIMException.LIST_CLOSED -- tentou-se acessar um EventList, ContactList, ToDoList o PIMList quando ele estava fechado
              * PIMException.LIST_NOT_ACCESSIBLE -- o EventList, ContactList, ToDoList o PIMLIst não estão disponíveis (por exemplo, se se apagou a base de
              *                            dados correspondente)
              * PIMException.MAX_CATEGORIES_EXCEEDED -- tentou-se adicionar uma categoria mais do número que pode ser adicionado
              * PIMException.UNSUPPORTED_VERSION -- os dados estão guardados numa versão do PIM que não tem suporte na plataforma do aparelho
              * PIMException.UPDATE_ERROR -- não se pôde atualizar a informação                
              */

              int i = e.getReason();
  }

A metodologia para a modificação do acesso à lista de contatos é similar.