Compartilhando arquivos no Android 7 (Nougat) e a exception FileUriExposedException

Posted by rlecheta on novembro 03, 2016
Android, Tutorial / No Comments

É raro termos algum erro de compatibilidade ao atualizar as versões do Android no aplicativo, mas no caso do Android 7 (Nougat) temos a exception FileUriExposedException.

Se você ainda não se deparou com ela, logo irá.

Digamos que você possui um aplicativo que tire fotos. Para exemplificar, temos este trecho de código que cria um arquivo e chama a Intent da câmera:

screen-shot-2016-11-02-at-19-26-24

Tudo normal com o código certo? Mas se você atualizar o seu projeto para compilar com a API 24/25 (Android 7) verá uma exception igual esta:

screen-shot-2016-11-02-at-19-14-35

Segundo a documentação do Android, esta exception é lançada ao expor um arquivo por uma Uri para outra aplicação. Neste caso, o erro é porque estamos expondo o arquivo que criamos para a aplicação nativa da câmera, pois a câmera precisa salvar a foto neste arquivo.

https://developer.android.com/reference/android/os/FileUriExposedException.html

Sem mais demoras, vamos logo a solução:

Edite o arquivo AndroidManifest.xml e adicione a tag <provider> dentro da tag <application> .

Exemplo: AndroidManifest.xml

screen-shot-2016-11-02-at-19-19-45

Veja que dentro de <meta-data> é referenciado um arquivo XML @xml/provider_paths com a configuração de compartilhamento para os arquivos da aplicação, neste caso vamos colocar o “.”, para compartilhar tudo desde a raiz.

Exemplo: provider_paths.xml

screen-shot-2016-11-02-at-19-20-46

Feito estas configurações no projeto, basta trocar a linha que cria a Uri do arquivo:

Uri uri = Uri.fromFile(file);

Por esta:

Uri uri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + “.provider”, file);

Então, o código que chama a Intent da câmera que mostrei anteriormente fica assim:

screen-shot-2016-11-02-at-19-33-55

Exemplo: CameraUtil.java

Pronto! Agora podemos tirar fotos no Android 7 (Nougat). Espero que esta dica ajude alguém 🙂

Para maiores informações, veja a documentação oficial.

device-2016-11-02-193556

XCode 8 e Swift 3

Posted by rlecheta on outubro 23, 2016
iOS, Livros / 2 Comments

Olá pessoal

A 4a ed do livro de iOS foi feita utilizando o XCode 7 com Swift 2.
ios
Recentemente foi lançado o Xcode 8 com suporte ao Swift 3.
Para auxiliar os leitores que compraram a 4ed, este post visa explicar algumas das mudanças e também para dizer que atualizei os fontes no github com os exemplos com Swift 3.
Espero que o fonte ajude quem comprar a 4ed e precisar estudar Swift 3.
Para migrar os projetos da 4ed para Swift 3 foi simples. Eu abri cada projeto no Xcode 8 e o próprio Xcode mostrou o wizard para migrar para o Swift 3. Na maioria das vezes deu certo, e quando não funcionou fiz pequenos ajustes.
A figura abaixo mostra o wizard do XCode 8 durante a migração do Swift 2 para o Swift 3. Ele mostra um preview de cada arquivo, portanto eu recomendo que você leia cuidadosamente cada mudança pois é uma ótima maneira de aprender a nova sintaxe.
9-2
Mas o que mudou?
Algumas coisas foram a sintaxe como mostra esse código abaixo.

Swift 2: UIApplication.sharedApplication().openURL(NSURL(string:url)!)

Swift 3: UIApplication.shared.openURL(URL(string:url)!)

Note que a classe NSURL mudou para apenas URL. Isso acontece também com várias outras classes que tinham o prefixo NS.

A seguir temos outro exemplo de código que está diferente:

Swift 2:

self.window = UIWindow(frame: UIScreen.main.bounds)

self.window!.backgroundColor = UIColor.white

Swift 3:

self.window = UIWindow(frame: UIScreen.mainScreen().bounds)

self.window!.backgroundColor = UIColor.whiteColor()

Uma mudança importante foi na forma de declarar os métodos, pois foi adicionado um prefixo “_” opcional no primeiro parâmetro. Digamos que temos uma função soma(n1,n2) com a seguinte declaração.

func soma(n1:Int, n2:Int) -> Int {

   return n1 + n2

}

Par chamar a função você faria algo assim:

let n = soma(n1: 1, n2: 3)

print(n)

Note que é obrigatório informar o primeiro argumento “n1”. Caso você opte por simplificar a chamada e não informar o argumento, basta colocar o “_” antes de declarar o primeiro argumento, assim:

func soma(_ n1:Int, n2:Int) -> Int {

   return n1 + n2

}

Neste caso a chamada ficaria (não precisa informar o n1):

let n = soma(1, n2: 3)

print(n)

Bom, teve várias outras mudanças.. mas o que recomendo é que vocês migrem os projetos de Swift 2 para Swift 3 utilizando este wizard do XCode, pois é um excelente exercício e aprendizado.

Para quem tem a 4ed, recomendo antes estudar no XCode 7, pois assim os exemplos com Swift 2 vão todos funcionar. É possível encontrar versões antigas do XCode procurando no Google por “xcode older versions”. Depois que estudar os códigos do livro com Swift 2, recomendo instalar o XCode 8 e utilizar o wizard de migração para o Swift 3.. Será um bom aprendizado sobre a sintaxe.

É isso pessoal, espero que este rápido post tenha ajudado :-).

Temas no Android: O que fazer se a Action Bar estiver nula.

