domingo, 26 de agosto de 2012

Conhecendo o arquivo AndroidManifest.xml

Olá pessoal,

Após algum tempo sem escrever, venho falar hoje sobre o arquivo AndroidManifest.xml presente nas aplicações Android. Já foi citado nos posts anteriores o uso deste arquivo, neste post vou falar um pouco mais sobre ele.
O arquivo AndroidManifest.xml fica armazenado na raiz do projeto e é responsável pela definição dos componentes do aplicativo, das configurações de segurança, das classes de teste e dos requisitos responsáveis pela visualização da nossa aplicação.
O código abaixo apresenta o código de um arquivo AndroidManifest.xml.


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.configurationchanges"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Primeiro vamos falar deste código que estamos visualizando. A primeira linha é apenas o cabeçalho básico do XML informando que este é um arquivo de manifesto. O que interessa para nós, neste momento são os nós internos deste arquivo XML. 


    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

O nó representado acima é de extrema importância ao aplicativo que estamos desenvolvendo. Através dele definimos qual SDK podemos utilizar no nosso aplicativo. Os valor de minSdkVersion indica qual a menor versão de SDK em qual nosso aplicativo poderá ser executado e a targetSdkVersion indica para qual SDK nosso aplicativo está sendo executado. Para o desenvolvimento Android é uma boa prática utilizar o targetSdkVersion na maior versão possível, isso garante que você tem a capacidade de utilizar o máximo possível dos recursos de uma nova versão. E quanto as versões antigas, como os novos recursos irão se comportar? O Android gerencia estes problemas através de ferramentas de compatibilidade que fazem com que os recursos novos dos seus aplicativos tenham bom comportamento nas versões antigas. Além destes dois atributos, você pode também definir o maxSdkVersion para delimitar entre quais versões seu aplicativo pode ser executado. Como citado no post sobre a criação do dispositivo virtual, você pode ver as API's para Android através do link http://patrickreinan.blogspot.com.br/2012_07_01_archive.html.


    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

O nó application é responsável por definir algumas característcas do nosso aplicativo. O exemplo acima está bastante intuitivo. Os três primeiros atributos deste nó tratam do ícone do aplicativo (android:icon), do titulo do aplicativo no menu do usuário (android:label) e do tema visual (android:theme) que será utilizado para maquear nosso aplicativo. Repare que os três estão sob a boa prática de utilizar Resources. 
Após vermos os três atributos vemos agora o nó de Activities. Neste local ficam registradas todas as  Activities do nosso aplicativos. Elas devem sempre estar registradas aqui, caso contrário o aplicativo mostra uma mensagem de erro quando executado. Só temos uma Activity registrada neste código, mas podemos observar que temos o nome (representada sempre com um ponto á esquerda) e o rótulo desta atividade, mostrado na parte superior do aplicativo quando executado. 


<intent-filter>
   <action android:name="android.intent.action.MAIN" />
   <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>

O nó intent-filter é responsável por definir quais ações irão chamar a Activity. Neste caso podemos ver que será a ação MAIN dentro da categoria LAUNCHER.

Estas são as opções que estão visiveis quando criamos um novo projeto, mas podemos utilizar algumas outras para garantir o funcionamento do nosso aplicativo. 

uses-configuration
Com este nó de configuração, podemos definir quais as configurações são necessárias para o nosso aplicativo ser executado. Por exemplo, eu posso ter a necessidade de ter um trackball em meu dispositivo para que a aplicação seja executada, então eu colocaria esta linha abaixo dentro do nó manifest.

<uses-configuration android:reqNavigation="trackball" />

uses-feature
Você pode também definir as características do dispositivo em que seu aplicativo será executado. Por exemplo, sua aplicação pode utilizar bluetooth. Neste caso podemos configurar uma linha conforme o exemplo abaixo:

 <uses-feature android:name="android.hardware.bluetooth" android:required="true" />

supports-screens
Com esta configuração você pode definir os formatos de tela suportados pelo seu aplicativo. Por exemplo, nosso aplicativo pode suportar somente telas pequenas. 


   <supports-screens 
        android:
        android:largeScreens="false" 
        android:smallScreens="true"
        android:normalScreens="false"
        android:xlargeScreens="false"
           />

