Obtendo identificação dos arquivos da aplicação em Android

Muitas vezes queremos alterar dinâmicamente na Activity a imagem ou ler algum arquivo já disponível na aplicação.Para isso existe dois caminhos dos quais irei explicar abaixo.

O primeiro seria adicionar os arquivos na pasta “assets” de sua aplicação.

Por exemplo adicionar um arquivo de nome test.txt.

ABCDEF

Para ler então esse txt dentro de minha Activity:

AssetManager am = context.getAssets();
InputStream is = am.open("test.txt");

A segunda maneira seria buscar o arquivo por sua identificação.
Crie a pasta drawable em sua aplicação e adicione uma imagem, por exemplo, test.png.

Adicione em seu layout um componente ImageView.

<ImageView android:id="@+id/imgTest"/>

Para abrir a imagem teste no componente ImageView:

imgTest = (ImageView) rootView.findViewById(R.id.imgTest);
int resID = getContext().getResources().getIdentifier("test", "drawable", getContext().getPackageName());
imgTest.setImageResource(resID);

Algumas vezes a extensão do arquivo de imagem não é identificado, conforme acima o primeiro parâmetro do método getIdentifier() é o nome de da imagem, no meu caso, “test”.

Abraços,
André Rezende

Anúncios

Sessões SOAP dotNet em Ksoap-android.

Pela falta de informação sobre esse assunto resolvi publicar esse POST para não cair em esquecimento.

Se você precisa armazenar a sessão de uma conexão WS no Android utilizando o Ksoap, já adianto, não é possível fazer utilizando a biblioteca de versão 2.6.5. Mas para tanto, existe uma solução simples, mas que leva tempo para descobrir e segue abaixo.

package br.com.cacula.fv.servicos.soap.connection;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.ksoap2.HeaderProperty;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;

public class CustomHttpSE extends HttpTransportSE {
    private String sessionID;
    
    public CustomHttpSE(String URL, int timeout) {
        super(URL, timeout);
    }

    public String getSessionID() {
        return sessionID;
    }

    public void setSessionID(String sessionID) {
        this.sessionID = sessionID;
    }

    @Override
    public List call(String soapAction, SoapEnvelope envelope)
            throws IOException, XmlPullParserException {
        SoapSerializationEnvelope soapEnvelop
        headers = new ArrayList<HeaderProperty>();
        
        if (soapEnvelope.dotNet && !"".equals(sessionID)) {
            headers.add(new HeaderProperty("Cookie", "ASP.NET_SessionId="
                    + sessionID));
        }
        return super.call(soapAction, envelope, headers);
    }

}

Agora utilize a CustomHttpSE ao invés da HttpTransportSE que vem dentro do Ksoap, lembre-se de fazer um set ao sessionID e as seguintes opções de dotNET.

envelope.dotNet = true;
envelope.implicitTypes = true;
envelope.setAddAdornments(false);

Abraços,
André Rezende

Existe uma alternativa melhor do que usar emulador no Android?

virtualbox

Sim, isso é possível.
O emulador para Android tem vários bugs tais como: perda de configuração, lentidão para testes, travamentos inesperados dentre outros. Aí vem o fulano e diz, tem que usar o “device”, não tem como usar outra coisa.
Eu mesmo já pensei dessa forma até o dia de ontem.

Quem gosta de atrasar um cronograma de desenvolvimento por causa de emulador?
Felizmente a Google fornece uma linguagem, que no meu ponto, excelente, pois aumenta e muito a produtividade do pessoal que já está acostumado a trabalhar com Java, por outro lado, continua com esse emulador que parece evoluir a passos lentos.

Talvez não tenham interesse em disponibilizar algo mais “usável” aos desenvolvedores, outra estratégia de venda de dispositivos. Nós, não temos condição de ficar comprando vários dispositivos somente para uso nos testes de nossas aplicações.
Então, como posso fazer de uma forma mais rápida?
Já digo de antemão, a forma que irei descrever abaixo funciona com processadores de número igual ou maior de 4 núcleos.
Testei em algumas com dois núcleos e está tão lento quanto o emulador. A vantagem nesses casos com 2 núcleos, configurar uma única vez e inicializar sempre do mesmo modo, mesma configuração e outros.