Posted by rlecheta on outubro 07, 2016
Android, Livro Android, Tutorial / 2 Comments

Olá pessoal, recentemente um leitor da 4a edição do livro de Android veio tirar uma dúvida sobre um erro que acontecia com um exemplo do capítulo 4.

No caso a activity estava herdando de android.app.Activity.


public class AlgumaActivity extends Activity {

... código aqui

// dava erro nessa linha

getActionBar().setDisplayHomeAsUpEnabled(true);

}

O erro reportado foi que dava NullPointer ao acessar a action bar.

OK, mas porque isso acontece?

Na maioria das vezes, se a action bar está nula com certeza é a configuração do tema.

Olhando o styles.xml do meu colega, o tema do projeto estava configurado assim:

a

Vejam que está usando o tema AppCompat, que traz a compatibilidade para várias versões do Android. Este tema substitui os temas Holo, Material, etc e atualmente é recomendado pelo Google. Isso é o esperado mesmo e está correto, pois o Android Studio atualmente gera o projeto desta forma.

O problema é que na época que escrevi a 4a edição do livro, os exemplos eram gerados de outra forma pelo Android Studio, inclusive no github da 4ed está assim:

https://github.com/livroandroid/4ed/blob/master/capitulos/cap04-activity/HelloActivity/app/src/main/res/values/styles.xml

b

Veja que o tema que usei na época da 4ed foi o Holo, que é um específico para Android 3 (API Level 11). Enfim, mas isso está explicado no livro e não quero demorar aqui…

O livro 5a ed que está mais atualizado já traz os exemplos todos com o tema de compatibilidade, portanto este problema acontece apenas nos exemplos da 4 ed, pois o Android Studio mudou a forma de gerar o código dos projetos.

Bom, existem 2 formas de resolver este problema:

1) Caso você queira deixar o código das classes de Activity iguais estavam nos exemplos da 4ed, é preciso alterar o tema do projeto para Holo ou Material, conforme o github da 4ed. Isso é feito alterando o arquivo styles.xml conforme o exemplo que mostrei acima do github.

Basicamente, se o seu tema herda de Holo ou Material, você está usando um tema nativo. Então vc deve sempre usar a android.app.Activity como a activity mãe, e neste caso você pode utilizar o método getActionBar() que retorna a action bar nativa android.app.ActionBar.

Era dessa forma que era feito nos primeiros exemplos da 4 ed. Somente no capítulo de Action Bar que começo a explicar o tema AppCompat de compatibilidade.

2) A segunda forma de resolver, e talvez a recomendada é atualizar o código de todas as Activities para herdar de android.support.v7.app.AppCompatActivity, pois é a activity do tema de compatibilidade. Atualmente o Android Studio gera o projeto com o tema AppCompat, como vimos no styles.xml do meu colega logo no início deste post. Isto indica que o projeto usa o tema de compatibilidade.

Esta configuração de tema atualmente é a indicada. Porém como o fonte da 4ed está antigo, faça as seguintes alterações no código:

  • Altere todas as activities do projeto para herdar de AppCompatActivity.
  • Altere a chamada do método getActionBar() por getSupportActionBar(), pois este último vai retornar a action bar de compatibilidade, que é a classe android.support.v7.app.ActionBar.

Como o Android Studio atualmente gera o projeto com o tema de compatibilidade, na 5ed do livro todos os exemplos já estão assim.

É isso pessoal, este breve post foi só para explicar uma pequena diferença entre a 4ed e a 5ed. Como vimos o Android Studio mudou a forma de gerar os códigos do projeto e isso afetou um pouco, e essas coisas de tema e compatibilidade costumam ser complicadas para quem está estudando Android pela primeira vez :-).

Independente de como estão os códigos-fontes da 4ed e 5ed, estes conceitos é bom conhecer.

Qualquer dúvida perguntem, abs.

Tags:

Enviando mensagens de Push com o Firebase Cloud Messaging (FCM) – parte 2

Posted by rlecheta on julho 31, 2016
Android, Tutorial / 13 Comments

Olá pessoal, na Parte 1 deste tutorial aprendemos a criar um app Android para receber mensagens de Push utilizando o Firebase.

Se você ainda não leu, segue link da 1ª parte.

http://ricardolecheta.com.br/?p=862

Na 2ª parte do Tutorial vamos ver como fazer:

  1. Enviar mensagens de Push pelo web service do Firebase (sem utilizar o console);
  2. Exemplo de como ler mensagens do tipo chave=valor no Android.

Vimos que podemos usar o console do Firebase para enviar as mensagens de Push, mas muita gente tem me perguntado como que faz para enviar a mensagem manualmente no código.

Para enviar uma mensagem de Push, basta postar no web service do Firebase um JSON contendo as informações necessárias.

A figura abaixo mostra o endereço URL do endpoint do web service e os parâmetros que precisam ser enviados:

a

Veja que o endpoint do web service do Firebase é:

https://fcm.googleapis.com/fcm/send

Obs: se você não está acostumado com o termo, “endpoint” refere-se a URL de um web service.

Algo importante da requisição, é que ela deve ser feita via POST, e deve-se enviar no cabeçalho HTTP os parâmetros Content-TypeAuthorization.

O valor parâmetro Authorization é igual a “key=SUA_SERVER_KEY”.

A SERVER_KEY do FCM pode ser encontrada na página do Console, dentro das configurações do seu projeto.

Dentro da página do seu projeto, clique em Configurações conforme indicado na figura e depois no link Project Settings. Então entre na tab Cloud Messaging, onde você verá sua SERVER KEY.

b

