[Firebase] Implement base for per-register FCM tasks.

This commit is contained in:
Kuba Szczodrzyński 2020-01-12 21:39:06 +01:00
parent 45b96179a5
commit 93e70c38b7
12 changed files with 209 additions and 43 deletions

View File

@ -203,7 +203,7 @@
<service android:name=".receivers.BootReceiver$NotificationActionService" /> <service android:name=".receivers.BootReceiver$NotificationActionService" />
<service android:name=".Notifier$GetDataRetryService" /> <service android:name=".Notifier$GetDataRetryService" />
<service android:name=".data.api.ApiService" /> <service android:name=".data.api.ApiService" />
<service android:name=".sync.MyFirebaseService" <service android:name=".data.firebase.MyFirebaseService"
android:exported="false"> android:exported="false">
<intent-filter android:priority="10000000"> <intent-filter android:priority="10000000">
<action android:name="com.google.firebase.MESSAGING_EVENT" /> <action android:name="com.google.firebase.MESSAGING_EVENT" />

View File

@ -39,4 +39,18 @@ abstract class IApiTask(open val profileId: Int) {
override fun toString(): String { override fun toString(): String {
return "IApiTask(profileId=$profileId, taskId=$taskId, profile=$profile, taskName=$taskName)" return "IApiTask(profileId=$profileId, taskId=$taskId, profile=$profile, taskName=$taskName)"
} }
companion object {
fun enqueueAll(context: Context, tasks: List<IApiTask>) {
Intent(context, ApiService::class.java).let {
if (SDK_INT >= O)
context.startForegroundService(it)
else
context.startService(it)
}
tasks.forEach {
EventBus.getDefault().postSticky(it)
}
}
}
} }

View File