uses-permission
Você pode identificar no seu arquivo de manifesto quais as permissões que seu aplicativo necessita. No exemplo abaixo, está identificando que o sistema utilizar a permissão de localização.

<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”/>

Estas são algumas das configurações que podem ser feitas dentro do arquivo de manifesto para o nosso aplicativo utilizando o arquivo de manifesto. No próximo post, vou escrever sobre como manipular os eventos de mudança de configuração do ambiente.

Abraço




quinta-feira, 9 de agosto de 2012

Utilização de Resources

Olá pessoal,

Hoje vou escrever sobre a utilização de Resources, mas antes gostaria de avisar que disponibilizei o código fonte do post anterior neste link.

No post anterior quando desenvolvemos o Conversor de Medidas fizemos um breve uso de Resources, neste post vou explicar um pouco mais sobre a utilização dos mesmos.

Os resources são textos, imagens, constantes, entre outros, que utilizamos dentro do nosso aplicativo. É uma boa prática para separar o nosso código destes elementos, isso faz com que o código fique organizado, fácil de efetuar manutenções e de ser internacionalizado.

Imagine que você tenha um aplicativo que deve ser modificado de acordo com a linguagem do dispositivo que está sendo executado. Em um modelo de programação inadequado, um programador pensaria em colocar um "if" ou "case" no código para verificar a localização e aplicar cores e textos. Isso não é nada interessante por que dificulta a manutenção. Isso pode ser resolvido facilmente com a utilização dos Resources no Android.

Nossa aplicação de hoje será baseada em um aplicativo que se adapta a localização que está. Irá apresentar cores, imagens e textos baseados na localização.

Agora você já sabe criar uma aplicação Android, então crie uma nova aplicação nomeada UtilizandoResources com uma atividade em branco, como fizemos na aplicação anterior. Não vou repetir o passo a passo da criação de uma aplicação novamente, até mesmo para que você possa treinar. Em todo caso o código fonte está disponível no final deste artigo.

Se você leu o post anterior, já sabe que os recursos ficam armazenados na pasta "res" dentro do package do aplicativo. Vamos entrar na pasta layout e definir os layout do nosso aplicativo com o código abaixo:


<LinearLayout 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"
    android:background="@color/background_color"
    android:orientation="vertical" >

    <ImageView
        android:layout_width="@dimen/flag_width"
        android:layout_height="@dimen/flag_height"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/flag"
        android:contentDescription="@string/language_name"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/language_name"
        android:textColor="@color/foreground_color"
 />

</LinearLayout>

Neste ponto vamos entender um pouco do que está acontecendo. Se você reparar alguns valores estão definidos como @ e seguido de um tipo. Neste lugares estamos fazendo referencia aos resources da nossa aplicação. Quando você copiou e colou o código percebeu que apareceram algumas mensagens de erro. Isso acontece por que não definimos estes resources ainda. Dentro da estrutura dos Resources os tipos são divididos em pastas. Olhe para a estrutura de pastas e você verá algumas pastas que iniciam com o nome de "drawable", há uma pasta chamada "layout" que já conhecemos e outra chamada "values". Estas são as que nos interessam. Dentro da "drawable" ficam as imagens que serão exibidas no nosso aplicativo. A pasta layout, possui a definição dos "layouts" de todas as atividades de nosso aplicativo e a pasta "values" armazena valores simples, como cores, dimensões, strings e estilos.

O arquivo colors.xml tem a definição das cores que estamos utilizando no nosso layout, se você não tiver este arquivo, pode criá-lo e colar o código abaixo:


<resources>
    <color name="background_color">#00FF00</color>
    <color name="foreground_color">#FFFFFF</color>
</resources>

O arquivo dimens.xml tem todas as medidas que utlizamos em nosso aplicativo. No nosso caso ele trata a largura e altura da bandeira, uma vez que o texto é redimensionado automaticamente. Apague o código deste arquivo e cole o código abaixo.


<resources>
    <dimen name="flag_height">48dp</dimen>
    <dimen name="flag_width">48dp</dimen>
</resources>