No meu caso, o valor do parâmetro Authorization ficou assim:

key=AIzaSyBwaM5NAiGSGoft1gIESiuRaVcQTlxHe8E

Se você é novo em programação, procure sobre como fazer requisições HTTP na linguagem que você está programando, seja PHP, Java, Python, etc.. todas tem uma forma de fazer esta requisição.

Eu gosto de testar web services utilizando o plugin Postman do Chrome, pois é simples e prático. Para brincar vamos fazer um teste rápido 🙂

No Postman, siga os seguintes passos:

1) Configure o modo de envio para POST e digite a URL do endpoint do Firebase: https://fcm.googleapis.com/fcm/send

c

2) Clique em Headers e adicione os cabeçalhos Content-TypeAuthorization

Content-Type = application/json

Authorization = key=AIzaSyBwaM5NAiGSGoft1gIESiuRaVcQTlxHe8E

Lembre-se de colocar a sua SERVER_KEY.

d

3) Clique em Body e selecione a opção raw

Digite o seguinte JSON para enviar uma notificação:

{
 "to" : "Digite o Token (registration id) do dispositivo aqui",
 "notification" : {
 "title" : "Mensagem para o Firebase",
 "body" : "Teste firebase"
 }, 
 "data" : {
 "nome" : "Ricardo",
 "sobrenome" : "Lecheta"
 }
}

A figura a seguir mostra como fiz no Postman. Depois de preencher tudo corretamente, é só clicar no botão Send e pronto! Você verá lá em baixo o JSON de resposta do servidor do Google.

g

Veja que no JSON que enviei, mandei tanto o campo “notification” que possui os dados para mostrar o alerta de notificação no dispositivo (title e body), assim como foi enviado a estrutura “data” com os parâmetros com chave e valor.

Neste caso enviei os seguintes parâmetros:

nome=Ricardo

sobrenome=Lecheta

No código, basta ler estes parâmetros conforme mostra a figura abaixo.

Tinham me perguntado como fazer para ler os dados enviados, então é exatamente desta forma que deve-se fazer 🙂

f

Vale lembrar que o Firebase vai mostrar a notificação somente se o aplicativo estiver em background. Caso ele esteja aberto, você deverá ler a mensagem e mostrar a notificação/alerta manualmente.

É isso pessoal, espero que este tutorial tenha ajudado e qualquer dúvida é só perguntar 🙂 , abs.

Enviando mensagens de Push com o Firebase Cloud Messaging (FCM)

Posted by rlecheta on julho 25, 2016
Android, Tutorial / 34 Comments

Olá pessoal.

Esta é a 1ª parte do Tutorial. A 2ª parte está aqui.

No Google I/O 2016 o Google anunciou o Firebase, uma plataforma completa com diversos serviços comuns a aplicativos móveis como analytics, crash reports, notificações push, dentre outros.

firebase

Muito tem se falado do Firebase nos últimos meses, portanto serei rápido neste post. O mais importante que você precisa saber para seguir este tutorial é que ele deve levar no máximo 10 a 15 minutos, e as mensagens de Push do Firebase são gratuitas 🙂

No livro Google Android 5a ed, explico como enviar mensagens de Push no Android com o GCM (Google Cloud Message).

Capa_AndroidLecheta4ed_FINAL

Porém como o GCM foi migrado para o FCM (Firebase Cloud Messaging), é justo atualizar os leitores do meu livro com as novidades 🙂

Neste rápido tutorial vamos aprender a enviar mensagens de Push com a nova plataforma do Firebase, e o projeto que vamos fazer é baseado na documentação do Firebase, disponível neste link:

Set Up a Firebase Cloud Messaging Client App on Android

No github do Firebase você poderá encontrar diversos exemplos, inclusive o quickstart sobre o FCM. Os códigos deste tutorial, serão baseados neste quickstart.

https://github.com/firebase/quickstart-android/tree/master/messaging

Partiu pro código!

1) Passo 1 – Criar o projeto.

Crie um projeto no Android Studio conforme a figura abaixo. Eu escolhi o template Empty Activity.

Tenha atenção no nome do pacote que você vai escolher para o projeto, pois essa informação será necessária depois para configurar o Firebase.

001

2) Configurar o Firebase no Console.

Acesse a página do console do Firebase com sua conta do Google e clique no botão Create New Project.

https://console.firebase.google.com/

002

Escolha um nome para seu projeto, selecione o Brasil como país e prossiga.

Depois de criar seu projeto, você verá a página de administração do Firebase.

003

O Firebase possui APIs para Android, iOS e Web. Neste tutorial estamos criando um app Android, portanto clique no botão Add Firebase to your Android app para configurar o projeto.

No wizard insira o nome do seu pacote, o SHA1 do seu certificado e clique em Add App.

004

Siga o wizard, e no passo 2 faça o download do arquivo google-services.json conforme indicado na figura. Este arquivo contem as configurações da sua conta do Firebase e deve ficar dentro do módulo app do projeto, conforme indicado na figura.

005

No último passo do wizard, temos as instruções de como configurar o gradle. É só copiar o código e colar no local indicado. Veja que devemos alterar o arquivo build.gradle da raiz do projeto, e depois o arquivo app/build.gradle do módulo app.
006

Pronto! Agora vamos voltar ao projeto Android.

3) Configuração do projeto Android.

Crie a classe MyFirebaseInstanceIDService conforme o código deste link:

https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseInstanceIDService.java

Veja que vamos usar o próprio exemplo de quickstart do Firebase, assim não temos como errar :-).

