Skip to content

Commit 7705108

Browse files
fix: Notifications are ignored if the app was killed before. (#2136)
If a message arrives when the app is killed or in the background, it is first handled by `FCMHandlerService`. The service needs to access `GlobalModule` and `AccountsService` before it can call `PushService` in order to sync the app. (We don't use the received message directly as it might be out of sync - we perform a sync instead). But if the app is killed there is no `GlobalModule` (nor `AccountService`) present and the service silently stops without calling `PushService`. In this PR the service first ensures that the app is initialized properly. If the app simply works in the background, no initialization is needed and the code will work as before. If the app is killed, we will look for the stored global config and initialize the app according to it. Only if the config is missing, we will not initialize the app and the service won't work. To avoid this, the first launch of the app after installing it should be done through `LaunchActivity`: there we choose the backend and we save our decision in the stored backend config. After that, even if the app is killed, we will have the information about the chosen backend and the service will be able to initialize the app. (It didn't work before because if we had our Prod backend as default, it was not saved in the stored backend config, and the service didn't know that Prod was our backend).
1 parent 74b6959 commit 7705108

File tree

3 files changed

+27
-25
lines changed

3 files changed

+27
-25
lines changed

app/src/main/scala/com/waz/services/fcm/FCMHandlerService.scala

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import com.waz.service.{AccountsService, FCMNotificationStatsService, NetworkMod
2828
import com.waz.services.ZMessagingService
2929
import com.waz.threading.Threading
3030
import com.waz.utils.{JsonDecoder, RichInstant, Serialized}
31+
import com.waz.zclient.WireApplication
3132
import com.waz.zclient.log.LogUI._
3233
import org.json
3334
import org.threeten.bp.Instant
@@ -58,40 +59,34 @@ class FCMHandlerService extends FirebaseMessagingService with ZMessagingService
5859
* it is sometimes not enough time to process everything - leading to missing messages!
5960
*/
6061
override def onMessageReceived(remoteMessage: RemoteMessage) = {
61-
6262
import FCMHandlerService._
6363

64+
WireApplication.APP_INSTANCE.ensureInitialized()
65+
6466
Option(remoteMessage.getData).map(_.asScala.toMap).foreach { data =>
6567
verbose(l"onMessageReceived with data: ${redactedString(data.toString())}")
6668
Option(ZMessaging.currentGlobal) match {
6769
case Some(glob) if glob.backend.pushSenderId == remoteMessage.getFrom =>
6870
data.get(UserKey).map(UserId) match {
6971
case Some(target) =>
70-
accounts.accountsWithManagers.head.flatMap { accs =>
72+
accounts.accountsWithManagers.head.foreach { accs =>
7173
accs.find(_ == target) match {
7274
case Some(acc) =>
73-
accounts.getZms(acc).flatMap {
75+
accounts.getZms(acc).foreach {
7476
case Some(zms) => FCMHandler(zms, data, Instant.ofEpochMilli(remoteMessage.getSentTime))
75-
case _ =>
76-
warn(l"Couldn't instantiate zms instance")
77-
Future.successful({})
77+
case _ => warn(l"Couldn't instantiate zms instance")
7878
}
79-
case _ =>
80-
warn(l"Could not find target account for notification")
81-
Future.successful({})
79+
case _ => warn(l"Could not find target account for notification")
8280
}
8381
}
8482
case _ =>
8583
warn(l"User key missing msg: ${redactedString(UserKeyMissingMsg)}")
8684
tracking.exception(new Exception(UserKeyMissingMsg), UserKeyMissingMsg)
87-
Future.successful({})
8885
}
8986
case Some(_) =>
9087
warn(l"Received FCM notification from unknown sender: ${redactedString(remoteMessage.getFrom)}. Ignoring...")
91-
Future.successful({})
9288
case _ =>
9389
warn(l"No ZMessaging global available - calling too early")
94-
Future.successful({})
9590
}
9691
}
9792
}
@@ -123,7 +118,6 @@ object FCMHandlerService {
123118
data match {
124119
case NoticeNotification(nId) =>
125120
addNotificationToProcess(Some(nId))
126-
127121
case _ =>
128122
warn(l"Unexpected notification, sync anyway")
129123
addNotificationToProcess(None)
@@ -134,12 +128,12 @@ object FCMHandlerService {
134128
for {
135129
false <- accounts.accountState(userId).map(_ == InForeground).head
136130
drift <- push.beDrift.head
137-
now = clock.instant + drift
138-
idle = network.isDeviceIdleMode
139-
_ <- nId match {
140-
case Some(n) => fcmPushes.markNotificationsWithState(Set(n), Pushed)
141-
case _ => Future.successful(())
142-
}
131+
now = clock.instant + drift
132+
idle = network.isDeviceIdleMode
133+
_ <- nId match {
134+
case Some(n) => fcmPushes.markNotificationsWithState(Set(n), Pushed)
135+
case _ => Future.successful(())
136+
}
143137

144138
/**
145139
* Warning: Here we want to trigger a direct fetch if we are in doze mode - when we get an FCM in doze mode, it is
@@ -150,7 +144,8 @@ object FCMHandlerService {
150144
* online at once. For that reason, we start a job which can run for as long as we need to avoid the app from being
151145
* killed mid-processing messages.
152146
*/
153-
_ <- if (idle) push.syncHistory(FetchFromIdle(nId)) else Serialized.future("fetch")(Future(FetchJob(userId, nId)))
147+
_ <- if (idle) push.syncHistory(FetchFromIdle(nId))
148+
else Serialized.future("fetch")(Future(FetchJob(userId, nId)))
154149
} yield {}
155150
}
156151

app/src/main/scala/com/waz/zclient/LaunchActivity.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,12 @@ class LaunchActivity extends AppCompatActivity with ActivityHelper with DerivedL
4545
}
4646

4747
if (backendController.shouldShowBackendSelector) showDialog(callback)
48-
else callback(backendController.getStoredBackendConfig.getOrElse(Backend.ProdBackend))
48+
else backendController.getStoredBackendConfig match {
49+
case Some(be) => callback(be)
50+
case None =>
51+
backendController.setStoredBackendConfig(Backend.ProdBackend)
52+
callback(Backend.ProdBackend)
53+
}
4954
}
5055

5156
/// Presents a dialog to select backend.

app/src/main/scala/com/waz/zclient/WireApplication.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,13 +367,14 @@ class WireApplication extends MultiDexApplication with WireContext with Injectab
367367

368368
controllerFactory = new ControllerFactory(getApplicationContext)
369369

370-
inject[BackendController].getStoredBackendConfig.foreach { be =>
371-
ensureInitialized(be)
372-
}
370+
ensureInitialized()
373371
}
374372

375-
def ensureInitialized(backend: BackendConfig) = {
373+
def ensureInitialized(): Unit =
374+
if (Option(ZMessaging.currentGlobal).isEmpty)
375+
inject[BackendController].getStoredBackendConfig.foreach(ensureInitialized)
376376

377+
def ensureInitialized(backend: BackendConfig) = {
377378
JobManager.create(this).addJobCreator(new JobCreator {
378379
override def create(tag: String) =
379380
if (tag.contains(FetchJob.Tag)) new FetchJob
@@ -419,3 +420,4 @@ class WireApplication extends MultiDexApplication with WireContext with Injectab
419420
super.onTerminate()
420421
}
421422
}
423+

0 commit comments

Comments
 (0)