Buscar

TÓPICOS AVANÇADOS EM PROGRAMAÇÃO

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 10 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 10 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 10 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Aula 01 - Introdução ao Desenvolvimento Android
A arquitetura Android
A arquitetura Android é baseada em uma pilha organizada em 4 camadas. 
- A primeira camada, Linux Kernel, é a camada mais baixa da plataforma Android. Esta camada contém os serviços essenciais disponíveis a todos os seus dispositivos. Gerenciamento de processos e de memória são feitos nesta camada. O Linux Kernel também contém os drivers de dispositivos 
- A segunda camada de libraries (bibliotecas), encontramos temos as bibliotecas de sistema, normalmente escritas em C e C++, e que são utilizadas para o bom funcionamento do sistema operacional. Também encontramos bibliotecas Java criadas especificamente para Android.
- A terceira camada Android Runtime, este componente é responsável por fornecer a Core Java Library e a Dalvik Virtual Marchine. São semelhantes a uma máquina virtual, são eles que rodam as aplicações. 
- A quarta camada é a Applications, Nesta camada estão as aplicações criadas por diferentes fornecedores ou desenvolvedores. Estes não são obrigatórios para o funcionamento do celular. 
Introdução ao desenvolvimento Android
Este pacote normalmente possui a seguinte estrutura:
META-INF
MANIFEST.MF – arquivo de manifesto da aplicação
CERT.RSA – O certificado da aplicação
CERT.SF – Contém os hashes SHA1 para os arquivos incluídos no pacote
lib – diretório que contém o código compilado especifico para o tipo de processador
armeabi – código compilado para processadores ARM
armeabi-v7a – código compilado para todos os processadores ARMv7 e acima
arm64-v8a – código compilado para processadores ARMv8 e superior
x86 – código compilado para processadores x86
x86_64 – código compilado para processadores x86 64
mips – código compilado para processadores MIPS
res – diretório que contém todos os recursos não compilados no diretório resources.arsc
assets – diretório contendo todos os arquivos de componente bruto necessários para o funcionamento da aplicação, os quais podem recuperados através do AssetManager
AndroidManifest.xml – um arquivo de manifesto adicional, que descreve o nome, versão, direitos de acesso e bibliotecas utilizadas pela aplicação.
Classes.dex – as classes compiladas para o formato dex, que é entendido pela máquina virtual Dalvik
Resources.arsc – arquivo pré-compilado de recursos, como por exemplo XML binário
Componentes de aplicativo
Atividades (Activity)
Representam uma tela única de interface de um usuário. É implementada como uma subclasse de Activity. Estas fornecem a tela com a qual os usuários podem interagir. Cada atividade recebe uma janela, que representa a interface do usuário, com botões e caixas de texto, por exemplo. 
As atividades são ordenadas em forma de pilha no formato UEPS (último a entrar, primeiro a sair)
Serviços (Services)
Componentes executados em segundo plano para realizar operações de longa duração ou executar trabalhos remotos. Não representam uma interface com o usuário. Um serviço pode ter duas formas:
Iniciado – um componente do aplicativo, como uma activity, por exemplo, inicia-o chamando startService(). Após iniciado, o serviço pode ficar em segundo plano indefinidamente. 
Vinculado – neste caso, o componente vincula-se ao serviço, iniciando-o pela chamada bindService() Provedores de Conteúdo (Content Providers). São responsáveis por prover às aplicações o conteúdo dais quais elas necessitam para funcionar, ou seja, os dados. 
Receptores de Transmissão (Broadcast Receivers)
Este é o componente que responde (e inicia) anúncios a todo o sistema Android. Ao contrário de uma Activity, um BroadcastReceiver não possui qualquer tipo de interface com o usuário, mas possibilita a criação de uma notificação na barra de status.
A IDE Android Studio
A definição de classe (MainActivity), trata-se de uma classe com encapsulamento público e que herda (extends) os atributos e métodos da classe AppCompatActivity.
public class MainActivity extends AppCompatActivity {
Na linha 5, informamos que o método a seguir, criado na classe AppCompatActivity, deve ser redefinido por nossa classe MainActivity.
@Override3
O método a ser redefinido será o referente ao evento onCreate (que faz parte do ciclo de vida de uma Activity).
protected void onCreate(Bundle savedInstanceState) {
Na linha 7, informamos que, antes da redefinição do método, devemos repassar à classe antecessora (AppCompatActivity) os valores que nos foram informados no argumento savedInstanceState.
super.onCreate(savedInstanceState);
Na linha 8, finalmente, damos início à redefinição deste método, no caso, definindo que o ContentView a ser utilizado por esta Activity utilizará o layout designado pelo arquivo R.layout.activity_main
setContentView(activity_main);
AULA 2 - Interface Gráfica no Android
Activites
Um dos conceitos das activites é que são ordenadas em forma de pilha, a última a entrar será a ultima a sair. A cada nova a anterior é interrompida, ainda assim é armazenada na pilha, podendo ser reestabelecida caso o usuário retorne aquela tela, entretanto ao retornar, a última é destruída. 
Podemos dizer que uma Activity possui quatro estados e sete métodos principais, sendo eles:
Estados
A Activity não existe;
A Activity está em primeiro plano;
A Activity está em segundo plano;
A Activity está em pausa.
Métodos
onCreate();
onStart();
onResume();
onPause();
onStop();
onRestart();
onDestroy();
Monitorando o ciclo de vidas de uma Activity
Nossa MainActivity é composta da junção destes dois arquivos: no arquivo ManActivity.java desenvolvemos a classe Java que controla esta Activity enquanto no arquivo activity_main.xml criamos a interface que é apresentada ao usuário quando esta Activity é acionada.
Intent
Iniciamos uma nova Activity passando sua referência a uma Intent e então passando esta Intent ao método startActivity(). Nesse caso a Intent descreverá a atividade a iniciar e carregará todos os dados necessários. Caso você necessite obter um resultado quando a nova Activity finalizar, basta passar a Intent ao método startActivityForResult(). Assim, sua Activity estará apta a receber o resultado como um objeto Intent separado no retorno de chamada onActivityResult().
Ao criar uma nova classe, esta será pública e por default ainda sem formato de Activity. Depois disso devemos estender essa classe, pra que se comporte como Activity, acrescentando extends e depois o nome da classe que queremos herdar o comportamento. O próprio IDE irá indicar a ausência dos pacotes. 
Agora devemos redefinir o método OnCreate() desta classe, para que ela responda como desejamos não somente como a classe Activity responderia normalmente. Devemos também adicionar a importação de android.Bundle, pois utilizaremos o este objeto, ele agrupa os objetos. 
Criando uma interface: utilizaremos os layouts XML, clique nele e depois ‘new, layout resource file. Nome “activiy_segunda”. 
O método onCreate() será executado somente uma vez, durante a criação da classe.
O método onStart() será executado quando a aplicação iniciar, logo após do método onCreate(). No entanto ele também será executado caso a MainActivity entre no estado de segundo plano e esteja retornando para primeiro plano, logo após o método onRestart().
Finalmente o método onResume será acionado na criação do aplicativo, quando este estiver voltando do estado do segundo plano e ainda quando este estiver saindo do estado de “pausado”, ou seja, sua tela estava parcialmente visível (coberta por uma notificação, por exemplo).
Anotações: Intent é um objeto de mensagem, uma intenção de executar uma ação, assíncrono vc solicita ação mas continua em execução, . Não é possível iniciar uma atividade diretamente, a solicitação é feita com a ponte do android, então ele procura a atividade a ser realizada, e cria “oncreate” a atividade. 
Button
 Por isso vamos adicionar na MainActivity um botão para disparar a criação da SegundaActivity.
Para isso, nosso primeiro passo é modificar o layout, fornecendo um botãoa nossa interface.
No painel de Projeto, expanda a pasta res, layout e abra o arquivo activity_main.
Na Paleta de componentes (Pallete) localize o componente Button, e o arraste para dentro de nosso layout.
Agora precisamos criar dentro de MainActivity o objeto que corresponde ao comportamento do botão. A ligação entre o objeto Button e o xml é feita através de uma referência.
O comando findViewById se encarrega em localizar o componente mapeado na classe R. Com esta referência pronta, podemos finalmente estender as funcionalidades do objeto Button btnSegundaActivity para que este execute a chamada à SegundaActivity. Isto é feito através do método Button.setOnClickListener (). Este método cria um evento que será disparado todas as vezes que este botão for pressionado. No argumento do método devemos passar o evento desejado, no nosso caso um novo evento OnClickListener().
Agora vamos mover a criação do objeto Intent e o método startActivity para dentro desse evento, garantindo assim que os mesmos somente sejam disparados quando o usuário pressionar o botão.
AULA 3 - Activities
Para cada Activity que desejamos iniciar, devemos enviar ao sistema operacional um objeto de Intenção que informe ao mesmo o que desejamos fazer.
Enviando Parâmetros para uma Activity
Utilizamos o Objeto Intent para armazenar o valor que desejávamos retornar através do método setResult(). Para o envio de parâmetros à nova Activity, o processo é basicamente o mesmo. Devemos criar uma Intent e passar a ela os objetos que desejamos que sejam transmitidos à nova Activity.
Agora, em nosso arquivo TerceiraActivity.java devemos descrever o comportamento desejado para nossa nova Activity. Abra o arquivo TerceiraActivity.java.
A proposta para esta Activity é que, no momento de sua criação, o valor do texto para o componente TextView valorParametro seja alterado para o valor passado junto a Intent que o criou. Portanto, devemos criar a referência a este componente:
Lembre-se de que Activities são criadas sempre a partir de uma Intent (mesmo nossa MainActivity). A Intent que a originou é armazenada na classe Activity, e pode ser recuperada através do método getIntent().
Agora que temos acesso à Intent, basta buscarmos o valor desejado utilizando-se o método getStringExtra(); Este método buscará dentro da Intent por um objeto identificado pelo argumento passado ao mesmo e retornará o valor no formato String. O objeto Intent oferece métodos para retorno de valores no formato Int, Boolean, Char, Long entre outros.
Em nosso exemplo, vamos supor que o Intent que deu origem à nossa Activity veio com um extra do tipo String chamado “retorno”.
valorParametro.setText(intent.getStringExtra("retorno"));
AULA 4 - Armazenando Dados
Persistindo valores com SharedPreferences
O armazenamento de dados em SharedPreferences e permite que tipos primitivos sejam salvos no formato “chave,valor”. Seu uso é comum em situações onde você deve guardar alguma informação primitiva (ou seja, tipos simples) entre sessões de utilização de seu aplicativo. 
O acesso aos dados armazenados é feito através da instância de um objeto SharedPreferences, e a partir daí utilizamos métodos get para recuperação do valor.
Exemplo para acesso de preferencias em nível de Activity:
String nome;
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
prefs.getString(“nome”,nome);
A gravação de dados em SharedPreferences também é bastante simplificada. Devemos instanciar um objeto de edição a partirde SharedPreferences.Editor, chamando o método de SharedPreferences edit( ), deixando assim o arquivo de preferências pronto para edição e finalmente lançando seus valores com o comando putString( ), putBoolean( ), putFloat( ), putInt( ) ou putLong( ) ou putStringSet( ). A gravação (persistência) dos dados é feita a partir dos comandos apply( ) e commit( ).
O método apply( ) salva seus dados para a memória imediatamente em arquivo e em uma thread separada, garantindo assim que não haja nenhum bloqueio na thread principal, ou seja, seu aplicativo não irá congelar. 
O método commit( ) salva o dado diretamente em arquivo, mas o processo é executado dentro da thread principal do aplicativo, forçando a parada de todos os processos de seu aplicativo até que o arquivo esteja salvo. Este método retornará true caso o arquivo seja gravado com sucesso e false em caso de falha. Utilize o método commit( ) somente se necessitar de confirmação imediata da gravação dos registros em arquivo ou caso esteja desenvolvendo para dispositivos abaixo da API 9.
Se executarmos nosso aplicativo, veremos que agora nossos botões coloridos mudam a cor de fundo. Nosso campo de texto também permite a digitação de valores, mas o botão de gravação não executa nenhuma ação. Vamos declarar então o botão de “Gravar”:
Button btnGravar;
Instanciá-lo, vinculando-o ao componente correspondente no layout:
btnGravar = (Button) findViewById(R.id.btnGravar);
Finalmente, deve-se redefinir seu Listener OnClickListener:
btnGravar.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {
 }
});
Salvando dados utilizando o SQLite
O SQLite é uma pequena biblioteca, implementada em C que oferece acesso a uma base de dados racional SQL e suportando até 2 TB de dados. Seu armazenamento é feito em um arquivo de texto dentro do dispositivo, e não existe a necessidade de se estabelecer qualquer tipo de conexão JDBC ou ODBC por exemplo.
Duas classes são utilizadas para a criação do banco de dados:
SQLiteDataBase – contém os métodos de manipulação de dados;
SQLiteOpenHelper – responsável pela criação e versionamento do banco.
Nossa estrutura de armazenamento será:
Nome da tabela: amigos
Campo: id
Tipo : INTEGER (auto incremento)
Campo: nome
Tipo: TEXT
Campo: telefone
Tipo: TEXT
Campo: e-mail
Tipo: TEXT
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
     // comando sql responsável pela criação da estrutura da tabela amigos
