Relatórios com MEReport

06 novembro 2009 2 comentários

A maioria dos sistemas comerciais, seja móvel ou não, necessita de relatórios para mostrar de forma resumida a entrada e processamento dos dados. Através do blog Mobilidade é tudo descobrimos o MEReport, responsável por realizar essa tarefa de forma bastante simples.
A API ainda está sendo construída e precisando de desenvolvedores para contribuir no andamento do projeto. Quem quiser ajudar é só entrar em contato.

Segue uam prévia da classe Relatorio.java, que através da CustomItem, cria um layout de relatório com componentes personalizáveis.
import java.util.Vector;
import javax.microedition.lcdui.*;

class Relatorio extends CustomItem{
    private int minContentWidth;
    private int minContentHeight;
    
    private int prefContentHeight;
    private int prefContentWidth;
    
    private String title = "";
    private boolean titleBorder;
    private boolean titleFillColor;
    private int[] titleColorText;
    private int[] titleColorBack;
    private int[] titleColorBorder;
    private Font titleFont;
    private Font titleHeader;
    private short titleAlignment;
    
    public static final short LEFT = 0;
    public static final short CENTER = 1;
    public static final short RIGHT = 2;
    
    public String[] columnsText;
    
    public int[] columnsPercents;
    
    private boolean columnsBorder;
    private boolean columnsFillColor;
    private int[] columnsColorText;
    private int[] columnsColorBack;
    private int[] columnsColorBorder;
    private Font columnsFont;
    private short columnsAlignment;
    
    private Font textFont;
    private int[] textColor;
    private boolean textGridH;
    private boolean textGridV;
    private int[] textLinesColor;
    private Vector[] textData;
    private short textAlignment;
    
    private int[] posYInicial;
    private int[] posYFinal;
    
    private int indice;
    
    private Image imgBrasao;
    
    private int[] tamColunas;
    private int sobra;
    