Vamos aos passos: Antes de mais nada, os requisitos são a instalação(setup) do Oracle Virtual Machine e da Android ISO.

Realize a instalação do Oracle Virtualbox no processo, next, next e finish.

O tutorial para instalação da Android ISO.

Após esses passos serem realizados com sucesso, abra um terminal de prompt de comando.
Entre no diretório de instalação do VirtualBox.
No Windows, execute: cd /d C:\Program Files\Oracle\VirtualBox
Aperta a tecla ENTER

VBoxManage.exe setextradata "Android ICS" "CustomVideoMode1" "540x960x16"

A resolução informada no último parâmetro deverá ser a desejada, eu utilizei 549×960.
No VirtualBox, inicialize a VM;
Ao entrar na tela de escolha do SO, no GRUB, aperte a tecla a;
Na próxima tela, digite espaço e adiciona vga=ask, aperte a tecla ENTER;
Procura a resoluçao desejada e digite-a.
Você deve digitar o valor de hexdecimal transformado para decimal(por exemplo 360 hex é 864 em decimal).
Pronto, a sua VM será inicializada na configuração escolhida.

Para sempre incializar a com a configuração desejada.
Selecione no GRUB menu “Debug Mode”
Vá ao diretório /mnt/grub
Abra no vi o menu.lst

vi menu.lst

Adicione vga=864 a linha:

kernel /android-2.3-RC1/kernel quiet root=/dev/ram0 androidboot_hardware=eeepc acpi_sleep=s3_bios,s3_mode DPI=160 UVESA_MODE=320x480 SRC=/android-2.3-RC1 SDCARD=/data/sdcard.img vga=864

Salve o arquivo:

:wq

Desmonte a unidade:

mount -o remount,rw /mnt

Reinicialize a WM:

cd /
umount /mnt
reboot -f

Inicialize a VM do Android ICS, abra o terminal e digite:

ip a

Obtenha o endereço IP para realizar a conexão com seu adb.
Abra o ADB do Android, em minha máquina está no diretório \sdk\platform-tools
No prompt de comando, execute:

adb connect <ENDEREÇO IP OBTIDO NO ANDROID ICS>

Abra sua ferramente de desenvolvimento e automaticamente será reconhecido a VM como um dispositivo, semelhante ao emulador.

No VirtualBox é possível Exportar e Importar as configurações da VM, gerando um arquivo de extensão .ova.
Utilize essa opção se deseja realizar desenvolvimento e testes em mais de uma máquina, utilizei e funciona perfeitamente.

Abraços,
André Rezende

Média para um horário em DB2

Hora

Hora

Alguns dias atrás tive que gerar média de um horário de inicio de uma atividade realizada pelo pessoal da operação registrada em banco de dados(DB2).
Para isso eu poderia realizar uma lógica dentro do meu código, ou mais simples já trazer o valor que preciso direto da consulta realizada, ou seja, pela query.

A tabela é a seguinte:
OPERACAO (ID bigint PRIMARY KEY NOT NULL, INICIO TIMESTAMP)

Para tanto, realizei uma consulta onde obtenho o valor da hora multiplicado por 60 para tela em minutos e somo aos minutos, ao final realizo um avg para ter hora média de cada um desses valores em minutos.

select avg((HOUR(INICIO)*60) + MINUTE(INICIO)) from OPERACAO;

Com esse código, eu consigo a média em minutos.
Basta agora que minha aplicação converta essa hora “média” retornada em minutos para hora normal. Finalizando com a média das horas em que a operação é inicializada.

Abraços,
André Rezende

XML, ListView e Adapters no Android

Para criar uma lista simples na tela do Android, obtida de um banco de dados ou XML é necessários criar seu layout e então um Adapter para popular esses valores.
Abaixo um exemplo simples que lê um arquivo XML e exibe os valores em uma lista na tela principal.
Para isso crie um projeto Android no Eclipse.
Na pasta /res do seu projeto, crie uma pasta xml e adicione um arquivo XML de nome todolist.xml

Adicione o código abaixo no arquivo criado:

