FCMMessagingService in clean architecture?
Asked Answered
B

2

8

I am developing an app where I am using Firebase Cloud Messaging. And I am using clean architecture for my app. I want to know where(in which layer:data, domain, presentation) is the best solution to put my classes which are called MyFirebaseMessagingService and MyFirebaseInstanceServiceID? These are my classes: myFirebaseMessagingService:

public class myFirebaseMessagingService extends FirebaseMessagingService {

private static final String TAG="MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    super.onMessageReceived(remoteMessage);
    Log.d("onMessageReceived", "Pozvana funkcija onMessageReceived");
    Log.d(TAG, "From " + remoteMessage.getFrom());
    Log.d(TAG, "Body " + remoteMessage.getNotification().getBody());
    Log.d(TAG, "Location " + remoteMessage.getNotification().getClickAction());
    Log.d(TAG, "Value " + remoteMessage.getData().get("click_action"));
    sendNotification(remoteMessage);
    Log.d("Function called", "sendNotification");


}

private void sendNotification(RemoteMessage remoteMessage) {
    Intent intent = new Intent(myFirebaseMessagingService.this, MainActivity.class);
    intent.putExtra("click_action", "goToFragment1");
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);


    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
    Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notification=new NotificationCompat.Builder(this)
            .setSmallIcon(logo)
            .setContentText(remoteMessage.getNotification().getBody())
            .setContentTitle("Title")
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);
    NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, notification.build());
    String message=remoteMessage.getNotification().getBody();
    DataBaseHelper db=new DataBaseHelper(this);
    db.insertMsg(message);
    intent.putExtra("poruka",message );
    Log.d("Log>Poruka", message);


}

And this is myFirebaseInstanceServiceID:

public class myFirebaseInstanceServiceID extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIIDService";

@Override
public void onTokenRefresh() {
    super.onTokenRefresh();
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
    Log.d(TAG, "Refreshed token: " + refreshedToken);

    // TODO: Implement this method to send any registration to your app's servers.
    sendRegistrationToServer(refreshedToken);
}
private void sendRegistrationToServer(String token) {
    // Add custom implementation, as needed.
}
Bergquist answered 5/7, 2016 at 13:21 Comment(0)
B
6

I think this kind of classes should go into what you called the "presentation" layer.

The thing is that you mention only these 3 layers, but according to Uncle Bob's diagram the last layer can contain not only the presentation part but all "Framework specific" code.

It seems to me that communicating with Firebase is totally a framework specific part (as could be the Content Provider, the Retrofit calls, etc...).

Side note : in your code, you are using the DataBaseHelper directly from your service, maybe you should pass through a UseCase that will use the DataBaseHelper through an Interface. This way if your DatabaseHelper implementation change, no need to modify your Service.

Beitris answered 28/9, 2016 at 12:13 Comment(0)
T
1

Let's refer to the primary sources of Clean Architecture and Android App Architecture.

The Clean Architecture.

Here is the quote from the book "Clean Architecture: A Craftsman's Guide to Software Structure and Design (2017)":

The architect can employ the Single Responsibility Principle and the Common Closure Principle to separate those things that change for different reasons, and to collect those things that change for the same reasons—given the context of the intent of the system.

What changes for different reasons?

User interfaces change for reasons that have nothing to do with business rules. Business rules themselves may be closely tied to the application, or they may be more general. The database, the query language, and even the schema are technical details that have nothing to do with the business rules or the UI. Thus we find the system divided into decoupled at least four horizontal layers — the application-independent business rules, application-specific business rules, UI, and the Database.

Later in the book Robert Martin (creator and author of the clean architecture) describes in detail how to build these 4 corresponding layers, giving them names:

  1. Enterprise Business Rules (Entities)
  2. Application Business Rules (Use Cases)
  3. Interface Adapters
  4. Frameworks & Drivers.

enter image description here

  • If you are using The Clean Architecture, then MyFirebaseMessagingService and MyFirebaseInstanceServiceID classes will go to the "data" component from the "Frameworks & Drivers" layer.

Because they are implementation details that depend on an external service and are not part of the core business logic of the application. The data component is responsible for providing and persisting data from various sources, such as databases, web services, or device sensors. The "frameworks and drivers" layer is the outermost layer that contains the details that are specific to the platform, libraries, or drivers.

Android App Architecture

Since you mentioned that you have three layers: data, domain, and presentation, I can carefully assume that you follow the official architecture pattern from the Android documentation:

enter image description here

  • If you are using Android App Architecture, then MyFirebaseMessagingService and MyFirebaseInstanceServiceID classes will go to the "data sources" component from the "data" layer.

Because they are part of the data source that provides or receives data from an external service. The data layer is responsible for providing and persisting data from various sources, such as databases, web services, or device sensors. This way, we can isolate data sources from the core logic and UI of the application making it more testable and reusable.


As a side note, just wanted to draw your attention to how much different Clean Architecture and Android App Architecture are. In Android App Architecture "data" is independent and the "domain" depends on the "data" layer, in Clean Architecture on the other hand the only independent layer is "Entities". "Frameworks & Drivers" together with the "data" component depend on "Interface Adapters".

Tic answered 27/6, 2023 at 2:53 Comment(2)
data is independent and domain depends on data changes based on how you try to look at it, and from your perspective it is totally wrong if what you mean by data here is data layer. Domain layer do depends on what remote API provides but can also do more outside of what it offers. But that is because the remote API endpoints itself are the implementation of business logic as well it just not directly part of the app codebase.Fricke
Domain layer (business logic definitions) should never depend on data layer (implementation details) as it doesn't care how the data layer will solve the fetching or caching, it doesn't care if we use Room, SQLDelight, Realm and Retrofit, Ktor, etc.Fricke

© 2022 - 2024 — McMap. All rights reserved.