➙ Conteúdo completo, texto e vídeo, em: https://www.thiengo.com.br/como-impulsionar-o-app-android-compartilhamento-nativo
Neste conjunto de slides vamos estudar como compartilhar conteúdos em aplicativos Android utilizando APIs nativas, mais precisamente, utilizando Intent e IntentFilter.
➙ Para receber o conteúdo do blog em primeira mão, assine a lista de emails em: http://www.thiengo.com.br
Abraço.
▶ Treinamento oficial:
➙ Prototipagem Profissional de Aplicativos Android:
↳ https://www.udemy.com/android-prototipagem-profissional-de-aplicativos/persist_locale&locale=pt_BR
▶ Livros oficiais:
➙ Desenvolvedor Kotlin Android - Bibliotecas para o dia a dia:
↳ https://www.thiengo.com.br/livro-desenvolvedor-kotlin-android
➙ Receitas Para Desenvolvedores Android:
↳ https://www.thiengo.com.br/livro-receitas-para-desenvolvedores-android
➙ Refatorando Para Programas Limpos:
↳ https://www.thiengo.com.br/livro-refatorando-para-programas-limpos
▶ Redes:
➙ Udemy: https://www.udemy.com/user/vinicius-thiengo/?persist_locale&locale=pt_BR
➙ YouTube: https://www.youtube.com/user/thiengoCalopsita
➙ Facebook: https://www.facebook.com/thiengoCalopsita
➙ LinkedIn: https://www.linkedin.com/in/vin%C3%ADcius-thiengo-5179b180/
➙ GitHub: https://github.com/viniciusthiengo
➙ Twitter: https://twitter.com/thiengoCalops
➙ Google Plus: https://plus.google.com/+ThiengoCalopsita
▶ Blog App:
➙ https://play.google.com/store/apps/details?id=br.thiengocalopsita&hl=pt_BR
2. Compartilhamento via API nativa
Quando falamos de compartilhamento é comum pensar em redes sociais, mas na
verdade até mesmo o envio de dados de uma atividade a outra, no mesmo
aplicativo, é uma forma de compartilhamento de conteúdo.
Felizmente o Android tem as intenções, ou Intents, que nos permitem a fácil
comunicação entre atividades / aplicativos sem, principalmente, a dependência de
APIs específicas para permitir, por exemplo, o compartilhamento de algum dado.
Com as Intents é possível compartilhar conteúdos simples, como textos, até
conteúdos complexos que envolvem também binários (imagem, vídeo, áudio,
arquivos, …).
É importante ressaltar que o compartilhamento de conteúdo depende também do
aplicativo que receberá os dados em compartilhamento, pois de acordo com a
configuração do app receptor não é possível que este seja uma opção de share.
Neste conjunto de slides nosso foco é no compartilhamento utilizando Intents em
um aplicativo emissor, em futuros conteúdos trabalharemos também como fazer
com que um aplicativo Android possa ser um receptor de conteúdos compartilhados
via Intent.
3. Conteúdo simples, não binário
Compartilhar conteúdo somente em texto é bem simples. Veja o código a seguir:
Nos conteúdos que temos no Blog sobre Intent e IntentFilter há explicações
detalhadas da importância de cada propriedade dessas classes.
Mas adianto a ti que não há com que se preocupar se você ainda não conhece a
fundo as entidades Intent e IntentFilter, isso, pois as configurações de
compartilhamento são simples e com rótulos autocomentados.
O código anterior é válido também para compartilhamento de links, domínios
públicos.
As propriedades action e type são importantes para que aplicativos receptores
possam ou não aparecer como opções de compartilhamento.
5. Verificação de segurança
É prudente colocarmos uma verificação de segurança antes da invocação de
startActivity():
Esta verificação é recomendada principalmente para compartilhamentos onde
somente aplicativos específicos são aceitos, apps definidos na propriedade
package de Intent. Em slides posteriores abordaremos a propriedade package.
6. Caixa de diálogo para a escolha de aplicativo
A Chooser Dialog aparecerá somente quando mais de um aplicativo no aparelho do
usuário for um possível alvo do conteúdo que está para ser compartilhado:
7. Em casos onde somente um aplicativo é passível para compartilhamento do
conteúdo, esse app será aberto diretamente.
É possível customizarmos a Chooser Dialog, colocando um título personalizado.
Veja o código a seguir:
O uso de createChooser() é válido para qualquer tipo de conteúdo em Intent de
compartilhamento, não somente conteúdo em texto.
11. Email
Uma das técnicas que mais utilizo em aplicativos simples que também permitem o contato com
clientes é o uso de intenções para o fácil envio de email à empresa do aplicativo. A configuração
segura para envio de email é a seguinte:
12. Não deixe de ler os comentários do código anterior para entender o porquê de cada
configuração para aplicativos de email.
Executando o projeto com o código do slide anterior, temos:
13. Como no emulador de testes somente havia um aplicativo que respondia às
configurações de email que colocamos em Intent, mais precisamente o aplicativo
Gmail, então o acionamento do botão "COMPARTILHAR POR EMAIL" fez com que
este aplicativo abrisse direto, sem uma Chooser Dialog.
No projeto de exemplo do artigo deste conjunto de slides teremos um algoritmo
para o compartilhamento de conteúdo binário e em texto via email.
14. Conteúdo binário (imagem, vídeo, áudio, ...)
interno ao app
Agora se inicia as seções de slides que provavelmente você estava aguardando,
sobre compartilhamento de conteúdos binários. Aqui utilizaremos como exemplo
binários de imagens.
A seguir o código de compartilhamento de um binário que está dentro do aplicativo,
mais precisamente dentro do folder drawable:
18. É importante lembrar da autoridade que aplicativos receptores têm em relação ao conteúdo
compartilhado com eles. Mesmo quando esses aparecem como apps passíveis de
compartilhamento é possível de acontecer a não aceitação de alguns conteúdos em Intent.
Veja a seguir o resultado da tentativa de compartilhamento, utilizando o código anterior, no
app do Gmail:
19. Por algum motivo o aplicativo do Gmail não consegue anexar binários que estão
dentro do aplicativo emissor, mesmo se o app do Gmail estiver com a permissão de
acesso a conteúdo em armazenamento externo.
Temos de entender que essa é uma limitação do aplicativo do Gmail para binários
internos ao aplicativo. Certamente deve ter algum algoritmo que permite esse
contorno, ou seja, a compartilhamento de binário interno com o app do Gmail, mas
deveria ser algo trivial como foi no caso do Google Drive app.
Note que não há a necessidade de nosso aplicativo ter acesso a permissão de
armazenamento externo para compartilhar um binário interno a ele, mas o
aplicativo receptor tem de ter essa permissão e é ele que tem de solicitar essa
permissão quando no momento do compartilhamento, algo que não ocorre com o
aplicativo do Gmail, mas é realizado com maestria pelo app do Google Drive.
20. Conteúdo binário do armazenamento externo
Para o compartilhamento de conteúdo binário externo ao aplicativo, são necessárias ainda mais
configurações extras.
A primeira é a criação de um arquivo de configuração de FileProvider, arquivo que nos permitirá
definir a área do armazenamento externo ao aplicativo que poderemos acessar para obter conteúdos
binários.
É recomendado que este arquivo de configuração esteja em /res/xml e tenha um nome
autocomentado sobre a função dele, aqui o nome será file_path.xml:
21. É possível ter inúmeros "caminhos" (diretórios) como elementos de <paths>. Não é
possível colocar como valor do atributo path a definição de um arquivo em
específico, somente diretório.
Para conhecer as outras possíveis tags filhas de <paths>, acesse a documentação
oficial em: Specifying Available Files.
Antes de colocarmos o código de configuração do FileProvider no
AndroidManifest.xml é preciso saber o que é um FileProvider. Segundo a
documentação:
FileProvider é uma subclasse especial de ContentProvider que facilita o
compartilhamento seguro de arquivos associados a um aplicativo, mesmo
arquivos externos a ele, criando uma Uri content:// para um arquivo ao invés
vez de uma Uri file:/// que tem mais limitações em compartilhamento.
Resumidamente: um objeto FileProvider vai nos permitir o compartilhamento
seguro de qualquer arquivo presente nos paths definidos em <paths> sem que o
app receptor do compartilhamento tenha as permissões de leitura e escrita no
armazenamento externo, isso, pois essas permissões são concedidas
temporariamente devido à Uri gerada ser uma Uri ContentProvider.
22. Certo, já temos o arquivo de configuração de área de acesso do FileProvider, mas e a
definição do FileProvider?
Está vem no arquivo AndroidManifest.xml como um filho direto da tag <application>:
23. Antes de partirmos para o código com a Intent de compartilhamento de binário
externo ao app, ainda é preciso colocarmos o algoritmo de solicitação de
permissão em tempo de execução.
Primeiro as permissões necessárias, em AndroidManifest.xml:
Agora a vinculação da biblioteca EasyPermissions ao projeto de teste, está será
utilizada na administração do algoritmo de solicitação de permissão em tempo de
execução. A seguir a adição da API no Gradle Nível de Aplicativo, build.gradle
(Module: app):
Então o código de solicitação de permissão na classe que conterá o algoritmo de
compartilhamento de binário via Intent:
24.
25. O método askPermissionToShareBinaryContent() é o que primeiro deve ser
invocado antes do acesso ao algoritmo de compartilhamento.
Para saber mais sobre as vantagens de uso da API EasyPermissions e ainda mais
possibilidades com ela, não deixe de acessar meu novo livro Desenvolvedor Kotlin
Android - Bibliotecas para o dia a dia onde o primeiro capítulo tem 55 páginas
dedicadas somente a está API e a um exemplo de aplicativo utilizando ela.
Com isso somente temos de colocar em onPermissionsGranted() o algoritmo de
compartilhamento de binário via Intent:
28. Seção grande, não? Mas é assim que deve ser feito quando compartilhando
conteúdo binário presente no aparelho, mas não no aplicativo.
Apesar na expressiva quantidade de código, a maior parte dele é boilerplate,
exigindo pouca lógica de negócio.
29. Conteúdo binário remoto
Também é possível compartilhar conteúdos carregados de servidores remotos.
Assuma que o código a seguir é responsável por carregar uma imagem no
ImageView do layout da atividade principal do app de testes:
30. A API Picasso é uma das melhores em termos de eficiência e eficácia para
carregamento de imagens em aplicativos Android. A adição dela ao projeto é por
meio do Gradle Nível de Aplicativo, build.gradle (Module: app):
Em meu novo livro Desenvolvedor Kotlin Android - Bibliotecas para o dia a dia o
segundo capítulo é inteiramente dedicado a essa API, 87 páginas, mostrando ainda
mais funcionalidades possíveis com a Picasso Android.
Depois que a imagem já foi carregada na View alvo é possível acessa-la como um
Bitmap, mais precisamente como um BitmapDrawable que é um subtipo de
Bitmap:
31. Com um Bitmap em "mãos" o que precisamos é de um algoritmo que consiga
retornar uma Uri partindo do Bitmap, algoritmo como o a seguir:
Apesar de contentProvider também está sendo utilizado, para compartilhamento
de conteúdo remoto não é necessária a configuração de um FileProvider, como
fizemos na seção anterior. Mas aqui também são exigidas as permissões de
acesso ao armazenamento externo.
Vou abreviar o algoritmo e assim não mostrarei o código de solicitação de
permissão em tempo de execução, este você pode obter na seção anterior com a
API EasyPermissions.
32. Assuma que as permissões de armazenamento já foram concedidas. Assim temos o
código final para compartilhamento de um binário de uma fonte remota ao aparelho:
33. Executando o projeto de testes com o algoritmo anterior, temos:
O aplicativo que vai receber o binário em compartilhamento não precisa de
permissão de armazenamento, somente o app emissor da Intent.
Curiosidade: um nome aleatório é utilizado como rótulo do binário em
compartilhamento.
34. Vários conteúdos binários
As regras de compartilhamento de vários conteúdos binários são as mesmas já discutidas em
seções anteriores, ou seja, o algoritmo utilizado para cada conteúdo em compartilhamento
depende da origem dele.
No código a seguir, para manter a simplicidade, vamos ao compartilhamento de dois conteúdos
binários internos ao aplicativo, algo que dispensa a necessidade de qualquer código de
solicitação de permissão em tempo de execução:
Note o tipo da ação, Intent.ACTION_SEND_MULTIPLE, e como as Uris têm de ser
fornecidas em um ArrayList.
36. Diferentes tipos de dados
É possível compartilhar diferentes tipos de dados em um só Intent. O aplicativo
receptor é que deverá tratar corretamente cada tipo em compartilhamento.
Caso haja também binários no compartilhamento, todas as regras de negócio
discutidas em seções anteriores deverão ser levadas em conta de acordo com a
origem de cada binário.
No código do próximo slide estaremos compartilhando, junto com um texto, um
binário remoto, logo, assuma que as permissões de armazenamento foram
concedidas e que o método getImageUri() é o mesmo utilizado na seção de slides
"Conteúdo binário remoto”.
39. Conteúdos para aplicativos específicos
Caso seu aplicativo possa compartilhar determinados conteúdos somente com algum outro app,
é possível restringir esse "algum outro app" colocando o nome de pacote dele no Intent de
compartilhamento, isso utilizando o método setPackage().
No código a seguir somente o Gmail pode receber o conteúdo compartilhado:
O bloco condicional para verificação de presença de aplicativo compatível com o conteúdo em
compartilhamento é muito importante quando um package é fornecido, pois é possível que o
aplicativo não esteja instalado no aparelho.
43. Por que o conteúdo limitado sobre aplicativos
sociais?
Na verdade tudo que foi apresentado até aqui é passível de ser utilizado em
qualquer aplicativo social, porém alguns apps de redes sociais apresentam
limitações.
O aplicativo do Facebook, por exemplo, tem problemas com conteúdos em
compartilhamento que contém binários e não binários. Como solução o Facebook
tem uma API nativa somente para compartilhamento via aplicativos Android.
Na seção anterior, onde utilizamos como exemplo pacotes de aplicativos populares,
tem o modelo de algoritmo que permite também o compartilhamento somente com
apps sociais, caso seja necessária essa restrição.
De qualquer forma, havendo a possibilidade de compartilhamento de binários,
busque primeiro pela API nativa do app alvo como receptor do compartilhamento.
44. Pontos negativos
• O compartilhamento de conteúdo binário no armazenamento local não é
nada trivial, exigindo o entendimento de entidades, FilePovider, que
provavelmente não voltaremos a utilizar;
• Mesmo que a configuração de compartilhamento via Intent esteja bem
construída, ainda dependemos da qualidade do algoritmo do aplicativo
receptor.
45. Pontos positivos
• Comparando o código de compartilhamento via APIs nativas com o código de
APIs de terceiros, o de APIs nativas é ainda a melhor opção devido à
simplicidade quando não há, por exemplo, um binário, no armazenamento
local, a ser compartilhado;
• A fácil possiblidade de definirmos os aplicativos que podem receber o
conteúdo em compartilhamento faz com que muito código extra de API
específica seja evitado no projeto.
46. Conclusão
Provavelmente você é um daqueles desenvolvedores Android que quer ver o seu
aplicativo sendo utilizado pela massa de usuários.
Um dos algoritmos que podem ajudar isso acontecer, a adoção da massa, é o
algoritmo de compartilhamento.
Adicionar o compartilhamento via APIs nativas é, até o momento, a melhor opção,
além de não exigir a adição de referências extras que inflariam ainda mais o
tamanho final do aplicativo.
47. Fontes
Conteúdo completo, em texto e em vídeo, no link a seguir:
• Como Impulsionar o App Android - Compartilhamento Nativo.
Fontes:
• Sending simple data to other apps;
• Sharing Content with Intents;
• FileProvider;
• Send Email Intent - Resposta de thanhbinh84 e Community♦;
• Get the URI of an image stored in drawable - Resposta de Michael;
• How to get the Uri of a image stored on the SDCARD? - Resposta de SeyedPooya Soofbaf;
• How to share text to WhatsApp from my app? - Resposta de Sonny Ng e vault;
• How to share text to WhatsApp from my app? - Resposta de Jitendra Kumar. Balla e Paolo Forgia;
• Get Bitmap from ImageView in Android L - Resposta de Pankaj Arora e Bipin Bharti;
• How to get a Uri object from Bitmap - Resposta de Ajay e blueware;
• How to filter specific apps for ACTION_SEND intent (and set a different text for each app) -
Resposta de dacoinminster e Pragati Singh.
48. Para estudo
• Treinamento oficial:
• Prototipagem Profissional de Aplicativos Android.
• Meus livros:
• Desenvolvedor Kotlin Android - Bibliotecas para o dia a dia;
• Receitas Para Desenvolvedores Android;
• Refatorando Para Programas Limpos.
• Redes:
• Udemy;
• YouTube;
• Facebook;
• LinkedIn;
• GitHub;
• Twitter;
• Google Plus.
• Blog App.
49. Como Impulsionar o App Android -
Compartilhamento Nativo
thiengo.com.br
Vinícius Thiengo
thiengocalopsita@gmail.com