Meu Primeiro App Android

EATI 2016 - João Eduardo Montandon

Sobre Mim

Professor no COLTEC/MG

 

Área de Atuação: Engenharia de Software

 

Experiências:

Web

Mobile

Detecção de Bugs/Defeitos

Compreensão de APIs

Este sou eu :)

Sobre o Minicurso

O que, Por quê e como é Android?

 

Ferramentas, instalação & configuração

 

Hello, Droid!!

 

Nosso Primeiro App: MovieMe

Quem não possui um telefone hoje??

O Celular Hoje

O Celular Hoje

TVs

Smartphones

1.5 Bilhões

3 Bilhões

O Celular Hoje

  • O celular é hoje o dispositivo mais pessoal existente
  • Representa a extensão do nós mesmos
    • Compartilhamos, registramos, controlamos, vivemos...

Você anytime, anywhere

O Ecossistema Android

  • Sistema Operacional Móvel mantido pelo Google*
  • Líder mundial no segmento
  • Disponível para diversas plataformas
    • TVs
    • Relógios
    • Carros
    • Smartphones (é claro!!)

O Ecossistema Android

IDC: Smartphone OS Market Share 2015, 2014, 2013, and 2012 Chart

A Open Handset Alliance

  • Consórcio formado por 84 empresas
  • Objetivo: Contribuir para criação de um S.O. móvel aberto
    • Fabricantes: HTC, Samsung, LG, Motorola, etc.
    • Operadoras: Nextel, T-Mobile, Telefonica, etc.
    • Semicondutores: Intel, Broadcom, Nvidia, Qualcomm, etc.
    • Software: Google, eBay, Ascender, etc.
    • Comércio: Aplix, Noser, TAT, Wind River, etc.

O Ecossistema Android

Histórico de versões

1.5

1.6

05/09

2.1

2.2

2.3

3.0

4.0

4.1

4.4

5.0

6.0

09/09

10/09

05/10

12/10

02/11

10/11

06/12

10/13

11/14

10/15

1.6: Android Cupcake

 

2.3: Gingerbread

4.0: Ice Cream Sandwich

 

5.0: Lollipop

O Ecossistema Android

Principais Características

Dispositivo

  • Recursos limitados:
    • Bateria
    • Memória
    • Armazenamento
    • Processamento...

Aplicação

  • Mashups
  • Sandbox
  • Programação Intencional

O Ecossistema Android

Softwares Necessários

Java JDK Versão 1.5 a 1.7 (http://www.java.com/pt_BR/)

 

Android Studio  & SDK (http://developer.android.com/intl/pt-br/sdk/index.html)

Hello, Droid

Criando um Novo Projeto

File > New > Project

 

Minimum SDK: API 22

 

Template: Empty Activity

 

Activity: HelloActivity

package edu.ifmg.eati.hellodroid;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class HelloActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hello);
    }
}
<?xml version="1.0" encoding="utf-8"?>
<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="edu.ifmg.eati.hellodroid.HelloActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
</RelativeLayout>

Executando a Aplicação

  1. Run > Run app
  2. Selecionar Emulador
    • Criar se não existir um
  3. Executar
  • Alternativas ao emulador:
    • Genymotion
    • Xamarin Android Player
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="edu.ifmg.eati.hellodroid">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".HelloActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

Hello World pt. 2

<resources>
    <string name="app_name">HelloDroid</string>
    <string name="main_description">Meu primeiro App!!</string>
</resources>
<TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/main_description" />

strings.xml

activity_hello.xml

Porque dessa vez foi mais rápido?

Hello, Cara!!

Incrementando um pouco mais nosso app...

Hello, Cara!!

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout ...>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/main_description"
        android:textSize="40px"
        android:id="@+id/lbl_titulo"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/lbl_titulo"
        android:id="@+id/txt_nome"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/txt_nome"
        android:text="@string/btn_title"
        android:id="@+id/btn_update"/>
