I'm an android noob that is looking for some advice on how to properly use a service in Android. I am building an app that will connect to a server on the Internet to get a data stream via TCP. That data then needs to get send out to another device that is connected via a bluetooth serial port. I want this to continue to function in the background while the user looks at a different activity.
The app will be a NTRIP client, which pulls real time RTK correction data from the Internet and sends it to a RTK GPS receiver that I connect to via bluetooth. The data rate will be about 500 bytes/second. The user interface is a single button to connect or disconnect the data stream and some text to show status of the GPS receiver. There are also a few settings that will need to be configured by the user such as the IP/port of the server to connect to and the bluetooth device to communicate with.
I think I need to have the main activity spawn a local service, and then have the service spawn a thread for the TCP stream and another thread for the bluetooth connection. Does this sound right?
What is the best model for the service in this scenario?
-Start(bind) the service every time the activity starts, and have the connect/disconnect button send commands to the service to start/stop the threads. If I go this route, the service will continue to run after the user disconnects and goes to another app. The service would need an inactivity timer to terminate itself.
-Start and stop the service when the user presses the connect/disconnect button. The service only runs when data is moving. If I do this, the activity will need to see if the service is running when the activity starts, in order to know if it should bind to the service or tell the user that the link is disconnected.
Thanks.
I'd go with your second option. Checking if a service is running or not is an easy task and also you won't consume unnecessary processing time which will be better for the battery life.
Just because you can run a service for a long time in the background doesn't necessarily mean that you also should do that. At least not all the time.
As android supports more than one entry point into the app, you could define two entry points in the Manifest.xml.
<category android:name="android.intent.category.LAUNCHER" /> defines, that this class could be started from the launcher. I guess that would work for a service, too. I would do two entry points. One which spawns the activity first and gives the user some configuration control. And another which simply spawns the service.
As you have no control over the lifetime of an activity i would not suggest to do anything which should not be ended by the system. If you have an incoming call your activity would simply die.
If the user starts the service you could create an widget with the button. If the user starts the activity you could start the service and the widget.
And if the user starts the widget, the user decides, what should happen with the service.
I'm not a Java or Android programmer so take what I say with a grain of salt. The normal way to handle blocking IO in Java is to use threads. It sounds like the data flow is unidirectional but for maximum flexibility I would create 3 threads, one for the UI, one for the TCP connection and one for the bluetooth connection. Communication between the UI and two worker threads could be done using shared variables (need to careful about synchronization, race conditions, etc). I would pass the data NTRIP data to the other worker using a multi-threaded queue data structure.
The worker thread for the NTRIP data would be roughly:
while (app running) {
if (connection enabled) {
if (not connected) {
c = connect to remote
}
data = get data from c
queue.put(data)
if (options reconfigured) {
close c
}
}
}
For the bluetooth thread:
while (app runnning) {
data = queue.get()
if (UI settings changed and connected) {
close connection
}
if (not connected) {
c = connect to remote
}
send data over connection
}
In the normal state, both workers are blocking on IO and will be consuming essentially no CPU time. Based on my experience, I would recommend you write your code to handle communication errors. For your code to work well in the real world you have to handle connections closing, hanging, etc. Making it robust will likely be the most time consuming part of the development.
Related
I'm developing this dating app that allows users to browse profiles downloaded from a server.
But I'm not sure what kind of thread or service I should be using to do the uploading to and downloading from the server.
It has to be a service that runs in the background that first connects to the server via a socket and then waits for commands from user input (from the UI thread).
I read about the Service and IntentService classes.
IntentService seems to be appropriate except that it is destroyed once it has finished its job and returned a result to the calling thread. I need it to keep listening for requests.
I could start a new service each time but that means I would have to reconnect to the server with each request (let's say each time I browse a profile). That doesn't seem right.
Can anyone tell me what is the best approach for this purpose?
If you are asking about how to make the client send download/upload requests outside UI thread, then you could try using AsyncHttpClient. I've been using that in almost every application I developed, and it is highly reliable.
But if you want to send data from server to the client (in other words, client keep listening for any incoming data), I recommend you to use GCM. Here is a step-by-step tutorial of implementing GCM in Android device.
I am writing an app that connects to a Bluetooth device, continuously receives data from it, and stores in local db. Certain data received requires system alert to pop up. There is a main activity which just displays the status of connection and data received. It all works just fine so far, including the popups.
Since the app requires to be run in background I have implemented a "bluetooth connection" service that manages the BT connectivity, and displays ongoing notification in order to avoid being killed. For coding clarity reasons I would like separate background service to collect all data, and log it (instead of having BT service do all the work). I also prefer loose coupling between my app components, so am using GreenRobot's event bus for all IPC. As a result my BT connection service is completely unaware of any data collection/logging code - it just dispatches a message to event bus and I'd like to keep it that way.
Now I'd like to have my data collection/logging code to be run as another background service. Is there a way to ensure it runs as long as BT connection service is running? And without displaying yet another ongoing notification or tightly coupling the code between two services?
You could let your class extend service so in this case you dont have to make a notification for it. Basically it keep running in the background without the need of displaying notification on the status bar. Make sure before you exit your app to stopservice() otherwise it will keep running until the device restarted or in somehow the user force stop your app from application manager inside of the settings.
I need to launch 3-part App if it is not running and wait for it to complete loading to start interacting with it.
How to start app is clear, but how to determine when it loaded without any additional timers or loops codes?
interact in concrete situation means send some data over TCP connection to same localhost. But firstly i must launch taht listening app main activity and then send data over socket.
(for example, well known MapFactor navigation app accepts remoute commands over TCPIP only. From my app i need to send GPS destionation to calculate route for navigation, but if MapFactor is not running it is not listening to tcp socket).
Right now I have a server running on a desktop. I want to be able to start up my app, hit a button to start collecting data from this server, and only stop once I hit to button again. The user should always be grabbing data from this server after hitting the button, even if the app isn't active. So far I've considered setting up a Service or using Threads by themself.
A Service sounds exactly like what I need, but I've been told it isn't meant to sustain a long network connection. I poked through the BluetoothChat sample application and it didn't use a Service. Would a Service be the right thing to use then, or should I implement it with threads like the sample application does? The only reason I need a long connection is to listen for any error reports from the server. The other network stuff only happens when the user is directly using the app. I will have to use threads anyways because a Service runs in the same thread as the activity that calls it, but I guess my main question is whether I should scrap the Service part. Right now I have a basic Service set up that can handle messages sent to it and it seems really easy to use. The documentation on it is just all over the place, there needs to be a section saying "If you want to do X, then this is suggested!"
A Service runs on the UI thread, but an IntentService runs in its own thread.
It's ambiguous to say that the "app" isn't active. If you're running a Service, it's always active. An IntentService is active as long as it has finished the work in its onHandleIntent() method. None of the activities of the app may be active, which means that the app is in the background.
Other than that, I'd need to know more about what you're trying to do. In general, it's better to collect data in cycles rather than trying to keep the connection open constantly. For example, what do you do when the device loses connection to the Internet?
I am trying to develop an application which will require a service to
run in the background. I am relatively new to android programming,
and after reading many posts, blogs, how-to's and books on creating
and managing services, I am still pretty confused about which model I
should try to use.
First, let me present (in general) the application requirements: I
need an application which will spawn a background process (service?)
which will connect to a bluetooth device. The bluetooth device is
designed to deliver data to the android device. The issue is that the
data could come in at any moment, so the bluetooth connection has to
stay active. Note that the application is a VERY SPECIFIC app and is
NOT intended for public use. I do understand the arguments for not
having background apps running all the time, but please understand
that this is a very specific application for a very specific client.
Now, in general, I think the program flow would be to start the
application (and launch a UI activity). Then I need to configure and
connect to the bluetooth device. At this point, the user should be
able to do other things - make phone calls, check their email, etc.,
while the bluetooth connection is still active and potentially
receiving data. If data comes in, a notification is fired, etc.
So here are my questions and concerns:
If I start an app (which spawns a UI activity and ultimately my
bluetooth connection service) but the app is killed, apparently, the
service handling the bluetooth connection is killed as well. How can
I keep that alive? I read that Service.setForeground() was
depricated, but even if I were to set it to the foreground, if the app
is killed, the service is killed as well. I need to have it run in
the background with as high of a priority as possible (again, I do
understand that this is considered "bad form", but this is a specific
app and this functionality has been requested by the client).
If I started the app (and the service, etc.), but the user, say,
answers a phone call, the app is put into the background. However,
let's say the user goes back to the home screen and starts a DIFFERENT
instance of the app, i.e., he doesn't hold down the home key to select
the already running app from the task manager but starts a completely
new one. If the service handling the bluetooth connection is still
running, how will this new instance behave? i.e., how can I get it to
connect to the bluetooth service which is ALREADY running in the FIRST
instance of the app instead of this new instance? Do I have to use
some form of a Remote service instead of a local service? This is
where I'm a little confused by things as it seems remote services and
defining an AIDL seems to create a lot of extra overhead, and since
I'm already creating a lot of overhead with the service running in the
background all the time, I want to keep that as small as possible.
How can I insure I am connecting to the same service already running?
1)
The service does not depend on an Activity. You can have it running on the background until you call stopSelf().
You can have a BroadcastReceiver that listens to the android.intent.action.BOOT_COMPLETED so your service is started when the phone is turned on.
2)
Your Activity should bind to the service. And get the info from it.
Check this question.