    public Relatorio(int width, int height)
    {
        super("");
        
        titleFont = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_LARGE);
        titleColorText = new int[]{230, 230, 230};
        columnsColorText = new int[]{40, 40, 40};
        columnsFont = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
        textFont = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL);
        textColor = new int[]{0, 0, 0};
        
        titleAlignment = CENTER;
        titleBorder = true;
        titleColorBorder = new int[]{0, 0, 0};
        
        titleFillColor = true;
        titleColorBack = new int[]{50, 50, 50};
        
        prefContentHeight = height;
        prefContentWidth = width;
        
        minContentHeight = height;
        minContentWidth = width;
    }
    
    public void setImgBrasao(Image imgBrasao)
    {
        this.imgBrasao = imgBrasao;
    }
    
    //métodos referentes a barra superior, que contém o título
    //começo
    public void setTitle(String title)
    {
        this.title = title;
    }
    
    public void setTitleAlignment(short alignment)
    {
        this.titleAlignment = alignment;
    }
    
    public void setTitleFont(Font titleFont)
    {
        this.titleFont = titleFont;
    }
    
    public void setTitleFontHeader(Font titleFont)
    {
        this.titleHeader = titleFont;
    }
    
    public void setTitleBorder(boolean titleBorder)
    {
        this.titleBorder = titleBorder;
    }
    
    public void setTitleFillColor(boolean titleFillColor)
    {
        this.titleFillColor = titleFillColor;
    }
    
    public void setTitleColorText(int[] color)
    {
        this.titleColorText = color;
    }
    
    public void setTitleColorBack(int[] color)
    {
        this.titleColorBack = color;
    }
    
    public void setTitleColorBorder(int[] color)
    {
        this.titleColorBorder = color;
    }
    //fim
    
    //métodos referentes as colunas
    //começa
    
    public void setColumns(String[] columns)
    {
        this.columnsText = columns;
    }
    
    public void setColumnsPercents(int[] percents)
    {
        this.columnsPercents = percents;
        tamColunas = new int[columnsPercents.length];
        
        int total = 0;
        for (int i = percents.length-1; i >= 0; i--)
        {
            tamColunas[i] = ((prefContentWidth) / 100) * percents[i];
            total += tamColunas[i];
        }
        
        int sobra = ((prefContentWidth) - total) / 3;
        
        for (int i = percents.length-1; i >= 0; i--)
        {
            tamColunas[i] += sobra;
        }
    }
    
    public void setColumnsBorder(boolean columnsBorder)
    {
        this.columnsBorder = columnsBorder;
    }
    
    public void setColumnsFillColor(boolean fillColor)
    {
        this.columnsFillColor = fillColor;
    }
    
    public void setColumnsColorText(int[] color)
    {
        this.columnsColorText = color;
    }
    
    public void setColumnsColorBack(int[] color)
    {
        this.columnsColorBack = color;
    }
    
    public void setColumnsColorBorder(int[] color)
    {
        this.columnsColorBorder = color;
    }
    
    public void setColumnsFont(Font fontColumns)
    {
        this.columnsFont = fontColumns;
    }
    
    public void setColumnsAlignment(short alignment)
    {
        this.columnsAlignment = alignment;
    }
    
    //termina
    
    //métodos do texto
    //começa
    public void setTextFont(Font font)
    {
        this.textFont = font;
    }
    
    public void setTextData(Vector[] data)
    {
        this.textData = data;
    }
    
    public void setTextAlignment(short alignment)
    {
        this.textAlignment = alignment;
    }

    public void setTextColor(int[] color)
    {
        this.textColor = color;
    }
    
    public void setTextLineColor(int[] color)
    {
        this.textLinesColor = color;
    }
    
    public void setTextGridH(boolean grid)
    {
        this.textGridH = grid;
    }
    
    public void setTextGridV(boolean grid)
    {
        this.textGridV = grid;
    }
    //termina
    
    protected int getMinContentWidth() {
        return minContentWidth;
    }

    protected int getMinContentHeight() {
        return minContentHeight;
    }

    protected int getPrefContentWidth(int arg0) {
        return prefContentWidth;
    }

    protected int getPrefContentHeight(int arg0) {
        return prefContentHeight;
    }

    protected void paint(Graphics g, int largura, int altura) {
        int aux = 0;
        
        g.setColor(255, 255, 255);
        g.fillRect(0, 0, largura, altura);
        
        int tamTitulo = Math.max( (titleFont.getHeight() + 2), 
                (imgBrasao == null?0:imgBrasao.getHeight()));
        
        //espaço do título
        //se a variável titleFillColor for true significa que o usuário quer que o 
        //espaço do título seja preenchida com a cor definida no vetor 
        //titleColorBack
        if (titleFillColor) // se sim, o título tem cor de fundo
        {
            g.setColor(titleColorBack[0], titleColorBack[1], titleColorBack[2]);
            
            g.fillRect(0, 0, largura, tamTitulo);
            
            if (imgBrasao != null)
            {
                g.drawImage(imgBrasao, 0, 0, Graphics.LEFT|Graphics.TOP);
            }
        }
        
        //configura a cor que vai ser usada no título, para isso usa a variável 
        //titleColorText
        //em seguida é verificado o alinhamento escolhido para o título
        //na variável 
        //titleAlignment
        //o título está armazenado na variável 
        //title
        g.setColor(titleColorText[0], titleColorText[1], titleColorText[2]);
        g.setFont(titleFont);
        if (titleAlignment == LEFT)
            g.drawString(title, largura/2, tamTitulo/2 - titleFont.getHeight()/2, Graphics.LEFT|Graphics.TOP);
        else if (titleAlignment == CENTER)
            g.drawString(title, largura/2, tamTitulo/2 - titleFont.getHeight()/2, Graphics.HCENTER|Graphics.TOP);
        else
            g.drawString(title, largura/2, tamTitulo/2 - titleFont.getHeight()/26, Graphics.RIGHT|Graphics.TOP);
        
        //verifica se o usuário quer que o título seja contornado por uma borda
        //a variável titleBorder especifica isso
        //o vetor titleColorBorder Ccontém a cor da borda
        if (titleBorder) //verifica se o título tem borda
        {
            g.setColor(titleColorBorder[0], titleColorBorder[1], titleColorBorder[2]);
            g.drawRect(0, 0, largura, tamTitulo);
        }
        
        
        //desenha as colunas do título dos dados
        //ou seja, o cabeçalho
        aux = tamTitulo + 4;
        
        if (columnsFillColor)//se sim, as colunas tem background, senão, é transparente
        {
            int auxW = 0;
            g.setColor(columnsColorBack[0], columnsColorBack[1], columnsColorBack[2]);
            
            for (int i = 0; i < columnsText.length; i++)
            {
                g.fillRect(auxW - 1, aux, tamColunas[i]-1, 
                        titleHeader.getHeight() + 2);
                auxW += tamColunas[i];
            }
        }

        int auxW = 0;
        if (columnsBorder)
        {
            g.setColor(columnsColorBorder[0], columnsColorBorder[1], columnsColorBorder[2]);
            
            for (int i = 0; i < columnsText.length; i++)
            {
                g.drawRect(auxW - 1, aux, tamColunas[i]-1, 
                        titleHeader.getHeight() + 2);
                auxW += tamColunas[i];
            }
        }
        
        
        //escreve os títulos que representam os headers dos dados
        g.setColor(columnsColorText[0], columnsColorText[1], columnsColorText[2]);
        g.setFont(titleHeader);
        auxW = 0;
        for (int i = 0; i < columnsText.length; i++)
        {
            if (columnsAlignment == LEFT)
                g.drawString(columnsText[i], auxW, aux, Graphics.LEFT|Graphics.TOP);
            else if (columnsAlignment == RIGHT)
                g.drawString(columnsText[i], auxW + tamColunas[i] - 1, aux, 
                        Graphics.RIGHT|Graphics.TOP);
            else 
                g.drawString(columnsText[i], (auxW + tamColunas[i]/2), 
                        aux, Graphics.HCENTER|Graphics.TOP);
            auxW += tamColunas[i];
        }
        
        
        //Desenha as linhas verticais da tabela de dados
        aux += columnsFont.getHeight() + 8;
        g.setColor(0, 0, 0);
        g.drawLine(0, aux, largura, aux);
        
        if (textGridV)
        {
            g.setColor(textLinesColor[0], textLinesColor[1], textLinesColor[2]);
            
            auxW = 0;
            for (int i = 0; i < tamColunas.length-1; i++)
            {
                auxW += tamColunas[i];
                g.drawLine(auxW, aux, auxW, 
                    aux + (textFont.getHeight() * textData.length));
            }
        }
        
        //Desenha as linhas verticais da tabela de dados
        if (textGridH)
        {
            g.setColor(textLinesColor[0], textLinesColor[1], textLinesColor[2]);
            int aux2 = aux;
            for (int i = 0; i < textData.length; i++)
            {
                aux2 += textFont.getHeight();
                g.drawLine(0, aux2, largura, aux2);
            }
        }
        
        //preenche os valores da tabela
        posYInicial = new int[textData.length];
        posYFinal = new int[textData.length];
        
        g.setFont(textFont);
        for (int i = 0; i < textData.length; i++)
        {
            Vector dados = textData[i];
            auxW = 0;
            posYInicial[i] = aux;
            
            if (indice == i)
            {
                g.setColor(230, 230, 230);
                g.fillRect(0, aux+1, largura, textFont.getHeight()-1);
            }
            
            aux += textFont.getHeight();
            posYFinal[i] = aux;
            
            for (int j = 0; j < tamColunas.length; j++)
            {
                g.setColor(textColor[0], textColor[1], textColor[2]);
                if (textAlignment == LEFT)
                    g.drawString(dados.elementAt(j).toString(), auxW + 2, aux, 
                            Graphics.LEFT|Graphics.BOTTOM);
                auxW += tamColunas[j];
            }
        }
    }
    
    protected void pointerPressed(int x, int y)
    {
        for (int i = 0; i < posYFinal.length; i++)
        {
            if (y >= posYInicial[i] && y <= posYFinal[i])
            {
                indice = i;
                repaint();
                return;
            }
        }
    }
    
    protected void pointerDragged(int x, int y)
    {
    }
    
    protected void pointerReleased(int x, int y)
    {
    }
    
    protected boolean traverse(int dir, int viewportWidth, int viewportHeight, 
            int[] visRect_inout)
    {
        if (dir == 6)//pra baixo
        {
            if (indice < textData.length)
            {
                indice++;
                repaint();
                return true;
            }
            else 
            {
                return false;
            }
        }
        else if (dir == 1)//para cima
        {
            if (indice > 0)
            {
                indice--;
                repaint();
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return true;
        }
    }
    
    protected void traverseOut()
    {
        indice  = 0;
        repaint();
    }
}