</RelativeLayout>

activity_hello.xml

Layouts

O Android possui uma série de modelos de interface para organizar os componentes da tela.

Modelos Mais comuns:

  • RelativeLayout
  • LinearLayout
  • TableLayout
  • FrameLayout

Hello, Cara!!

public class HelloActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hello);

        final TextView lblHello = (TextView) findViewById(R.id.lbl_titulo);
        final EditText txtNome = (EditText) findViewById(R.id.txt_nome);
        Button btnAtualizar = (Button) findViewById(R.id.btn_update);


        btnAtualizar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                lblHello.setText("Olá, " + txtNome.getText());
            }
        });
    }
}

HelloActivity.java

A Classe R.java

...

final TextView lblHello = (TextView) findViewById(R.id.lbl_titulo);
final EditText txtNome = (EditText) findViewById(R.id.txt_nome);
Button btnAtualizar = (Button) findViewById(R.id.btn_update);
...

Todos os componentes de interface são mapeados na classe R.java

Dessa forma é possível recuperá-los dinamicamente, por meio do método findViewById()

O Princípio de Hollywood

...
btnAtualizar.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        lblHello.setText("Olá, " + txtNome.getText());
    }
});
...

O desenvolvimento em Android é baseado no conceito de arcabouço

  • Você desenvolve, mas o Android decide quando ele será executado

"Não ligue para gente, nós ligaremos para você"

Executando no Celular

  • Para executar no celular, precisamos habilitar o modo desenvolvedor

 

  • Configurações > Programador
    • Caso ainda não esteja visível, tocar "Número da versão" 7 vezes.

MovieMe

MovieMe

Aplicativo onde o usuário poderá cadastrar quais filmes, seriados e documentários ele assistiu.

Todo mundo assiste a filmes, seriados, documentários, desenhos, etc.

 

Contudo, nunca nos lembramos do filme para compartilhar com os amigos..

Ideia

MovieMe

  1. Listagem dos filmes cadastrados
  2. Interface para cadastro de novos filmes

Requisitos Principais

Setup do Projeto

  • Novo projeto...
  • SDK versão 21 ou superior
  • Selecionar Empty Activity

A Classe Movie

Classe responsável por representar cada filme

public class Movie {

    private String name;
    private int rating;
    private String comment;


    public Movie(String name, int rating, String comment) {
        this.name = name;
        this.rating = rating;
        this.comment = comment;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getRating() {
        return rating;
    }

    public void setGrade(int rating) {
        this.rating = rating;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }
}
  • name: Nome do filme
  • rating: Nota do filme
  • comment: Comentário do filme

Listagem de Filmes

  • A listagem será feita por meio de um ListView

 

  • Um botão irá redirecionar para o cadastro de um novo filme

Tela responsável por listar os filmes cadastrados até o momento

Listagem de Filmes

Lidando com ListView

Baseado no conceito de Adapter

  • Adapter: "Cola" entre interface e modelo

Listagem de Filmes

ListView: Interface

<RelativeLayout ...>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/main_filmes_cadastrados"
        android:textSize="20dp"
        android:layout_marginBottom="20dp"
        android:id="@+id/txt_title"/>

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/txt_title"
        android:id="@+id/movies_list"/>

</RelativeLayout>

activity_main.xml

Listagem de Filmes

ListView: Adapter

public class MoviesAdapter extends BaseAdapter {

    private ArrayList<Movie> movies;    

    private Context context;

    public MoviesAdapter(Context context) {
        this.context = context;
        this.movies = new ArrayList<>();
    }

    .
    .
    .  

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Movie movie = this.movies.get(position);

        TextView lblMovie = new TextView(context);
        lblMovie.setTextSize(20);
        lblMovie.setText(movie.getName() + " -- " + movie.getRating());

        return lblMovie;
    }
}

Não ficou mto legal...

Listagem de Filmes

ListView: Adapter Customizado