O arquivo strings.xml nós utilizamos no post anterior. Nele nós guardamos o texto que utilizamos no nosso aplicativo. Além disso guardamos também os IDs dentro dele.



<resources>

    <string name="app_name">Utilizando Resources</string>
    <string name="title_activity_main">Utilizando Resources</string>
    <string name="language_name">Português (Brasil)</string>
 
</resources>


O arquivo styles.xml define o estilo do nosso aplicativo.



Vamos remover a pasta menu dos resources pois não iremos utilizá-lo em nosso aplicativo. Ela server para definir o menu do sistema.

Depois da remoção da pasta menu, substitua o código da MainActivity.java pelo código abaixo. Isso fará com que a referencia padrão ao menu também seja removida.

package com.example.utilizandoresources;

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

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

}



Vamos colocar algumas imagens dentro de uma das pastas "drawable", vamos utilizar a pasta "drawable-hdpi".

É importante saber que as pastas têm uma estrutura de nome que o Android utiliza em tempo de execução para definir quais Resources serão utilizados. A primeira parte do nome das pasta identifica o tipo da mesma, o que vem depois do hifen serve para definir características de dispositivo ou localização. Por exemplo "hdpi" significa "High dots por inch", isso na frente do nome da pasta "drawable" indica que uma tela de alta densidade irá utilizar estes recursos. Se não colocarmos nas outras pastas, o Android irá utilizar uma delas. Como o h signfica "high", "l" signifca "low", "m" significa "medium" e "xh" significa "Extra high". Estas nomenclaturas são sempre em letras minusculas.

Execute seu código, você deve ter algo do tipo:


Agora vamos fazer com que este aplicativo seja automaticamente traduzido quando o dispositivo estiver em Inglês. Para isso você irá criar uma nova pasta "values", porém seguida da linguagem "en" (values-en). Você pode copiar a pasta atual, pois só iremos alterar valores.

Dentro desta pasta é necessária a presença de dois arquivos, strings.xml e colors.xml. Que devem estar como abaixo, respectivamente:

<resources>

    <string name="app_name">Using Resources</string>
    <string name="title_activity_main">Using Resources</string>
    <string name="language_name">English (USA)</string>
   
</resources>


<resources>
    <color name="background_color">#FF0000</color>
    <color name="foreground_color">#FFFFFF</color>
</resources>

Altere a configuração de idioma do dispositivo e execute novamente, veja que automaticamente o sistema alterou a linguagem e a cor de fundo, faltando apenas a bandeira.

Com a bandeira, será o mesmo caso, porém vamos duplica a pasta "drawable-hdpi" e colocar o "en" entre o tipo e a densidade (drawable-en-hdpi). Além disso vamos trocar o arquivo flag.png, por uma bandeira dos Estados Unidos. O resultado agora será este:



Se você trocar a localização para outro país, o sistema voltará ao português pois este é o padrão dele. 

Esta foi uma utilização simples dos Resources, mais para frente veremos também como utilizá-los via código através da classe R. 







quarta-feira, 1 de agosto de 2012

A primeira aplicação - Mãos no código

Olá a todos,

Como disse no post anterior, a minha intenção era não fazer o nosso primeiro código no formato de um Hello World, mas fazer um aplicativo com um pouco de funcionalidade e que pudéssemos ver alguns recursos da plataforma Android. Pensei em reescrever o meu primeiro código em Android e postar aqui, mas ache interessante começar algo do zero. Foi a melhor escolha que pude fazer, pois descobri que há recursos muito interessantes nas últimas alterações do ADT plugin para o Eclipse. Antes das atualizações, ao iniciar uma nova aplicação, poucos da aplicação era configurado no assistente. Agora temos 5 telas antes de começar o projeto, que ajudam muito.

No post anterior criamos a AVD para executar nosso aplicativo, hoje iremos fazer uso dela. Mas para isso teremos que ter algo construído, bom vamos criar nosso primeiro projeto.

Entre no Eclipse e vá até o menu File > New > Java Project...
O assistente será iniciado como a próxima imagem. Nesta tela você pode escolher o tipo de projeto que deseja criar. No nosso caso será Android Application Project, mas se você reparar, irá perceber que temos templates prontos para outros tipos de aplicativos sem ser Android.

