科尔多瓦 6.3.1
Phonegap Firebase 插件 0.1.12
设备: LG G5 与 Android 6.0.1
这是我正在使用的代码:
`var app = {
// 应用程序构造器
初始化:函数(){
this.bindEvents();
},
// 绑定事件监听器
//
// 绑定启动时需要的任何事件。 常见事件有:
// “加载”、“设备就绪”、“离线”和“在线”。
绑定事件:函数(){
document.addEventListener('deviceready', this.onDeviceReady, false);
},
// 设备就绪事件处理程序
//
// 'this' 的作用域是事件。 为了调用'receivedEvent'
// 函数,我们必须显式调用'app.receivedEvent(...);'
onDeviceReady: 函数 () {
console.log ("Estamos en onDeviceReady");
if (navigator.connection.type == Connection.NONE) {
navigator.notification.alert('Se requiere conexión a Internet');
} 别的 {
window.FirebasePlugin.onNotificationOpen(function(notification) {
控制台日志(通知);
navigator.notification.alert(“Recibido”);
}, 函数(错误){
控制台日志(错误);
});
}
},
};
app.initialize();`
我在所有情况下都在系统托盘中收到通知:应用程序在后台,前台和关闭,当我点击通知时,在三种情况下应用程序打开但未触发回调。
代码有什么问题吗?
提前致谢。
同样的问题,在 android 通知到达但在应用程序内部没有调用回调。
v. 0.1.12
@voidbrain @Kibukita请从 repo 测试最新版本。 我试图改进打开通知。 谢谢。
@BugsBunnyBR我只是尝试更新到最新版本的 repo 并对其进行了测试。 在 Android 上它仍然没有执行 onNotificationOpen。
@superheroben ,您能否提供一个存储库,其中包含您如何调用插件代码的示例? 你是如何发送通知的? 我用主题消息进行了测试。
同样的问题在这里。
调用 getInstanceId() 回调,通知到达,但从未调用 onNotificationOpen()。
客户代码:
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();
}
我的通知数据结构:
(
[to] => (device token)
[notification] => Array
(
[title] => Title
[text] => Test message
[sound] => default
[vibrate] => 1
[badge] => 2
)
)
我的服务器端代码(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);
在 Cordova Android 5.2.2 上工作。 用于测试的设备运行 Android 4.4.2。 插件版本 0.1.12。
@arivanbastos ,您是否尝试过指向 github 存储库?
从github安装部分解决了这个问题。 谢谢你。
cordova plugin remove cordova-plugin-firebase
cordova plugin add https://github.com/arnesson/cordova-plugin-firebase/
现在,当应用程序在后台时调用 onNotificationOpen() 回调。
当应用程序处于前台时,而不是文档说明,通知到达并且不调用 onNotificationOpen():
应用程序在前台:
用户在 JavaScript 回调中收到通知数据,设备本身没有任何通知(这是推送通知的正常行为,由您作为开发人员来通知用户)
如果您发送“通知”类型(没有数据主体)的推送,则当应用程序处于前台时,不应显示通知。
对不起,我没看懂。 我应该在我的通知数据中添加一个“数据”部分吗?
(
[to] => (device token)
[notification] => Array
(
[title] => Title
[text] => Test message
)
[data] => Array
(
[test] => 1
)
)
这并没有解决问题。
通过“数据”重命名“通知”部分会使应用程序在通知到达时崩溃(“应用程序已停止”):
(
[to] => (device token)
[data] => Array
(
[title] => Title
[text] => Test message
)
)
https://firebase.google.com/docs/cloud-messaging/android/receive
这里描述的很好。
如果应用程序在后台,您的通知将发送到系统托盘,如果应用程序在前台,您的通知将发送到 onMessageReceived()。
如果您的消息包含数据,则始终将其传递给 onMessageReceived()。
我觉得是onMessageReceived()的实现有问题。
当我查看代码时,我解释如下:
NotificationManager.notify(id, notification) 发布要在状态栏中显示的通知。
然而,对我来说,这似乎是预期的,每次我收到来自 FCM 的消息时,它都会在状态栏中显示一条通知。
我没有看到任何检查应用程序是否在前台,也没有看到对回调的任何调用。 我不是 Android 开发人员,所以也许我错了,但所描述的行为符合这一点。
好的,我找到了调用回调的代码段。
随着 BugsBunnyBR 的最后一次提交,OnNotificationOpenReceiver 发生了变化,这解释了 arivanbastos 在指向 github 存储库时执行他的回调。
但是,如果有文本或标题(在通知或数据中),通知只会发送(到 OnNotificationOpenReceiver 和 NotificationManager)。 这意味着不可能在不将通知发送到 NotificationManager 的情况下将数据发送到您的应用程序,该通知在状态栏中显示它。
@arivanbastos
我对你说错了。 对于那个很抱歉。
你试过指向这个 repo 版本吗?
@packowitz和@robertarnesson 。 好的,我的实现将始终*尝试显示通知。 或者 Firebase 自动显示的通知或onMessageReceived
的一个构建将被显示。
当onMessageReceived
被调用或通知同时具有数据和通知正文时,将调用onNotificationOpen
回调。 在我介绍onNotificationOpen
公关中,我试图解释通知类型的推送通知不会触发回调。 建议始终包含数据主体和通知主体,以便插件可以检测并触发回调。
大多数 Android 应用程序开发人员希望他们的通知显示在系统托盘中,即使应用程序在前台也是如此。 我知道在某些情况下,例如聊天应用程序,这种行为不是一件好事。
当我开发 Android 通知功能时,我并不关心聊天应用程序的需求或遵守 Firebase。
可以做的是:
1)开发一个在应用程序打开时设置的标志,说“嘿,我希望你即使在应用程序打开时也显示通知”并用它来控制行为。 如果应用程序在打开时始终设置标志,则不需要将其保存在任何存储中。
2)只需注释此行并在应用程序处于前台时禁用通知。
_Always_ -> 如果插件在通知正文中找到“文本”或“标题”。
@BugsBunnyBR我喜欢有一个标志来选择行为的想法。
我会将 NotificationManager 与回调您的 JS 回调的 OnNotificationOpenReceiver 分离。 我的建议是引入一个检查,如果消息中有数据,如果有,则使用数据调用回调。
对于通知,最好有标志。
谢谢你。
@BugsBunnyBR我刚刚测试切换到 github 存储库,发现点击通知会重新启动我的应用程序,即使它已经在运行。 即使应用程序在前台并且我点击通知也会发生。
但回调现在有效;)
同样在这里,对我来说,版本 0.1.13 导致我的应用程序在前台时重新启动。 0.1.12 版本运行良好。
通知在 repo 版本中无法正常工作。 原因是我认为,如果在打开通知之前调用onNotificationOpen
,它会被忽略。
https://github.com/arnesson/cordova-plugin-firebase/blob/master/src/android/FirebasePlugin.java#L123
在registerOnNotificationOpen
,如果有notificationBundle
等待,它只会注册回调
此外,如果已经打开,应用程序似乎重新加载的原因在OnNotificationOpenReceiver
它明确指出
launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
这会强制客户端重新加载,当onNotificationOpen
回调注册时notificationBundle
可用时,客户端会收到通知。
我已经重新编写了整个onNotificationOpen
处理,并且几乎可以按我的预期工作,即:
onNotificationOpen
(无需重新加载)onNotificationOpen
(无需重新加载)剩下的唯一一件事就是让通知立即发送给客户端,而无需打开,如果可能的话(还没有研究过)。
我是一个 Android 菜鸟,所以可能会有一些改进,但它似乎工作正常,所以我想我会分享。
OnNotificationOpe nReceiver:onReceive现在只需调用
FirebasePlugin.onBroadcastReceive(context, intent);
将FirebasePlugin
更改如下
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);
}
}
嗯......我注意到当客户端没有运行(已被杀死)时,通知没有发送(到设备)。
尝试直接打开 firebase 提供的通知并查看行为。我猜他们重新启动了我认为是正确行为的主要活动。
抱歉耽搁了。 我尝试了 0.1.13,但我的应用程序在通知打开后重新启动。
任何新闻 ?
我无法在使用 0.1.17 的 android 上获得任何 onNotificationOpen 回调成功或失败。 使用有效负载通过 API 或 GUI 发送都不起作用。 有什么建议?
为什么我们不用@Mehuge发布的代码创建一个拉取请求?它对我来说就像 android 上的魅力一样。
我不得不更新 FirebasePlugin 中的 onNewIntent 以过滤掉正常的启动意图,所以我的 onNewIntent 代码现在看起来像这样
<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");
}
}
}
我对此并不完全满意。 它通过在我的服务器代码总是发送的意图包中查找 id 属性来工作。 似乎没有任何 GCM 或 FBM 可靠地添加到包中可用于将意图识别为通知/消息的内容。 有时我们会添加一些 google 属性(如果我们从托盘打开通知)但是对于在前台时直接传递给客户端的消息和通知,除了消息中的数据告诉您这是一个启动意图之外别无其他由于通知,至少我可以看到。
可能有更好的方法来处理这个问题。
@Mehuge你介意用你拥有的所有文件创建
好的,这里是https://gist.github.com/Mehuge/374ee24d9e18a6c7ccc171d3e521b7ad
但是请注意,其中有一些特定于我们的应用程序的位。 我最终将代码移到了我们的项目中,因为我对其进行了大量更改。 事后看来,我可能应该对插件进行分叉并以这种方式对其进行修改,但此时,我已经落后于计划并且对整个事情感到非常厌烦,所以我采取了最快的方式来让一些东西工作。 自定义位相当明显,因此应该很容易排除。
另请注意,我实现插件的方式,它需要知道客户端何时暂停(或更具体地说是未暂停),以便它可以决定是创建通知还是直接传递消息。 您可能需要也可能不需要该功能,但在我们的例子中,我们不希望客户端在前台时发送的通知来创建 android 通知,而是直接传递给客户端进行处理。 要通知插件客户端的暂停状态,请将以下代码添加到您的主要活动中。
<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();
}
您可能需要解决另一个问题,即如果通知在后台到达但用户直接启动应用程序,而不是通过打开 android 通知,您可能需要以某种方式处理该问题。 在我们的应用程序案例中,我可以清除任何未打开的通知。 您的情况可能有所不同。
我对最终结果并不完全满意,例如添加的一些额外键是实验性的,实际上并没有被使用,我只是没有时间删除它们。
会对任何反馈或建议的改进或指出任何缺陷感兴趣。 我特别感兴趣的是找到一种方法来更好地检测来自正常发射的 GCM 有效载荷的发射意图。 我发现 google 属性仅在某些情况下添加。 此外,我尝试检测不同类型的通知(is_push、is_notify、broadcast)并没有真正奏效。
见#108
对我来说,我可以解决提出这样的请求:
{
"registration_ids": [...tokens],
"notification" : {
"title": "Notf title",
"body": "Notification body"
},
"data": {
"click_action": "/call/dwEugLJ9PTVdcFb064CX"
}
}
但是我不得不将 click_action 作为参数并手动进行重定向(我使用的是带有 react 应用程序的cordova)。
最有用的评论
我已经重新编写了整个
onNotificationOpen
处理,并且几乎可以按我的预期工作,即:onNotificationOpen
(无需重新加载)onNotificationOpen
(无需重新加载)剩下的唯一一件事就是让通知立即发送给客户端,而无需打开,如果可能的话(还没有研究过)。
我是一个 Android 菜鸟,所以可能会有一些改进,但它似乎工作正常,所以我想我会分享。
OnNotificationOpe nReceiver:onReceive现在只需调用
将
FirebasePlugin
更改如下