@ -1,8 +1,8 @@
/* /*
* Copyright (c) Kuba Szczodrzyński 2019-10-11. * Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/ */
package pl.szczodrzynski.edziennik.sync package pl.szczodrzynski.edziennik.data.firebase
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-11. * Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/ */
package pl.szczodrzynski.edziennik.sync package pl.szczodrzynski.edziennik.data.firebase
class FirebaseSendException(reason: String?) : Exception(reason) { class FirebaseSendException(reason: String?) : Exception(reason) {
companion object { companion object {

View File

@ -2,7 +2,7 @@
* Copyright (c) Kuba Szczodrzyński 2020-1-11. * Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/ */
package pl.szczodrzynski.edziennik.sync package pl.szczodrzynski.edziennik.data.firebase
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.PendingIntent import android.app.PendingIntent

View File

@ -1,4 +1,8 @@
package pl.szczodrzynski.edziennik.sync; /*
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -19,22 +23,18 @@ import pl.szczodrzynski.edziennik.MainActivity;
import pl.szczodrzynski.edziennik.R; import pl.szczodrzynski.edziennik.R;
import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask; import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask;
import pl.szczodrzynski.edziennik.data.db.entity.Event; import pl.szczodrzynski.edziennik.data.db.entity.Event;
import pl.szczodrzynski.edziennik.data.db.full.EventFull;
import pl.szczodrzynski.edziennik.data.db.entity.EventType; import pl.szczodrzynski.edziennik.data.db.entity.EventType;
import pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage; import pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage;
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore;
import pl.szczodrzynski.edziennik.data.db.entity.Profile; import pl.szczodrzynski.edziennik.data.db.entity.Profile;
import pl.szczodrzynski.edziennik.data.db.entity.Team; import pl.szczodrzynski.edziennik.data.db.entity.Team;
import pl.szczodrzynski.edziennik.data.db.full.EventFull;
import pl.szczodrzynski.edziennik.network.ServerRequest; import pl.szczodrzynski.edziennik.network.ServerRequest;
import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment; import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment;
import pl.szczodrzynski.edziennik.utils.models.Notification; import pl.szczodrzynski.edziennik.utils.models.Notification;
import static pl.szczodrzynski.edziennik.App.APP_URL; import static pl.szczodrzynski.edziennik.App.APP_URL;
import static pl.szczodrzynski.edziennik.data.db.entity.Event.TYPE_HOMEWORK; import static pl.szczodrzynski.edziennik.data.db.entity.Event.TYPE_HOMEWORK;
import static pl.szczodrzynski.edziennik.data.db.entity.LoginStore.LOGIN_TYPE_MOBIDZIENNIK;
import static pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_FEEDBACK_MESSAGE;
import static pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_NEW_SHARED_EVENT;
import static pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_NEW_SHARED_HOMEWORK;
import static pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_SERVER_MESSAGE;
import static pl.szczodrzynski.edziennik.utils.Utils.d; import static pl.szczodrzynski.edziennik.utils.Utils.d;
import static pl.szczodrzynski.edziennik.utils.Utils.strToInt; import static pl.szczodrzynski.edziennik.utils.Utils.strToInt;
@ -93,7 +93,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
Profile profile = null; Profile profile = null;
for (Profile profileFull: profileList) { for (Profile profileFull: profileList) {
if (profileFull.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK if (profileFull.getLoginStoreType() == LoginStore.LOGIN_TYPE_MOBIDZIENNIK
&& studentId == profileFull.getStudentData("studentId", -1)) { && studentId == profileFull.getStudentData("studentId", -1)) {
profile = profileFull; profile = profileFull;
break; break;
@ -182,7 +182,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
case "message": case "message":
app.notifier.add(new Notification(app.getContext(), remoteMessage.getData().get("message")) app.notifier.add(new Notification(app.getContext(), remoteMessage.getData().get("message"))
.withTitle(remoteMessage.getData().get("title")) .withTitle(remoteMessage.getData().get("title"))
.withType(TYPE_SERVER_MESSAGE) .withType(pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_SERVER_MESSAGE)
.withFragmentRedirect(MainActivity.DRAWER_ITEM_NOTIFICATIONS) .withFragmentRedirect(MainActivity.DRAWER_ITEM_NOTIFICATIONS)
); );
app.notifier.postAll(); app.notifier.postAll();
@ -209,7 +209,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
app.notifier.add(new Notification(app.getContext(), feedbackMessage.text) app.notifier.add(new Notification(app.getContext(), feedbackMessage.text)
.withTitle(remoteMessage.getData().get("title")) .withTitle(remoteMessage.getData().get("title"))
.withType(TYPE_FEEDBACK_MESSAGE) .withType(pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_FEEDBACK_MESSAGE)
.withFragmentRedirect(MainActivity.TARGET_FEEDBACK) .withFragmentRedirect(MainActivity.TARGET_FEEDBACK)
); );
app.notifier.postAll(); app.notifier.postAll();
@ -231,7 +231,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
}); });
app.notifier.add(new Notification(app.getContext(), remoteMessage.getData().get("message")) app.notifier.add(new Notification(app.getContext(), remoteMessage.getData().get("message"))
.withTitle(remoteMessage.getData().get("title")) .withTitle(remoteMessage.getData().get("title"))
.withType(TYPE_FEEDBACK_MESSAGE) .withType(pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_FEEDBACK_MESSAGE)
.withFragmentRedirect(MainActivity.TARGET_FEEDBACK) .withFragmentRedirect(MainActivity.TARGET_FEEDBACK)
); );
app.notifier.postAll(); app.notifier.postAll();
@ -285,7 +285,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
EventType eventType = app.db.eventTypeDao().getByIdNow(profile.getId(), event.type); EventType eventType = app.db.eventTypeDao().getByIdNow(profile.getId(), event.type);
app.notifier.add(new Notification(app.getContext(), app.getString((oldEvent == null ? R.string.notification_shared_event_format : R.string.notification_shared_event_modified_format), event.sharedByName, eventType == null ? "wydarzenie" : eventType.name, event.eventDate.getFormattedString(), event.topic)) app.notifier.add(new Notification(app.getContext(), app.getString((oldEvent == null ? R.string.notification_shared_event_format : R.string.notification_shared_event_modified_format), event.sharedByName, eventType == null ? "wydarzenie" : eventType.name, event.eventDate.getFormattedString(), event.topic))
.withProfileData(profile.getId(), profile.getName()) .withProfileData(profile.getId(), profile.getName())
.withType(event.type == TYPE_HOMEWORK ? TYPE_NEW_SHARED_HOMEWORK : TYPE_NEW_SHARED_EVENT) .withType(event.type == TYPE_HOMEWORK ? pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_NEW_SHARED_HOMEWORK : pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_NEW_SHARED_EVENT)
.withFragmentRedirect(event.type == TYPE_HOMEWORK ? MainActivity.DRAWER_ITEM_HOMEWORK : MainActivity.DRAWER_ITEM_AGENDA) .withFragmentRedirect(event.type == TYPE_HOMEWORK ? MainActivity.DRAWER_ITEM_HOMEWORK : MainActivity.DRAWER_ITEM_AGENDA)
.withLongExtra("eventDate", event.eventDate.getValue()) .withLongExtra("eventDate", event.eventDate.getValue())
); );
@ -304,7 +304,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
if (oldEvent != null) { if (oldEvent != null) {
app.notifier.add(new Notification(app.getContext(), app.getString(R.string.notification_shared_event_removed_format, oldEvent.sharedByName, oldEvent.typeName, oldEvent.eventDate.getFormattedString(), oldEvent.topic)) app.notifier.add(new Notification(app.getContext(), app.getString(R.string.notification_shared_event_removed_format, oldEvent.sharedByName, oldEvent.typeName, oldEvent.eventDate.getFormattedString(), oldEvent.topic))
.withProfileData(profile.getId(), profile.getName()) .withProfileData(profile.getId(), profile.getName())
.withType(oldEvent.type == TYPE_HOMEWORK ? TYPE_NEW_SHARED_HOMEWORK : TYPE_NEW_SHARED_EVENT) .withType(oldEvent.type == TYPE_HOMEWORK ? pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_NEW_SHARED_HOMEWORK : pl.szczodrzynski.edziennik.data.db.entity.Notification.TYPE_NEW_SHARED_EVENT)
.withFragmentRedirect(oldEvent.type == TYPE_HOMEWORK ? MainActivity.DRAWER_ITEM_HOMEWORK : MainActivity.DRAWER_ITEM_AGENDA) .withFragmentRedirect(oldEvent.type == TYPE_HOMEWORK ? MainActivity.DRAWER_ITEM_HOMEWORK : MainActivity.DRAWER_ITEM_AGENDA)
.withLongExtra("eventDate", oldEvent.eventDate.getValue()) .withLongExtra("eventDate", oldEvent.eventDate.getValue())
); );

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
import android.util.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.App
import kotlin.coroutines.CoroutineContext
class MyFirebaseService : FirebaseService(), CoroutineScope {
companion object {
private const val TAG = "MyFirebaseService"
}
private val app by lazy { applicationContext as App }
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onNewToken(token: String?) {
Log.d(TAG, "Got new token: $token")
app.config.sync.tokenApp = token
}
override fun onMessageReceived(message: Message) {
launch(Dispatchers.Default) {
Log.d(TAG, "Message received from ${message.from}: $message")
val profiles = app.db.profileDao().profilesForSyncNow
when (message.from) {
"640759989760" -> SzkolnyAppFirebase(app, profiles, message)
"747285019373" -> SzkolnyMobidziennikFirebase(app, profiles, message)
"513056078587" -> SzkolnyLibrusFirebase(app, profiles, message)
"987828170337" -> SzkolnyVulcanFirebase(app, profiles, message)
}
}
}
}

View File

@ -0,0 +1,14 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.entity.Profile
class SzkolnyAppFirebase(val app: App, val profiles: List<Profile>, val message: FirebaseService.Message) {
init {
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.entity.Profile
class SzkolnyLibrusFirebase(val app: App, val profiles: List<Profile>, val message: FirebaseService.Message) {
/*{
"gcm.notification.e": "1",
"userId": "1234567u",
"gcm.notification.sound": "default",
"gcm.notification.title": "Synergia",
"gcm.notification.sound2": "notify",
"image": "www/assets/images/iconPush_01.png",
"gcm.notification.body": "Dodano nieobecność nauczyciela od godziny 15:30 do godziny 16:15",
"gcm.notification.icon": "notification_event.png",
"objectType": "Calendars/TeacherFreeDays",
}*/
init {
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_ATTENDANCE
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_BEHAVIOUR
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_GRADES
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask
import pl.szczodrzynski.edziennik.data.api.task.IApiTask
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.getLong
import pl.szczodrzynski.edziennik.getString
class SzkolnyMobidziennikFirebase(val app: App, val profiles: List<Profile>, val message: FirebaseService.Message) {
/*{
"id": "123456",
"body": "Janósz Kowalski (Nauczyciele) - Temat wiadomości",
"icon": "push",
"type": "wiadOdebrana",
"color": "#025b8e",
"login": "1234@2019@szkola",
"notId": "1234567",
"sound": "default",
"title": "Nowa wiadomość - mobiDziennik",
"global_id": "123456",
"vibrate": "true",
"sync_url": "https://szkola.mobidziennik.pl/api2/logowanie"
}*/
/*{
"body": "Kowalski Janósz - zapowiedziany sprawdzian na jutro:\njęzyk niemiecki (kartkówka - nieregularne 2)",
"icon": "push",
"type": "sprawdzianyJutro",
"color": "#025b8e",
"login": "1234@2019@szkola",
"notId": "1234567",
"sound": "default",
"title": "Sprawdziany jutro - mobiDziennik",
"global_id": "123456",
"vibrate": "true",
"sync_url": "https://szkola.mobidziennik.pl/api2/logowanie"
}*/
init { run {
val type = message.data.getString("type") ?: return@run
if (type == "sprawdzianyJutro" || type == "zadaniaJutro" || type == "autoryzacjaUrzadzenia")
return@run
val globalId = message.data.getLong("global_id")
/* assets/www/js/push.js */
val viewIdPair = when (type) {
"wiadOdebrana" -> DRAWER_ITEM_MESSAGES to TYPE_RECEIVED
"oceny", "ocenyKoncowe" -> DRAWER_ITEM_GRADES to 0
"uwagi" -> DRAWER_ITEM_BEHAVIOUR to 0
"nieobecnoscPierwszaLekcja", "nieobecnosciDzisiaj" -> DRAWER_ITEM_ATTENDANCE to 0
else -> return@run
}
val tasks = profiles.filter {
it.getStudentData("globalId", 0L) == globalId
}.map {
EdziennikTask.syncProfile(it.id, listOf(viewIdPair))
}
IApiTask.enqueueAll(app, tasks)
}}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.data.firebase
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.entity.Profile
class SzkolnyVulcanFirebase(val app: App, val profiles: List<Profile>, val message: FirebaseService.Message) {
/*{
"data": {
"loginid": 12345,
"pupilid": 1234,
"unitid": 2,
"event": "CDC",
"day": "2019-09-09",
"table": "Frekwencja"
},
"title": "Frekwencja",
"message: "Uczeń Janósz otrzymał nieobecność na 7 lekcji"
}*/
init {
}
}

View File

@ -1,25 +0,0 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-1-11.
*/
package pl.szczodrzynski.edziennik.sync
import android.util.Log
import pl.szczodrzynski.edziennik.App
class MyFirebaseService : FirebaseService() {
companion object {
private const val TAG = "MyFirebaseService"
}
private val app by lazy { applicationContext as App }
override fun onNewToken(token: String?) {
Log.d(TAG, "Got new token: $token")
app.config.sync.tokenApp = token
}
override fun onMessageReceived(message: Message) {
Log.d(TAG, "Message received from ${message.from}: $message")
}
}