Clique em Next e você verá a tela para configuração de nome, pacote, build e localização do código do seu projeto.
Application Name é o nome que seu aplicativo terá na Play Store
Project Name é o nome do projeto para ser gerenciado pelo Eclipse
Package Name é o nome do pacote onde seu código será agrupado
Build SDK é a versão do SDK que estamos utilizando (neste exemplo o 4.1)
Minimum Required SDK é a versão minima na qual o nosso sistema pode executar (neste exemplo 2.2)


No momento são estas as configurações que nos interessam nesta tela. Em outras eu também não devo explicar o que não será muito relevante no momento.

Click em Next e na próxima tela iremos escolher o ícone do nosso programa. Eu baixei uma imagem do Google somente para ilustrar. Nesta tela você deve escolher Foreground: Image e selecionar uma imagem no campo Image File.

A próxima tela questiona sobre a criação de uma "atividade". Vamos criar uma atividade em branco. Como estamos começando não temos condições de utilizar a mais detalhada.


Clique em Next. As atividades (ou Activity) definem a interface de interação com o usuário, funciona grosseiramente falando, como um formulário em uma aplicação Windows Forms. Nesta tela podemos definir o nome da Activity e seu layout. No nosso caso vamos utilizar os valores padrão.


Clique em finalizar e somente para matar a vontade de ver algo rodando vamos executar a nossa AVD e testar nossa aplicação. Se você está atento a esta postagem deve ter reparado que nossa aplicação está preparada para o Android 4.1 e nós criamos uma AVD com a versão 4.0.3. Isso foi proposital para que você veja que uma aplicação feita para uma versão 4.1 pode ser executada até o SDK minimo definido durante nossas configurações. Se você só tem a versão 4.0.3, não tem problema, pode utilizá também.

Se você leu a postagem anterior já sabe como iniciar uma AVD, caso não tenha lido, tem mais uma chance agora clicando aqui.

Vamos executar nosso aplicativo clicando com o botão direito do mouse sobre o projeto e escolhendo a opção Run As > Android Application e veja que temos o famoso Hello World na tela, mas que não vai ficar ai por muito tempo.
Vamos falar agora sobre a estrutura do nosso aplicativo e como o desenvolvimento funciona para Android. Tanto no livro que estou lendo, quanto na referencia do Google, há muito cuidado com a organização do código visando sempre manter as boas práticas e a facilidade de entendimento. O primeiro impacto que tive é em relação a organização do código de um aplicação Android. As partes são divididas em pastas. Dê uma olhada do lado esquerdo da tela, na estrutura de pastas. Não vamos falar muito desta estrutura hoje, mas note que há uma pasta chamada res (resources) que é contem uma pasta dedicada ao layout, outra dedicada a telas, outra dedicada a menu, e algumas a valores. Acreditem, neste única aplicação vamos falar um pouco de cada uma delas. 


Logo no começo da estrutura há uma pasta chamada src que contém o código fonte do nosso projeto, inclusive uma classe representando a atividade principal (MainActivity.java). 
Este tipo de estrutura divide nitidamente o código do layout. 
Agora vamos começar a codificar. A nossa aplicação será muito simples, terá uma caixa de texto onde o usuário informa um valor em metros e três botões logo abaixo serão responsáveis por converter para centimetros, kilometros e metros (que irá retornar para o primeiro valor). 
Primeiro vamos desennhar o layout de nosso aplicativo, através do arquivo que está na pasta res\layout\activity_main.xml. Clique duas vezes sobre ele e você verá uma representação visual da tela do sistema.