É possível Customizar o Layout de cada linha:

  1. Criar o layout customizado do adapter
  2. Importar o layout no método getView()

Listagem de Filmes

ListView: Adapter Customizado

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout ...>

    <TextView ... android:text="My Movie"/>
    <TextView ... android:text="5"/>
    <TextView ... android:text="lorem ipsum comment"/>

</RelativeLayout>
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    Movie movie = this.movies.get(position);

    View view = LayoutInflater.from(this.context).inflate(R.layout.adapter_movies, parent, false);

    TextView lblName = (TextView) view.findViewById(R.id.lbl_movie_name);
    TextView lblGrade = (TextView) view.findViewById(R.id.lbl_movie_grade);
    TextView lblComment = (TextView) view.findViewById(R.id.lbl_movie_comment);

    lblName.setText(movie.getName());
    lblGrade.setText(String.valueOf(movie.getRating()));
    lblComment.setText(movie.getComment());

    return view;
}

Listagem de Filmes

  • Adicionar FAB no arquivo XML da interface

 

  • Implementar evento de click no arquivo Java da Interface

FABs: utilizados para prover ações essenciais a tela

Floating Action Buttons

Listagem de Filmes

Floating Action Buttons

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout ...>
    .
    .
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/btn_new_movie"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        android:layout_alignBottom="@id/movies_list"
        android:layout_alignRight="@id/movies_list"
        android:tint="@color/white"
        android:src="@android:drawable/ic_input_add" />
</RelativeLayout>

activity_main.xml

@Override
protected void onCreate(Bundle savedInstanceState) {
    .
    .
    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.btn_new_movie);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d(MainActivity.this.getClass().getName(), "Novo filme");
        }
    });
}

MainActivity.Java

Listagem de Filmes

FABs: Redirecionando para nova tela

@Override
protected void onCreate(Bundle savedInstanceState) {
    .
    .
    FloatingActionButton fab = ...;
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Criação da Intent
            Intent intent = new Intent(MainActivity.this, 
                                       NewMovieActivity.class);

            // Requisição ao Android para iniciar a Intent
            startActivity(intent);
        }
    });
}

Nós não invocamos novas Telas diretamente (Princípio de Hollywood)

 

Precisamos registrar a nossa intenção de abrir a nova tela

Intent

 

Classe responsável por "criar" as intenções no sistema

Cadastro de Novos Filmes

  • O cadastro deverá ser realizado em uma tela separada
  • O Formulário deverá ter três campos
    • Nome (Campo de Texto)
    • Nota (Slider)
    • Comentário (Campo de Texto)
  • Um botão de confirmação deverá realizar o cadastro

Cadastro de Novos Filmes

Criando a NewMovieActivity

  1. File > New > Empty Activity
  2. Dar um título a Activity
  3. Implementar Interface
  4. Implementar ação de click

Cadastro de Novos Filmes

Dando um título a Activity

  • O título é uma propriedade da Activity
  • Pode ser customizado no AndroidManifest.xml
<application
    ...
    android:label="@string/app_name">
    <!-- Atividade Principal -->
    <activity android:name=".MainActivity">
            ...
    </activity>

    <!-- Atividade de cadastro dos filmes -->
    <activity android:name=".NewMovieActivity" 
        android:label="@string/activity_new_movie_title"></activity>
</application>

Cadastro de Novos Filmes

Implementando Interface

<LinearLayout ...
    android:orientation="vertical">

        <!-- Nome do filme -->
        <TableRow ... >
            <TextView ... 
                android:text="@string/new_movie_name"/>

            <EditText ...
                android:id="@+id/txt_movie_name"/>
        </TableRow>

        <!-- Nota do filme -->
        <TableRow ...>
            <TextView ...
                android:text="@string/new_movie_rating"/>

            <SeekBar ...
                android:max="10"
                android:id="@+id/sk_movie_rating" />
        </TableRow>

        <!-- Comentário do filme -->
        <TextView ...
            android:text="@string/new_movie_comment"/>
        <EditText ...
            android:layout_height="120dp"
            android:inputType="textMultiLine"
            android:id="@+id/txt_comment" />

        <!-- Botão de cadastro -->
        <Button ...
            android:text="@string/new_movie_btn_ok"/>
