Cordova-plugin-firebase: 更改推送通知图标 - 2018 年的空白 android 图标问题

创建于 2018-07-06  ·  22评论  ·  资料来源: arnesson/cordova-plugin-firebase

大家好你们好,

对于在cordova 8+上使用此插件的人,您可能会发现更改通知图标不起作用,并且您在Android上遇到了旧的“通知图标为空白方块”问题。 发生这种情况是因为 android 通知图标必须是透明背景上的简单 1 颜色形状,如果您尚未提供此类图标,android 将使用应用程序图标代替。 这些很可能是一个没有任何透明背景的彩色方块。

这在设置新的 Ionic 3 项目并尝试使用此插件时非常烦人。

自述文件 atm 没有描述正确更改图标的过程。 以下是更改图标所需的步骤:

0)停止在谷歌上搜索并拉出你的头发。 一步一步地按照这个说明操作,你会得到它的工作,相信我。
1) 准备在透明背景上只有 1 种颜色形状的应用程序图标版本
2)去这里: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 按“图像”在左上角,上传您的图标,修剪它/如果需要添加填充
3) 如果看起来不错,请按右上角的箭头下载“drawable”文件夹。 它将为您提供一个带有res文件夹的 zip 文件和 5 个drawable-xxx文件夹,每个文件夹都有不同大小的图标
4) 将那些 drawable 文件夹复制到您的项目中。 对我来说,我将它们复制到图标和闪屏资源旁边: project-root/resources/android/notification_icon
5) 配置您的 config.xml 文件以使用<resource-file />指令将这些文件复制到您的 android 应用程序中。 请注意,从 crodova 8.x 开始,正确的目标路径是app/src/main/res在cordova < 8 上它只是res (因为以前资源文件保存在platforms/android/res目录中,现在它们在platforms/android/app/main/res )。 大多数关于空白 android 通知图标的在线“已解决”问题都没有提及。

<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) 现在您在应用程序中有您的图标作为可绘制资源,您需要强制您的应用程序使用它。 不管这里的自述文件写了什么,自动发现名为“notification_icon”的可绘制资源对我不起作用。 我不确定为什么,因为它似乎在此处的代码库中:https://github.com/arnesson/cordova-plugin-firebase/blob/master/src/android/FirebasePluginMessagingService.java#L140 但我猜测最新版本的 android 上的资源发现发生了一些变化。
7)因此,我可以使用的唯一其他解决方案是在向 firebase 发送推送通知时从后端发送icon参数。 请注意,他们的 api 可能正在进行一些更改,因为它在正确合并有效负载的notificationandroid部分方面存在问题。 因此,您必须将图标参数添加到 json 的notification部分。 使用 android 特定参数不起作用。

因此,您从后端发送到 firebase 的通知负载必须看起来像这样:这是唯一有效的版本

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

让我重申一下 -自 2018 年 7 月起,使用 ANDROID 特定参数不适用于 FIREBASE - 以下将无法使用,并且您的通知图标不会改变,无论他们的文档如何说明

{
  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) 完成所有步骤后,您现在可以测试新图标了。 我强烈建议在 android 模拟器中对其进行测试 - 一些 android 皮肤会接管通知栏并使用应用程序图标,无论您设置什么(即小米的 MIUI)。 我还发现有时图标会被缓存。 因此,在新创建的 AVD 上的模拟器中对其进行测试是最安全的选择。 在测试运行之间手动删除您的应用程序并重新启动模拟器/设备以避免缓存问题。

我希望这篇长文能在未来对其他人有所帮助,因为改变 10x10 小图标所必须经历的障碍实在是太高了……

最有用的评论

请测试此代码添加到 config.xml <platform name="android">标签是否会将图标添加为默认通知图标。

<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>

这适用于我通过 Firebase 云消息传递面板或后端发送,负载上没有图标。
请在此处发布反馈。
如果它有效,您添加到此代码中的教程将对很多人有所帮助,并且应该打开 PR 将其添加到自述文件中。

所有22条评论

请测试此代码添加到 config.xml <platform name="android">标签是否会将图标添加为默认通知图标。

<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>

这适用于我通过 Firebase 云消息传递面板或后端发送,负载上没有图标。
请在此处发布反馈。
如果它有效,您添加到此代码中的教程将对很多人有所帮助,并且应该打开 PR 将其添加到自述文件中。

谢谢@madsheep !! 你救了我的命 !!

嗨,感谢您的道义支持,并让我觉得我不是唯一陷入这种混乱的人。 然而,不幸的是,我被吸引回了前步骤 0,在途中掉了头发。

当我尝试通过 http/post 方法发送通知时,我从 firebase api 收到错误,指出 json 无效。 我试过两种方式:

这就是我将图标包含为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.]]

这是将图标包含为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.]]

但也许我在错误的上下文中使用它(我们的后端云代码使用 firebase 云消息传递向客户端应用程序发送通知)。

这对我来说很好(我使用 firebase 函数发送通知):
const payload = { notification: { title: ........, body: ........., icon: 'notification_icon' } };

