quarta-feira, 8 de dezembro de 2010

Java ME: Configuração do Ambiente

Olá povo,

Nessa sexta começo minha carreira como professor universitário :) Ministrarei a disciplina de Java ME no Curso de Especialização em Engenharia de Software com Ênfase em Tecnologias para Desenvolvimento de Aplicações Móveis do CESAR.edu. Então como vocês devem imaginar, vão vir por aí alguns post sobre o assunto. O primeiro deles será sobre como configurar o ambiente e fazer o bom e velho "Hello World".

Baixando o JDK

Precisaremos incialmente do JDK que está disponível em:
http://www.oracle.com/technetwork/java/javase/downloads/index.html

A instalação em bem simples, basta seguir o assitente. (e venhamos e convenhamos, todos que estão lendo este post já devem ter o JDK na máquina :)

Baixando o WTK (Wireless Toolkit)

Para baixar o WTK devemos acessar a seguinte URL:
http://www.oracle.com/technetwork/java/javame/downloads/index.html

A versão mais recente da plataforma é a 3.0, mas atualmente ela só está disponível para Windows. Dessa forma, utilizaremos a versão 2.5.2 que está disponível para Windows e Linux.


Após baixar o WTK, basta seguir as instruções do assistente.


Instalando a IDE

Para desenvolvermos aplicações Java ME, podemos utilizar a IDE de nossa preferência. As mais famosas são o Eclipse e o Netbeans. Ambas contam com plugins para desenvolvimento para edição móvel de Java.


O Eclipse conta com uma versão especial para desenvolvimento mobile chamada Pulsar. Ela já vem com as ferramentas necessárias para criação de aplicações Java ME, e para baixá-la basta acessar: http://www.eclipse.org/pulsar/
e descompactar em qualquer lugar do seu HD.

Mas para quem já tem seu Eclipse já todo configurado, não precisa se preocupar em instalar outra versão da IDE. Basta adicionar o plugin MTJ (Mobile Tools for Java) e você terá um ambiente pronto para criar suas aplicações Java ME. Para isso, acesse o menu Help > Install new software e adicione a URL: http://download.eclipse.org/mtj/updates/1.1.2/stable e em seguida prosseguir com o assitente.


Para os desenvolvedores que utilizam o Netbeans, a IDE já pode ser baixada com o Mibility Pack. Que permite a criação de aplicativos Java ME. Caso sua versão não conte com esse plugin, basta baixa-lo dentro da própria ferramenta acessando o menu Tools > Plugins e selecionando o plugin Mobility.

Configurando a IDE para o SDK

Uma vez que temos o SDK e a nossa IDE favorita instalados, devemos fazer a ligação de ambos.

Para o Eclipse faremos o seguinte:
1) Acesse o menu Window > Preferences;
2) Clique em Java ME e em seguida preencha o campo WTK home com o local onde o WTK está instalado;
3) Na mesma janela, clique em Device Management que é um subitem de Java ME. Clique no botão Manual Install... para informar os emuladores que iremos utilizar.
4) Abrirá a janela Manual Device Installation, clique no botão Browse... e selecione o diretório de instalação do WTK.
5) Clique em Finish para fechar a tela atual e OK para fechar a tela de configuração.

Para o Netbeans:
1) Acesse o menu Tools > Java Plaforms;
2) Clique em Add Platform. Em seguida, selecione Emulator for Java ME Platform e clique em Next;
3) O assistente deve achar o local da instalação automaticamente, caso contrário indique o local da instalação e clique em Next.
4) Clique em Finish e a configuração estará concluída.


Hello World!!!

Vamos agora satisfazer os deuses da programação e fazermos um HelloWorld com a plataforma Java ME.

Eclipse
1) Acesse o menu File > New > Project...
2) Em seguida, selecione Java ME > MIDlet Project
3) Dê o nome de HelloWorld ao projeto e clique em Finish
4) Na pasta src clique com o botão direito, e selecione New... > Java ME MIDlet
5) Abrirá o assitente de criação de classes. Dê a classe o nome de HelloWorldMIDlet e clique em Finish

Netbeans
1) Acesse o menu File > New project...
2) Na categoria Java ME, selecione Mobile Application
3) Dê o nome de HelloWorld ao projeto.
O Netbeans já disponibiliza uma opção que cria o HelloWorldMIDlet (estraga prazer:) Desmarque essa opção e clique em Finish.
4) Na pasta src clique com o botão direito, e selecione New... > MIDlet...
5) Abrirá o assitente de criação de classes. Dê a classe o nome de HelloWorldMIDlet e clique em Finish

Agora, deixe a classe HelloWorldMIDlet conforme abaixo:
public class HelloWorldMIDlet extends MIDlet {
public HelloWorldMIDlet() {
Display d = Display.getDisplay(this);

Form form = new Form("Hello!");
form.append("Olá mundo Java ME");

d.setCurrent(form);
}

protected void destroyApp(boolean unconditional) {}

protected void pauseApp() {}

protected void startApp() {}
}