Ter uma ferramenta para criar o layout visualmente é muito interessante e produtivo, mas como estamos começando é importante saber o que corre por de trás do layout. Nesta tela você tem duas guias, sendo uma delas nomeada com o nome do arquivo. Clique nela e você verá o código XML da atividade. 
No Android, os controles de uma Activity ficam dentro de um layout, representando no código que você está vendo por <RelativeLayout>...</RelativeLayout>, que define o posicionamento dos controles na tela. Há um controle dentro deste layout chamado TextView que é responsável pela exibição de textos. Nós iremos utilizar um destes mais para frente neste código. Iremos mudar este tipo de layout para linear neste momento, vou explicar sobre isso em outras postagens mais para frente. Para agilizar vou passar passar o código do nosso layout pronto aqui e vou explicar os pontos importantes.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <EditText
         android:id="@+id/txtvalue_id"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/textvalue_hint"
        android:inputType="numberDecimal" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/button_cm_id"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="converterCM"
            android:text="@string/button_cm_text" />

        <Button
            android:id="@+id/button_m_id"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="converterM"
            android:text="@string/button_m_text" />

        <Button
            android:id="@+id/button_km_id"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="converterKM"
            android:text="@string/button_km_text" />
    </LinearLayout>

    <TextView
        android:id="@+id/textview_resultado_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

    </TextView>

</LinearLayout>




Vamos ao que é interessante para nosso conhecimento neste momento.

Se você reparar todos os controles tem as propriedades layout_width e layout_height que definem como será a largura do nosso controle. Eu utilizei algumas opções pré-definidas do Android. A wrap_content aumenta de acordo com o conteúdo, a match_parent ajusta de acordo com a largura do objeto pai. Um detalhe interessante são nossos botões. Todos eles estão como match_parent para a largura, mas cada não são todos do tamanho do controle pai, isso por que estamos utlizando o layout_weight que através do número de controles que tem agrupado faz uma proporção de tamanho, como defini 1 para todos, eles ficaram iguais se eu por exemplo tivesse feito 2 para um deles, este seria maior do que os outros. 
Utilizei o controle LinearLayout para agrupar os botões.
Se você foi apressado e copiou e colou o código irá perceber que ocorreram vários erros. Isso por que você não tem definidas as strings do seu projeto. É uma boa prática separar o texto também em arquivos, pois facilita a internacionalização do software, o que veremos mais para frente em outras postagens. Então vamos fazer isso, copie o código abaixo e substitua o conteúdo de res\values\strings.xml. 

<resources>

    <string name="app_name">Conversor de Medida</string>
    <string name="txtvalue_id">txtvalue</string>
    <string name="textvalue_hint">Valor em metros</string>
    <string name="button_cm_text">cm</string>
    <string name="button_m_text">m</string>
    <string name="button_km_text">km</string>
    <string name="button_cm_id">btncm</string>
    <string name="button_km_id">btnkm</string>
    <string name="button_m_id">btnm</string>
    <string name="menu_settings">menu_settings</string>
    <string name="textview_resultado_id">txtResultado</string>

</resources>




Outro detalhe são os ids que também são definidos fora do local de desenho do layout. Repare que eles são precedidos por "@+".



Execute o código e veja na AVD que já temos o nosso layout pronto, mas falta o código que iremos fazer em seguida.


Abra agora o código da Activity em MainActivity.java dentro da pasta src\<packagename> e cole o trecho de código abaixo. Você verá que o código que vem agora é simples e nós falaremos das particularidades depois. O único detalhe que vale ressaltar agora é que a classe R é compilada pelo Eclipse automaticamente quando fazemos alguma alteração nos resources.

package com.patrickreinan.conversormedida;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

private double valorOriginal=0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

public void converterM(View view) {

if(valorOriginal==0||valorOriginal!=retornarValor())
valorOriginal = retornarValor();
mostrarResultado(valorOriginal);
}

public void converterCM(View view) {
if(valorOriginal==0||valorOriginal!=retornarValor())
valorOriginal = retornarValor();
mostrarResultado(valorOriginal*100);
}

public void converterKM(View view) {
if(valorOriginal==0||valorOriginal!=retornarValor())
valorOriginal = retornarValor();
mostrarResultado(valorOriginal*0.001);
}

private double retornarValor(){
double retorno;
EditText txt = (EditText)findViewById(R.id.txtvalue_id);
retorno = Double.parseDouble(txt.getText().toString());
return retorno;
}
private void mostrarResultado(double valor)
{
TextView txtview = (TextView)findViewById(R.id.textview_resultado_id);
txtview.setText(Double.toString(valor));
}
}

Com isso temos nossa primeira aplicação sendo executada.

Faça o download deste código aqui.