A a classe MEReportMidlet.java mostra como podemos trabalhar com o MEReport.
import java.util.Vector;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class MEReportMidlet extends MIDlet {
private Display display;

private Relatorio relatorio;

private StringItem titulo;
private Form fmMain;

private Font fonte;
private Font fonte2;
private Font fonte4;

private Image imgBrasao;

public void startApp() {
display = Display.getDisplay(this);

fmMain = new Form("Relatório de Cidades");
titulo = new StringItem("Estado: ", "Rio Grande do Sul");

fmMain.append(titulo);

try{
imgBrasao = Image.createImage("/brasao.PNG");
}
catch (Exception e){
System.out.println("Erro na imagem: " + e.getMessage());
}

relatorio = new Relatorio(fmMain.getWidth(), 200);
fonte = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_LARGE);
fonte2 = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
fonte4 = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL);
relatorio.setTitle("Cidades - RS");
relatorio.setImgBrasao(imgBrasao);
relatorio.setTitleBorder(true);
relatorio.setTitleFillColor(true);
relatorio.setTitleFont(fonte);
relatorio.setTitleFontHeader(fonte2);
relatorio.setTitleColorBack(new int[]{22, 50, 117});
relatorio.setTitleColorText(new int[]{255, 255, 255});
relatorio.setTitleColorBorder(new int[]{0, 0, 0});
relatorio.setTitleAlignment(Relatorio.CENTER);
relatorio.setColumns(new String[]{"Cód.", "Cidade", "Pop."});
relatorio.setColumnsAlignment(Relatorio.LEFT);
relatorio.setColumnsBorder(true);
relatorio.setColumnsColorBorder(new int[]{0, 0, 0});
relatorio.setColumnsColorBack(new int[]{200, 200, 255});
relatorio.setColumnsColorText(new int[]{0, 0, 0});
relatorio.setColumnsFillColor(true);
relatorio.setColumnsFont(fonte);
relatorio.setTextColor(new int[]{0, 0, 0});
relatorio.setTextLineColor(new int[]{22, 50, 117});
relatorio.setTextFont(fonte2);
relatorio.setTextGridH(true);
relatorio.setTextGridV(true);