String tabela_amigos = "CREATE TABLE amigos ("
             + "id INTEGER PRIMARY KEY autoincrement,"
             + "nome TEXT,"
             + "telefone TEXT,"
             + "email TEXT"
             + ")";
     // executando o sql de tabela_amigos
     sqLiteDatabase.execSQL(tabela_amigos);
}
Adapters
O adaptador provê acesso aos dados e também é responsável por criar uma View para cada registro presente no conjunto de dados.
O primeiro passo na criação de um adaptador é definir qual objeto armazenará os dados que serão enviados a ele. Vamos então definir uma List de Amigos:
private List<Amigo> amigos;
Devemos também armazenar o Contexto no qual este adaptador está sendo renderizado (ou seja, o componente responsável por sua renderização):
Context context = null;
E o objeto responsável por “inflar” o layout (ou seja, renderizá-lo):
private LayoutInflater inflater;
Podemos agora criar o construtor para nossa classe, que inicializará os objetos declarados:
public AmigoAdapter(Context context, List<Amigo> amigos){
 this.amigos = amigos;
 this.inflater = LayoutInflater.from(context);
 this.context = context;
}
Para implementarmos o método getCount(), devemos retornar a quantidade de registros encontrados em nossa List de amigos. Para isto, basta utilizarmos o método size():
@Override
public int getCount() {
 return this.amigos.size();
}
O método getItem é responsável por retornar o objeto do tipo Amigo que se encontra em uma determinada posição de nossa List.
@Override
public Object getItem(int i) {
 return this.amigos.get(i);
}
O método getItemID é responsável por retornar o id do objeto do tipo Amigo em determinada posição:
@Override
public long getItemId(int i) {
 return i
}
AULA 5 – Permissões
Trabalhando com Permissões
Em seu arquivo MainActivity.java, devemos agora vincular nosso componente de layout TextView a um objeto, portanto declare:
TextView txtContato;
Uma vez declarado, em nossométodo onCreate() iremos inicializar o objeto, vinculando-o ao layout xml:
txtContato = (TextView) findViewById(R.id.txtContatos);
Agora criaremos o método que fará acesso aos dados de nossos contatos. Chamaremos este método de buscaContato().
public void buscaContato(){}
Criamos então o objeto Uri, que armazenará informações referentes ao objeto ContactsContract.Contacs:
Uri CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
String _ID = ContactsContract.Contacts._ID;
String DISPLAY_NAME = ContactsContract.Contacts.DISPLAY_NAME;
String HAS_PHONE_NUMBER = ContactsContract.Contacts.HAS_PHONE_NUMBER;
Definimos o objeto URI, que armazenará informações referentes aos números de telefone.
Uri PhoneCONTENT_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String Phone_CONTACT_ID = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
String NUMBER = ContactsContract.CommonDataKinds.Phone.NUMBER;
E finalmente o objeto URI, que conterá informações referentes aos e-mails:
Uri EmailCONTENT_URI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
String EmailCONTACT_ID = ContactsContract.CommonDataKinds.Email.CONTACT_ID;
String DATA = ContactsContract.CommonDataKinds.Email.DATA;
Feito isso, buscamos o ContentResolver, que criará uma interface de acesso entre a URI, e um Cursor, que nos permitirá navegar entre os registros.
ContentResolver contentResolver = getContentResolver();
Feito isso, buscamos o ContentResolver, que criará uma interface de acesso entre a URI, e um Cursor, que nos permitirá navegar entre os registros.
Cursor cursor = contentResolver.query(CONTENT_URI, null,null, null, null);
Interagindo com outros aplicativos
Podemos nos aproveitar de aplicativos que executem a mesma tarefa. Isso é feito através de intenções implícitas.
Entre as Intenções Implícitas comuns em dispositivos Android, podemos destacar:
ACTION_SET_ALARM – Cria um alarme
ACTION_SHOW_ALARMS – Mostra uma listagem de todos os alarmes definidos
ACTION_IMAGE_CAPTURE – Abre o aplicativo de câmera e recebe a imagem capturada
ACTION_VIDEO_CAPTURE – Abre o aplicativo de câmera e recebe o vídeo capturad
Quanto intente tentar executar alguma ação implícita, o android vai procurar algum aplicativo que disponibilize tais funções solicitadas, havendo mais de um, será listada a relação dos apps disponíveis. 
Serviços
Um serviço é um componente que representa o desejo da aplicação de executar uma tarefa de longa duração sem interação com o usuário final, ou suprir funcionalidades para uso de outras aplicações, mas sem interação com o usuário.
O ciclo de vida de um serviço é muito mais simples do que o de uma Activity e pode seguir por dois caminhos:
Serviço iniciado: criado quando outro componente chama startService() e permanece em execução indefinidamente, devendo ser interrompido pela chamada stopSelf(). Outro componente pode também interrompê-lo chamando o método stopService(). Quando um serviço é interrompido, o sistema o elimina.
Serviço vinculado: é criado quando outro componente executa o método bindService. O componente que o chamou comunica-se então com o serviço através da interface IBinder, e vários componentes podem ser vinculados a um mesmo serviço. Quando todos os vínculos terminam o sistema destrói o serviço, ou seja, o serviço não precisa ser interrompido por uma chamada ao final.
A principal diferença entre um serviço iniciado e um serviço vinculado (bind) é que um serviço iniciado será executado em segundo plano até que alguém o finalize ou este finalize sozinho. Ele é usado para executar operações que possam levar muito tempo. Um serviço vinculado (bind) será executado enquanto houver uma ligação com algum componente e este interaja com ele. Além disso, serviços vinculados podem retornar valores aos componentes com os quais estão vinculados.
Serviços iniciados ficarão na memória mesmo depois que o componente que os iniciou já não esteja mais em memória, ou seja, encerrado. Um bom exemplo de uso de serviços iniciados são envio de mensagens SMS, download de arquivos, etc.
Serviços vinculados são executados quando existe a necessidade de retorno para o componente que os iniciou. Como o fluxo de dados acontece do serviço para o componente, um canal de comunicação é criado. Tal qual Activities, os serviços também requerem sua definição no arquivo de Manifesto de sua aplicação, para que possam ser executados.
Ciclo de vida simplificado do Serviço Iniciado:
onCreate()
onStartCommand()
onDestroy()
Ciclo de vida simplificado do Serviço Vinculado:
onCreate()
onBind
onUnbind()
onDestroy()
AULA 6 - Conectando à Internet
Processamento Concorrente
Quando um aplicativo Android é iniciado, uma nova linha de processamento chamada UIThread é iniciada em seu dispositivo. A UIThread é a principal linha de execução de seu aplicativo. É nela que a maior parte de seu código é executado. Todos os seus componentes de aplicação (Activiy, Services, Content Providers e BroadcastReceivers) são criados nesta thread e várias chamadas de sistema a esses componentes são executadas nela.
Se a UIThread for bloqueada por mais de 05 segundos será retornada a mensagem de que o aplicativo não está respondendo. 
Para tarefas que consumam muito tempo ou uso intensivo da CPU, temos basicamente duas maneiras de criar isso:
✔ Threads Java 
 Operações simples de rede que não requeiram o download de muitos dados.
 Tarefas dze disco que não ocupem mais do que poucos milissegundos.
