Where does Service (or BroadcastReceiver, etc..) belongs to in clean architecture package structure? I am wondering between domain and data layer... I would create new package called services in domain package. Is that right, or I should do it other way?
When thinking about clean architecture You should think of an Android Service in similar way as on any other Android application component like Activity for example.
Service and Activity can both do similar things like playing music, performing network requests etc. with one difference being the lack of user-interface in case of a Service (although one could think of a Notification as an UI for a Service). This lack of UI might be misleading at first.
Having in mind similar purposes of those application components we can imagine that both Service and Activity can be located in the same layer of the clean architecture project.
First I wouldn't choose the data layer as it is a place for Your data sources (concrete implementations of the abstractions defined in the domain layer) like web APIs or database controllers. One would argue that a Service is somewhat of a data source for the application because You can bind to it and get data from the background but if You look at Activities or Fragments You will notice that they can also be data sources for other Activities by using the Intents or arguments.
I wouldn't choose the domain package as well - it is supposed to contain definitions of the business logic of the app - interfaces of repositories etc. Moreover, this layer should be platform-independent, so no Android components should be there. A Service definitely does not belong there.
The app (or presentation) layer is left. It is an Android-specific layer - and this is the place for a Service. Service can communicate directly with a neighbour domain layer to access the data via use-cases that it can pass to a bound Activity, display a Notification with the data or whatever. All that while not violating the clean architecture rules.
Related
The separation of app and service is just frustratingly disgusting.
The app and service do not have access to each other's variables and data can only be made available to each other through the Messenger. This results in duplication and makes the conversion of PC to Android code an absolute, absolute pain.
Is there an API or some trick to make them share data totally transparently, or do I just have to settle for this cumbersome rubbish implementation (which is the answer that I am expecting)?
You should read the Services developer guide, if you haven't already.
There are a variety of ways for Activity and Service to communicate with each other. If you bind the Service to the Activity, you can share data.
You can also create a custom Application object, which would let you share information across app components. A custom Application acts like a singleton.
Sorry. I'm new, so I'm experienced, but to follow the MVC design pattern in Android, where is the model stored? I was thinking in Application since it pretty much has a very wide scope and any component can pull from it. Is this a good way of thinking?
On a project that we have here, we do use the Application to persist it but in a certain structured pattern.
Just to start with, the Model is, as you would guess, layered through classes that will represent your persistent entities, so e.g. if you persist clients, you will have a Client class that will hold it's structure, so I guess when you say about Model, I think you talk about the persistence of state-full model objects that will live across your application lifecycle.
We use android annotations just to start with. We use singleton classes (Annotated with #EBean(scope=Scope.singleton)) and our Application object has a reference to that singleton.
We have other entities (singletons as well) that we use as controllers that are the only ones that are able to access and manipulate at certain degrees with that "model singleton" and our activities have an interface-like communication with the controllers, those controllers can access the persistent data on the "model singleton" and provide feedback to the activities through it's interface.
In general, it's probably better to use a ContentProvider or even a singleton class. The problem with keeping state in your Application is that if any part of your app ever needs to run in a different process, that process will have its own copy of the Application. Running things in separate processes isn't common, but there are a few reasons to do it. A singleton class doesn't address the problem of sharing state with another process, but the other process might not care about the application's model. If the model is in the Application, the other process gets a copy whether it wants it or not.
how does a good architecture for an android app look like? Should all the "work/business logic" been done in a background service and the Activity communicates just with the service to query/fetch data from somewhere (local/distant)?
Would you implement the "service" that the Activity calls as a real Android-service? Or a POJO-Singleton that does the work (perhaps using background threads). Or instantiate background threads in your activity for time-consuming actions (query a webservice).
How do you abstract your data access the right way? Would you use a ContentProvider to access/abstract your data? How/From where should it be queried? Activity? Service? ..?
I've tried to search for a good app architecture design, but I only found how the Android architecture looks like, not how an Android app should look like.
So what's your opinion about that? What components of an Android application should communicate which each other to ensure best extensibility/encapsulation,...?
There's no one answer to this question. Good OO design isn't Android specific. I'd say that the rule is - if the framework gives you a high level object (such as Service in the case of Android) that fits your use case, use it. If you find yourself making POJO implementations of the same things you get for free with the framework, go with the framework.
As far as separation of concerns, this is standard OO stuff. Don't put anything in your Activity classes that isn't the job of the Activity. Over-stuffing the Activity with methods and properties that the Activity needs but aren't really the job of the Activity is bad - makes the intention of your Activity hard to understand.
I usually separate stuff into sub-packages in my apps.
com.myname.myproject.app - base classes, global application functionality
com.myname.myproject.net - network stuff, network related utils
com.myname.myproject.data - db helpers, providers, etc
com.myname.myproject.model - object model
etc.
As far as communication within your app...
I always have a custom Application class that I register in the manifest. This way, when I have controllers and helpers that need to be a "single instance", I don't have to do all that crazy thread safe singleton stuff...I just keep one global copy of.
RoboGuice is a dependency injection framework that makes this even easier to accomplish...definitely worth looking into. If this interests you, the Google Group for RoboGuice is great and is constantly filled with the creators of the framework who can basically answer anything you need.
As far as in-app communication, I use my single instance Controller and State classes to hold state and do common tasks, and I usually use BroadcastIntents to communicate back to Activities from Services
My Application has an Activity for the UI and a Service for background polling fun. Seems like standard fare.
Can AlarmManager trigger the Service Intent without Activity OnCreate being called?
Is there any benefit to putting the Activity & Service into different Applications? Would this create 2 apk's and make it impossible to put into Market as one app? Can you put 2 applications into one manifest somehow?
Regarding communication between the two:
-If Activity & Service are part of the same Application - can't I just store common objects (like User object) at the Application scope for the 2 to share?
-It seems like I don't even need to bother with AIDL - the two could just have weak references to each other at the Application scope as well - and they can call methods on each other that way? Or should they pub/sub each other with some kind of Observer Pattern or BroadcastListener thing?
Can AlarmManager trigger the Service Intent without Activity OnCreate being called?
Yes.
Is there any benefit to putting the Activity & Service into different Applications?
IMHO, no.
Would this create 2 apk's and make it impossible to put into Market as one app?
Yes.
Can you put 2 applications into one manifest somehow?
From a pure XML standpoint, there is room in the manifest for more than one <application> element. However, AFAIK, only one is supported.
If Activity & Service are part of the same Application - can't I just store common objects (like User object) at the Application scope for the 2 to share?
For very quick things, yes. However, bear in mind that your service may get shut down (by Android, by user, etc.), after which your process may get terminated, and your Application object goes poof. I'd use this for light caching only.
It seems like I don't even need to bother with AIDL
Correct -- that is only needed for inter-process service binding.
the two could just have weak references to each other at the Application scope as well
I wouldn't do that in a million years. Please use the platform responsibly. There are plenty of ways for activities and services to communicate yet remain loosely coupled (or, in the case of the local binding pattern, tightly-coupled in an Android-aware fashion).
Or should they pub/sub each other with some kind of Observer Pattern or BroadcastListener thing?
Something along those lines would be preferable. While the activity and the service may be co-resident in the same process at the same time, they are not designed to be directly linked to one another.
I've been working with Android for well over a year now, but I still have trouble determining when different types of messaging/communication between processes/threads should be used. I'm mainly talking about broadcasting Intents, using AIDL for services, using Handlers to send messages and socket communication.
Many of these tools can be used to accomplish similar tasks, but which is better suited to particular situations?
This is a pretty open ended question, but let me take a shot at describing how I see the intra/inter application communication working best.
One of the key aspects of Android messaging is the concept of all application components being loosely bound. Because all applications run in a separate process, and one 'app' may actually consist of several applications (responsible for providing different Activities or Services), the messaging techniques are all based around the idea of marshaling messages across process boundaries.
Intents
The preferred technique for messaging, always try to use an Intent whenever possible. It is the most 'native' way to transfer messages within Android.
Advantages
Using Intents for messaging maintains the loose binding of application components, letting you transfer messages seamlessly between several applications. Intents are used heavily within the core system to start Activities and Services, and to broadcast and receive system events.
Using extras Bundles you can include key/value pairs of primitives as payload data within Intents to easily pass information from one application component to another - even if those components are running in different processes.
Disadvantages
Because Intents are designed to go between processes, the extras payload only supports primitive types. If you need to send an object using an Intent you'll need to deconstruct it into primitives at one end and reconstruct it at the other.
Application Class
If you only want to communicate within a single application running in a single process this is a handy solution.
Advantages
By extending the Application class (and implementing it as a Singleton) you get an object that will exist whenever any of your application components exist, providing a centralized place to store and transfer complex object data between application components.
Disadvantages
This technique limits your messaging to components within a single application.
Service Binding, IPC, and AIDL
Binding to a service lets you access its methods and exchange objects with it. AIDL is a way of defining how to serialize an object into OS primitives so that it can be marshalled across process boundaries if the Service you're binding to is running in a separate application.
Advantages
When you bind to a Service you have access to it as though it was an object within the calling class. That means you can execute methods on the Service and exchange rich objects with it.
Note that if you're binding to a Service in a different application process you'll need to create the AIDL definitions that tell Android how to seralize / deserialize any objects you want to pass between applications.
Disadvantages
Creating the AIDL classes for IPC is a bit of extra work, and binding creates additional dependencies between Services and Activities which can make it harder for the kernel to clean up resources when other applications are being starved.
Marshelling messages across process boundaries is expensive though. So if you're not executing methods on a Service, using binding and IPC is probably overkill - see if you can achieve the same thing using Intents.
Sockets
If you're resorting to sockets to communicate within or between applications running on a single device, it's either because there's no other way or you've missed a trick somewhere. If your messages are leaving the device then sockets are a good, fast, alternative. If you're staying on the device chances are Intents or IPC is going to be a better option.
It all depends on the use case and kind of your application. If the application is running all the time better to go with AIDL approach as it is most secure way to communicate. If application need not run all the time, then you can go with either broadcast intent or pending intent approach to communicate between applications.
My 2 cents
I have not used local sockets.
Seems like overkill since you have to
generate and parse the data.
Intents are for either things that
other apps might want to do (launch
me in a compose window or to pick
something out)
AIDL/Parcels/Handlers for having a
GUI talk to a headless process that
is running constantly. Depending on
the app a lot of the actual data
transfer might happen using a content
provider but I tend to have some data
that needs to be transferred outside
of that channel.
This is a good article I found helpful in trying to find a substitute for Cocoa's NSUserDefaults class:
http://developer.android.com/guide/appendix/faq/framework.html