Cordova-plugin-firebase: Alterando o ícone de notificação push - problema de ícone do Android em branco em 2018

Criado em 6 jul. 2018  ·  22Comentários  ·  Fonte: arnesson/cordova-plugin-firebase

Oi pessoal,

Para pessoas que usam este plug-in com cordova 8+, você pode descobrir que mudar o ícone de notificação não funcionará e você clicar no antigo problema 'o ícone de notificação é um quadrado em branco' no Android. Isso acontece porque os ícones de notificação do Android devem ter uma forma simples de 1 cor em um fundo transparente e, se você não tiver fornecido esse ícone, o Android usará o ícone do aplicativo. Provavelmente são quadrados cheios e coloridos sem fundo transparente.

Isso é muito irritante ao definir um novo projeto Ionic 3 e tentar usar este plugin.

Leiame aqui atm não descreve o processo de alteração do ícone corretamente. Aqui estão as etapas que você precisa seguir para alterar o ícone:

0) Pare de procurar no Google e puxar o cabelo. Siga estas instruções passo a passo e você fará com que funcione, confie em mim.
1) Prepare uma versão do ícone do seu aplicativo que seja apenas uma forma de 1 cor em fundo transparente
2) Vá aqui: http://romannurik.github.io/AndroidAssetStudio/icons-notification.html#source.type=clipart&source.clipart=ac_unit&source.space.trim=1&source.space.pad=0&name=notification_icon pressione "imagem" no canto superior esquerdo, carregue seu ícone, corte-o / adicione preenchimento se necessário
3) Se parecer bem, pressione a seta no canto superior direito para baixar as pastas 'drawable'. Ele lhe dará um zip com a pasta res dentro e 5 drawable-xxx pastas, cada uma com tamanhos diferentes de seu ícone
4) Copie essas pastas drawable em algum lugar do seu projeto. Para mim, eu os copiei ao lado dos recursos do ícone e da tela inicial: project-root/resources/android/notification_icon
5) Configure seu arquivo config.xml para copiar esses arquivos dentro de seu aplicativo Android usando a diretiva <resource-file /> . Observe que, desde o crodova 8.x, o caminho de destino correto é app/src/main/res . Em cordova <8 era apenas res (já que anteriormente os arquivos de recursos eram mantidos no diretório platforms/android/res e agora estão em platforms/android/app/main/res ). A maioria dos problemas 'resolvidos' online no ícone de notificação do Android em branco não menciona isso.

<platform name="android">
(...) 
  <resource-file src="resources/android/notification_icon/drawable-mdpi/notification_icon.png" target="app/src/main/res/drawable-mdpi/notification_icon.png" />
  <resource-file src="resources/android/notification_icon/drawable-hdpi/notification_icon.png" target="app/src/main/res/drawable-hdpi/notification_icon.png" />
  <resource-file src="resources/android/notification_icon/drawable-xhdpi/notification_icon.png" target="app/src/main/res/drawable-xhdpi/notification_icon.png" />
  <resource-file src="resources/android/notification_icon/drawable-xxhdpi/notification_icon.png" target="app/src/main/res/drawable-xxhdpi/notification_icon.png" />
  <resource-file src="resources/android/notification_icon/drawable-xxxhdpi/notification_icon.png" target="app/src/main/res/drawable-xxxhdpi/notification_icon.png" />
</platform>

6) Agora que você tem seu ícone no aplicativo como um recurso drawable, você precisa forçar seu aplicativo a usá-lo. Independentemente do que está escrito no leia-me aqui, a descoberta automática de recurso drawable chamado 'notification_icon' não funcionou para mim. Não sei exatamente porque, porque parece estar na base de código aqui: https://github.com/arnesson/cordova-plugin-firebase/blob/master/src/android/FirebasePluginMessagingService.java#L140 mas estou supondo que algo mudou com a descoberta de recursos nas versões mais recentes do Android.
7) Por causa disso, a única outra solução que eu poderia usar era enviar o parâmetro icon do back-end ao enviar notificação push para o firebase. Observe que a API deles provavelmente está passando por algumas mudanças porque tem problemas com a fusão correta das partes notification e android da carga útil. Por esse motivo, você deve adicionar o parâmetro de ícone à parte notification do json. Usar parâmetros específicos do Android não funcionará.

Portanto, a carga útil de notificação que você envia para o firebase a partir do seu back-end deve se parecer com isto: ESTA É A ÚNICA VERSÃO QUE FUNCIONA