Vector[] dados = new Vector[5];
Vector passoFundo = new Vector();
passoFundo.addElement("0");
passoFundo.addElement("Passo Fundo");
passoFundo.addElement("212.700");
Vector portoAlegre = new Vector();
portoAlegre.addElement("2");
portoAlegre.addElement("Porto Alegre");
portoAlegre.addElement("1.400.500");
Vector davidCanabarro = new Vector();
davidCanabarro.addElement("3");
davidCanabarro.addElement("David Canabarro");
davidCanabarro.addElement("960.300");
Vector gramado = new Vector();
gramado.addElement("5");
gramado.addElement("Gramado");
gramado.addElement("87.000");
Vector uruguaiana = new Vector();
uruguaiana.addElement("6");
uruguaiana.addElement("Uruguaiana");
uruguaiana.addElement("134.820");
dados[0] = passoFundo;
dados[1] = portoAlegre;
dados[2] = davidCanabarro;
dados[3] = gramado;
dados[4] = uruguaiana;
relatorio.setTextData(dados);

relatorio.setColumnsPercents(new int[]{10, 58, 32});

fmMain.append(relatorio);

display.setCurrent(fmMain);
}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
}
}

Referência: Mobilidade é tudo

Brasil atinge 166,1 milhões de celulares

22 outubro 2009 0 comentários
Segundo Bianconi, o Brasil encerrou setembro com 166,1 milhões de celulares, com adição de 1,58 milhão de habilitações em setembro, de acordo com dados divulgados nesta quarta-feira pela Agência Nacional de Telecomunicações (Anatel).