Nesta classe, o método onTokenRefresh() é chamado quando o aplicativo receber um token (registration id). Como você aprendeu no livro Google Android 5ed, este token representa o identificador do dispositivo e precisa ser enviado ao seu servidor, pois com ele é possível enviar uma mensagem para este dispositivo.

 

@Override
 public void onTokenRefresh() {
 // Get updated InstanceID token.
 String refreshedToken = FirebaseInstanceId.getInstance().getToken();
 Log.d(TAG, "Refreshed token: " + refreshedToken);

// TODO: Implement this method to send any registration to your app's servers.
 sendRegistrationToServer(refreshedToken);
 }

Feito isso, crie a classe MyFirebaseMessagingService. Ela será responsável por receber as mensagens de push e criar notificações para avisar ao usuário.

Novamente, vamos copiar a classe de exemplo do quickstart do Firebase.

https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java

O método onMessageReceived(msg) é chamado quando uma notificação de Push é recebida, simples assim 🙂


@Override
 public void onMessageReceived(RemoteMessage remoteMessage) {
 // Faça algo aqui como mostrar uma notificação.
 }

Depois de criar estes 2 serviços  do Firebase, é preciso cadastrá-los no AndroidManifest.xml, conforme mostra a figura abaixo.

b

c

Para ajudar, copie o trecho de código do manifest dos exemplos do Firebase.

https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/AndroidManifest.xml

Ao rodar o aplicativo você verá a mensagem que o token deste dispositivo foi gerado com sucesso. Funciona mesmo no emulador do Android SDK.


I/FirebaseInitProvider: FirebaseApp initialization successful
07-23 21:04:53.633 16360-16514/br.com.livroandroid.hellofirebasemessaging D/MyFirebaseIIDService: &amp;amp;amp;amp;lt;strong&amp;amp;amp;amp;gt;Refreshed token&amp;amp;amp;amp;lt;/strong&amp;amp;amp;amp;gt;: cJmLLI-dIR0:APA91bGtuSyWqc-T7kBx_eeC2ANJbBmyl2v1zlZ74afrRiqyJOC0Y7apmfdcDuuKL0JX2_gDpGW-xzROEQS3qKYRXNTfMOloSYoE8o3dqOJobeXTsLHG4jbSU1lQ5JV2-LEM9jN5B_BI

4) Enviando uma mensagem pelo console do Firebase.

Já temos tudo configurado, e só falta enviarmos uma mensagem para testar o Push. O legal do Firebase é que isso pode ser feito pela sua própria página de console.

No console do Firebase, acesse o menu Notifications e envie uma notificação. Basta preencher o campo Message text e selecionar o aplicativo com o seu pacote no campo Target.

d

Ao enviar uma mensagem com o aplicativo aberto, você verá no LogCat conforme indicado na figura abaixo 🙂

MyFirebaseMsgService: Message Notification Body: Hello Firebase!

e

Agora pressione o botão Home do Android e deixe o aplicativo em background. Neste caso ao enviar a mensagem o Firebase vai mostrar uma notificação automaticamente, conforme este print.

f

Veja que a notificação só foi exibida com o app em background, e este é o comportamento padrão do firebase.

Basicamente, existem 2 tipos de mensagens: data messages (pares de chave=valor) e notification messages.

1) As mensagens do tipo data messages são sempre recebidas no método onMessageReceived(removeMessage), independente se o app está aberto ou em background.

Para identificar se a mensagem é do tipo data message, basta verificar se o método getData() retorna um Map com registros (chave=valor).

if (remoteMessage.getData().size() &gt; 0) {
&nbsp; &nbsp;Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}

Neste caso o desenvolvedor é sempre responsável por mostrar uma notificação para o usuário, ou seja, é preciso programar para mostrar a notificação. No código de exemplo do firebase tem até um exemplo disso basta descomentar o código.

Para enviar uma mensagem do tipo data message pelo console do Firebase, entre em opções avançadas e preencha a estrutura de chave=valor, é bem simples. Depois no app você poderá ler os valores.

2) As mensagens do tipo notification messages possuem um comportamento um pouco diferente, e foi esta mensagem que enviamos, pois ela não continha nenhum parâmetro do tipo (chave=valor).

Neste tipo de mensagem, se o app está aberto o método onMessageReceived(removeMessage) é executado. Neste caso, o desenvolvedor é responsável por programar a leitura da mensagem e mostrar a notificação para o usuário. Porém, caso o app esteja em background o Firebase vai mostrar uma notificação automaticamente para o usuário. Ao clicar na notificação os dados da mensagem de push serão enviados para a activity principal do aplicativo, então é só fazer o tratamento ao abrir o app e pronto 🙂

Para maiores detalhes sobre os tipos de notificações veja esse link:

https://firebase.google.com/docs/cloud-messaging/concept-options

É isso pessoal 🙂 Espero que este breve tutorial tenha ajudado a entender um pouco sobre como enviar mensagens de Push com o Firebase. Vale lembrar que o Google ainda vai dar suporte para o GCM um bom tempo, até porque existem muitas aplicações que estão utilizando este serviço em produção. Mas para novos apps, recomenda-se utilizar o Firebase.

Uma dica é usar o Firebase também para aplicativos iOS, pois o serviço de Push do Google é bem mais simples que o serviço da APNS (Apple Push Notification Service) da Apple.

Se você gostou, confira a 2ª parte do tutorial aqui.

Abs

 

Paginação com web services

Posted by rlecheta on junho 27, 2016
Tutorial, Web Services / 2 Comments

Olá pessoal

Sempre recebo perguntas de como fazer paginação ao fazer um web service, pois no meu livro de Web Services os exemplos sempre retornam todos os registros do banco de dados.

