I am new to Android development and am not sure of the best way to go about handling the following problem.
Background:
I have a TCP client running on android talking to a server. this is up and running just fine however when moving to the next step i am unsure of what to do.
Problem:
I have a UI that draws based on a users touch. I need for the tcp client running on the phone to send the coordinates and some other data to the server. Also there are multiple activities in this process that would be sending data.
What would be the best way to handle this?
Here are some of my thoughts.
1) A class that would have a Runnable client that works on another thread (I think its is an invalid solution because it would not be easy to use the same connection on multiple activities)
2) A local service that can the main activity can start and the rest of the activities can bind to it and send data to it.
If the correct answer is number 2 I am a little confused on how a service like that would work. What I am thinking is that in the OnCreate() method of the service it will launch a tcp connection with the server. Once the socket connection is established I am a bit unsure of how to actually keep in communication with the service and give it the data it needs to send over the client.
You would start the service with startService(). Include in the Intent extras that contain your data to send to the server. The service would retrieve these extras in onStartCommand() and would have a background thread actually send the data.
Be sure to stop the service when you are done with it.
Related
I am currently developing an android application using HTTP/REST requests to communicate with my backend. I am not using any particular library yet since until now the built-in HttpURLConnection works fine for me. However I would like to have some kind of fallback mechanism if my requests fail due connectivity issues. A similiar problem is also described in https://stackoverflow.com/questions/31786486/android-volley-internet-queue but has not been answered yet and other related posts rather focus on caching older responses to redirect requests to the cache when there is no connection is available.
Up to now I considered using Volley but as far as I understand it it only allows to retry a failed request until it finally connects. I think it would be a cleaner solution to cache the failed request and attempt to resend it after I registered a change in my connectivity state via a BroadcastReceiver. Is there an existing solution which does that for me or do I have to set up an internal database and manage the whole process myself ?
TL;DR
I want to store failed HTTP/REST requests on my android device when my device is offline and resend them when the device can establish a connection again. What am I looking for ?
I had the same situation with a reporting service. What I implemented was a Service that receives requests and queues them. In a separate thread (started when the service starts) it checks the queue and attempts to make the connection. If you use a BlockingQueue you have the 'signalling' between threads for free, so you don't need to idle-poll.
You can use set up a receiver for WifiManager.WIFI_STATE_CHANGED_ACTION and/or ConnectivityManager.CONNECTIVITY_ACTION events, so that you start the service or wake up the thread and attempt to re-send when the connection is up again.
I suggest a Service so you can detach all this from the code in your Activities and have some facilities for starting and stopping it. I personally used an IntentService because that allows me to serialize the requests through Intents, and let the OS handle the Intent management sending for me. You might implement it differently, even without a Service, just with a Singleton object.
If you also need storing them when your app is not running, I would use a SQLite Database.
As #Sebastian wrote you can write queue handler yourself, or perhaps check if existing implementations, like android-priority-jobqueue is not going to be useful for you.
I want to develop an Android application that satisfies the following specifications:
Record data from a sensor (for example the accelerometer) at an
approximate rate of 10-30 Hz.
Upload this raw data to a remote server (for example using TCP
sockets).
The user interface should be minimum, just a pair of buttons to start
or stop the recording and transmission of the data.
All the process should be unnoticeable for the user and keep working
when the screen goes off for several hours.
Battery life is not critical (it should last several hours).
Vision: I would like to analyse in quasi-real time the sensor measurements of a group of users without their intervention (apart from starting the application).
After some research, I could manage to perform these tasks separately and inefficiently. I've tried classes such as Service and IntentService, SensorEventListener, etc. I don't know if I should use Thread, Service or IntentService for each task. Specifically, I have serious problems to communicate them.
My questions:
What class(es) do you recommend to use in order to solve this
problem?
What task should be done on each of them?
If the tasks are performed in different entities (threads, services,
intentservices, etc.), how should I intercommunicate them (I'm
thinking about the recording and uploading tasks)?
I am asking for the best-practice structure to solve my problem. You do not need to go into details in terms of developing/coding the solution.
Thank you very much and feel free to ask if something is not clear enough.
David
UPDATE:
After some more research and thanks to DROIDcoder, I manage to design a skeleton for my app:
Main UI: Activity object presenting two buttons (start/stop) that
will launch a Service with the usual startService/stopService methods
Background: Service object
Awake when screen goes off: the service requests a power lock in onCreate() and releases the power lock in onDestroy(). Find more info here: https://developer.android.com/training/scheduling/wakelock.html#cpu
Log sensor values: implement SensorEventListener in the Service as usual
Upload sensor values to server: use AsyncTask in the service as described here: How to use AsyncTask
Data formatting and transmission: use GSON library + HttpClient as described here: How to send POST request in JSON using HTTPClient?
Testing: use the website http://www.jsontest.com/ to test the JSON queries
As this is only a proposition, I add it as an edition. I will post a detailed answer when the whole system works.
The questions remains: can you think about a better design for the application?
Thanks again!
Finally what I have done:
Issue 1: record data from a sensor on the background for a long period of time.
Solved using the class Service to initialize the sensor and listen for callbacks.
Issue 2: communicate the Activity class holding the UI with the Service class.
Solved using the startService(Intent myMessage) method from the Activity class combined with a switch in the onStartCommand() method from the Service class to classify the message.
Issue 3: communicate the Service class with the Activity class.
Solved registering a custom BroadcastReceiver in the Activity and sending Intents from the Service. I've used it to update a progress bar (in the Activity) during the file uploading (in the Service). An exceptional tutorial can be found here.
Issue 4: upload data to a remote server.
Solved using AsyncTask inside the Service like in this site.
here are my suggestion
Upload this raw data to a remote server
You can use JSON parsing for server communications. you will use AsynTask(Background Thread) for background data uploading
All the process should be unnoticeable for the user and keep working when the screen goes off for several hours.
You should use services for background long term processing
My app has a UI and a connection is made to a bluetooth device which is periodically sending barcode scan data to my app. I then want to cache this data in a sqlite db and have another process push this data up to a web server.
I have managed to get the UI and bluetooth scan process separated by using an Intent Service for the scanner component... The thread in the intent service connects to the bluetooth device and loops endlessly pulling in new scan data as it comes... communicating with the UI via broadcast messages as it needs to.
So now I need to handle storing the data in a sqlite db and pushing it up to the Internet.
I'm thinking I can insert a db row directly in the intent service loop I already have working for the bluetooth data... would I do that by firing of an async task or something like that?
Then, would I have a completely different intent service running and looping endlessly checking for new records to be processed and pushed up to my web server via an http post?
I guess the main reason I'm thinking of using intent services is that they seem to keep running even if I lock my phone and put it in my pocket... has worked so far for the bluetooth barcode scanner... can scan away happily with my phone locked and in my pocket.
I also need to handle the reality that internet won't always be available... hence the sqlite db... kind of like a safe buffer to store data until it can eventually be pushed up to the Web server.
Am I going down the right path? I'm really new to Android development and even after much research I'm still unsure about my approach.
You can store data or communicate from IntentService onHandleIntent() directly. You don't need to run it in separate thread, unless you want reading bluetooth to continue ASAP.
Handling everything in an infinite loop smells. Also keeping service alive depends on few factors. If IntentService dies, it won't be restored because by default IntentService.onStartCommand implicitly returns START_NOT_STICKY, or START_REDELIVER_INTENT if you call setIntentRedelivery(true) on this service. Check Service javadoc for more info.
If you can scan bluetooth periodically then I would consider kind of scheduler. For that you would probably need to implement Service, not IntentService and handle background thread yourself. Alternatively, you could use a Timer. These are more hints, not ready solution. Since you asked about direction, I assume you will investigate solutions yourself.
Depending on handled data you could separate DB operations and network to separate services. Think about them as modules which are decoupled. You will benefit maintaing this code in the future and in case one service goes down due to any reason, the rest will keep working. It depends on data size because it's not a good practise to push heavy data between service/activities(data is serialised and deserialised every time it is sent).
If DB is just a buffer/queue then maybe use it directly after reading bluetooth data. In other words queue data for sending. Create second service for HTTP communications. Don't push entire data to second service, just inform it about(knock the door :)) and let HTTP service access DB by itself. I would wrap DB in ContentProvider and access it from services.
There are probably different techniques out there too, but that's what I thought about it in the first place.
I am trying to do the following and am looking into other people's experiences:
I want to have an HTTP server running on Android that receives GET requests from a client. From there, the server must deliver the query parameters to a Service that will do some processing (sometimes quite heavy). When the service is done, it sends back the data to the server that will then return the response.
Of course, the startService(intent) call is asynchronous so I'm wondering how to tell the server to wait for the processing to be done before sending back the response. At the moment, the inter process messaging is done with the Messenger and Message classes.
What sort of design would be able to achieve that?
Use a bound service (one that implements onBind()) and a transact call on the returned IBinder object. Or write your own AIDL to describe the service's synchronous interface.
You want to bind to your service on app startup, before the HTTP requests start coming, since the bind operation itself is async.
By the way, why does the functionality have to be in the service? If the service is in the same app, can you move it directly to the HTTP server class?
I have a school assignment about building a UDP based chat client on android. Now, my first idea was to make an activity that starts a service and the service handle all the networking and the activity all the input an output. But a have found a problem.
If i try to start the service so that the startCommand function starts and calls the socket.receive to start receiving network message, I can not bind the service so that i can pass input from the activity to the service (input = messages that the user want to send). It just hangs and a ANR exception is thrown. If i only bind it (so that receive is never called), it works like a Charm.
Maybe I'm not approaching this problem right. Or should it work to bind the service wen it's on a blocking receive call?
I did something like this once. I took the necessary data needed to track down the other device and fed it into an asyncTask where I kicked off a Runnable that basically kept a connection going on in the background.(This way you don't have to worry about binding) I found that instead of making your own socket connections its easier just to use Apache Mina or Netty. (No need to reinvent the wheel). If you just pass the data transmissions from the session running in the background to a List or a Queue and have an asyncTask check it and update the UI accordingly you should be all set for chatting. Maybe this isn't the best way, but it worked for me. Hope some of this helps.