✔ AsyncTasks
Operações de rede que envolvam quantidades maiores de dados (tanto para upload quando para download).
Tarefas de alto consumo de CPU que necessitem ser executadas em segundo plano.
Quando criamos novos processos, devemos ter duas regras básicas em mente:
1. Não podemos bloquear o processamento da UIThread.
2. Não podemos acessar os componentes de interface do usuário do android e fora da UIThread.
Notificações ao Usuário
Ao ser disparada, uma notificação passa por duas etapas: primeiro, ela aparece como um ícone na área de notificação. Quando o usuário clica nessa área, a gaveta de notificação é aberta, onde estão disponíveis as notificações que foram emitidas para aquele dispositivo.
Notificações podem ser percebidas através do ícone na barra de notificações, aparecendo na tela de trava do dispositivo, piscando o LED, tocando um som, vibrando ou aparecendo momentaneamente na tela atual.
As notificações são representadas pela classe Notification. Para criar uma notificação você pode utilizar a classe NotificationManager, que pode ser recebida de um Context.
As ações e informações da interface de usuário da notificação são criadas no objeto NotificationCompat.Builder. Para criar a própria notificação, chama-se o método NotificationCompat.Builder.build(), que retorna um objeto do tipo Notification contendo suas especificações.
Para se emitir a notificação, passamos o objeto Notification ao sistema chamando o método NotificationManager.notify();
Todo objeto Notification deve conter o seguinte:
✔ um ícone pequeno, definido por setSmallIcon();
✔ um título, definido por setContentTitle();
✔ um texto de detalhes, definido por setContentText().
Quando uma notificação é criada, é importante associarmos ao menos uma ação à mesma. Geralmente, a ação padrão em uma notificação é abrir uma Activity em seu aplicativo. A execução dessa Activity é passada à notificação através de uma Intent.
Como as Activities trabalham no formato de pilha, devemos utilizar o objeto TaskStackBuilder para criar uma pilha virtual que será passada ao sistema operacional quando uma Activity for iniciada a partir de uma Notificação.
Após a criação da pilha virtual, informamos ao Builder qual será a Intent disparada (ou colocada no topo da pilha), através do objeto PendingIntent.
BroadCast Receivers
Um BroadcastReceiver é o componente Android que possibilita ao seu aplicativo registrar-se para o recebimento de eventos de aplicativos ou de sistema.
Por exemplo, aplicativos podem registrar-separa o evento ACTION_BOOT_COMPLETE, que é disparado sempre que o dispositivo Android termina o processo de boot.
O ciclo de vida básico de um BroadcastReceiver é composto do método chamado onReceive(). Assim que esse método é executado, o sistema considera o objeto finalizado e não mais ativo.
Um BroadcastReceiver pode ser registrado via o manifesto AndroidManifest.xml. Esse tipo de registro, via AndroidManifest.xml, é conhecido como registro estático. No entanto, é possível também registrar-se dinamicamente, utilizando-se o método Context.registerReceiver().
A classe que implementa esse objeto deve ser derivada da classe BroadcastReceiver. Se o evento para qual essa classe é disparada, então, o método onReceive() é chamado automaticamente pelo sistema Android.
Aula prática
Layout 
Relative layout: Cada item está vinculado ao item mais próximo. Se um componente for remanejado os demais vinculados a ele também serão vinculado, efeito cascata.
Relative Linear: Ele vai dividindo as telas de acordo com a quantidade de componentes, exemplo: 03 componentes, a tela será dividida em 3 telas. Serão divididos seguindo o parâmetro escolhido: linear vertical ou horizontal. 
Os layouts podem ser mesclados, em uma mesma tela pode-se acrescentar um linear horizontal em outro vertical, e o inverso. 
 
FrameLayout: Possibilita a criação contínua de telas, exemplo, ao rolar a barra de rolarolagem a tela vai apenas descendo, não criando uma nova.
ArrayList: Como as arrays comuns, cria-se um grupo com informações. Cada objeto será devidamente inserido com suas primary key.

Outros materiais