rest

Por exemplo, neste web service é retornado todos os carros do servidor:

http://livrowebservices.com.br/rest/carros

E para quem leu o livro de REST, sabe que podemos buscar os carros por tipo, dentre outras buscas, exemplo:

http://livrowebservices.com.br/rest/carros/tipo/classicos

http://livrowebservices.com.br/rest/carros/tipo/esportivos

http://livrowebservices.com.br/rest/carros/tipo/luxo

Mas e se existir 1 milhão de registros no banco de dados? Neste caso o recomendado é retornar os registros paginados, por exemplo de 10 em 10, ou 20 em 20, conforme a necessidade.

Fazer isso é simples, então se você tem o código-fonte do projeto RESTful dos carros, é só fazer 2 pequenas alterações:

Na classe CarrosResource, tem um exemplo do tipo GET configurado, o qual retorna todos os carros no formato JSON, lembra-se?

@GET
public List<Carro> get() {
	List<Carro> carros = carroService.getCarros();
	return carros;
}

O que podemos fazer é adicionar 2 parâmetros. Um deles para indicar a página que você está solicitando e outro para indicar a quantidade de registros que devem ser retornados.

Exemplo:

@GET
@Path("/page/{page}/max/{max}")
public List<Carro> get(@PathParam("page") int page,@PathParam("max") int max) {
	List<Carro> carros = carroService.getCarros(page,max);
	return carros;
}

Isso vai criar os seguintes links do web service:

1ª página: http://livrowebservices.com.br/rest/carros/page/0/max/5

2ª página: http://livrowebservices.com.br/rest/carros/page/1/max/5

3ª página: http://livrowebservices.com.br/rest/carros/page/2/max/5

Veja que a 1ª página começa em zero (0) e neste exemplo solicitei que o servidor retorne sempre 5 carros.

E por aí vai…

Para o exemplo compilar, crie o seguinte método na classe CarroDAO.

public List<Carro> getCarros(int page, int max) {
	Query q = getSession().createQuery("from Carro");
	setPage(q, page, max);
	List<Carro> carros = q.list();
	return carros;
}

O framework Hibernate que estudamos no livro nos ajuda a fazer a paginação. Eu gosto de criar um método setPage(…) como esse:

protected void setPage(Query q, int page, int max) {
	// Paginação
	int firstResult = 0;
	if (page != 0) {
		firstResult = page * max;
	}
	q.setFirstResult(firstResult);
	q.setMaxResults(max);
}

Bom é isso 🙂 Se alguém tiver alguma dúvida avisa, pois o conceito é bem simples.

Com web services paginados, o correto seria alterar os aplicativos mobile para buscar sempre de 10 em 10 registros, por exemplo. Oas isso fica para uma próxima vez 🙂

abraço

 

github 5ed Livro Android atualizado com PreferenceFragmentCompat

Posted by rlecheta on maio 22, 2016
Android, Livro Android / No Comments

Olá pessoal,

Postei no forum dos livros uma explicação sobre o PreferenceFragmentCompat, e atualizei o git do livro com exemplos.

Mais detalhes aqui.

Grupo de discussão para os Livros

Posted by rlecheta on maio 04, 2016
Livros, Notícias / No Comments

Olá pessoal,

Como recebo muitos emails, mensagens no facebook, comentário aqui no blog, etc… criei um grupo de discussão para tirar dúvidas sobre meus livros. Peço que perguntem qualquer coisa lá para centralizar as respostas.

https://groups.google.com/forum/#!forum/livros-lecheta

O grupo vai ajudar a responder melhor a dúvida de todos, pois muitas vezes respondo as mesmas perguntas…

Não vou mais responder dúvidas em outro canal, obrigado 🙂

Livro Android Essencial

Posted by rlecheta on março 15, 2016
Android, Livro Android, Livros / 13 Comments

Olá pessoal,

Foi lançado meu livro Android Essencial  :-).

Esse post é para explicar meu objetivo ao escrevê-lo e qual a diferença com o Livro Android 5ª  edição “a bíblia”.

Android Essencial (384 páginas) é um resumo do livro Google Android, 5ª edição (1.072 páginas).

“Para quem tem o Google Android 5ª edição, não precisa ler esse. Como eu falei o essencial é um resumo da 5ª edição.”

capa_android_essencial

Para começar a explicação, vamos ler o texto que está na capa do livro:

O Android é o sistema operacional móvel mais utilizado no mundo, e o objetivo deste livro é apresentar ao leitor os conceitos essenciais do desenvolvimento de aplicativos para Android, por meio de uma explicação simples e prática.

Android Essencial é um resumo do livro Google Android, 5ª edição, com o objetivo de prepará-lo rapidamente para o mercado. É para leitores que não querem rodeios e precisam aprender logo, seja por questões de estudos ou por uma necessidade de trabalho.

Este livro utiliza o Android Studio, é focado nas boas práticas de interface do Google e do Material Design, e oferece uma abordagem prática direcionada ao desenvolvimento de aplicativos. Durante a leitura você vai desenvolver um aplicativo completo, com boa usabilidade de interface e com acesso a web services e banco de dados, além de utilizar recursos de multimídia e mapas.

O livro também apresenta capítulos resumidos dos principais conceitos da arquitetura do Android, como notificações, intents, broadcast receivers, services, alarmes, mensagens de push, câmera e fotos.

Depois de ler o livro Android Essencial você terá um bom entendimento sobre o desenvolvimento de aplicativos para Android.

