#android #push-notification #rabbitmq #jobservice
Вопрос:
Я пытаюсь создать службу уведомлений в своем приложении для Android, которая всегда прослушивает мой сервер RabbitMQ для получения новых сообщений. Я хочу, чтобы он мог отправлять уведомления даже в фоновом режиме. В основном я пытаюсь создать связь уведомлений между двумя клиентскими приложениями (App1 и App2) через Rabbit MQ и отправлять уведомления обоим приложениям в случае события.
Я реализовал его с помощью класса обслуживания ЗАДАНИЙ, но он не согласован, и через некоторое время он останавливается. Может кто-нибудь, пожалуйста, помочь мне лучше понять архитектуру. Как я могу создать что-то вроде службы обмена сообщениями Firebase, но через Rabbit MQ?
Пример кода, который я использовал ниже:
public class StoreOrderJobService extends JobService {
private static final String TAG = "JobService";
Random random = new Random();
SharedPrefManager prefManager;
private boolean jobCancelled = false;
@Override
public boolean onStartJob(JobParameters jobParameters) {
Log.d(TAG, "Job Started");
prefManager = new SharedPrefManager(this);
subscribeStore(prefManager.getUserId(), jobParameters);
return true;
}
private void subscribeStore(String storeId, JobParameters parameters) {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(HOST_IP);
factory.setAutomaticRecoveryEnabled(false);
String queueName = prefManager.getSessionId();
if (queueName != null) {
Thread subscribeStoreThread = new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "Job Started");
try {
if (jobCancelled) {
return;
}
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
Log.d("OrderService", "Session Id " queueName);
channel.queueDeclare(queueName, false, false, false, null);
channel.queueBind(queueName, "store_test", storeId);
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
Log.d("OrderService", "Received message " message);
Envelope envelope = delivery.getEnvelope();
String routingKey = envelope.getRoutingKey();
if (routingKey.equals(storeId)) {
channel.basicAck(envelope.getDeliveryTag(), true);
String message_new = new String(delivery.getBody(), "UTF-8");
Gson gson = new Gson();
OrderSubscribePayload payload = gson.fromJson(message_new, OrderSubscribePayload.class);
Log.d("order Service", "Order Id " payload.getOrderId());
sendOrderNotification(random.nextInt(), payload);
}
};
channel.basicConsume(queueName, false, deliverCallback, consumerTag -> {
});
} catch (TimeoutException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
});
subscribeStoreThread.start();
}
}
private void sendOrderNotification(int id, OrderSubscribePayload payload) {
Log.d("Service", "sendOrderNotification " payload.getOrderId());
Intent contextIntent = new Intent(this, OrderDetails.class);
Bundle args = new Bundle();
args.putSerializable("orderDetails", (Serializable) payload);
contextIntent.putExtra("Bundle", args);
int iUniqueId = (int) (System.currentTimeMillis() amp; 0xfffffff);
PendingIntent pIntent = PendingIntent.getActivity(this, iUniqueId, contextIntent, 0);
Notification n = new NotificationCompat.Builder(this, ManagedApplication.CHANNEL_ORDER_ID)
.setContentTitle("New Order")
.setContentText("Received New Order")
.setSmallIcon(R.drawable.ic_stat_name)
.setContentIntent(pIntent)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setColor(getResources().getColor(R.color.color_primary))
.setCategory(NotificationCompat.CATEGORY_REMINDER)
.build();
NotificationManager notificationManager =
(NotificationManager) getSystemService(Service.NOTIFICATION_SERVICE);
notificationManager.notify(id, n);
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
Log.d(TAG, "Job Cancelled");
jobCancelled = true;
return true;
}
}
Я вызываю эту работу для входа пользователей, как показано ниже:
private void startNotificationJob() {
ComponentName componentName = new ComponentName(this, StoreOrderJobService.class);
JobInfo info = new JobInfo.Builder(123, componentName)
.setPersisted(true)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPeriodic(15 * 60 * 1000)
.build();
JobScheduler jobScheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
int result = jobScheduler.schedule(info);
if (result == JobScheduler.RESULT_SUCCESS) {
Log.d("JOB Scheduler", "Job Scheduled");
} else Log.d("JOB Scheduler", "Job Scheduled Failed");
}
Ответ №1:
Я реализовал его с помощью класса обслуживания ЗАДАНИЙ, но он не согласован, и через некоторое время он останавливается.
Ничто не будет поддерживать ваш процесс в рабочем состоянии, что вам понадобится для желаемой функциональности. Ничто не будет постоянно поддерживать процессор включенным, что также будет необходимо для вашей желаемой функциональности.
Пожалуйста, имейте в виду, что то, что вы хотите, довольно вредно для срока службы батареи.
Как я могу создать что-то вроде службы обмена сообщениями Firebase, но через Rabbit MQ?
Используйте службу переднего плана с непрерывной частичной WakeLock
обработкой в отдельном процессе ( android:process
атрибут манифеста), отличном от пользовательского интерфейса вашего приложения. Вам также может потребоваться код для восстановления подключения MQ, когда устройство меняет подключение (например, с Wi-Fi на мобильные данные) или теряет, а затем восстанавливает подключение.
Вам также нужно будет попросить своих пользователей зайти в приложение «Настройки» и попытаться отключить ваше приложение от всех оптимизаций заряда батареи. Обратите внимание, что это будет возможно не на всех устройствах.
Вам также нужно будет попросить своих пользователей никогда не убивать задачу вашего приложения. Отдельный процесс может помочь на некоторых устройствах, если пользователи забудут, но это поведение, по-видимому, зависит от устройства.
И вам нужно будет принять во внимание, что ваше решение не будет надежным, потому что некоторые производители устройств запрещают разработчикам делать то, что вы хотите, так как это плохо сказывается на времени автономной работы.
Комментарии:
1. Привет, спасибо за подробное объяснение. Так что это не очень хорошая практика и совсем не правильный способ ее применения. Каким должен/может быть правильный способ сделать это? Кроме того, как тогда другие приложения, такие как Zomato, Whatsapp и т.д., Отправляют push-уведомления пользователю? Является ли единственным решением использование службы обмена сообщениями от Firebase? Еще раз спасибо за ваш ответ
2. @HarshPalit: «Так что это не очень хорошая практика и совсем не правильный способ ее применения» — я бы описал ее как чреватую проблемами. «Каким должен/может быть правильный способ сделать это?» — У облачных сообщений Firebase есть свои недостатки (проприетарные, привязанные к сервисам Google и т. Д.), Но это поможет вам преодолеть проблемы, упомянутые в моем ответе. Для устройств, не связанных с игровыми сервисами, см., какие опции предоставляются производителем устройства. «как другие приложения, такие как Zomato, Whatsapp и т. Д., Отправляют push-уведомления пользователю?» — Вероятно, облачные сообщения Firebase, хотя у меня нет хорошего способа узнать.
3. Спасибо вам за ваше обсуждение. Попытаюсь внедрить облачные сообщения Firebase в мою архитектуру