<?xml version="1.0" encoding="UTF-8"?>
<todoitems>
    <item
        title="Alimentar cão"/>
    <item
        title="Churrasco"/>
    <item
        titulo="Ir ao Pub"/>
    <item
        titulo="Tomar banho"/>
</todoitems>

No xml da atividade padrão, localizado na pasta /layout do seu projeto, substitua o código por:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >
    <ListView
        android:id="@+id/listview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    </ListView>
</RelativeLayout>

Na activity criada pelo Wizard do Eclipse, adicione o código abaixo:

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

import com.example.listview.adapters.CustomAdapter;

public class MainActivity extends Activity {
    static ArrayList<String> todoItems = new ArrayList<String>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final ListView listview = (ListView) findViewById(R.id.listview);
        final CustomAdapter adapter = new CustomAdapter(this,
                android.R.layout.simple_list_item_1, getResources().getXml(
                        R.xml.todolist));
        listview.setAdapter(adapter);

    }
}

Ao final, adicione o Adapater, que será responsável por adicionar e exibir os valores contidos no arquivo XML:

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.content.res.XmlResourceParser;
import android.util.Log;
import android.widget.ArrayAdapter;

public class CustomAdapter extends ArrayAdapter<String> {
    public CustomAdapter(Activity a, int textViewResourceId,
            XmlResourceParser xmlParsers) {
        super(a, textViewResourceId, getListFromXml(xmlParsers));

    }

    private static List<String> getListFromXml(XmlResourceParser xmlParser) {
        List<String> todoItems = new ArrayList<String>();
        int eventType = -1;
        while (eventType != XmlResourceParser.END_DOCUMENT) {
            if (eventType == XmlResourceParser.START_TAG) {

                String strNode = xmlParser.getName();
                if (strNode.equals("item")) {
                    todoItems.add(xmlParser.getAttributeValue(null, "titulo"));
                }
            }

            try {
                eventType = xmlParser.next();
            } catch (XmlPullParserException e) {
                Log.e("Teste", e.getMessage());
            } catch (IOException e) {
                Log.e("Teste", e.getMessage());
            }
        }
        return todoItems;
    }
}

O método getListFromXml() lê o arquivo XML e retorna lista dos itens ao construtor da classe ArrayAdapter. Caso isso não aconteça na chamada do super, os valores não irão ser exibidos.
Abraços,
André Rezende

Profissionais de TI em imigração

gnomos-dindim-254x300
A algumas semanas atrás fui contactado por um recrutador da Irlanda para verificar minha disponibilidade para ir trabalhar lá. A cidade era de nome Athlone, mas fiquei curioso com o termo, apesar de não estar interessado de sair da empresa onde trabalho no momento.
Achei a seguinte pesquisa e a Irlanda está para profissionais programadores/desenvolvedores de TI.
Segue link aos interessados “Os 20 profissionais estrangeiros mais procurados” .
O site permite escolher a profissão e verificar quais países estão correndo atrás do pessoal para trabalhar.

Abraços,
André Rezende

O que esperar de lambda no Java 8? Parte 2

lambda
Na primeira parte realizei um introdutório a expressões lambda.
Expressões lambdas deixam a linguagem Java mais poderosa, legível e concisa.
É possível com lambdas passar o comportamento desejado, não somente valores, tornando o código mais genérico e flexível.

 

Tendo a lista de números abaixo:

List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6);

Para somar todos os valores da lista em um código Java, realizaríamos uma implementação semelhante abaixo:

public int somaTodos(List<Integer> numeros) {
    int total = 0;
    for (int numero : numeros) {
        total += numero;
    }
    return total;
}

Se depois alguém requisitar para alterar o código que soma todos números pares precisaríamos alterar a implementação acima para algo como:

public int somaTodos(List<Integer> numeros) {
    int total = 0;
    for (int numero : numeros) {
        if (numero % 2 == 0) {
            total += numero;
        }
    }
    return total;
}

Em lambda teríamos algo mais genérico, que passando um comportamento utilizaríamos o mesmo “método” para o primeiro caso.

 somaTodos(numeros, n -> true);

E para a última regra requisitada:

 somaTodos(numeros, n -> n % 2 == 0);

Concluindo, passamos um comportamento lambda para obter a somatória dos valores baseado em uma condição parametrizada.

Abraços,
André Rezende