O que me levou a escrever o livro foram várias coisas:

  1. Eu precisava de uma forma rápida de treinar novos integrantes da Livetouch. Penso que o livro Google Android 5ª edição precisa ser lido por alguém que queira apavorar no desenvolvimento de apps, mas por ter + de 1.000 páginas ele não era um curso relâmpago, como muitas vezes tenho necessidade. O livro Android Essencial surgiu para isso, penso em usá-lo para treinar rapidamente os novos recursos da empresa, assim como usar em cursos pessoais, cursos na Novatec, e até como guia na Pós Graduação de Dispositivos Móveis e Computação em Nuvem que ministro na Universidade Positivo.
  2. Por ser um resumo do Google Android 5ª edição, o livro é essencial para aprender Android rapidamente, pelo menos o básico e pode ser usado como guia em cursos. Também foi uma ideia da editora Novatec.
  3. O livro Android Essencial tem um custo mais baixo, então também tivemos a ideia de oferecer uma opção de custo mais acessível para quem não pode comprar a 5ª edição.
  4. Outro fator que me levou a escrever, foi ter identificado que muitas pessoas, inclusive devs bons de Android não chegam a ler o livro 5ª edição inteiro. Eu fiz capítulos avançados sobre Threads e várias coisas que percebo que muitos devs não chegam a ler. O mesmo acontece com capítulos como Bluetooth, Gestos, Wear, etc.. É o tipo de assunto que o leitor pode ler ou pesquisar quando ele tiver a necessidade (quando for usar na prática).. mas muitas vezes o que acontece é que o leitor precisa aprender o essencial que é: Instalar Android Studio, criar um projeto e executar no Android/Emulador, criar interfaces (formulários, listas), web services, banco de dados, vídeo, mapa, e é isso!
  5. Sabendo esse básico do desenvolvimento já é suficiente para muitos devs, principalmente aqueles que não vão a fundo. Esse é o caso daquela estudante que precisa fazer o TCC correndo, vai estudar Android rápido e talvez nunca mais.

Creio que é isso pessoal.

Em minha opinião, se você quer um livro de custo mais acessível e quer aprender o básico rápido (android studio, criar telas, listas, web services, banco de dados, mapas, GPS, vídeo, foto, push, etc) e dar um tapa nos conceitos principais (intents, services, receiver, notifications), esse livro é um bom ponto de partida.

Depois de ler o livro Android Essencial você terá um bom entendimento sobre o desenvolvimento de aplicativos para Android, e então você decidirá o caminho a seguir!

Se seu objetivo foi aprender o “essencial” e se sentir satisfeito com o conteúdo, ótimo :-). Penso que vai ser o caso de muitos estudantes que precisam fazer o TCC :-). Mas se você for um desenvolvedor que vai trabalhar com Android todos os dias, recomendo ir mais a fundo. Tendo essa necessidade, você poderá complementar a leitura com o livro Google Android 5ª edição, ou a própria documentação oficial.

Lembre-se: O livro Android Essencial (384 páginas) é um resumo do Google Android 5ª edição (1.072 páginas).

Mudanças no iOS 9 e Swift 2.0

Posted by rlecheta on janeiro 18, 2016
iOS, Livros / 11 Comments

Olá pessoal

Este post visa esclarecer algumas coisas que mudaram no Xcode 7 e Swift 2.0.

O objetivo é ajudar os leitores do meu livro de iOS 3a edição que foi feito para iOS 8, Xcode 6 e Swift 1.1, na época.

Com a atualização do iOS 9 e Swift 2, a Apple mudou algumas coisas na sintaxe da linguagem e na assinatura de alguns métodos. Este post visa explicar alguns destes problemas, espero que ajude 🙂

Para deixar claro:

  • livro iphone 3 edição: iOS 8, Xcode 6 e Swift 1.1
  • lirvo iphone 4 edição (quando for lançado): iOS 9, Xcode 7 e Swift 2

Vamos ser rápidos, então bora pro código:

1) Wizard de migração

Se você abrir um projeto no Xcode que utiliza Swift 1, verá este wizard de migração. Recomendo clicar em Convert e ver o resultado. A função print() é uma das mudanças simples que você pode automatizar com este wizard.

Screen Shot 2016-01-10 at 9.04.13 PM

2) Sobrescrevendo o construtor.

A notação a seguir para sobrescrever o construtor:

override init() { … }

Mudou para (não precisa colocar a palavra override):

init() { … }

O construtor que recebe NSCode utiliza a sintaxe init? (failable initializer)

init?(coder aDecoder: NSCoder)

Portanto, caso for sobrescrevê-lo, não esqueça de colocar a ?:

required init?(coder aDecoder: NSCoder) {  super.init(coder: aDecoder) }

3) Função print() virou println().

Essa é simples, é só alterar no código e boa.

4) as, as! e as?

No swift 1.0 somente existia a palavra chave as para fazer cast. Mas no Swift 2.0 foram criadas mais algumas opções.

·       as: utilizado para fazer upcasting (cast para o tipo superior);

·       as?: faz o cast (downcasting) e retorna um tipo opcional ?, portanto você deve utilizar esta maneira se possui alguma dúvida do tipo do objeto. Se o objeto não é do tipo correto é retornado nil.

·       as!: faz o cast (downcasting) quando você tem certeza que é o tipo correto, e já faz o unwrapping da variável. Mas tome cuidado, pois se não for o tipo correto o aplicativo vai travar (crash);

Exemplo de código que mostra o cast com as!:

Screen Shot 2016-01-10 at 4.13.49 PMNeste código, altere a sintaxe do cast de as! para as? para ver a diferença. O compilador vai acusar erro ao utilizar a variável c pois ela é do tipo opcional. Neste caso teria que inicializá-la ou utilizar a sintaxe c!.nome. Ou ainda, se preferir a sintaxe if let como você aprendeu no livro.

