Кордова 6.3.1
Плагин Phonegap Firebase 0.1.12
Устройство: LG G5 с Android 6.0.1
Это код, который я использую:
`var app = {
// Конструктор приложения
инициализировать: function () {
this.bindEvents ();
},
// Связываем слушателей событий
//
// Связываем любые события, которые требуются при запуске. Общие события:
// 'load', 'deviceready', 'offline' и 'online'.
bindEvents: function () {
document.addEventListener ('deviceready', this.onDeviceReady, ложь);
},
// Обработчик событий deviceready
//
// Область действия this - событие. Чтобы вызвать «receiveEvent»
// функция, мы должны явно вызвать app.receivedEvent (...);
onDeviceReady: function () {
console.log ("Estamos en onDeviceReady");
if (navigator.connection.type == Connection.NONE) {
navigator.notification.alert («Se Requiere conexión a Internet»);
} еще {
window.FirebasePlugin.onNotificationOpen (функция (уведомление) {
console.log (уведомление);
navigator.notification.alert («Рецибидо»);
}, функция (ошибка) {
console.log (ошибка);
});
}
},
};
app.initialize (); `
Я получаю уведомления на панели задач во всех ситуациях: приложение в фоновом режиме, на переднем плане и закрыто, и когда я нажимаю на уведомление, приложение открывается в трех случаях, но обратный вызов не запускается.
Что-то не так в коде?
Заранее спасибо.
та же проблема, на Android-уведомления приходят, но внутри приложения не вызывается обратный вызов.
Версия 0.1.12
@voidbrain @Kibukita, пожалуйста, протестируйте последнюю версию из репо. Пытался улучшить открытое уведомление. Спасибо.
@BugsBunnyBR Я просто попробовал обновить репо до последней версии и просто протестировал ее. На 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 , вы пробовали указывать на
Установка с гитхаба частично решила проблему. Спасибо.
cordova plugin remove cordova-plugin-firebase
cordova plugin add https://github.com/arnesson/cordova-plugin-firebase/
Теперь обратный вызов onNotificationOpen () вызывается, когда приложение находится в фоновом режиме.
Когда приложение находится на переднем плане, а не в документации, приходит уведомление и onNotificationOpen () не вызывается:
Приложение на переднем плане:
Пользователь получает данные уведомления в обратном вызове JavaScript без каких-либо уведомлений на самом устройстве (это нормальное поведение push-уведомлений, уведомление пользователя зависит от вас, разработчика)
Если вы отправляете push типа «уведомление» (без тела данных), уведомление не должно отображаться, когда приложение находится на переднем плане.
Извините, я не поняла. Должен ли я просто добавить раздел «данные» в мои данные уведомления?
(
[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 (идентификатор, уведомление) отправляет уведомление, которое будет отображаться в строке состояния.
Однако мне кажется, что каждый раз, когда я получаю сообщение от FCM, в строке состояния будет отображаться уведомление.
Я не вижу никакой проверки, находится ли приложение на переднем плане, и я не вижу никаких вызовов обратного вызова. Я не разработчик Android, поэтому, возможно, я ошибаюсь, но описанное поведение подходит к этому.
Хорошо, я нашел фрагмент кода, который вызывает обратный вызов.
С последней фиксацией от BugsBunnyBR было изменение в OnNotificationOpenReceiver, которое объясняет, что arivanbastos запускает свой обратный вызов при указании на репозиторий github.
Но все же уведомление отправляется (в OnNotificationOpenReceiver и NotificationManager) только в том случае, если есть текст или заголовок (в уведомлении или в данных). Это означает, что невозможно отправить данные в ваше приложение, не получив уведомление, отправленное в NotificationManager, который показывает его в StatusBar.
@arivanbastos
Я сказал тебе что-то не так. Извини за это.
Вы пробовали указать на эту версию репо?
@packowitz и @robertarnesson . Хорошо, моя реализация ВСЕГДА * будет пытаться показать уведомление. Или будет отображаться автоматически отображаемое уведомление Firebase или одна сборка внутри onMessageReceived
.
Обратный вызов onNotificationOpen
будет вызываться при вызове onMessageReceived
или когда уведомление имеет тела данных и уведомлений одновременно. В моем PR, который представил onNotificationOpen
я пытался объяснить, что push-уведомления типа Notification не вызовут обратный вызов. Рекомендуется всегда включать тело данных и тело уведомления, чтобы плагин мог обнаруживать и запускать обратный вызов.
Большинство разработчиков приложений для Android хотят, чтобы их уведомления отображались в системном трее, даже если приложение находится на переднем плане. Я знаю, что в приложениях для чата есть случаи, когда такое поведение нехорошо.
Когда я разрабатывал функцию уведомлений для Android, меня не волновали потребности приложений чата или соответствие Firebase.
Что можно сделать:
1) Разработайте флаг, который будет установлен, когда приложение открыто, говоря «эй, я хочу, чтобы вы показывали уведомление, даже когда приложение открыто», и используйте его для управления поведением. Его не нужно было бы сохранять в каком-либо хранилище, если бы приложение всегда устанавливало флаг при открытии.
2) Просто прокомментируйте эту строку и отключите уведомление, когда приложение находится на переднем плане.
_Всегда_ -> Если плагин находит «текст» или «заголовок» в теле уведомления.
@BugsBunnyBR Мне нравится идея иметь флаг для выбора поведения.
Я бы отделил NotificationManager от OnNotificationOpenReceiver, выполняя обратный вызов вашего JS-обратного вызова. Я рекомендую ввести проверку, есть ли данные в сообщении, и если да, то вызвать обратный вызов с данными.
Для уведомления хорошо бы иметь флаг.
Спасибо.
@BugsBunnyBR Я только что протестировал переключение на
Но теперь обратный вызов работает;)
То же самое и здесь, для меня версия 0.1.13 вызывает перезапуск моего приложения, когда оно находится на переднем плане. Версия 0.1.12 работает нормально.
Уведомления просто не работают разумно в репо-версии. Причина в том, что я думаю, что если 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);
который заставляет клиента перезагружаться, когда доступен notificationBundle
когда зарегистрирован обратный вызов onNotificationOpen
поэтому клиент получает уведомление.
Я переписал всю обработку 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, но мое приложение перезапускается после открытия уведомления.
какие-нибудь Новости ?
Я не могу добиться успеха или сбоя обратного вызова onNotificationOpen на Android, используя 0.1.17. Ни отправка через API, ни GUI с полезной нагрузкой не работает. Какие-либо предложения?
Почему бы нам не создать пул-реквест с опубликованным кодом
Мне пришлось обновить onNewIntent в FirebasePlugin, чтобы отфильтровать обычные намерения запуска, поэтому мой код 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 Не могли бы вы создать gists со всеми имеющимися у вас файлами?
Хорошо, вот это 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 в качестве параметра и выполнить перенаправление вручную (я использовал cordova с приложением реакции).
Самый полезный комментарий
Я переписал всю обработку
onNotificationOpen
и теперь она работает почти так, как я ожидал, а именно:onNotificationOpen
вызывается в текущем клиенте (без перезагрузки)onNotificationOpen
вызывается текущим клиентом (без перезагрузки)Единственное, что осталось, - это немедленно доставить уведомление клиенту, не открывая его, если это вообще возможно (еще не изучил).
Я немного новичок в Android, поэтому могут быть внесены некоторые улучшения, но, похоже, все работает нормально, поэтому подумал, что поделюсь.
OnNotificationOpe nReceiver: onReceive теперь просто вызывает
Изменен
FirebasePlugin
следующим образом