No Eclipse, clique com o botão direito sobre o projeto e selecione: Run as > Emulated Java ME JAD.
No Netbeans, basta clicar no botão play verdinho :p

Quando o emulador for executado, clique na tecla do celular correspondente a opção Launch. O resultado deve ser conforme a figura abaixo:



Qualquer dúvida ou sugestão, deixem seus comentários.

4br4ç05,
nglauber

sábado, 4 de dezembro de 2010

Enviando e Recebendo SMS no Android

Olá povo,

Questionar é uma coisa muito sábia. Quando estava dando aula sobre SMS um aluno (Renato se não me engano) questionou meu código, que na verdade estava muito similar (pra não dizer igual) ao código do livro de Ricardo Lecheta. Quando paramos pra analisar vimos como ficou fácil interceptar um SMS.

Primeiro devemos criar um BroadcastReceiver e registrá-lo no AndroidManifest.xml para ser disparado quando a ação "android.provider.Telephony.SMS_RECEIVED" for disparada pelo sistema operacional. Além disso, deve-se utilizar as permissões para enviar e receber SMS.


public class SmsReceiver extends BroadcastReceiver {

public void onReceive(Context context, Intent it){
SmsMessage message =
SMSUtils.getMessagesFromIntent(it)[0];

Toast.makeText(context,
"Mensagem recebida de "+
message.getOriginatingAddress() + " - "+
message.getMessageBody(),
Toast.LENGTH_LONG).show();
}
}


<receiver android:name="SmsReceiver">
<intent-filter>
<action
android:name="android.provider.Telephony.SMS_RECEIVED"/>
<category
android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>

<!-- Adicione essas permissões na tag manifest -->
<uses-permission
android:name="android.permission.RECEIVE_SMS"/>
<uses-permission
android:name="android.permission.SEND_SMS"/>



public class SMSUtils {

public void enviarSms(String numero, String msg) {

SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(numero, null, msg,
null, null);
}

public static SmsMessage[] getMessagesFromIntent(
Intent intent){

Object[] pdusExtras =
(Object[])intent.getSerializableExtra("pdus");

SmsMessage[] messages =
new SmsMessage[pdusExtras.length];

for (int i = 0; i < pdusExtras.length; i++) {
messages[i] = SmsMessage.createFromPdu(
(byte[])pdusExtras[i]);
}
return messages;
}

}// end class


O Android utiliza o formato de mensagens em PDU que permite a leitura de SMS em vários encondings. Por isso, ao receber as mensagens, lemos a informação extra da intent chamada de "pdus". Essa informação é um array de arrays de bytes. Percorremos o array de bytes (que em cada posição tem outro array) e passamos cada array para um método que cria a mensagem SMS. Uma vez com o objeto android.telephony.SmsMessage, podemos obter as informações como telefone de origem e texto da mensagem.

Quando a mensagem é recebida ela vai para a caixa de entrada. Para excluírmos a mensagem recebida, basta usar o content provider da aplicação de SMS conforme explicado nesse post

Se quisermos evitar que a mensagem chegue na aplicação de mensagens, basta colocar uma prioridade (android:priority) maior do que a da aplicação de mensagens no intent-filter do Broadcast que recebe o SMS. E dentro dele, chamar o método abortBroadcast().

4br4ç05,
nglauber

sexta-feira, 3 de dezembro de 2010

Artigo "Android Froyo"

Olá povo,

A revista Web Mobile desse mês (edição 33) trás uma matéria sobre a versão 2.2 do Android de condinome Froyo. Essa matéria foi escrita por mim em parceria e por meus colegas Bruno Vinícius (da Gluo Games) e José Berardo (da Especializa Treinamentos) ,

Neste artigo apresentamos as novidades da versão 2.2 do sistema operacional para dispositivos móveis da Google. O Android Froyo vem para encarar e superar seus concorrentes através de várias melhorias de desempenho e diversas novas funcionalidades para os usuários dos dispositivos que utilizam a plataforma.

Espero que vocês gostem.

4br4ç05,
nglauber

p.s.: essa matéria foi escrita logo quando saiu o Froyo, mas só foi publicada agora :)

quinta-feira, 2 de dezembro de 2010

Android: Dicas de programação da semana

Olá povo,

No novo projeto em que estou envolvido estamos desenvolvendo várias aplicações. Como temos várias pessoas envolvidas, algumas dúvidas se tornam recorrentes, então resolvi postá-las.

Pergunta 1: Quando eu giro o telefone o método onCreate da Activity é chamado novamente. Tem como evitar isso?

Resposta: Sim, basta adicionar a propriedade android:configChanges na tag <activity> do seu AndroidManifest.xml. Isso evitará que a atividade seja recriada.

<activity android:name="MinhaActivity"
android:configChanges="keyboardHidden|orientation"/>

No caso acima, se o telefone mudar de orientação ou se o teclado físico (se houver) for aberto, a atividade não será recriada.

Pergunta 2: Tem como deixar uma atividade apenas em landscape ou portrait?

