Cordova 6.3.1
Plug-in Firebase Phonegap 0.1.12
Dispositivo: LG G5 com Android 6.0.1
Este é o código que estou usando:
`var app = {
// Application Constructor
inicializar: função () {
this.bindEvents ();
},
// Ligar ouvintes de eventos
//
// Vincule quaisquer eventos que sejam necessários na inicialização. Os eventos comuns são:
// 'load', 'deviceready', 'offline' e 'online'.
bindEvents: function () {
document.addEventListener ('deviceready', this.onDeviceReady, false);
},
// deviceready Event Handler
//
// O escopo de 'isto' é o evento. Para chamar o 'receivedEvent'
// função, devemos chamar explicitamente 'app.receivedEvent (...);'
onDeviceReady: function () {
console.log ("Estamos en onDeviceReady");
if (navigator.connection.type == Connection.NONE) {
navigator.notification.alert ('Se requiere conexión a Internet');
} senão {
window.FirebasePlugin.onNotificationOpen (function (notification) {
console.log (notificação);
navigator.notification.alert ("Recibido");
}, função (erro) {
console.log (erro);
});
}
},
};
app.initialize (); `
Recebo notificações na bandeja do sistema em todas as situações: aplicativo em segundo plano, primeiro plano e fechado e quando clico na notificação, o aplicativo é aberto nos três casos, mas o callback não é acionado.
Há algo errado no código?
Desde já, obrigado.
mesmo problema, no Android as notificações chegam, mas dentro do aplicativo nenhum retorno de chamada é chamado.
v. 0.1.12
@voidbrain @Kibukita , teste a versão mais recente do repo. Tentei melhorar a notificação de abertura. Obrigado.
@BugsBunnyBR Acabei de tentar atualizar para a versão mais recente do repo e testei. No Android ainda não está executando o onNotificationOpen.
@superheroben , você poderia fornecer um repositório com uma amostra de como está chamando o código do plugin? Como você está enviando as notificações? Eu testei com mensagens de tópico.
Mesmo problema aqui.
O retorno de chamada getInstanceId () é chamado, a notificação chega, mas o onNotificationOpen () nunca é chamado.
Código do cliente:
if (window.FirebasePlugin)
{
window.FirebasePlugin.getInstanceId(
function(token) {
thiss.saveToken(token);
},
function(error) {
console.log(error);
}
);
window.FirebasePlugin.onNotificationOpen(
function(notification) {
alert("Yeah!!!");
},
function(error) {
alert("Error!");
console.error(error);
}
);
window.FirebasePlugin.grantPermission();
}
Minha estrutura de dados de notificação:
(
[to] => (device token)
[notification] => Array
(
[title] => Title
[text] => Test message
[sound] => default
[vibrate] => 1
[badge] => 2
)
)
Meu código do lado do servidor (PHP):
$jsonData = json_encode($data);
$ch = curl_init("https://fcm.googleapis.com/fcm/send");
$header = array(
'Content-Type: application/json',
"Authorization: key=".MY_GCM_API_KEY
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, true);
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
$result = curl_exec($ch);
curl_close($ch);
Trabalhando no Cordova Android 5.2.2. O dispositivo usado para testar executa o Android 4.4.2. Versão 0.1.12 do plugin.
@arivanbastos , você tentou apontar para o repositório github?
A instalação a partir do github resolveu parcialmente o problema. Obrigada.
cordova plugin remove cordova-plugin-firebase
cordova plugin add https://github.com/arnesson/cordova-plugin-firebase/
Agora, o retorno de chamada onNotificationOpen () é chamado quando o aplicativo está em segundo plano.
Quando o aplicativo está em primeiro plano, em vez de a documentação diz, a notificação chega e o onNotificationOpen () não é chamado:
O aplicativo está em primeiro plano:
O usuário recebe os dados de notificação no retorno de chamada do JavaScript sem qualquer notificação no próprio dispositivo (este é o comportamento normal das notificações push, cabe a você, o desenvolvedor, notificar o usuário)
Se você enviar um push do tipo "notificação" (sem um corpo de dados), a notificação não deve ser exibida quando o aplicativo está em primeiro plano.
Desculpe, não entendi. Devo apenas adicionar uma seção de "dados" aos meus dados de notificação?
(
[to] => (device token)
[notification] => Array
(
[title] => Title
[text] => Test message
)
[data] => Array
(
[test] => 1
)
)
Isso não corrigiu o problema.
Renomear a seção "notificação" por "dados" faz o aplicativo travar ("O aplicativo parou") quando a notificação chega:
(
[to] => (device token)
[data] => Array
(
[title] => Title
[text] => Test message
)
)
https://firebase.google.com/docs/cloud-messaging/android/receive
Aqui está muito bem descrito.
Sua notificação vai para a bandeja do sistema se o aplicativo estiver em segundo plano e para onMessageReceived () se o aplicativo estiver em primeiro plano.
Se sua mensagem contiver dados, eles sempre serão transmitidos para onMessageReceived ().
Acho que há um problema na implementação de onMessageReceived ().
Quando vejo o código que interpreto é o seguinte:
NotificationManager.notify (id, notificação) posta a notificação a ser mostrada na barra de status.
No entanto, para mim, parece que é normal que sempre que recebo uma mensagem do FCM seja exibida uma notificação na barra de status.
Não vejo nenhuma verificação se o aplicativo está em primeiro plano e não vejo nenhuma chamada para o retorno de chamada. Não sou um desenvolvedor Android, então talvez eu esteja errado, mas o comportamento descrito se encaixa nisso.
OK, encontrei o trecho de código que chama o retorno de chamada.
Com o último commit do BugsBunnyBR, houve uma mudança no OnNotificationOpenReceiver, o que explica que arivanbastos obtém seu callback executado ao apontar para o repositório github.
Mesmo assim, a notificação só é enviada (para OnNotificationOpenReceiver e NotificationManager) se houver um texto ou título (na notificação ou nos dados). Isso significa que não é possível enviar dados ao seu aplicativo sem receber a notificação enviada ao NotificationManager, que os mostra no StatusBar.
@arivanbastos
Eu disse algo errado para você. Desculpe por isso.
Você já tentou apontar para esta versão do repo?
@packowitz e @robertarnesson . Ok, minha implementação SEMPRE * tentará mostrar a notificação. Ou a notificação exibida automaticamente do Firebase ou a versão dentro de onMessageReceived
será exibida.
O retorno de chamada onNotificationOpen
será chamado quando onMessageReceived
for chamado ou quando a notificação tiver dados e corpos de notificação ao mesmo tempo. No meu pr que introduziu o onNotificationOpen
, tentei explicar que notificações push do tipo Notificação não disparariam o retorno de chamada. A recomendação é sempre incluir um corpo de dados e um corpo de notificação, para que o plug-in possa detectar e disparar o retorno de chamada.
A maioria dos desenvolvedores de aplicativos Android deseja que suas notificações sejam mostradas na bandeja do sistema, mesmo que o aplicativo esteja em primeiro plano. Eu sei que há casos, em aplicativos de bate-papo, em que esse comportamento não é bom.
Quando desenvolvi o recurso de notificação do Android, não me importei com as necessidades dos apps de bate-papo ou em conformidade com o Firebase.
O que pode ser feito é:
1) Desenvolva um sinalizador para ser definido quando o aplicativo for aberto dizendo "ei, eu quero que você mostre a notificação mesmo quando o aplicativo estiver aberto" e use-o para controlar o comportamento. Não precisaria ser persistido em nenhum armazenamento se o aplicativo sempre definisse o sinalizador ao abrir.
2) Basta comentar esta linha e desabilitar a notificação quando o aplicativo estiver em primeiro plano.
_Always_ -> Se o plugin encontrar um "texto" ou "título" no corpo da notificação.
@BugsBunnyBR Gosto da ideia de ter um flag para escolher o comportamento.
Gostaria de desacoplar o NotificationManager do OnNotificationOpenReceiver chamando de volta seu retorno de chamada JS. Minha recomendação é introduzir uma verificação, se há dados na mensagem e se houver, chamar o retorno de chamada com os dados.
Para a notificação, seria bom ter a bandeira.
Obrigada.
@BugsBunnyBR Acabei de testar a mudança para o repositório github e descobri que tocar em uma notificação reinicia meu aplicativo, mesmo que ele já esteja em execução. Acontece mesmo quando o aplicativo está em primeiro plano e eu toco na notificação.
Mas o retorno de chamada funciona agora;)
O mesmo aqui, para mim a versão 0.1.13 está fazendo com que meu aplicativo reinicie apenas quando ele está em primeiro plano. A versão 0.1.12 está funcionando bem.
As notificações simplesmente não funcionam bem na versão repo. O motivo é, creio, que se onNotificationOpen
for chamado antes de uma notificação ser aberta, ela será ignorada.
https://github.com/arnesson/cordova-plugin-firebase/blob/master/src/android/FirebasePlugin.java#L123
Em registerOnNotificationOpen
ele só registra o retorno de chamada SE houver um notificationBundle
esperando
Além disso, o motivo pelo qual o aplicativo parece recarregar se já estiver aberto está em OnNotificationOpenReceiver
, diz explicitamente
launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
que força o cliente a recarregar, quando o notificationBundle
está disponível quando onNotificationOpen
callback é registrado para que o cliente então receba a notificação.
Reescrevi todo o manuseio de onNotificationOpen
e quase funcionou como eu esperava, que é:
onNotificationOpen
é chamado no cliente atual (sem recarregar)onNotificationOpen
é chamado com o cliente atual (sem recarregar)Resta que a notificação seja entregue imediatamente ao cliente, sem a necessidade de abrir, se isso for possível (ainda não verifiquei).
Eu sou um pouco noob do Android, então pode haver algumas melhorias que podem ser feitas, mas parece funcionar bem, então pensei em compartilhar.
OnNotificationOpe nReceiver: onReceive agora simplesmente chama
FirebasePlugin.onBroadcastReceive(context, intent);
Alterou FirebasePlugin
seguinte forma
private static CallbackContext callbackContext;
// ...
private void registerOnNotificationOpen(final CallbackContext callbackContext) {
FirebasePlugin.callbackContext = callbackContext;
}
// called when in foreground
public static void onBroadcastReceive(Context context, Intent intent) {
Log.d("FirebasePlugin", "onBroadcastReceive");
Bundle data = intent.getExtras();
FirebasePlugin.onNotificationOpen(data);
}
// called when in background
<strong i="32">@Override</strong>
public void onNewIntent(Intent intent) {
Log.d(TAG, "new intent " + intent);
super.onNewIntent(intent);
FirebasePlugin.onNotificationOpen(intent.getExtras());
}
public static void onNotificationOpen(Bundle bundle) {
if (FirebasePlugin.callbackContext == null ) {
Log.d("FirebasePlugin", "no callback context, onNotificationOpen ignored");
return;
}
if (callbackContext != null && bundle != null) {
JSONObject json = new JSONObject();
Set<String> keys = bundle.keySet();
for (String key : keys) {
try {
json.put(key, bundle.get(key));
} catch (JSONException e) {
Log.d("FirebasePlugin", "onNotificationOpen: json exception");
PluginResult result = new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
return;
}
}
Log.d("FirebasePlugin", "onNotificationOpen: send notification to javascript");
PluginResult result = new PluginResult(PluginResult.Status.OK, json);
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
}
}
Humm ... Notei que as notificações não são entregues (ao dispositivo) quando o cliente não está em execução (foi eliminado).
Tente abrir uma notificação apresentada pelo firebase diretamente e veja o comportamento .. Eu acho que eles reiniciam a atividade principal que eu acho que é o comportamento correto.
Desculpe pelo atraso. Tentei com o 0.1.13, mas meu aplicativo é reiniciado depois que a notificação é aberta.
alguma novidade ?
Não consigo obter sucesso ou falha de retorno de chamada onNotificationOpen no Android usando 0.1.17. Nem o envio por meio da API ou GUI com uma carga útil funciona. Alguma sugestão?
Por que não criamos uma solicitação de pull com o código postado por @Mehuge ? Funciona
Tive que atualizar onNewIntent no FirebasePlugin para filtrar intents de inicialização normais, então meu código onNewIntent agora se parece com este
<strong i="6">@Override</strong>
public void onNewIntent(Intent intent) {
Log.d(TAG, "new intent " + intent);
super.onNewIntent(intent);
Bundle data = intent.getExtras();
if (data != null) {
String id = data.getString("id");
if (null != id) {
FirebasePlugin.handleNotificationBundle(data);
} else {
Log.d(TAG, "Not a notification intent, ignored");
}
}
}
Não estou totalmente feliz com isso. Ele funciona procurando uma propriedade id no pacote de intent que meu código de servidor sempre envia. Não parece haver nada que o GCM ou FBM adicione de forma confiável ao pacote que possa ser usado para identificar o intent como uma notificação / mensagem. Às vezes, obtemos algumas propriedades do Google adicionadas (se estivermos abrindo uma notificação da bandeja), mas para mensagens e notificações entregues diretamente ao cliente quando está em primeiro plano, não há nada além dos dados na mensagem que informam que é uma intenção de inicialização por causa de uma notificação, pelo menos que eu pude ver.
Provavelmente existe uma maneira melhor de lidar com isso.
@Mehuge , você se importaria de criar gists com todos os arquivos que você tem?
Ok, aqui está https://gist.github.com/Mehuge/374ee24d9e18a6c7ccc171d3e521b7ad
Observe, entretanto, que existem alguns bits que são específicos para nosso aplicativo. Acabei movendo o código para o nosso projeto porque estava mudando muito. Em retrospecto, eu provavelmente deveria ter feito o fork do plugin e modificado dessa forma, mas neste ponto, eu estava muito atrasado e farto de tudo, então peguei o caminho mais rápido para fazer algo funcionar. Os bits personalizados são bastante óbvios, portanto, devem ser fáceis de excluir.
Observe também que, da forma como implementei o plug-in, ele precisa saber quando o cliente está pausado (ou, mais especificamente, não pausado) para que possa decidir se deve criar uma notificação ou entregar a mensagem diretamente. Você pode ou não precisar dessa funcionalidade, mas em nosso caso, não queríamos que as notificações que fossem enviadas quando o cliente estava em primeiro plano criassem notificações do Android, mas que fossem entregues diretamente ao cliente para lidar com elas. Para informar o plugin do estado de pausa do cliente, adicione o seguinte código à sua atividade principal.
<strong i="9">@Override</strong>
protected void onResume() {
FirebasePlugin.setPaused(false);
super.onResume();
}
<strong i="10">@Override</strong>
protected void onPause() {
FirebasePlugin.setPaused(true);
super.onPause();
}
Há outro problema com o qual você pode ter que lidar: se uma notificação chegar enquanto estiver em segundo plano, mas o usuário iniciar o aplicativo diretamente, em vez de abrir a notificação do Android, talvez seja necessário lidar com isso de alguma forma. Em nosso caso de aplicativos, eu poderia simplesmente limpar todas as notificações não abertas. Sua situação pode ser diferente.
Não estou totalmente satisfeito com o resultado final, algumas das chaves extras adicionadas, por exemplo, eram experimentais e não estão realmente sendo usadas, eu simplesmente não tive tempo de removê-las.
Estaria interessado em qualquer feedback ou melhorias sugeridas ou em apontar quaisquer falhas. Eu estaria particularmente interessado em encontrar uma maneira de detectar melhor uma intenção de lançamento com uma carga útil de GCM de um lançamento normal. Descobri que as propriedades do Google são adicionadas apenas em algumas circunstâncias. Além disso, minhas tentativas de detectar os diferentes tipos de notificações (is_push, is_notify, broadcast) não estão realmente funcionando.
veja # 108
Para mim, eu poderia resolver fazer a solicitação desta forma:
{
"registration_ids": [...tokens],
"notification" : {
"title": "Notf title",
"body": "Notification body"
},
"data": {
"click_action": "/call/dwEugLJ9PTVdcFb064CX"
}
}
Mas eu tive que pegar o click_action como parâmetro e fazer o redirecionamento manualmente (eu estava usando o Cordova com o app react).
Comentários muito úteis
Reescrevi todo o manuseio de
onNotificationOpen
e quase funcionou como eu esperava, que é:onNotificationOpen
é chamado no cliente atual (sem recarregar)onNotificationOpen
é chamado com o cliente atual (sem recarregar)Resta que a notificação seja entregue imediatamente ao cliente, sem a necessidade de abrir, se isso for possível (ainda não verifiquei).
Eu sou um pouco noob do Android, então pode haver algumas melhorias que podem ser feitas, mas parece funcionar bem, então pensei em compartilhar.
OnNotificationOpe nReceiver: onReceive agora simplesmente chama
Alterou
FirebasePlugin
seguinte forma