Do total de acessos, 136,56 milhões são pré-pagos e 29,56 milhões pós-pagos.

No acumulado de janeiro a setembro, a expansão totaliza 15,5 milhões de linhas telefônicas móveis. É o segundo melhor desempenho histórico do setor para o período de nove meses, atrás apenas de igual intervalo de 2008, quando foram 19,8 milhões de novas habilitações.

A Vivo, controlada por Telefónica e Portugal Telecom, encerrou setembro com 48,8 milhões de clientes, ou 29,4 por cento do mercado total.

A Claro, do grupo mexicano América Móvil, aparece em seguida, com 42,3 milhões de assinantes, ou 25,5 por cento. Em terceiro aparece a TIM, com 39,6 milhões de clientes (23,9 por cento), seguida por Oi, com 34,8 milhões de clientes (20,9 por cento).

As participações de mercado das quatro operadoras permaneceram praticamente estáveis em setembro na comparação com agosto.

Fonte: Reuters

Capturando fotos em Java ME com a MMAPI

20 outubro 2009 0 comentários

Caso seja leigo neste assunto veja o post anterior, sobre MMAPI, que aprensenta alguns conceitos necessários para o entendimento do código que será mostrado.

Neste post mostraremos como capturar uma foto e mostrá-la em um form.

Para a captura de uma imagem é requerido instâncias de um Player, um VideoControl e um
Display.

O VideoControl é utilizado para contolar o vídeo vindo da câmera e mostrá-lo em um
form.

Primeiramente vamos criar uma instância de Player e configurá-lo para ele perceber o
estado.
// “capture://image” é usado para indicar que queremos uma imagem.
//Esta string é necessária para utilizar o método getSnapshot(), que será mostrado depois.
Player mPlayer = Manager.createPlayer("capture://image");
mPlayer.realize();
Agora inicializaremos uma instância de VideoControl e adicionaremos o vídeo em um form.
VideoControl mVideoControl=(VideoControl) mPlayer.getControl("VideoControl");
Form form = new Form("Camera form");
Item item = (Item) mVideoControl.initDisplayMode(GUIControl.USE_GUI_PRIMITIVE, null);
form.append(item);
O método getSnapshot(), do VideoControl, é utilizado para capturar as fotos. Este
método retorna um array de bytes. Para mostrar esta imagem é necessário uma instância de Image. Depois configuramos os estados dos players para fechar e setar como null nossa instância de VideoControl.
//Obtendo a imagem
byte[] raw = mVideoControl.getSnapshot(null);
Image image = Image.createImage(raw, 0, raw.length);

// Colocando o form principal.
if (this.size() > 0 && this.get(0) instanceof StringItem)
this.delete(0);
append(image);

// Volta ao form principal
mDisplay.setCurrent(this);
// desliga o player.
mPlayer.close();
mPlayer = null;
mVideoControl = null;
Ainda podemos pegar a foto que foi inserida no Form e salvá-la como uma imagem no cartão de memória do celular ou gravar no RMS, por exemplo, mas isso fica como desafio ao leitor ;)

Para baixar o projeto completo clique aqui.
É importante dizer que este código não roda no emulador.
T
estado em um Nokia 5220.

Referências:
http://efforts.embedded.ufcg.edu.br/javame/
http://developers.sun.com/mobility/apis/articles/mmapi_overview/