</LinearLayout>

LinearLayout

Layout que organiza a interface em linhas (verticais ou horizontais)

Cadastro de Novos Filmes

Implementando ação de click

public class NewMovieActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_new_movie);

        Button okButton = (Button) findViewById(R.id.btn_new_movie);
        okButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Invoca o pop up para dizer que foi cadastrado
                Toast.makeText(NewMovieActivity.this, 
                    "Filme cadastrado com sucesso", Toast.LENGTH_LONG).show();

                // finaliza a Atividade
                NewMovieActivity.this.finish();
            }
        });
    }
}

Toast

Exibe pop-ups no dispositivo

NewMovieActivity.java

Mas como cadastrar o filme???

Cadastro de Novos Filmes

Implementando ação de click

startActivity()
startActivityForResult()
startActivity()
startActivityForResult()
finish()
finish()
onActivityResult()

Cadastro de Novos Filmes

Implementando ação de click

protected void onCreate(Bundle savedInstanceState) {
    
    ...
    final EditText txtName = (EditText) findViewById(R.id.txt_movie_name);
    final SeekBar skRating = (SeekBar) findViewById(R.id.sk_movie_rating);
    final EditText txtComment = (EditText) findViewById(R.id.txt_comment);

    Button okButton = (Button) findViewById(R.id.btn_new_movie);
    okButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent returnIntent = new Intent();
            returnIntent.putExtra("name", txtName.getText().toString());
            returnIntent.putExtra("rating", skRating.getProgress());
            returnIntent.putExtra("comment", txtComment.getText().toString());

            setResult(RESULT_OK, returnIntent);

            Toast.makeText(NewMovieActivity.this, 
                           "Filme cadastrado com sucesso", Toast.LENGTH_LONG).show();
            NewMovieActivity.this.finish();
        }
    });
}

Cadastro de Novos Filmes

Implementando ação de click

private static final int NEW_MOVIE_CODE = 1;

MoviesAdapter adapter;    // deve ser global para adicionar o filme posteriormente

protected void onCreate(Bundle savedInstanceState) {
    .
    .
    .
    fab.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            Intent intent = new Intent(MainActivity.this, NewMovieActivity.class);
            startActivityForResult(intent, NEW_MOVIE_CODE);
        }
    });
}
.
.
.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == NEW_MOVIE_CODE && resultCode == RESULT_OK) {
        String name = data.getStringExtra("name");        // recupera o nome
        int rating = data.getIntExtra("rating", -1);      // recupera a nota
        String comment = data.getStringExtra("comment");  // recupera o comentário

        Movie newMovie = new Movie(name, rating, comment); // cria o objeto filme
        adapter.addNewMovie(newMovie);                    // adiciona filme no adapter
    }
}

Cadastro de Novos Filmes

Implementando ação de click

public class MoviesAdapter extends BaseAdapter {

    .
    .
    .
    public void addNewMovie(Movie newMovie) {
        this.movies.add(newMovie);

        // atualiza o adapter com o novo filme
        this.notifyDataSetChanged();
    }
}

Precisamos adicionar o novo filme na lista.

 

Essa adição pode ser feita por meio do adapter

Próximos Passos...

  • Armazenamento persistente
  • Compartilhamento por e-mail
  • Geolocalização & Maps
  • Consumo web services (Rotten Tomatoes)
  • Submissão a play store

Resumo de Hoje

  • A importância do mobile em nossas vidas
  • O ecossistema Android
    • Principais características
    • Conceitos básicos (app Hello, Droid)
  • MovieMe App

Muito Obrigado!!

eati2016

By João Eduardo Montandon