Resposta: Sim, basta utilizar a propriedade android:screenOrientation na tag <activity> do seu AndroidManifest.xml.

<activity name=".MinhaActivity"
android:screenOrientation="landscape"/>


Pergunta 3: Como permitir apenas letras na caixa de texto (EditText)?

Resposta: Não existe uma propriedade para fazer isso. Se quisermos colocar para aceitar apenas números podemos utilizar a propriedade android:inputType="number". Ou quando queremos deixar todas as letras em maiúsculo podemos usar o valor textCapCharacters. Mas para não aceitar nem números nem símbolos só com a boa e velha expressão regular.

Pattern pattern = Pattern.compile(
"^[A-ZÁÀÄÃÂÆÅÉÈËÊÍÌÏÎÓÒÖÕÔØŒÚÙÜÛÝÿYÑÇ ]+$");

Matcher matcher = pattern.matcher(
meuEditText.getText().toString().toUpperCase());

if (!matcher.matches()){
Log.e("ERRO",
"Esse campo só aceita letras e espaço em branco!");
}


Pergunta 4: Como fazer uma lista múltipla que eu possa selecionar vários itens?

Resposta: Devo confessar que esse problema me encheu muito o saco. Não para criar a lista, mas sim para obter os itens selecionados. Pra informar que sua ListView permite seleção múltipla use o método setChoiceMode(int).

lstView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

Feito isso, sua lista já permitirá seleção múltipla. Agora como fazer para obter os itens selecionados? Bem, a classe ListView tem dois métodos que você pode obter arrays com as posições e os ids dos itens selecionados: getCheckItemPositions() e getCheckItemIds(). Infelizmente não tive uma boa experiência com eles. Ao marcar e desmarcar itens, aconteciam momentos em que os itens ficavam inconsistentes, ou seja, ele informava que itens estavam marcados, quando na verdade não estavam. Sendo assim, preferi fazer da minha forma:

private int getCheckedCount(){
lstView.getCheckItemIds();

int count = 0;
int listSize = lstView.getAdapter().getCount();
for (int i = 0; i < listSize; i++) {
if (lstView.isItemChecked(i)){
count++;
}
}
return count;
}

// Para marcar ou desmarcar um item específico,
// podemos usar:
lstView.setItemChecked(posicao, false);


Pergunta 5. Como carregar uma imagem da aplicação baseada no nome do arquivo?

Resposta: Se esse recurso estiver na pasta res/drawable você pode fazer via reflection. Eu já fiz um post sobre isso, que vocês podem conferir aqui. Mas se quiser usar de maneira descente :) podem usar a pasta assets do seu projeto. Coloque as imagens que você deseja carregar dinamicamente nesse diretório e faça como abaixo:

try {
InputStream is = getAssets().open("imagem.png");
Bitmap bmp = BitmapFactory.decodeStream(is);
ImageView img = (ImageView)
findViewById(R.id.ImageView01);

img.setImageBitmap(bmp);

} catch (IOException e) {
e.printStackTrace();
}


Pergunta 6. Como salvar uma informação simples como o recorde do jogo?

Resposta: Para persistir informações simples, o Android disponibiliza a classe SharedPreferences onde você pode salvar pequenas configurações. Vejam abaixo como ler/escrever uma preferência através de dois métodos de exemplo que salvam e recuperam o recorde de pontos de um jogo.

public int getRecord(){
SharedPreferences prefs =
context.getSharedPreferences(
"configs", Context.MODE_PRIVATE);

return prefs.getInt("record", 0);
}

public void setRecord(int record){
SharedPreferences prefs =
context.getSharedPreferences(
"configs", Context.MODE_PRIVATE);

SharedPreferences.Editor editor = prefs.edit();
editor.putInt("record", record);
editor.commit();
}


Pergunta 7. Como ler um XML do diretório res/xml?

Resposta: Quem é meu aluno já conhece essa frase que eu uso sempre nas aulas: Existem mil maneiras de se fazer Neston :) Uma das maneiras de ler um XML é usando o XMLResourceParser, segue um exemplo bem simples do seu uso. Clique aqui pra ver o post original.


private String getEventsFromAnXML(Context c)
throws XmlPullParserException, IOException {

StringBuffer stringBuffer = new StringBuffer();
Resources res = c.getResources();
XmlResourceParser xpp = res.getXml(R.xml.meu_xml);
xpp.next();

int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_DOCUMENT) {
stringBuffer.append("--- Start XML ---");

} else if(eventType == XmlPullParser.START_TAG){
stringBuffer.append("\nSTART_TAG: "+
xpp.getName());

} else if(eventType == XmlPullParser.END_TAG){
stringBuffer.append("\nEND_TAG: "+
xpp.getName());

} else if(eventType == XmlPullParser.TEXT) {
stringBuffer.append("\nTEXT: "+xpp.getText());
}
eventType = xpp.next();
}
stringBuffer.append("\n--- End XML ---");
return stringBuffer.toString();
}

De acordo com a evolução do projeto vou colocando mais dicas.

4br4ç05,
nglauber