I've read multiple clean architecture tutorials for android, but all of them had very basic structure with simple network calls which leaves me wondering.
What I want to know is where should I put code that handles accelerometer, geofencing, location, sms and similar? My initial thought was to put them in separate repositories. But as these are separate long running processes that could be started or stopped, it just doesn't feel right. I've tried renaming these classes from repository to service, just so the intent would be more clearly expressed. But still seems a bit off. What would be a good alternative?
To be able to receive sent sms status, I need to register a receiver. Who should be responsible for that? Would the repository itself, upon receiving a call to sendSms(), should register that receiver, send message and release receiver, or would a UseCase first would have to check if SmsRepository is started, and if not would start it, thus registering receiver, and then call the sendSms() method? Or maybe there should be another approach taken to register receiver on app start and unregister on close?
Is this an appropriate package structure?
EDIT: 4. What to do in case you want to constantly listen for server result? Do you directly subscribe to repository from viewmodel or do you keep calling same usecase (whose purpose is to fetch result once) after it finishes? My understanding of UseCase is that it only returns single result and is not supposed to be subscribable.
My humble opinions:
1) Since accelerometer, gyroscope.. are kind of Data Sources, you can put them in SensorRepository/SensorDataSource/ (Data Layer which sits outside of Domain/Core layer and can have Android code). When you need to access them, you can go through UseCase class, where you would have this logics: sampling frequency, data filter, format changing, maybe buffer count etc...
To put accelerometer, gyroscope, location into same or different classes, should be decided feature based, not by sensor type based. If one feature (e.g. profile) needs both location and sms, they should be under same class.
Starting/stopping them can happen by calling StopLocationUseCase, StartLocationUseCase which will call start()/stop() of those Repository etc... StartLocationUseCase should be idempotent, if there is already started (UseCase will ask Repository), it won't start again.
2) Knowing 'sms sent/not sent' status feels like it is part of sendSms() operation. So all register/send/unregister should be called in sendSms() synchronously if possible.
3) Feature based is preferred (even project modules should be feature-based)
4) UseCase can return Observable kind of data type but IMHO it should not contain state.
Related
I have a two part question. Both are somewhat general.
I'm creating an app that relies heavily on communication with a server. I plan to have different classes for each repository I'll need. Is an Android service the correct pattern to use here? There may be certain situations where I'll want to cache things between activities. Will a service allow me to do this?
Assuming a service is what I want to use for this, how can I load content once the service is bound. When the user opens the app, I want to start loading content. However, binding a service isn't blocking, so I can't write the code that makes requests with the service in my onStart() right? Is there some helper class that will wait for the service to load then execute a function? I know I could put some code in my onServiceConnected() method but I'd like to stay away from coupling like that.
Hopefully that wasn't too abstract. Thanks in advance.
Yes, Service is the way to go, but a started service, not a bound one.
You could make async request methods, and the Service can broadcast the result back to your Activity.
The async request in this case is a startService(intent) with an
Intent containing the request parameters. The service would start a background thread for the operation, optimally you can use a networking library for this (for example Volley).
And the reply is a broadcast by the Service with the relevant data.
This answers the problem of caching, because the Service can decide what to return. So in case the Service does not have the requested resource, it will download (and return) it. But if the Service has the resource, then it will just simply return the cached version.
To start, you should get yourself familiar with these topics:
Started Services (for the requests)
LocalBroadcastReceiver (for the reply)
Event Bus (alternative to LocalBroadcastReceiver, for example Otto)
I don't know much about your concrete needs, but it seems like you want to implement a REST client with cache. There is a really good Google IO presentation on that here. Definately worth to watch!
1)If you need code to run even when your Activity isn't, the correct answer is a Service. If you just need to cache data, then storing it in a global static variable somewhere may be ok.
2)Your service can start a Thread or AsyncTask. These execute in parallel. onStartCommand generally launches it in this case.
As with most things, the answer to these questions are subjective at best. I would need more information then I currently have, but I'll take a vague, general stab at this...
If you need something persistently hitting your server repeatedly I would say use a service.
Where you call it is not nearly as important as how many times it needs to be called. That being said the answer is yes. If you need this data as soon as the application or activity loads, then the onCreate method is where it needs to be loaded.
My reccomendation is either A) service or B)AsyncTask.
Go with A if you have to hit the server repeatedly for data and need it in regular intervals. Otherwise go with an AsyncTask and load all the data you need into an object for storage. Then you can use it as you need and it will essentially be "cached".
The difference between the two is simply "best tool for the job". I see you use some javascript. To give a proper analogy, using a service for a server call rather than an async task, is the equivalent of using a web socket (node js) when you could of just used an ajax call. Hope this helps. Oh and PS, please don't use static variables in Android =).
I am writing an application that shows "Japanese Traditional Time" (JTT for short). There are several components (notification, widgets, application itself, alarms) which all use the same data - current JTT.
My current version uses a single service that does all the calculation and uses a Handler to notify everyone about "ticking", mimicking ACTION_TIME_TICK.
However with alarms I need to also have a way to translate "usual time" to JTT and vice versa. The calculations are quite CPU-heavy (it's all based on sunrises and sunsets) and thus I prefer having it all done in a single place and then cached (calculating stuff knowing sunrise and sunset times is not as heavy).
So I have several ways to do that now:
Keep it all in Service
And use binding to request the data I need. It's actually already done in one case and seems a bit cumbersome since I have to handle asynchronous responses
Move to content provider
And use content observers instead of broadcasting
Or send broadcasts from provider
Combine both ways
Use content provider to calculate the data for service which in turn will broadcast it when needed
Which would be better? Maybe something else?
Content providers are for structured data, so it doesn't really fit your use case. Not sure what you mean by 'asynchronous responses'? Calling a remote service is usually just like a local function call, it will block and return a value when done. If you have to notify multiple components a broadcast is the way to go. Explore using a LocalBroadcast if all components are in the same process (check Android support library source), or set a permission on it to make sure other apps cannot get it if you need to send a system-wide (regular) one.
I'm sticking with "just service" - I have discovered Sticky Broadcasts which actually cover the problem I had with common Broadcasts (having to request latest data from service after registering but before getting the first "tick") and that leaves me with much less cases where I need actual service connection.
Okay so up front I will say that I am new to Android. I have made a few small projects and played with a few things and done tons and tons of reading. So here is the task I am trying to accomplish:
I have a remote service that runs in the foreground of my phone that can send and receive information with other android devices over a wifi network. APK's on the phone that are built to use this service contain multiple SQLite DB's. I want these APK's to register there content providers with the service so the service always know where to put data that it recieves (I have accomplished this task). When data comes in I will identify where it belongs and place it in the right DB (no problem here). So what would be the best way to notify the correct activity that new data has been received. Do I register Broadcast Receivers for my service to call? Will Broadcast Receivers work if the APK has been killed by the OS? Once the correct activity is loaded would I use a content observer to show the new data? Why would I use IntentServices?
I'm sorry for so many questions. Like I said I am learning fast but Android's SKD is massive and there are so many cool things. I want to make sure I am thinking things through right with best practices and making this very easily maintainable and expandable. Thanks for any help or advice I can get.
If you are asking what the best way is for a current Activity to know data has changed in the ContentProvider it is reading from, than the answer is a ContentObserver.
Lets say, for examples sake, you have a set of Activities and ContentProviders. Activity A is a list view of items from Content Provider A, and that list view is populated via a CursorAdapter of some kind. Whenever you have a query on a ContentProviders CONTENT_URI, the cursor should automatically monitor the CONTENT_URI for changes via a ContentObserver.
The reason this works is because in the ContentProvider:
Your query method calls setNotificationUri on your cursor to the URI that was queried.
Whenever a change happens in an insert/update/delete method, you are calling notifyChange on the URI.
If there is additional data that can change in your service that is not tied to a ContentProvider, than you have a few choices on how to pass data. If the Activity is in the same APK as your service, than you could use some sort of static variable, or the application context, or some other custom form of communication. The methods are rather liberal here because you are running in the same VM, so you have a lot of things available to you.
In your situation, it sounds like most activities will be in separate APKs. If that is the case, you will probably want to send out broadcast Intents to let the entire system knwo about the changes. If these changes only matter when an activity is running, you can register a BroadcastReceiver for the life of the Activity that cares about the change. Alternatively, you could put a BroadcastReceiver in the applications manifest, and always receive that change.
That brings us to IntentServices. IntentServices are the "easiest" way to handle long running tasks in Android. All they do, is create a background thread that will handle intents being sent into the service. A common use case is as follows:
You receive a broadcast intent that you need to react to (and it will take a while)
Send a directed intent (intent with a set component name) to an IntentService with some info from the broadcast intent.
IntentService either spawns a new BG thread, or adds the intent to the processing queue on the existing BG thread
The onHandleIntent function is called in the IntentService so that you can now process that change using as much processing time as you want.
I'm currently learning to develop for Android and I'm having a somewhat hard time figuring out when and how to use services. I have already seen the numerous questions asked about very similar things, but I can't quite find the exact answer to my questions.
I have an app which talks to a restful api. I fetch several lists which I would like to cache in memory and only update if the user hits a refresh button, or certain activities are created. If a list is refreshed, sometimes several activities need to be notified, so that they update their content (if they are on screen at the time). I store the data I retrieve in value objects.
On a non-android app I would usually create a sort of dataproxy class in a singleton pattern. I could ask the dataproxy to update its data via http request, and then it would send some kind of system-wide notification as soon as the data is changed, so the interested views can all be updated. I hope this makes sense.
My question is now: How do I do this the android way? Do I bind and unbind to a dataproxy service, which I can actively ask to fetch certain data? Should I do my non-persistent caching in this service or somewhere else? Do I need AIDL, or can I just use normal objects for moving data between a service and an activity? Although I find the android dev guide pretty well written and useful, I haven't found much information on services best practice.
Thank you in advance!
How do I do this the android way?
You assume that there is a single "android way".
Do I bind and unbind to a dataproxy service, which I can actively ask to fetch certain data?
You can either bind, or send commands via startService().
Should I do my non-persistent caching in this service or somewhere else?
If you're sure that you only want it to be in RAM, I'd lean towards static data members. Make the service be the "do-er", not the store.
That being said, I'd treat this more as a synchronization pattern, with the real store being a database or directory, with a cache in RAM. Users will find this less frustrating -- under your current plan, if they are in your app, then take a phone call for a while, they'll have to have you download all the data again.
Do I need AIDL, or can I just use normal objects for moving data between a service and an activity?
If they are all in the same process, normal objects is fine via binding, or use Intent extras for the command pattern.
Now, back to:
How do I do this the android way?
Option #1: Wrap your store in a ContentProvider and use ContentObserver for changes.
Option #2: Have your service send a broadcast to your package when the data changes, so the foreground activity can find out about the change via a BroadcastReceiver registered via registerReceiver(). Other activities simply grab a fresh look at the data in onResume() -- the only one that immediately needs to know of the data change is the one the user is interacting with, if any.
Option #3: Use the binding pattern with the service, and have the foreground activity register a listener with the service. The service calls the listener when data is updated. Once again, ather activities simply grab a fresh look at the data in onResume()
Option #4: Cook up your own listener system as part of your static data members, being very very careful to avoid memory leaks (e.g., static reference to an activity or service that is destroyed, preventing its garbage collection).
There are probably other options, but this should get you started.
The Google IO session mentioned by Andrew Halloran:
http://www.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html
Check out the Google I/O session videos. I implemented REST api calls the easy BUT wrong way. It wasn't until watching this Google I/O video that I understood where I went wrong. It's not as simple as putting together an AsyncTask with a HttpUrlConnection get/put call.
I know that an activity can communicate with a local service using the IBinder interface; I am trying to find a way for communication between two services.
Specifically, I have my main service starting an IntentService to handle file uploads. I want this IntentService to inform back to the main service once it is done uploading, and before it dies.
Any ideas about how this would happen?
You have to use BroadcastReceiver to receive intents, and when you want to communicate simply make an Intent with appropriate values.
This way you should be able to make a 2-way communication between any component.
In Android, there is a special way of completing tasks like yours. Look at AIDL (it's not well documented in official docs, but there are some extra sources on the web). This is a way of implementing two-way communication between any components placed in separate processes. In comparison to BroadcastReceivers, using this you'd get direct calls and callbacks, that will be less dirty than relying on something would come from somewhere in BroadcastReceiver.
To reach the needed effect, you'll have to define an interface for a callback and an interface for performing actions (with a callback supplied, or register/unregister methods). Than, after you received some command using the second interface, you should perform the job and post back the result through callback. To reach the asynchronous completion add a key work "oneway" before method signature (return type). To separate in and out params (if you need it), use "in", "out" and "inout" keywords near params.
As it comes to restrictions, only primitives, arrays and parcelables (and parcelable arrays) might be transferred between processes.
To control your callbacks lifecycle and operations atomicity, use RemoteCallbacksList for storing registered callbacks and notifying recipients using the duplicate of your list got from beginBroadcast.
If you have any troubles, you're free to ask here.