How to start a clientTask from within a ServerTask in Android? - android

I have a client-server app, where each app has both client-server functionalities.
The client in one app sends a number, to which the server side on the second app has to reply. To reply, I need to start a client Task to do it. But I get the error "Method executeOnExecutor must be called from the main thread, currently inferred thread is worker".
I cannot show the exact code, so I am posting some psuedo code for better explanation :
private class ServerTask extends AsyncTask<ServerSocket, String, Void> {
#Override
protected Void doInBackground(ServerSocket... sockets) {
...receive from client.. do processing. need to reply
new ClientTaskName.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR,message);
}
}
private class ClientTaskName extends AsyncTask<Message, Void, Void> {
#Override
protected Void doInBackground(Message... params) {
//... do something...
return null;
}
}
If I am not allowed to create a clientTask from within the serverTask, what are my options ?
EDIT:
I am adding a basic overall process flow:
Process A send msg1 to process B.
Process B receives it in ServerTask, replies to it
Process A receives the reply, decides some additional parameters based on the reply, sends ACK with the decided parameter.
Process B receives ACK and configures its own future messages with received parameter.
This requires that the ServerTask handle two types of messages in its doInBackground function, one where it expects only ACK, and one where it will reply to the received message.
The steps 1-4 will run arbitrary number of times.
SDK used : API 19

Use threads instead of AsyncTasks.
That is how it is normally done.

Related

retrofit for android - how to do sequential network calls

in my android app i have 3 network calls and they are dependent on the call before it. So 1 must finish, then 2 can go and finally 3 gets run with the data from the previous ones. So i need the network calls to run sequentially is the goal. after one call is finished it will have data passed to the next call, etc. I dont want to use rxJava. Is there a way with retrofit to make this happen ? My project is already using retrofit thus i want to continue using it ? I've tried playing around with asynchTask but its not clean and since im using retrofit i thought i would ask.
If you're using Retrofit with the asynchronous Callbacks then for the first network call you can pass in the generated interface which represents the web service that you're interacting with. In the success method you can then use the instance of the generated interface to make a second network call, using the data which came back in success under the parametrised type T, and so on for the third call inside a second callback. For example:
class FirstCallback implements Callback<First> {
private Api api;
public FirstCallback(Api api) {
this.api = api;
}
void success(First data, Response response) {
api.secondCall(data, new SecondCallback(api))
}
}
// somewhere else in your code
api.firstCall(new FirstCallback(api));
This is a quick solution using chaining with the asynchronous calls. This would most likely look more sequential and easier to read inside of an AsyncTask using the synchronous calls, which would return the type T directly. For example:
class MyTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
First first = api.firstCall();
Second second = api.secondCall(first);
// ...and so on until you return the final result
}
}

Android - sending SeekBar values via TCP

