Выполнил все пожелания из технического задания плюс еще сверху то, что я запрашивал, он реализовал.
Всем рекомендую фрилансера!
Есть приложение для андроида, в котором реализованы push-уведомления, но они работают не так, как мне хотелось бы. Если приложение открыто, то уведомления появляются сверху и их видно. Но если приложение свернуто или не запущено, то уведомления приходят, но беззвучно, и узнать о том, что уведомление пришло, можно только открыв шторку и найдя его.
Вот так у меня реализованы уведомления в файле MessagingService.kt
package app.provapp.online
import android.Manifest
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.media.RingtoneManager
import android.os.Build
import android.util.Log
import android.widget.RemoteViews
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
const val channelId = "main_channel"
SuppressLint("MissingFirebaseInstanceTokenRefresh") # Убрал знак собаки, потому что фриланс не публикует проект, думая, что это имейл :)
class MessagingService: FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
message.notification!!.title?.let { message.notification!!.body?.let { it1 ->
createNotificationChannel(it, it1
) } }
Log.d("SDDS", "DSADAS")
}
private fun createNotificationChannel(title: String, body: String) {
val notificationChannel = NotificationChannel(channelId,
"Message Channel",
NotificationManager.IMPORTANCE_HIGH)
notificationChannel.canBypassDnd()
notificationChannel.setBypassDnd(true)
notificationChannel.enableVibration(true)
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.createNotificationChannel(notificationChannel)
val notification: Notification = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body)
.setChannelId(channelId)
.setDefaults(Notification.DEFAULT_ALL)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setPriority(NotificationCompat.PRIORITY_HIGH) // heads-up
.setFullScreenIntent(null, true)
.build()
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
return
}
notificationManager.notify(0, notification)
}
}То же самое приложение имеет версию для айфона, и там уведомления работают как надо - они всегда появляются сверху, даже если приложение не запущено, таким образом пользователь видит, что уведомление пришло.
Бюджет: 500 UAH Срок: 1 день
Давайте разберемся в чем проблема.
У меня есть опыт с пушами.
Обращайтесь.
Бюджет: 500 UAH Срок: 1 день
Привет!
Я готов взять на себя выполнение этой задачи. У меня около трех лет опыта разработки Android-приложений, в частности, я уже работал с подобными функциями. Могу быстро и качественно реализовать необходимый функционал.
Готов обсудить все детали в личных сообщениях. Могу приступить к работе сегодня.
Буду рад сотрудничеству!
1. Сповіщення обробляється у фоновому режимі Firebase SDK, але ви не встановлюєте правильний контекст для звукового сигналу.
2. Пріоритет повідомлення може бути недостатнім (хоча у вас стоїть PRIORITY_HIGH).
3. FullScreenIntent може бути некоректно реалізований або не потрібний.
Ось кілька способів вирішити проблему:
1. Налаштуйте звуковий сигнал
У вашому методі createNotificationChannel можна додати кастомний звук для каналу:
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
notificationChannel.setSound(soundUri, Notification.AUDIO_ATTRIBUTES_DEFAULT)
2. Оновіть FullScreenIntent
Замість null використовуйте PendingIntent для відкриття Activity, якщо це потрібно:
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(
this, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val notification: Notification = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body)
.setChannelId(channelId)
.setDefaults(Notification.DEFAULT_ALL)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setFullScreenIntent(pendingIntent, true) // Важливо!
.build()Це змушує Android відображати сповіщення навіть тоді, коли додаток не запущений.
3. Переконайтеся, що IMPORTANCE_HIGH
Канал сповіщень має мати максимальний рівень важливості, як ви вказали:
notificationChannel.importance = NotificationManager.IMPORTANCE_HIGH
4. Перевірте дозволи на сповіщення
Переконайтеся, що у вас є дозвіл POST_NOTIFICATIONS, який потрібен з Android 13. Для пристроїв нижче Android 13 це не потрібно:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
// Запросіть дозвіл
return
}
}
5. Обробка сповіщень у фоновому режимі
В Android, коли додаток у фоновому режимі, Firebase передає сповіщення напряму у системний менеджер сповіщень. У такому разі вам потрібно обробляти дані через RemoteMessage.data, якщо використовуються data-сповіщення:
override fun onMessageReceived(message: RemoteMessage) {
if (message.data.isNotEmpty()) {
val title = message.data["title"] ?: "Default Title"
val body = message.data["body"] ?: "Default Body"
createNotificationChannel(title, body)
} else {
message.notification?.let {
createNotificationChannel(it.title ?: "Default Title", it.body ?: "Default Body")
}
}
}
6. Перевірте серверну конфігурацію
Якщо ви використовуєте Firebase Console для надсилання сповіщень, переконайтеся, що обираєте опцію “High Priority”. Якщо це ваш сервер, у JSON-даних встановіть priority: "high":
{
"to": "DEVICE_TOKEN",
"priority": "high",
"notification": {
"title": "Заголовок",
"body": "Текст повідомлення"
}
}
Після внесення цих змін перевірте додаток. Це має вирішити проблему із фоновими сповіщеннями
При спробі додати
"priority" => "high",отримую помилку
{ "error": { "code": 400, "message": "Invalid JSON payload received. Unknown name \"priority\" at 'message': Cannot find field.", "status": "INVALID_ARGUMENT", "details": [ { "@type": "type.googleapis.com/google.rpc.BadRequest", "fieldViolations": [ { "field": "message", "description": "Invalid JSON payload received. Unknown name \"priority\" at 'message': Cannot find field." } ] } ] } }
Ось правильний формат для запиту до FCM API: {
"message": {
"token": "DEVICE_TOKEN",
"notification": {
"title": "Заголовок",
"body": "Текст повідомлення"
},
"android": {
"priority": "high"
}
}
}
Зараз все по старому: в шторці сповіщення з'являється, але heads-up не відбувається, тобто користувач може дізнатися що було сповіщення лише подивившись в шторці.
У вас буде час подивитися вихідний код андроїду? Може там щось не доналаштовано? Хоча я дивився всі ті параметри що ви наводили в мене прописані: і NotificationCompat.PRIORITY_HIGH і NotificationManager.IMPORTANCE_HIGH
1. Неправильний NotificationChannel
У вашому коді є правильне створення каналу сповіщень, але перевірте, чи дійсно канал налаштований правильно. Зокрема:
• Перевірте, чи використовується IMPORTANCE_HIGH, який дозволяє сповіщенням з’являтися у вигляді heads-up (спливаючих) повідомлень.
• Для пробудження екрана потрібно також забезпечити, щоб канал мав дозвіл на порушення режиму “Не турбувати”. Ви вже викликаєте setBypassDnd(true), але цього недостатньо — на деяких пристроях це потребує явного дозволу від користувача.
Рішення: Додайте код для перевірки та явного дозволу для обходу режиму DND:
if (!notificationManager.areNotificationsEnabled()) {
// Направляємо користувача до налаштувань
val intent = Intent(android.provider.Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.putExtra(android.provider.Settings.EXTRA_APP_PACKAGE, packageName)
startActivity(intent)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = notificationManager.getNotificationChannel(channelId)
if (channel != null && !channel.canBypassDnd()) {
val intent = Intent(android.provider.Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(android.provider.Settings.EXTRA_APP_PACKAGE, packageName)
.putExtra(android.provider.Settings.EXTRA_CHANNEL_ID, channelId)
startActivity(intent)
}
}
2. setFullScreenIntent
Ваш setFullScreenIntent налаштований на null, що може не спрацьовувати для heads-up повідомлень або пробудження екрану.
Рішення: Використовуйте реальний PendingIntent:
val fullScreenIntent = Intent(this, MainActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(
this, 0, fullScreenIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notification: Notification = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body)
.setChannelId(channelId)
.setDefaults(Notification.DEFAULT_ALL)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setPriority(NotificationCompat.PRIORITY_HIGH) // heads-up
.setFullScreenIntent(fullScreenPendingIntent, true) // Важливо
.build()3. Специфіка пристрою
Деякі пристрої, такі як Xiaomi, Huawei, Oppo, мають власні обмеження на показ сповіщень:
• Фонова активність: Переконайтесь, що ваш додаток має дозвіл на запуск у фоновому режимі.
• Автоматична оптимізація батареї: Відключіть оптимізацію батареї для вашого додатку через налаштування пристрою.
Код для вимкнення оптимізації батареї:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val intent = Intent(android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
intent.data = Uri.parse("package:$packageName")
startActivity(intent)
}4. Налаштування екрану
Перевірте, чи дозволяє пристрій пробуджувати екран від сповіщень. Додайте це до коду:
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
if (!powerManager.isInteractive) {
val wakeLock = powerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP,
"app:WakeLock"
)
wakeLock.acquire(3000) // Пробудження на 3 секунди
}5. Додаткова перевірка дозволів
На Android 13 і вище потрібні дозволи для відображення heads-up сповіщень.
Переконайтесь, що дозволи POST_NOTIFICATIONS та USE_FULL_SCREEN_INTENT видані:
ActivityCompat.requestPermissions(this, arrayOf(
Manifest.permission.POST_NOTIFICATIONS
), 100)
android:exported
Ви встановили android:exported="false". Це означає, що цей сервіс може бути викликаний тільки вашим додатком, а не іншими програмами або системою.
Для Firebase Cloud Messaging (FCM) сервіс має бути доступним системі Firebase, тому android:exported має бути встановлено у true.
Ви отримуєте сповіщення, коли додаток не запущений? Чи тільки тоді, коли він запущений?
Є рішення для обох випадків…
Сповіщення приходять, але непомітно, тобто вони в шторці з'являються без видимого "вилітання" вгорі екрану (heads-up)
Здравствуйте, вы хотите, чтобы экран пробуждался, когда приходит уведомления?
Дорого, давайте за 500 грн як в задачі ))
Пуши в мене працюють, треба тільки щоб вони вспливали коли додаток згорнутий.
Напевно десь якийсь параметр треба написати і все. Тим паче якщо ви вже це робили то у вас це не займе багато часу.
Мы DTC wellness бренд, продаем БАДы на рынок США по подписке, а приложение является помощником, который ближе узнает клиента, получит его данные для дальнейшей рассылки по базе, которая будет напоминать о приеме БАДов (AM/PM), отмечать прием в календаре, показывать прогресс. Приложение геймифицировано с ачивками, персонализированными пуш-уведомлениями с комплиментами на каждый день и приятными предсказаниями (как в печеньках). Бекенд / данные — Firebase 1. ОнбордингПользователь открывает приложение — первый экран с логотипом SHE·8, фото девушки и текстом «Ваш ежедневный сброс начинается с вас.» Внизу кнопка «НАЧАТЬ», под ней ссылка «Уже есть аккаунт? Войти».2. РегистрацияПосле нажатия «Начать» начинается опрос из 5 шагов (Шаг 1 из 5). Первый вопрос: «Какова ваша основная цель?» — варианты: Лучший сон, Меньше стресса, Больше энергии (выбрано), Лучший фокус. Кнопка «ДАЛЕЕ» ведет дальше по шагам.3. Настройка напоминанийПосле опроса пользователь задает время двух напоминаний — утреннего (08:00) и вечернего (20:00), с пояснением, что приложение напомнит о приеме капсул. Кнопка «СОХРАНИТЬ».4. Утренний сбросЭкран приветствия: «Доброе утро, Сара ☀️», «День 8 вашего сброса», иллюстрация капсул со стаканом воды, инструкция принять утренние капсулы. Кнопка «Я СДЕЛАЛ ЭТО ✓» — пользователь отмечает выполнение.5. Поздний чек-ин / Вечерний сбросТемный экран с луной — «Вечерний сброс», текст «Самое время расслабиться и позаботиться о себе». Кнопка «Я СДЕЛАЛ ЭТО ✓».6. Напоминание, если пропущен вечерний приемЕсли пользователь забыл отметиться, показывается экран «Привет, Сара! » с иконкой уставшего смайлика, текстом «Вы еще не отметили вечерний прием» и двумя кнопками: «Да, сделать сейчас» (основная) и «Позже» (второстепенная).7. Главная панельПосле онбординга или входа пользователь попадает на главный экран: «Привет, Сара! », мотивационная фраза, блок «Текущая серия — 8 дней » и круговой индикатор «Прогресс — 80%». Внизу нижняя навигация: Главная, Прогресс, Календарь, Я.8. ПрогрессВкладка «Мой прогресс»: текущая серия (8 дней), «Дни завершены 8/10» с прогресс-баром, недельный трекер (Пн–Вс с отметками выполнено/пропущено), общий «Общий прогресс — 80%».9. КалендарьВкладка «Календарь»: месячный вид (Июнь 2025), дни отмечены цветом — выполнено (зеленый), сегодня (синий), пропущено (красный). Пользователь может нажать на конкретный день.10. Деталь дняПри выборе дня (8 июня 2025) открывается детальный экран: статус утреннего (08:15 ✓ Завершено) и вечернего (20:05 ✓ Завершено) приемов, плюс поле «Ежедневная заметка» с личной заметкой пользователя.11. Ваши результатыЭкран «Ваши результаты» — сравнение показателей «До» и «После» (Энергия, Сон, Стресс) в виде прогресс-баров, которые наглядно показывают улучшение. Кнопка «ПОСМОТРЕТЬ МОЙ ПУТЬ».12. МотивацияЭкран «Ежедневная мотивация» с фоновым фото и вдохновляющей цитатой: «Маленькие ежедневные действия создают большие изменения.»13. ДостиженияВкладка «Достижения»: список полученных наград (Первый шаг, 7 дней подряд, 10 дней подряд) и следующая цель («Следующее достижение — 30 дней подряд», прогресс 8/30).14. ПрофильВкладка «Профиль»: аватар и имя пользователя (Сара), список настроек — Личная информация, Напоминания, Уведомления, Подписка, Помощь и поддержка, и кнопка «Выйти».
Мы пройдемся по каждому пункту. Техническое задание на разработку мобильного приложения для службы доставки суши Необходимо разработать мобильное приложение (Android и iOS) по функционалу, максимально приближенное к сайту 911sushi.com.Основные требованияИнтеграция Полная интеграция с Poster POS. Все заказы должны автоматически поступать непосредственно в Poster. Использование существующей клиентской базы Poster. Автоматическое применение персональных скидок гостя, которые уже настроены в Poster.Авторизация пользователей Регистрация и авторизация. Вход по номеру телефона (или другой современный способ авторизации). Сохранение истории заказов. Персональные скидки и акции для пользователя.Меню Просмотр категорий и товаров. Детальная информация о позициях. Возможность добавления товаров в корзину. Выбор модификаторов и добавок (по необходимости).Корзина и оформление заказа Выбор адреса доставки. Сохранение нескольких адресов пользователя. Выбор города. Выбор времени доставки или "как можно быстрее". Отображение стоимости доставки в зависимости от зоны. Поддержка зон доставки с возможностью их редактирования.Административная панель Необходима удобная админ-панель с возможностью: редактирования меню; добавления и удаления позиций; изменения цен; изменения категорий; управления акциями; создания и рассылки промокодов; установки лимита использования промокодов; просмотра статистики.Акции и маркетинг Предусмотреть возможность: промокода на первый заказ; бонуса или скидки за установку приложения; создания промокодов с ограниченным количеством использований; массовых рассылок промокодов пользователям; проведения акций без необходимости обновления приложения.Аналитика Нужна детальная статистика: общая статистика работы приложения; статистика по каждой позиции меню; конверсия пользователей; количество установок; количество оформленных заказов; средний чек; повторные покупки; аналитика доставок по адресам; выборка 100 самых популярных улиц доставки; другие ключевые показатели для анализа продаж.Информационные разделы В приложении должны быть: ссылки на социальные сети; контакты; карта с расположением заведения; информация о компании; условия доставки и оплаты.Требования к работе приложения быстрая и стабильная работа; отсутствие зависаний и критических ошибок; современный и понятный интерфейс; поддержка актуальных версий Android и iOS.Дизайн Отдельного дизайна на данный момент нет. В качестве основы можно взять существующий сайт 911sushi.com. Все необходимые материалы уже подготовлены: логотипы; фирменные цвета; меню; брендбук (при наличии).Поэтапная реализация Рассматриваю поэтапную разработку:Этап 1 базовый функционал; интеграция с Poster; меню; корзина; оформление заказа; авторизация; личный кабинет.Этап 2 промокоды; система акций; аналитика; статистика; дополнительные маркетинговые инструменты; другие функции, которые будут возникать в процессе развития проекта.Дополнительные условия После завершения разработки нужно предоставить 30 дней тестового периода, в течение которого будут исправляться возможные недостатки. После успешного тестирования - финальный расчет. Важно, чтобы исполнитель был готов к постепенному расширению функционала, так как новые задачи могут возникать в процессе работы. Приоритет - максимально короткие сроки реализации без потери качества. Желательно, чтобы исполнитель был из Луцка, но это не является обязательным условием.Прошу в ответе на заявку указать: ориентировочные сроки реализации; стоимость; стек технологий; примеры похожих проектов; опыт интеграции с Poster POS; готовы ли работать поэтапно; предоставляете ли гарантийную поддержку после запуска.