Notificação de Engajamento Pelo Firebase Console - Parte 12
(8134) (25)
CategoriasAndroid, Design, Protótipo
AutorVinícius Thiengo
Vídeo aulas186
Tempo15 horas
ExercíciosSim
CertificadoSim
CategoriaEngenharia de Software
Autor(es)Vaughn Vernon
EditoraAlta Books
Edição1ª
Ano2024
Páginas160
Opa, blz?
Nesse post damos continuidade a série Firebase Android, dessa vez mostrando como enviar notificações push message via Firebase Notification Console.
Apesar de esse ser o post 12 da série Firebase Android, ao menos a parte de notificação foi desvinculada da APP de Chat, pois ainda não é o momento de colocarmos notificação nela, primeiro vamos ter de estrutura a base de dados.
Entenda que foi utilizado o termo Engajamento, pois um dos principais motivos para fazer uso da notificação via Firebase Console é com o objetivo de os usuários da APP voltarem a se engajar nela.
Com isso podemos prosseguir com o software de exemplo.
Crie um projeto com o nome FirebaseNotification. Utilize as configurações padrões do Android Studio para um novo projeto. Somente na escolha da Activity que você deve utilizar uma BaseActivity para seguir o exemplo na integra.
Logo depois configure o Firebase em seu novo projeto, como realizado aqui: Add Firebase To Your Android Project
Depois da configuração nosso primeiro passo é configurar o gradle do projeto, mais especificamente o gradle app level, build.gradle (Module: app), para que ele possa trabalhar com notificações:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:design:23.4.0'
compile 'com.google.firebase:firebase-messaging:9.0.2' /* daqui para baixo */
compile 'org.greenrobot:eventbus:3.0.0'
}
EventBus vai ser utilizado?
Isso mesmo, no decorrer do post você vai entender.
Agora podemos ir ao layout, começando pelo activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="br.com.thiengo.firebasenotification.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
</android.support.design.widget.CoordinatorLayout>
E então o content_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
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"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="br.com.thiengo.firebasenotification.MainActivity"
tools:showIn="@layout/activity_main"
android:orientation="vertical">
<TextView
android:textSize="20sp"
android:gravity="center"
android:id="@+id/id_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""/>
<TextView
android:textSize="20sp"
android:id="@+id/id_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""/>
<View
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:background="#888"
android:layout_width="match_parent"
android:layout_height="0.8dp"/>
<TextView
android:textSize="20sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Topics"/>
<CheckBox
android:textSize="20sp"
android:id="@+id/id_chk_soccer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Futebol"/>
<CheckBox
android:textSize="20sp"
android:id="@+id/id_chk_basketball"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Basquete"/>
<CheckBox
android:textSize="20sp"
android:id="@+id/id_chk_volley"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Volei"/>
<CheckBox
android:textSize="20sp"
android:id="@+id/id_chk_swimming"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Natação"/>
<CheckBox
android:textSize="20sp"
android:id="@+id/id_chk_news"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Notícias gerais"/>
<View
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
android:background="#888"
android:layout_width="match_parent"
android:layout_height="0.8dp"/>
<TextView
android:textSize="20sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Unique token id"/>
<TextView
android:textSize="20sp"
android:id="@+id/id_token"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""/>
</LinearLayout>
Esse layout vai permitir que o usuário defina os tópicos que ele quer ou não participar, além de apresentar a última mensagem enviada do Firebase Notification Console e também o token único do usuário.
Token único?
Sim, nesse post vamos falar mais sobre esse token, por enquanto vamo voltar ao projeto e ir colocando as partes já definidas sem a utilização do Firebase Notification.
Nosso próximo passo é definir o MainActivity. Começando com as variáveis de instância e o método onCreate():
public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener {
private TextView tvTitle;
private TextView tvContent;
private TextView tvToken;
private int[] checkBoxIds = {
R.id.id_chk_soccer,
R.id.id_chk_basketball,
R.id.id_chk_volley,
R.id.id_chk_swimming,
R.id.id_chk_news
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initViews();
}
...
}
Note que temos um array de IDs. Esse array é necessário para que possamos colocar algumas configurações nas Views de Checkbox que estão em nosso layout. Com os IDs em array, somente um loop será o suficiente para a configuração de cada um dos Checkboxes. No código de configuração, initCheckboxes(), ficará mais claro o porquê de utilizarmos um array de IDs.
Continuando com o código, vamos colocar os métodos de inicialização das views:
private void initViews(){
tvTitle = (TextView) findViewById(R.id.id_title);
tvContent = (TextView) findViewById(R.id.id_content);
tvToken = (TextView) findViewById(R.id.id_token);
initCheckBoxes();
}
private void initCheckBoxes(){
for( int id : checkBoxIds ){
retrieveSPCheckboxValue( id );
setOnCheckedChangeListener( id );
}
}
private void setOnCheckedChangeListener( int viewId ){
((CheckBox) findViewById( viewId )).setOnCheckedChangeListener(this);
}
private void retrieveSPCheckboxValue( int id ){
CheckBox checkBox = (CheckBox) findViewById(id);
SharedPreferences sp = getSharedPreferences("sp", MODE_PRIVATE);
boolean value = sp.getBoolean( String.valueOf( id ), false );
checkBox.setChecked( value );
}
private void setSPCheckboxValue( int id, boolean value ){
SharedPreferences sp = getSharedPreferences("sp", MODE_PRIVATE);
SharedPreferences.Editor edit = sp.edit();
edit.putBoolean( String.valueOf( id ), value );
edit.apply();
}
O método retrieveSPCheckboxValue() é responsável por acessar o SharedPreferences e então obter o valor real daquele Checkbox em teste, de acordo com a última escolha do usuário (registrado ou não no tópico). Com isso conseguimos manter o Checkbox sempre com o valor que o usuário escolheu sem precisar de utilizar SQLite, Realm ou Firebase database.
Veja que o ID do Checkbox no layout é a chave de acesso ao valor dele no SharedPreferences, dessa forma não precisamos ficar criando em código uma chave para cada Checkbox, tendo em mente que o ID utilizado é único e não muda.
O método setSPCheckboxValue() é responsável por colocar o novo valor do Checkbox em teste no SharedPreferences. Esse método, diferente do retrieveSPCheckboxValue(), é utilizado no listener de valor alterado no Checkbox, que vamos definir logo abaixo:
public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener {
...
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
String topic = getTopic( buttonView );
if( isChecked ){
displayMessage( "Vc foi inscrito no tópico: "+topic );
}
else{
displayMessage( "Vc foi removido do tópico: "+topic );
}
setSPCheckboxValue( buttonView.getId(), isChecked );
}
private String getTopic( CompoundButton buttonView ){
switch( buttonView.getId() ){
case R.id.id_chk_soccer:
return "soccer";
case R.id.id_chk_basketball:
return "basketball";
case R.id.id_chk_volley:
return "volley";
case R.id.id_chk_swimming:
return "swimming";
default:
return "news";
}
}
private void displayMessage( String message ){
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
Implementando a Interface OnCheckedChangeListener temos o método onCheckedChanged() que além de alterar o valor do Checkbox no SharedPreferences apresenta uma mensagem ao usuário sobre como ele está em relação ao tópico escolhido, registrado ou não.
O método getTopic() tem os rótulos de tópicos que vamos estar utilizando no Firebase Console, para enviar mensagens somente para usuários que assinam determinados tópicos.
Nosso próximo passo é criarmos uma notificação no Firebase Console para ver a reação da APP assim que a notification é ativada pelo usuário.
Acesse o painel do Firebase e logo no menu esquerdo clique em Notifications. Logo depoiis clique em CRIAR MENSAGEM ou em NOVA MENSAGEM. Em seguida preencha os campos como abaixo. Segue primeira parte do formulário:
No campo Texto da mensagem temos o texto que vai aparecer como corpo da mensagem na área de notificações do aparelho.
O campo Rótulo da mensagem é utilizado para que possamos identificar a mensagem no dashboard do Firebase Notification. O campo Data envio permite a seleção de Agora ou uma data e horário em específico, incluindo o fuso.
Segue segunda parte do formulário, mais precisamente a parte que selecionaremos quem receberá a mensagem. Segmentação:
Os rádio buttons já nos indicam o bastante sobre como é realizada a segmentação, por aplicativos, tópicos ou individualmente. Em nosso exemplo vamos utilizar a versão de segmentação por aplicativo, todos os usuários cadastrados no aplicativo selecionado vão receber a mensagem.
Segue a terceira parte do formulário, Eventos de conversão, que por hora somente nos é útil em definir no relatório se as mensagens foram enviadas e se foram abertas. O outro evento de conversão é opcional e não vamos estar utilizando aqui:
Segue quarta e última parte do formulário, opções avançadas:
O campo Título defini o título que será apresentado junto a notificação na área de notificações do device. No select de Prioridade podemos colocar Alta ou Normal.
A grande diferença entre as prioridades é que quando Alta o device, mesmo que no estado idle (ocioso), a notificação será entregue, quando Normal o Firebase Cloud Message (FCM) aguarda até o device voltar a ser utilizado.
O select de Som dispensa comentários, somente escolha se quer ou não a ativação do som quando a notificação for entregue. Note que as configurações do device é que vão prevalecer.
Os selects de Expira em são referentes ao item time_to_live do JSON que é enviado como mensagem de notificação. Ele se refere ao máximo de tempo que uma mensagem permanece nos servidores do FCM.
Por que isso?
Porque pode ser que alguns dos devices como alvo de recebimento de mensagem não estejam conectados a rede e consequentemente os servidores do FCM têm de guardar as mensagens até poderem eniviar. Esse "guardar as mensagens" é que tem o tempo de time_to_live configurado. O valor padrão e máximo é de quatro semanas, mas você pode definir um personalizado. Passado o tempo e o device ainda não ativo para receber as push messages, as mensagens são descartadas.
Como o time_to_live, existem outros "n" campos, dê uma olhada aqui: Firebase Cloud Messaging HTTP Protocol
Com o decorrer dos posts sobre notificação e push message no Firebase Android nós vamos abordar alguns outros campos também importantes.
E agora sim os campos na seção Personalizar dados. Os dados chave/valor definidos nessa seção vem todos dentro de um campo data que está dentro do campo principal: notification. Se você acessou o conteúdo de Firebase Cloud Messaging HTTP Protocol vai perceber que pode utilizar alguns outros campos predefinidos dentro desse notification.
Em data não, pois ele está no mesmo nível que os campos predefinidos e os campos de data estão um nível abaixo, veja o JSON a seguir:
{
"to": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification": {
"body": "great match!",
"title": "Portugal vs. Denmark",
"icon": "myicon",
"data": {
"title": "test",
"content": "test"
}
}
}
O JSON acima não é o JSON que estaremos enviando como push message, é apenas um exemplo de uma notificação, veja o nível dos dados de data. Esses não têm efeitos predefinido no device, então coloque somente os dados úteis a sua lógica de negócio.
E tenha em mente que no total, digo, de todo o conteúdo dentro de um JSON com o exemplo acima você tem somente 2KB de dados.
Agora podemos clicar em ENVIAR MENSAGEM e teremos no device:
E clicando na notificação temos que nada dessa notification é apresentado na APP, APP foi apenas aberta:
Depois de alguns minutos, no Firebase Notification Console temos um relatório da mensagem enviada (essa foi uma mensagem anterior):
Agora vamos configurar o projeto FirebaseNotification para administrar o conteúdo da notificação, quando possível.
Quando possível?
Sim, com o FCM temos dois tipos de mensagens: Notification e Data.
O Data é possível utilizar somente com nossos próprios servidores, como fazíamos em Google Cloud Message. Ele, diferente do Notification, permite até 4KB de dados.
O Notification é ainda mais leve e podemos utilizá-lo tanto via nosso próprio servidor Web quanto pelo Firebase Notification Console, porém não mais como no GCM, nós temos acesso ao conteúdo de uma mensagem de notificação somente quando a APP estiver aberta, ou seja, no primeiro plano (foreground), caso onde não há necessidade de notificação na barra de status.
Caso contrário o System Tray do Android se encarrega de ler as configurações da mensagem e então colocá-la como notificação na área de notificações do device.
Isso por um lado é até uma vantagem, pois ainda é possível configurar a mensagem, mas utilizando somente os campos do JSON dela, nada de código extra com a antiga entidade Notification.
Sobre o campo Data vamos falar mais nos posts posteriores da série.
Ok. O que é gerado com o clique na notificação?
Os dados dela vão para um Intent que pode ser acessado na Activity principal do projeto por meio da chamada a getIntent(). Logo vamos começar com essa configuração:
public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener {
private TextView tvTitle;
private TextView tvContent;
private TextView tvToken;
private int[] checkBoxIds = {
R.id.id_chk_soccer,
R.id.id_chk_basketball,
R.id.id_chk_volley,
R.id.id_chk_swimming,
R.id.id_chk_news
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
initViews();
intentData( getIntent() );
}
private void intentData(Intent intent){
/* Claúsula de Guarda */
if( intent == null || intent.getExtras() == null ){
return;
}
tvTitle.setText( intent.getExtras().getString("title") );
tvContent.setText( intent.getExtras().getString("content") );
}
...
}
Em intentData() estamos utilizando o padrão Cláusula de Guarda para somente prosseguirmos caso os dados de Intent sejam válidos.
Lembra de nossa mensagem de notificação de teste? Ela continha os campos title e content, eles serão utilizados para preecherem as TextViews tvTitle e tvContent.
Com o código acima já estamos administrando os dados que queremos da notificação quando clicada. Porém ainda temos o caso da APP estar aberta, temos também que obter os dados nessa condição. Para isso vamos criar um Service, dentro de um novo package em nosso projeto, o package service. Segue classe CustomFirebaseMessagingService que estará dentro desse novo pacote:
public class CustomFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
/* TODO */
}
}
Para obtermos os dados que estão no campo data de nosso JSON temos de realizar a chamada a remoteMessage.getData().get("title") e a remoteMessage.getData().get("content").
Mas antes temos de ter em mente que esses dados estão chegando em um Service que foi criado pelo Firebase e não pelo nosso código. Temos de enviar esses dados para a Activity. Para isso vamos utilizar o EventBus. Então voltamos a MainActivity para registrar nossa Activity como listener do EventBus:
public class MainActivity extends AppCompatActivity implements CompoundButton.OnCheckedChangeListener {
private TextView tvTitle;
private TextView tvContent;
private TextView tvToken;
private int[] checkBoxIds = {
R.id.id_chk_soccer,
R.id.id_chk_basketball,
R.id.id_chk_volley,
R.id.id_chk_swimming,
R.id.id_chk_news
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
EventBus.getDefault().register(this); /* ESSA LINHA */
initViews();
intentData( getIntent() );
}
@Override
protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this); /* E ESSA LINHA */
}
...
}
O trabalho com o EventBus é bem simples. A utilização dele é opcional. Optei por ele pois é o que, a princípio, precisa de menos código e pode ser utulizada em qualquer parte da APP.
Feito isso precisamo definir um método subscriber para obter os dados de mensagens disparadas pelo EventBus, mas antes temos de ter uma classe que vai conter esses dados, essa classe vai servir de envelope para os dados uteis da notificação. Segue classe NotificationEvent:
public class NotificationEvent {
private Intent content;
public NotificationEvent(Intent content ){
this.content = content;
}
public Intent getContent(){
return content;
}
}
Ok, mas vamos utilizar uma Intent como variável de instância para que?
Lembra de nosso código de intentData()? Para que possamos reaproveitá-lo, trabalhar com um Intent em NotificationEvent é uma excelente opção. Para lembrar do código:
private void intentData(Intent intent){
if( intent == null || intent.getExtras() == null ){
return;
}
tvTitle.setText( intent.getExtras().getString("title") );
tvContent.setText( intent.getExtras().getString("content") );
}
Vamos realizar uma chamada a ele dentro de nosso método subscriber de eventos EventBus com a classe NotificationEvent, dentro de nossa MainActivity. Segue método:
@Subscribe(threadMode = ThreadMode.MAIN)
public void onNewNotification(NotificationEvent notification){
intentData( notification.getContent() );
}
Sempre que houver uma mensagem no EventBus com um objeto do tipo NotificationEvent esse método será disparado. Note que o código @Subscribe(threadMode = ThreadMode.MAIN) é necessário, caso contrário as views não são atualizadas dentro da Thread Principal.
Para saber mais sobre o EventBus acesse o post do blog sobre ele: EventBus Lib, Comunicação Entre Entidades Android. E também as docs dele em Green Robot EventBus
Agora voltando ao nosso Service CustomFirebaseMessagingService temos:
public class CustomFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Intent intent = getIntentBody(remoteMessage );
NotificationEvent notificationEvent = new NotificationEvent( intent );
EventBus.getDefault().post(notificationEvent);
}
private Intent getIntentBody(RemoteMessage remoteMessage ){
Intent intent = new Intent();
Bundle extras = new Bundle();
for( String key : remoteMessage.getData().keySet() ){
extras.putString( key, remoteMessage.getData().get( key ) );
}
intent.putExtras(extras);
return intent;
}
}
O método getIntentBody() é utilizado para construir a exata estrutura necessária no método intentData() da MainActivity.
Agora somente devemos configurar esse Service no AndroidManifest.xml, segue:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.thiengo.firebasenotification">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- ACRESCENTE O TRECHO ABAIXO -->
<service android:name=".service.CustomFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
</manifest>
Com isso já estamos obtendo os dados da notificação quando a APP está no background ou foreground.
Nosso próximo passo é definirmos a inscrição e a remoção de inscrição nos tópicos de nosso projeto. Apenas vamos modificar o código de nosso listener onCheckedChanged(), segue:
...
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
String topic = getTopic( buttonView );
if( isChecked ){
FirebaseMessaging.getInstance().subscribeToTopic( topic );
displayMessage( "Vc foi inscrito no tópico: "+topic );
}
else{
FirebaseMessaging.getInstance().unsubscribeFromTopic( topic );
displayMessage( "Vc foi removido do tópico: "+topic );
}
setSPCheckboxValue( buttonView.getId(), isChecked );
}
...
Na chamada a FirebaseMessaging.getInstance().subscribeToTopic( topic ) é realmente onde o tópico está sendo criado. Nós não o criamos no dashboard do Firebase ou código backend de nossos servidores, ele é criado quando ao menos um usuário se inscreve nele e esse tópico ainda não está configurado no projeto.
Note que o tópico pode ter qualquer nome, porém somente com os possíveis caracteres (expressão regular): "a-zA-Z0-9-_%". Para o tópico criado aparecer no dashboard pode levar até um dia (bad!).
Com isso, já temos o código de configuração de tópico colocado no projeto. Agora somente nos resta acessar o token único do usuário, mais precisamente, colocá-lo na TextView tvToken.
Primeiro atualizamos o initViews():
...
private void initViews(){
tvTitle = (TextView) findViewById(R.id.id_title);
tvContent = (TextView) findViewById(R.id.id_content);
tvToken = (TextView) findViewById(R.id.id_token);
/* O TRECHo ABAIXO */
tvToken.setText( FirebaseInstanceId.getInstance().getToken() );
Log.i("log", "token: "+FirebaseInstanceId.getInstance().getToken());
initCheckBoxes();
}
...
Para obtermos o token somente devemos invocar FirebaseInstanceId.getInstance().getToken(). Caso o token não tenha sido gerado ainda (ele é gerado de forma assíncrona assim que a APP com o FCM configurado é aberta) o valor null é retornado.
Para que seja possível obter o token sempre que um novo é gerado, precisamos criar um outro Service, dessa vez que herde de FirebaseInstanceIdService, segue CustomFirebaseInstanceIdService:
public class CustomFirebaseInstanceIdService extends FirebaseInstanceIdService {
@Override
public void onTokenRefresh() {
String token = FirebaseInstanceId.getInstance().getToken();
TokenEvent tokenEvent = new TokenEvent( token );
EventBus.getDefault().post(tokenEvent);
}
}
Para evitar a "fadiga" já colocamos o código do EventBus que nesse ponto não deve mais ser novidade para ti. Agora vamos a definição da classe TokenEvent:
public class TokenEvent {
private String token;
public TokenEvent(String token ){
this.token = token;
}
public String getToken(){
return token;
}
}
A configuração do CustomFirebaseInstanceIdService no AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.thiengo.firebasenotification">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<service android:name=".service.CustomFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
</application>
</manifest>
E então o método subscriber para mensagens do tipo TokenEvent no EventBus, onNewToken() em MainActivity:
...
@Subscribe(threadMode = ThreadMode.MAIN)
public void onNewToken(TokenEvent tokenEvent){
tvToken.setText( tokenEvent.getToken() );
}
...
Dessa forma temos já todo o necessário para o funcionamento de notificações em nossa APP. Duplicando a última mensagem enviada do Firebase Notification Console temos o seguinte resultado:
Com isso finalizamos o projeto de teste com o Firebase Notification. Acesse o Console de Notificação no Firebase e realize testes para ver o funcionamento com outras segmentações e valores.
Lembrando que esse post é ainda parte da série Firebase Android, porém esse de notificação foi construído fora do projeto de Chat, que ainda será utilizado na série.
Acesse esse projeto completo no GitHub: https://github.com/viniciusthiengo/FirebaseNotification
Abaixo o vídeo de implementação completo desse projeto:
Segue lista de todos os posts da série até aqui:
Crash Reporting, Firebase Android - Parte 11
Múltiplos Links de Autenticação e Correção de Código, Firebase Android - Parte 10
GitHub Login, Firebase Android - Parte 9
Recuperação de Senha, Firebase Atualizado - Parte 8
Twitter Login (Fabric), Firebase Android - Parte 7
Google SignIn API, Firebase Android - Parte 6
Facebook Login, Firebase Android - Parte 5
Remoção de Conta e Dados de Login, Firebase Android - Parte 4
Atualização de Dados, Firebase Android - Parte 3
Eventos de Leitura e Firebase UI Android - Parte 2
Persistência Com Firebase Android - Parte 1
Para complementar o entedimento do conteúdo desse post:
SharedPreferences no Android, Entendendo e Utilizando
Abaixo os links fontes para a construção do exemplo:
Send a Notification to a User Segment
Firebase Cloud Messaging HTTP Protocol
How to get started with EventBus in 3 steps
O bug comentado em vídeo:
Issue 212879: Google Play Services out of date on API 23 emulator
Vlw.
Comentários Facebook