Screen Shot 2016-01-10 at 4.13.58 PM

5) var vs let

Você já sabe que var é uma variável e let uma constante. No Xcode 7, o compilador mostra um warning caso você utilize var em uma variável que nunca é alterada, pois nestes casos é recomendado usar let.

Um exemplo deste warning, é a figura abaixo:

Variable ‘url’ was never mutated; consider changing to ‘let’ constant

Screen Shot 2016-01-10 at 11.39.26 AMPara corrigir, troque por let. @Dica, faça isso pelo assistente de código.

Screen Shot 2016-01-10 at 11.39.34 AM

6) Mudança na assinatura dos métodos de vários protocolos.

No cap 8 sobre WebView implementamos logo no início alguns métodos do protocolo UIWebViewDelegate.

A Apple já mudou algumas vezes a assinatura dos métodos. Antes não tinha o ! antes dos parâmetros, depois colocaram o ! e agora resolveram tirar de novo. Mas o compilador te ajuda nestes casos e ele avisa do erro.

Screen Shot 2016-01-10 at 11.32.24 AM

Tirando o ! do parâmetro UIWebView resolve o problema. O mesmo acontece com outros protocolos, como o UITableViewDegate, etc.

Screen Shot 2016-01-10 at 11.32.39 AM

7) HTTP vs HTTPs

A partir do iOS 9, requisições HTTP (mesmo com WebView) são bloqueadas pois não são seguras. A Apple recomenda o uso de HTTPS.

No app dos Carros que mostro no livro, o WebView pode falhar e mostrar o seguinte erro:

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app’s Info.plist file.

Para solucionar este problema no iOS 9, abra o arquivo Info.plist e adicione o item App Transport Security Settings. Dentro deste item adicione um sub-item chamado Allow Arbitrary Loads com o valor YES.

Feito isso a conexão HTTP será permitida e o exemplo com WebView que mostrei no app dos carros vai funcionar. Lembrando que isso é necessário para iOS >=9 .

Screen Shot 2016-01-10 at 5.31.16 PM

8) Método supportedInterfaceOrientations()

Controle de telas na vertical e horizontal foi o assunto do capítulo 10. Na revisão do livro encontrei essa mudança.

Até o iOS 8 o método supportedInterfaceOrientations() utilizado para controlar a orientação (vertical/horizontal) da tela do view controller retornava um Int.

Screen Shot 2016-01-10 at 8.44.29 PM

Agora a função ficou com uma assinatura mais esperta, e retorna direto alguma das constantes da estrutura UIInterfaceOrientationMask:


Screen Shot 2016-01-10 at 8.44.18 PM

9) UILabel, a propriedade text e String vs NString

A propriedade text da classe UILabel é do tipo String.

Screen Shot 2016-01-10 at 9.23.57 PM

No capítulo 10 onde estudamos o acelerômetro, tinha um código que formatava a String utilizando o construtor de NSString.

Para o código compilar foi necessário fazer o cast para String, com a notação (as String).

Isso é preciso pois o NSString é uma classe do Obj-C e a classe String é do Swift. Mas como a classe NSString contém mais métodos que a String, muitas vezes ainda utilizamos elas para fazer algumas tarefas como essa (até você descobrir outro jeito rsrs):

Screen Shot 2016-01-10 at 9.25.20 PM

10) Projeto sem Launch Screen.

Ao revistar alguns projetos para iOS 9, me deparei com algumas telas com a nav bar e tab bar pretas assim:

Screen Shot 2016-01-10 at 9.28.49 PM

Isso acontece porque o projeto não possui um arquivo de Launch Screen. Para solucionar crie o arquivo com o wizard > iOS > User Interface > Launch Screen e associe este arquivo nas propriedades do projeto em Target.

Por mais bizarro que isso pode ser, faça isso que vai resolver :-). Veja resultado abaixo:

Screen Shot 2016-01-10 at 9.29.38 PM

11) Assinatura dos métodos do protocolo NSXMLParserDelegate

No capítulo 11 sobre XML/JSON, teve outra alteração, referente a sintaxe dos métodos do protocolo NSXMLParserDelegate.

Recomendo ver os métodos aqui:

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/NSXMLParserDelegate_Protocol/

Mas basicamente a Apple trocou de ! para ? (opcionais) alguns parâmetros. Então quando o compilador reclamar no Xcode é só trocar. Qualquer dúvida avise.

12) Obter a quantidade de elementos de um array.

No Swift 1.1 tinha a estranha função countElements(array) que agora virou array.count, algo mais comum em linguagens de programação.

Veja como ficou a sintaxe:

//Array<Carro>: array de carros…
let carros = parserXML_SAX(data)

// Swift 1
var count = countElements(carros)

// Swift 2
let count = carros.count

13) Idem com a classe String.

Já que falamos de como obter a quantidade de elementos, com a classe String também mudou.

Antes era countElements(string), depois virou count(string) e agora é string.characters.count.

Basicamente você acessa o array de caracteres dentro da classe String e obtem a quantidade por meio do array.

14) Try/Catch

Na explicação de parser de XML com DOM a classe SMXMLDocument era usada assim:

let document = SMXMLDocument(data: data, error:nil)

O 2º parâmetro era do tipo NSError, que inclusive nem usei no código rsrs. Isso era usado para obter o erro do método que faz o parser .