{
  notification: {
    body: 'Imma push your notification if you know what i mean!',
    icon: 'notification_icon',
  },
  data: { someExtraData: 'goes_here' }
}

Deixe-me reiterar - USAR PARAMS ESPECÍFICOS DO ANDROID NÃO FUNCIONA COM O FIREBASE EM julho de 2018 - ABAIXO NÃO FUNCIONARÁ E SEU ÍCONE DE NOTIFICAÇÃO NÃO ALTERARÁ INDEPENDENTEMENTE DO QUE SUA DOCUMENTAÇÃO DIZ :

{
  notification: {
    body: 'Imma push your notification if you know what i mean!'
  },
  data: { someExtraData: 'goes_here_if_you_need_it' },
  android: { 
    icon: 'notification_icon'
  } 
}

8) Com todas as etapas concluídas, você agora está pronto para testar seu novo ícone. Eu sugiro fortemente testá-lo dentro do emulador do Android - algumas das skins do Android assumem a barra de notificação e usam o ícone do aplicativo independentemente do que você definir (ou seja, MIUI de xiaomi). Também descobri que às vezes os ícones são armazenados em cache. Por esse motivo, testá-lo em um simulador de AVD recém-criado é sua aposta mais segura. Remova seu aplicativo manualmente entre as execuções de teste e reinicie o simulador / dispositivo para evitar problemas de cache.

Espero que este longo texto ajude outras pessoas no futuro, já que a quantidade de obstáculos que se tem que passar para mudar um ícone 10x10 pequeno é simplesmente muito alta ...

Comentários muito úteis

Teste se este código adicionado à tag config.xml <platform name="android"> adicionará o ícone como ícone de notificação padrão.

<config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml">
    <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>

Isso funciona para mim enviando pelo painel Firebase Cloud Messaging ou back-end sem ícone na carga útil.
Por favor, poste aqui o feedback.
Se funcionar, seu tutorial adicionado a este código ajudará muita gente e deverá abrir um PR para adicioná-lo ao README.

Todos 22 comentários

Teste se este código adicionado à tag config.xml <platform name="android"> adicionará o ícone como ícone de notificação padrão.

<config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml">
    <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>

Isso funciona para mim enviando pelo painel Firebase Cloud Messaging ou back-end sem ícone na carga útil.
Por favor, poste aqui o feedback.
Se funcionar, seu tutorial adicionado a este código ajudará muita gente e deverá abrir um PR para adicioná-lo ao README.

Obrigado @madsheep !! você salvou minha vida !!

Oi, obrigado pelo apoio moral, e me dando a sensação de que não sou o único que acabou nessa bagunça. Porém, infelizmente, eu gravitei de volta ao pré-passo 0, perdendo cabelo no caminho.

Quando tento enviar a notificação por meio do método http / post, recebo erros da api do firebase informando que o json é inválido. Eu tentei das duas maneiras:

Isso é o que eu obtenho ao incluir o ícone como message: { notification: { icon: 'notification_icon', ... }, ... }

Error code=400, message=Invalid JSON payload received. Unknown name "icon" at 'message.notification': Cannot find field., status=INVALID_ARGUMENT, details=[@type=type.googleapis.com/google.rpc.BadRequest, fieldViolations=[field=message.notification, description=Invalid JSON payload received. Unknown name "icon" at 'message.notification': Cannot find field.]]

Esta é a mensagem que recebo ao incluir o ícone como message: { android: { icon: 'notification_icon' }, ... }

Error code=400, message=Invalid JSON payload received. Unknown name "icon" at 'message.android': Cannot find field., status=INVALID_ARGUMENT, details=[@type=type.googleapis.com/google.rpc.BadRequest, fieldViolations=[field=message.android, description=Invalid JSON payload received. Unknown name "icon" at 'message.android': Cannot find field.]]

mas talvez eu esteja usando isso no contexto errado (nosso código de back-end em nuvem enviando uma notificação para aplicativos cliente usando o Firebase Cloud Messaging).

funcionou bem para mim (envio notificações usando funções do Firebase):
const payload = { notification: { title: ........, body: ........., icon: 'notification_icon' } };

Obrigado, isso resulta no primeiro dos dois erros para mim. Estou usando o serviço REST por meio de uma biblioteca javascript / request e envio de acordo com o formato https://firebase.google.com/docs/cloud-messaging/js/first-message . Suponho que o formato da mensagem / notificação esteja descrito em https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#Notification .

Na verdade, quando li isso, sugeri que o ícone deveria estar em message.android.notification.icon , ou seja, um nível mais profundo.

Eu apenas tentei, e isso realmente funciona para mim! Então, suponho que depende do protocolo do servidor como a carga útil deve ser estruturada ...

Obrigado a todos por esta discussão. Isso finalmente resultou em eu parar de puxar meu cabelo ...

fechando como resolvido

@madsheep Não está funcionando. Depois de adicionar 'ícone' sob notificação na função de nuvem, dá o seguinte erro:

{ Error: Invalid JSON payload received. Unknown name "icon" at 'message.notification': Cannot find field

errorInfo:
{código: 'mensagem / argumento inválido',
mensagem: 'Carga útil JSON inválida recebida. Nome desconhecido "ícone" em 'message.notification': Campo não encontrado. ' },
codePrefix: 'messaging'}

tente message.android.notification.icon vez de message.notification.icon .

@madsheep @guilhermehtk Funcionou para mim! THX.

Teste se este código adicionado à tag config.xml <platform name="android"> adicionará o ícone como ícone de notificação padrão.

<config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml">
    <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>

Isso funciona para mim enviando pelo painel Firebase Cloud Messaging ou back-end sem ícone na carga útil.
Por favor, poste aqui o feedback.
Se funcionar, seu tutorial adicionado a este código ajudará muita gente e deverá abrir um PR para adicioná-lo ao README.

Você fez meu dia,

se alguém enfrentar problemas na construção, como

AAPT: erro: prefixo não ligado.

em seguida, tente adicionar o

xmlns: android = " http://schemas.android.com/apk/res/android "

atributo deve ser adicionado à raiztag dentro do config.xml

você salvou meu dia!

Para quem está enfrentando esse problema em 2019 com o Android build 7.1.1, a pasta de recursos parece ter mudado !!

Ao verificar o Android Studio e os arquivos gerados, aqui está o que funcionou para mim:

<resource-file src="resources/android/notification/notification_icon.png" target="app/src/main/res/drawable/notification_icon.png" />
<config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml">
            <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>

A 1ª linha é a parte importante, pois não era para mim.

@alarv O ícone não está aparecendo para algum telefone Android, qualquer ajuda sobre isso, por favor.

Ei @bioyeneye quais modelos? Qual versão do Android eles estão executando? Estoque ou outro?

@bioyeneye Tenho outra solução para o Ionic 4 para fazer os ícones funcionarem em todos os dispositivos Android.
Não estou usando um png para ícone, mas XML. Estou usando um gancho para incluir isso nos seguintes diretórios:

'res/drawable-hdpi',
'res/drawable-mdpi',
'res/drawable-xhdpi',
'res/drawable-xxhdpi',
'res/drawable-xxxhdpi',
'res/mipmap-hdpi',
'res/mipmap-mdpi',
'res/mipmap-xhdpi',
'res/mipmap-xxhdpi',
'res/mipmap-xxxhdpi'

criar um exemplo de arquivo:
android_notification_resources.js

Neste novo arquivo de gancho, adicione:


// COMEÇAR
const fs = require ("fs");
const path = require ("path");
const Q = requer ("q");

var sourceDir = 'resources / android / notification_icon'; // aqui é onde está o seu ícone
var platformDir = 'platform / android / app / src / main /';
var resourceDirs = [
'res / drawable-hdpi',
'res / drawable-mdpi',
'res / drawable-xhdpi',
'res / drawable-xxhdpi',
'res / drawable-xxxhdpi',
'res / mipmap-hdpi',
'res / mipmap-mdpi',
'res / mipmap-xhdpi',
'res / mipmap-xxhdpi',
'res / mipmap-xxxhdpi'
];

module.exports = function (ctx) {

if (ctx.opts.platforms.indexOf ('android') <0) {
Retorna;
}

var diferido = Q.defer ();
var androidPlatformDir = path.join (ctx.opts.projectRoot, platformDir);
var customResourcesDir = path.join (ctx.opts.projectRoot, sourceDir);

cópia da função (src, dest) {
var diferido = Q.defer ();

fs.stat(src, function(err, stats) {
  if (err || !stats.isFile()) {
    return deferred.reject(err);
  }

  fs.stat(path.dirname(dest), function(err, stats) {
    if (err || !stats.isDirectory()) {
      return deferred.reject(err);
    }

    var rs = fs.createReadStream(src);

    rs.on('error', function(err) {
      console.error(err.stack);
      deferred.reject(err);
    });

    var ws = fs.createWriteStream(dest);

    ws.on('error', function(err) {
      console.error(err.stack);
      deferred.reject(err);
    });

    ws.on('close', function() {
      deferred.resolve();
    });

    rs.pipe(ws);
  });
});

return deferred.promise;

}

fs.stat (customResourcesDir, function (err, stats) {
if (err ||! stats.isDirectory ()) {
return deferred.resolve ();
}

fs.readdir(customResourcesDir, function(err, files) {
  var copies = [];

  for (var i in files) {
    for (var j in resourceDirs) {
      var filePath = path.join(ctx.opts.projectRoot, sourceDir, files[i]);
      var destPath = path.join(androidPlatformDir, resourceDirs[j], files[i]);

      copies.push([filePath, destPath]);
    }
  }

  copies.map(function(args) {
    return copy.apply(copy, args);
  });

  Q.all(copies).then(function(r) {
    deferred.resolve();
  }, function(err) {
    console.error(err.stack);
    deferred.reject(err);
  });
});

});

return deferred.promise;
}
// FIM


em seu config.xml, adicione esta linha para incluir seu gancho:

O que o gancho fará é copiar seu ícone da pasta de recursos e adicioná-lo em diferentes pastas de drawables. Fiz isso para ter certeza de que funciona em todos os dispositivos. Até agora tudo bem.

Deixe-me saber se funcionou para você! Felicidades

@RobinGiel Obrigado, estou usando o ionic 3, vai funcionar?

Ola @Flucadetena
Android 9
Plataformas Cordova: android 7.1.1

@bioyeneye Estou usando o iônico 3 também. Vou verificar tudo e deixar você saber. ;)

@bioyeneye Sim, será, você terá que modificar algumas linhas do gancho.

var sourceDir = 'resources / android / notification_icon';
var platformDir = 'plataformas / android';

e talvez em vez de usar const Q = require ("q"); remova essa linha e use-a aqui .. exemplo:

module.exports = function (ctx) {

if (ctx.opts.platforms.indexOf ('android') <0) {
Retorna;
}

var Q = ctx.requireCordovaModule ('q'); // use aqui
var diferido = Q.defer ();
var androidPlatformDir = path.join (ctx.opts.projectRoot, platformDir);
var customResourcesDir = path.join (ctx.opts.projectRoot, sourceDir);


Adicione no config.xml chamando o mesmo exemplo before_build e before_run:

<hook type="before_run"         src="hooks/android_notification_resources.js" />
<hook type="before_build"       src="hooks/android_notification_resources.js" />

Teste se este código adicionado à tag config.xml <platform name="android"> adicionará o ícone como ícone de notificação padrão.

<config-file parent="/manifest/application/" target="app/src/main/AndroidManifest.xml">
    <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>

Isso funciona para mim enviando pelo painel Firebase Cloud Messaging ou back-end sem ícone na carga útil.
Por favor, poste aqui o feedback.
Se funcionar, seu tutorial adicionado a este código ajudará muita gente e deverá abrir um PR para adicioná-lo ao README.

Você fez meu dia,

se alguém enfrentar problemas na construção, como

AAPT: erro: prefixo não ligado.

em seguida, tente adicionar o

xmlns: android = " http://schemas.android.com/apk/res/android "

atributo deve ser adicionado à tag raiz dentro do config.xml

Isso aqui funciona para mim, mas o ícone parece ser incrivelmente pequeno, qual é o tamanho correto do arquivo que devemos usar?

Edit: Eu adicionei 256x256 mas ainda mostra um pequeno ponto na barra de status. arrastar a barra de status para o fundo mostra uma ligeiramente maior

É

Você é meu salvador !! Obrigada!!!
Notas:
Eu adiciono a cor: '# e50012' na seção de notificação para mudar para a cor do ícone. (Mude para qualquer cor).
ex:
{
"nome": "minha_notificação",
"notificação": {
"body": "Corpo de notificação",
"título": "Título de notificação",
"color": "# e50012"
},
"dados":{ ... }
}

Esta página foi útil?
0 / 5 - 0 avaliações