谢谢,这导致了我的两个错误中的第一个。 我通过 javascript / request 库使用 REST 服务,并根据https://firebase.google.com/docs/cloud-messaging/js/first-message格式发送。 我想消息/通知格式在https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#Notification 中有描述。

事实上,当我读到这个时,这表明图标应该在message.android.notification.icon ,即更深一层。

我刚刚尝试过,这实际上对我有用! 所以我想这取决于服务器协议应该如何构造有效负载......

谢谢大家的讨论。 它终于导致我停止拔头发......

关闭已解决

@madsheep它不起作用。在云功能的通知下添加“图标”后,出现以下错误:

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

错误信息:
{代码:'消息/无效参数',
消息:'收到无效的 JSON 负载。 “message.notification”中的未知名称“icon”:找不到字段。 },
代码前缀:'消息'}

尝试message.android.notification.icon而不是message.notification.icon

@madsheep @guilhermehtk对我

请测试此代码添加到 config.xml <platform name="android">标签是否会将图标添加为默认通知图标。

<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>

这适用于我通过 Firebase 云消息传递面板或后端发送,负载上没有图标。
请在此处发布反馈。
如果它有效,您添加到此代码中的教程将对很多人有所帮助,并且应该打开 PR 将其添加到自述文件中。

你让我今天很开心,

如果有人在构建中遇到问题

AAPT:错误:未绑定前缀。

然后尝试添加

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

属性应该添加到根config.xml 中的标签

你救了我的一天!

对于在 2019 年使用 android build 7.1.1 遇到此问题的任何人,资源文件夹似乎已更改!!

通过检查 Android Studio 和生成的文件,这里对我有用:

<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>

第一行是重要的部分,因为这对我来说是错误的。

@alarv某些 android 手机没有显示图标,请对此提供任何帮助。

@bioyeneye什么型号? 他们运行的是什么版本的 Android? 股票还是其他?

@bioyeney我有另一个 Ionic 4 解决方案,可以让图标在所有 android 设备上工作。
我没有使用 png 作为图标,而是使用 XML。 我正在使用钩子将其包含在以下目录中:

'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'

创建文件示例:
android_notification_resources.js

在这个新的钩子文件中添加:


// 开始
const fs = require("fs");
const path = require("path");
const Q = require("q");

var sourceDir = 'resources/android/notification_icon'; // 这是你的图标所在的位置
var platformDir = 'platforms/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 = 函数(ctx){

如果 (ctx.opts.platforms.indexOf('android') < 0) {
返回;
}

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

功能复制(源,目标){
var deferred = 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()) {
返回 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);
  });
});

});

返回 deferred.promise;
}
// 结尾


在您的 config.xml 添加这一行以包含您的钩子:

钩子会做的是从你的资源文件夹中复制你的图标,并将它添加到不同的 drawables 文件夹中。 我这样做是为了确保它适用于所有设备。 到现在为止还挺好。

让我知道它是否对你有用! 干杯

@RobinGiel谢谢,我正在使用 ionic 3,这行得通吗?

你好@Flucadetena
安卓 9
Cordova 平台:android 7.1.1

@bioyeneye我也在使用 ionic 3。 我会检查一切并让你知道。 ;)

@bioyeneye是的,您将不得不修改钩子中的几行。

var sourceDir = 'resources/android/notification_icon';
var platformDir = '平台/安卓';

也许而不是使用 const Q = require("q"); 删除该行并在此处使用它.. 示例:

module.exports = 函数(ctx){

如果 (ctx.opts.platforms.indexOf('android') < 0) {
返回;
}

var Q = ctx.requireCordovaModule('q'); // 在这里使用
var deferred = Q.defer();
var androidPlatformDir = path.join(ctx.opts.projectRoot, platformDir);
var customResourcesDir = path.join(ctx.opts.projectRoot, sourceDir);


在 config.xml 中添加调用相同钩子 before_build 和 before_run 示例:

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

请测试此代码添加到 config.xml <platform name="android">标签是否会将图标添加为默认通知图标。

<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>

这适用于我通过 Firebase 云消息传递面板或后端发送,负载上没有图标。
请在此处发布反馈。
如果它有效,您添加到此代码中的教程将对很多人有所帮助,并且应该打开 PR 将其添加到自述文件中。

你让我今天很开心,

如果有人在构建中遇到问题

AAPT:错误:未绑定前缀。

然后尝试添加

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

属性应添加到 config.xml 内的根标记

这对我有用,但图标似乎小得令人难以置信,我们应该使用的文件大小合适吗?

编辑:我添加了一个 256x256,但仍然在状态栏上显示一个小点。 将状态栏拖到底部显示一个稍大的

它是

你是我的救命稻草!! 谢谢!!!
笔记:
我在通知部分添加 color: '#e50012' 以更改图标的颜色。(将其更改为您的颜色)。
前任:
{
"name": "my_notification",
“通知”: {
"body": "通知正文",
"title": "通知标题",
“颜色”:“#e50012”
},
“数据”:{ ... }
}

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

merbin2012 picture merbin2012  ·  4评论

DanielAccorsi picture DanielAccorsi  ·  3评论

matthitachi picture matthitachi  ·  5评论

jdla1990 picture jdla1990  ·  4评论

danielpalen picture danielpalen  ·  5评论