I'm currently developing an android app that communicates with some other device, that acts like a server. Basically to build the application's views, I first have to send a query via a TCP connection to the server to get the info. I (successfully) execute these queries with the help of an async task:
private class TCPQuery extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
//connect the socket send the query and receive feedback
}
#Override
protected void onPostExecute(String result) {
//parse server feedback and build the view
}
}
This approach works fine when it comes to single queries that are made only a couple of times during the application's lifetime. What I have trouble implementing is the following:
a certain view in the application, contains seekbars. So basically, every change of the seekbar value (every time the onProgressChange method fires) must be sent to the server(no feedback this time), so it can keep track of the actual values.
How would you go about implementing this? Of course, no networking in android may be done on the main thread. But here establishing a connection, sending a message and closing the connection every time the value changes is not acceptable. Sliding the bar only a little already results in a dozen such calls in a split second.
I've tried approaching this problem by implementing a service. The service had its own socket to communicate with the server. I would connect the socket to the server and keep it open, so that I would be able to call the service's send method any time a seekbar change has been made. But that seemed to interfere with the other queries I mentioned before (the ones executed with async tasks). I couldn't connect one while the other was active. Now I'm not sure whether my service implementation was just bad, or if I am misunderstanding a crucial networking concept here.
I have thought of only sending the data onStopTrackingTouch, but that is not really what I am after. Any help would be very much appreciated!
Use the system clock to check when the last query has been sent, and don't send another until a certain time has elapsed.
You can change seekbar's value as you want, but the query will be sent only every X milliseconds.
static long sendInterval = 600; //milliseconds
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
long nextSend = 0;
}
#Override
public void onProgressChanged(......) {
if (nextSend < uptimeMillis()) {
...send the query and parse feedback...
nextSend = uptimeMillis() + sendInterval ;
}
Start with nextSend = 0, so the first time the query will be sent immediatly.
Choose sendInterval value according to server's response time. Start with a high value and decrease until you see that all is working well.
If the query itself and the response are small (a few bytes) consider using UDP instead of TCP, it's faster and you can use lower values of sendInterval.
Other way to do it, different and maybe better:
since the response time may vary much depending on network traffic, query complexity and server load, you can use a boolean flag. Set it to False before sending the query, set it to True after parsing the response. Use it in an If statement:
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
boolean readyForQuery = true;
}
#Override
public void onProgressChanged(......) {
if (readyForQuery) {
readyForQuery = false;
<...asyncronous send the query, parse feedback and set readyForQuery=true;...>
}
Consider also the worst case: when the server is down and will not respond at all to the query.
Take care to find a way to set the flag True after a reasonable amount of time and/or when the query code generates an exception, otherwise you won't get further responses even when the server goes up again.

Fetching big amount of data, what is the best way to go?

I have severals URLs I need to get data from, this should happen in order, one by one. The amount of data returned by requesting those URLs is relatively big. I need to be able to reschedule particular downloads which failed.
What is the best way to go? Shall I use IntentService, Loaders or something else?
Additional note: I would need not only to download, but also post process the data (create tables in db, fill it with data, etc). So DownloadManger can't be of help here.
I would use an IntentService.
It has a number of advantages that are suitable for your needs, including being able to download the data without your application running and supporting automatic restart of the service using setIntentRedelivery().
You can set a number of identifiers for the particular job, you need to perform using Intent extras, and you can keep track of the progress using SharedPreferences - that way you can also resume the work if it's been cancelled previously.
The easiest way is probably to use the system DownloadManager http://developer.android.com/reference/android/app/DownloadManager.html
(answering from my phone, so please excuse the lack of formatting)
I would suggest a service for this. Having service resolves many problems
It would allow reporting of progress asynchronously to the application so you can enable or disable a specific gui in application based on the download status of data
It will allow you to continue the download even if the user switches to other application or closes the application.
Will allow you to establish independent communication with server to prioritize downloads without user interaction.
Try a WakefulIntentService for creating a long-running job that uses wakelocks to keep your task alive and running https://github.com/commonsguy/cwac-wakeful .
Also, if your whole app process is getting killed, you may want to look into persisting the task queue to disk, using something like Tape, from Square
I think the way to go is loading urls in an array, then starting an AsyncTask, returning a boolean to onPostExecute indicating if the operation has success or not. then, keeping a global int index, you can run the AsyncTask with the next index if success, or the same index otherwise. Here is a pseudocode
private int index=0;
//this array must be loaded with urls
private ArrayList<String> urlsArray;
new MyDownloaderAsyncTask().execute(urlsArray.get(index));
class MyDownloaderAsyncTask extends AsyncTask<String,String,Boolean>{
#Override
doInBackground(String... input){
//downlaod my data is the function which download data and return a boolean
return downloadMyData();
}
#Override
onPostExecute(Boolean result){
if(result)
new MyDownloaderAsyncTask().execute(urlsArray.get(++index));
else
new MyDownloaderAsyncTask().execute(urlsArray.get(index));
}
}
hope this help
I have just completed an open source library that can do exactly what you need. Using droidQuery, you can do something like this:
$.ajax(new AjaxOptions().url("http://www.example.com")
.type("GET")
.dataType("JSON")
.context(this)
.success(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
//since dataType is JSON, params[0] is a JSONObject
JSONObject obj = (JSONObject) params[0];
//TODO handle data
//TODO start the next ajax task
}
})
.error(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
AjaxError error = params[0];
//TODO adjust error.options before retry:
$.ajax(error.request, error.options);
}
}));
You can specify other data types, which will return different object types, such as JSONObject, String, Document, etc.
Similar to #Murtuza Kabul I'd say use a service, but it's a little complicated than that. We have a similar situation related to constant internet access and updates, although ours places greater focus on keeping the service running. I'll try to highlight the main features without drowning you in too much detail (and code is owned by the company ;) )
android.permission.RECEIVE_BOOT_COMPLETED permission and a BroadcastReceiver listening for android.intent.action.BOOT_COMPLETED to poke the service awake.
Don't link the service to the Activity, you want it running all the time. eg we call context.startService(new Intent(context.getApplicationContext(), OurService.class))
The service class is just a simple class which registers and calls an OurServiceHandler (as in our case we fire off repeated checks and the Handler manages the 'ticks')
We have an OurServiceRunnable which is a singleton which is checked and called by the Handler for each test. It protects against overlapping updates. It delegates to an OurServiceWorker to do the actual lifting.
Sounds heavy handed, but you want to ensure that the service is always running, always ticking (via the Handler) but only running a single check at a time. You're also going to run into database issue if you use the standard SqlLite DbHelper paradigm, as you can't open the DB on multiple threads and you definitely want the internet access off the main thread. Our hack was a java.util.concurrent.locks.ReentrantLock protecting access to the DB, but you could probably keep DB access on the UI thread and pass DB operations via the Handler.
Beyond this it's just a matter of keeping the downloads atomic in terms of "get task, download task, complete task" or enabling it to pick up from a failed state eg downloaded OK, attempt to complete.
You should take a look at the volley library :
http://www.javacodegeeks.com/2013/06/android-volley-library-example.html
There is also an interesting video of the author that took place at google io 2013 :
http://www.youtube.com/watch?v=yhv8l9F44qo
Mainly because it eases the process of managing a lot of these fastidious tasks that are connection checking, connection interruption, queue management, retry, resume, etc.
Quoting from the javacodegeeks "Advantages of using Volley :
Volley automatically schedule all network requests. It means that Volley will be taking care of all the network requests your app executes for fetching response or image from web.
Volley provides transparent disk and memory caching.
Volley provides powerful cancellation request API. It means that you can cancel a single request or you can set blocks or scopes of requests to cancel.
Volley provides powerful customization abilities.
Volley provides Debugging and tracing tools"
Update from dennisdrew :
For large file, better use a variant of volley which authorize using another http client implementation. This link gives more details :
The volley article about this modification :
http://ogrelab.ikratko.com/android-volley-examples-samples-and-demos/
The github file detail :
https://github.com/ogrebgr/android_volley_examples/blob/master/src/com/github/volley_examples/toolbox/ExtHttpClientStack.java
public class FetchDataFromDBThread implements Runnable {
/*
* Defines the code to run for this task.
*/
#Override
public void run() {
// Moves the current Thread into the background
android.os.Process
.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
FetchDataFromDB();
}
}