Mas no Swift 2 apareceu o try/catch e o tratamento de exceções, então o construtor deste método mudou e agora ele lança uma exceção. O Legal é usar a sintaxe try? que abrevia o try/cach e tenta executar o código que pode lançar uma exceção. Se funcionar ele retorna uma variável opcional, senão retorna nulo.

O código atualizado é assim:

let document = try? SMXMLDocument(data: data)
if(document == nil) {
print(“Erro ao ler os dados”);
return carros
}
// Continue usando o document aqui…

Como o retorno é uma variável opcional ‘?’, depois temos que fazer o unwrapping ou usar o document!. Para maiores detalhes veja no livro 🙂

15) Parser de JSON

Ainda no capítulo sobre XML/JSON, o jeito de fazer o parser de JSON com a classe NSJSONSerialization também mudou. Na verdade é porque novamente antes usava o NSError como parâmetro para obter o erro no parser, e agora é usado as exceções com try/catch.

Novamente gosto de usar o try?. Podemos até usar o if let para inicializar o dicionário do json.

Segue código atualizado:

// Faz a leitura do JSON, converte para dictionary
let dictOp = try? NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
if let dict = dictOp {
// usar o dicionário para ler os dados do carro aqui…
} else {
// erro
}

16) Threads e Web Services

Neste capítulo não encontrei grandes mudanças, então é só para constar.

Tem pequenas coisas de ! e ? na assinatura do método dataTaskWithURLpara variar, mas nada que você não vai conseguir resolver.

17) Estilo do botão na nav bar.

No capítulo de web services, foi adicionado um botão “Atualizar” na navigation bar. Esse botão faz a atualização da lista de carros. No iOS9 o estilo Bordered ficou deprecated. Agora recomenda-se utilizar o estilo Plain.

let btAtualizar = UIBarButtonItem(title: “Atualizar”, style: UIBarButtonItemStyle.Plain,target: self, action: “atualizar”)

self.navigationItem.rightBarButtonItem = btAtualizar

18) Conversão de String para Int

No capítulo de persistência de dados, a classe Prefs tem uma pequena mudança.

let valorInt = valorString.toInt()

Isso mudou para:

let valorInt = Int(valorString)

19) SQLite

Na parte de SQLite teve poucas mudanças. Nada que trocar uns ! por ? e fazer cast com as! não resolva.

Se alguém tiver problemas é só me informar aqui neste post.

20) Mapas

Na parte de mapas não teve grandes mudanças.

Teve esse construtor do UIButton que mudou de:

let btPin = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIView

Para:

let btPin = UIButton(type: UIButtonType.DetailDisclosure) as UIView

No exemplo de Geocoding a assinatura do método mudou. Para auxiliar, veja trecho do código atualizado mostrado no livro.

Screen Shot 2016-01-13 at 2.00.58 PM

21) Video

No capítulo de multimídia, a classe VideoUtil teve um problema no iOS9, pois a classe MPMoviePlayerController ficou deprecated. No iOS9, A Apple recomenda usar a AVPlayerViewController.

Para ajudar o pessoal que comprou a 3ª edição, segue classe atualizada 😉

VideoUtil.swift

Como no iOS 9 utiliza-se a classe AVPlayerItem, devemos utilizar as suas constantes de notificação para monitorar os eventos do player de vídeo. No exemplo que mostro para interceptar o evento do fim do vídeo, basta trocar a constante por esta:

NSNotificationCenter.defaultCenter().addObserver(self, selector: “videoFim”,name:”AVPlayerItemDidPlayToEndTimeNotification“, object: nil)

22) Áudio

Novamente devido ao novo tratamento de exceções e o uso de try/catch, temos algumas mudanças em outras classes, pois não é mais usado aquele NSError como parâmetro.

Um exemplo desta alteração, é no exemplo que mostra como tocar e gravar músicas com a  classe AVAudioPlayer.

do {
// Inicializa o player com a URL do arquivo
self.player = try AVAudioPlayer(contentsOfURL: url)
} catch let error as NSError {
self.player = nil
print(“Error \(error)”)
return
}

23) Câmera e galeria de fotos

Na parte da câmera e tirar fotos não teve mudanças.

Mas no exemplo que mostra como acessar a galeria de fotos, os métodos do protocolo UIImagePickerControllerDelegate mudaram um pouco. Segue trecho atualizado:

// Delegate UINavigationControllerDelegate

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

print(“didFinishPickingMediaWithInfo”)

let image = info[UIImagePickerControllerOriginalImage] as! UIImage

self.imageView.image = image

self.imagePicker.dismissViewControllerAnimated(true, completion:nil)

}

func imagePickerControllerDidCancel(picker: UIImagePickerController) {

print(“imagePickerControllerDidCancel”)

self.imagePicker.dismissViewControllerAnimated(true, completion:nil)

}

24) IPad e Popover

No iOS9 mudou a forma de mostrar Popovers.

Para facilitar, criei a classe PopoverUtil.swif.

Para usá-la é simples assim:

PopoverUtil.show(self, viewController: vc, source: view, width: 400, height: 800)

25) Tratamento de eventos de Touch

No capítulos sobre Quartz e Views customizadas, foi mostrado como tratar o evento de touch. Como a assinatura do método mudou, segue aqui o código atualizado:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

if let touch = touches.first {

// Lê a posicão do touch

let point = touch.locationInView(self)

self.x = Int(point.x)

self.y = Int(point.y)

self.setNeedsDisplay()

}

super.touchesBegan(touches , withEvent:event)

}

É isso pessoal 🙂

Espero que este post tenha ajudado os leitores do livro do meu livro de iOS 3a edição. Com estas explicações fica mais fácil migrar para o iOS 9.

 

 

Tags: