Я использую OkSse , чтобы подписаться на события, отправленные моим сервером.
Когда сервер отправляет новое сообщение, должно отображаться уведомление, находится ли приложение на переднем плане, свернуто или полностью закрыто .
Уведомления работают, как и ожидалось, когда свернуто или на переднем плане , но когда полностью закрыто , это работает только на некоторых устройствах марки .
Исследуя бит , я обнаружил, что:
эта проблема замечена только на телефонах такими производителями, как Xiaomi,
Oppo, One Plus, Vivo, Lenovo, Huawei, Samsung и некоторые другие.
Как WhatsApp, Facebook, Slack, Gmail, etc..
отображает уведомления, даже если приложение закрыто?
Я не пользуюсь FCM
, просто подпишитесь на Sse
.
У меня также есть в манифесте:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name="com.goparty.communication.NotificationsAlarmReceiver">
<intent-filter>
<action android:name="android.media.action.DISPLAY_NOTIFICATION" />
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Как мне этого добиться?
Обновление
Мне удалось заставить его работать, используя IntentService
и BroadcastReceiver
, но это вылетает для Oreo
версий.
После более чтения я обнаружил, что JobIntentService
является заменой IntentService
при таргетинге Android O
и выше.
Переход на JobIntentService
был довольно простым, но опять же, мое решение не работает, когда я закрываю приложение.
Цель уведомлений - работать, даже когда приложение закрыто.
Использование IntentService
работало в фоновом режиме, отправив broadcast
с новым намерением моего сервиса.
Я делаю то же самое с JobIntentService
без удачи.
Вот мой код:
public class NotificationService extends JobIntentService {
private static final int JOB_ID = 1;
private NotificationManager notificationManager;
public static void enqueueWork(Context context, Intent intent) {
enqueueWork(context, NotificationService.class, JOB_ID, intent);
}
@Override
public void onCreate() {
super.onCreate();
Logger.logGoParty(getClass().getSimpleName() + "#onCreate");
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
public void onDestroy() {
super.onDestroy();
Logger.logGoParty("Running in background.");
sendBroadcast(new Intent(getApplicationContext(), NotificationService.class));
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
Logger.logGoParty(getClass().getSimpleName() + "#onHandleWork");
Logger.logGoParty("Sse initialized");
Request request = new Request.Builder().url("the sse url").build();
OkSse okSse = new OkSse();
ServerSentEvent sse = okSse.newServerSentEvent(request, new ServerSentEvent.Listener() {
@Override
public void onOpen(ServerSentEvent sse, Response response) {
Logger.logGoParty(response.toString());
}
@Override
public void onMessage(ServerSentEvent sse, String id, String event, String message) {
Logger.logGoParty("Sse#onMessage: " + message);
try {
JSONObject promoJson = new JSONObject(message);
sendNotification(...);
} catch (JSONException e) {
Logger.logGoParty("JSONException: " + e.toString());
}
}
// ...
});
}
private void sendNotification(String promoImageUrl, String notificationContent, String title) {
try {
URL url = new URL(promoImageUrl);
Bitmap bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
style.bigPicture(bitmap);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Intent intent = new Intent(this, MapsActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("page-to-open", "promotions");
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, GoParty.PROMO_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle(title)
.setAutoCancel(true)
.setSound(defaultSound)
.setContentText(notificationContent)
.setContentIntent(pendingIntent)
.setStyle(style)
.setLargeIcon(bitmap)
.setWhen(System.currentTimeMillis())
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE);
notificationManager.notify(0, notificationBuilder.build());
Log.i("GoParty", "Notification sent ----- ");
} catch (MalformedURLException e) {
Logger.logGoParty(e.toString());
} catch (IOException e) {
Logger.logGoParty(e.toString());
}
}
}
Получатель уведомлений:
public class NotificationReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent notificationIntent = new Intent(context, NotificationService.class);
NotificationService.enqueueWork(context, notificationIntent);
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.goparty">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".scopes.application.GoParty"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps"
android:screenOrientation="portrait">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.goparty.LoginActivity" />
</activity>
<service
android:name=".jobs.NotificationService"
android:permission="android.permission.BIND_JOB_SERVICE" />
<receiver android:name=".receivers.NotificationReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>