Blocking/Synchronous function call in AIDL

I am working on a android service, this service provided a AIDL interface for applications, Now application calls function GetData() using AIDL interface, this function is implemented in Service , it does some network operation, connect to server and fetch some data, this network transaction happen in background thread, Problem is that I want function GetData() should NOT return until network operation is complete, result comes from server and I want to return it into GetData(), GetData function returns immediately and network operation in background thread keep on running in parallel, how to avoid this, cannot call network operation also in main thread. I read about countDownlatch, is it only possible solution?
Service Main Thread
GetData
GetDataFromServer-----------> in Background thread
/*this is problem */ GetData returns; |
|
|
communication in progress
|
|
|
/*I want GetData should return here <-------------------transaction complete
Create some interface and implement that interface in your class and pass the interface object to that particular service after response came from the network pass the data to that interface object.
i think this help you.
you can call startService from AsyncTask.I can have the same problem in my nearest place application that need data from google map.enter code here
protected void getLocationAndUpdatePlaces(boolean updateWhenLocationChanges) {
// This isn't directly affecting the UI, so put it on a worker thread.
AsyncTask<Void, Void, Void> findLastLocationTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
// Find the last known location, specifying a required accuracy of within the min distance between updates
// and a required latency of the minimum time required between updates.
// start a service that require data from web.
}
};
findLastLocationTask.execute();
`

How to make requests to server from Android applications

I'm currently developing an application on Android platform that needs to contact the main server multiple times to do various stuff. I'm now coping with the issue of software design in terms of making every request to the server in a separate thread (otherwise, I get a NetworkOnMainThreadException and it's not recommended to do so).
So I have 3 classes in my example:
The requester class that wants to, say, fill up a Spinner with data from a database located in a server.
The middle class that asks a DBConnection to perform a new connection, then wait for it to finish and parse the data to the appropriate format.
The lower class that makes the connection to the database and retrieves a raw String, which then is passed to the middle class to be parsed.
I know that for every connection made to the server, I'll have to create a new thread, so that's made in the class that establishes the connection (lower class) and waits for results. This way I don't overload the top layers of my software with AsyncTasks and stuff that they shouldn't be aware of.
The problem is that after I receive the data I have to parse it, and the do stuff with it. Also I have to fill up the spinner (as in the example).
I know it might be a good idea to make a DataFromServerListener interface or something like that, but I think it's gonna get cluttered with methods all around to handle data from server. On the other hand, I'd have to make every top class start the separate thread with an AsyncTask and might not be the best solution.
I'd really appreciate any suggestions on this subject. :D
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
return "Executed";
}
#Override
protected void onPostExecute(String result) {
}
}
This is kind of what I needed. Actually, it solves problems I didn't take care of before.
http://www.codeproject.com/Articles/162201/Painless-AsyncTask-and-ProgressDialog-Usage

Categories

Resources