Multiple backend call with Retrofit at same time [duplicate] - android

I'm using Android SDK 4.0.3 API15 and I want to run multiple AsyncTasks parallely. I'm getting my data from web server and animating(10 fps) it real-time. But depending on user operations I need to send some data to web server also. When this occurs my animation pauses for a short time (sending data gets into queue and getting data waits it to finish ) and therefore I can't catch the real-time.
This answer is quite explaining but I couldn't make it work. So any help will be very appreciated.
I think I need to use this function to achieve that:
AsyncTask.executeOnExecutor(Executor exec, Params... params)
But I can't pass an executor as a parameter and I can't instantiate an executor. This is my AsyncTask class:
public class GetPlayers extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
rawData="";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
if((rawData = buffer.readLine()) == null){
rawData = "error";
}
} catch (Exception e) {
e.printStackTrace();
}
}
return rawData;
}
#Override
protected void onPostExecute(String result) {
manipulate();
}
}
And I execute it like this:
GetPlayers task = new GetPlayers();
requestString = "web adress is here...";
task.execute(new String[] { requestString });

This is how I do that:
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new MyAsyncTask().execute();
}
where MyAsyncTask is regular AsyncTask subclass. Or you can wrap this all in helper class:
class TaskHelper {
public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task) {
execute(task, (P[]) null);
}
#SuppressLint("NewApi")
public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task, P... params) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
} else {
task.execute(params);
}
}
}
and then just do:
TaskHelper.execute( new MyTask() );
or
TaskHelper.execute( new MyTask(), args );
or
TaskHelper.execute( new MyTask(constructorParams), args );

This problem occured to me, when updating my app in AndroidStudio to
sdk 25 from Intelliy using Android 2.3
Just the little change (executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, string1, ...); ) works perfectly.
I have an AsyncTask running in a Service for download and
create AsyncTasks for upload in no service.

Related

Finish procedure before starting a new one

I am beginner in Android and I need some help. So, I have a procedure with sub-procedures inside. How can I finish one before starting a new one. Here is a code to better understand:
public void onCellLocationChanged(CellLocation lokacija) {
super.onCellLocationChanged(lokacija);
location = (GsmCellLocation) Phone.getCellLocation();
textCellId.setText(String.valueOf(location.getCid() % 65536));
textCellLac.setText(String.valueOf(location.getLac()));
String JSON_URL_string=JSON_URL + "?cellid=" + String.valueOf(location.getCid()%65636);
getJSON(JSON_URL_string);
myJSONString = textCellNameSakriven.getText().toString();
ParseJSON(myJSONString);
}
Problem is that myJSONString is empty, cause textCEllNameSkriven is also empty. That textView textCellNameSkriven is made when getJSON(JSON_URL_string) is finished. If I run debugger and go step by step, app goes directly from getJSON(JSON_URL_string) row to the next one and the next etc
Edit: Maybe the problem is that onPostExecute is not finished before starting ParseJSON. Here is also a code for getJSON:
private void getJSON(String url) {
class GetJSON extends AsyncTask<String, Void, String> {
ProgressDialog loading;
#Override
protected void onPreExecute() {
super.onPreExecute();
loading = ProgressDialog.show(MainActivity.this, "Please Wait...", null, true, true);
}
#Override
protected String doInBackground(String... params) {
String uri = params[0];
BufferedReader bufferedReader = null;
try {
URL url = new URL(uri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder();
bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String json;
while ((json = bufferedReader.readLine()) != null) {
sb.append(json + "\n");
}
return sb.toString().trim();
} catch (Exception e) {
return null;
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loading.dismiss();
textCellNameSakriven.setText(s);
}
}
GetJSON gj = new GetJSON();
gj.execute(url);
}
Since you are running a async task it practically runs on a different thread, so your getJson method need not wait for post execute and can return after starting the async task, so you can never be sure in this way that parseJson gets executed after textView is populated. You are running into classic race condition issue.
Your issue could be easily solved, if you have a callback which is called after postExecute is done, and you can handle parseJson there
So, something simple like , create interface MyCallback
public interface MyCallback {
public OnReadJsonDone();
}
Let your activity implement this MyCallback
public MainActivity implements MyCallback
{
...........
#Override
public OnReadJsonDone(){
parseJson();
}
Now change signature of getJson to
getJSON(string json, final MyCallback callback) {
Now in onpostexecute
//call OnReadJsonDone
callback.OnReadJsonDone()
So, all you now need is while calling getJSon pass this as second param
getJSON(JSON_URL_string,this);
Haven't tested this but you get the idea

Checking the AsyncTask status seems not working correctly (log doesn't appear on log cat)

I'm trying to see how works an Asynctask class in android. In particular i want reveal in real time the status of the class for see when it is running and when it has finished. For do this, i have created a class that extend the main activity and another class that is the asynctaks class.
This is my main class:
public class PhotoManagement extends Activity{
private String numberOfSelectedPhotos;
private Bitmap currentImage;
private String initConfiguration = "http://www.something.com";
private String response;
private ArrayList<String> formatPhotoList = new ArrayList<String>(); //create a list that will contains the available format of the photos downloaded from the server
private ArrayList<String> pricePhotoList = new ArrayList<String>(); //create a list that will contains the available price for each format of the photos
DownloadWebPageTask webPage = new DownloadWebPageTask();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume(){
super.onResume();
webPage.execute(initConfiguration);
if(webPage.getStatus() == AsyncTask.Status.PENDING){
Log.i("STATUS","PENDING");
}
if(webPage.getStatus() == AsyncTask.Status.RUNNING){
Log.i("","RUNNING");
}
if(webPage.getStatus() == AsyncTask.Status.FINISHED){
Log.i("","FINISHED");
}
}
}
As you can see i want only see the passages of the status with a simple log.
And here there is the asynctask class.
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient(); //create a new http client
HttpGet httpGet = new HttpGet(url); //create a new http request passing a valid url
try {
HttpResponse execute = client.execute(httpGet); //try to execute the http get request
InputStream content = execute.getEntity().getContent(); //prepare the input stream to read the bytes of the request
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s; //until is present a line to read, the response variable store the value of the lines
}
} catch (Exception e) {
Log.i("MyApp", "Download Exception : " + e.toString()); //Print the error if something goes wrong
}
}
return response; //return the response
}
#Override
protected void onPostExecute(String result) {
result = doInBackground(initConfiguration); //take the result from the DownloadWebPageTask class
result = result.replace("null", "");
Log.i("RESULT",""+result);
//find the price and format value from the result using XmlPullParser
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput( new StringReader ( result ) );
int attributeNumber = xpp.getAttributeCount();
int eventType = xpp.getEventType();
String currentTag = null;
while(eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_TAG) {
currentTag = xpp.getName();
if (currentTag.equals("product")){
xpp.getAttributeValue(null, "name");
formatPhotoList.add(xpp.getAttributeValue(null, "name"));
Log.i("FORMAT PHOTO",""+xpp.getAttributeValue(null, "name"));
}
}
eventType = xpp.next();
}
} catch (XmlPullParserException e) {
e.printStackTrace();
Log.i("","ERROR XML PULL PARSER");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.i("","ERROR IOEXCEPTION");
}
}
}
}
As you can see i have implemented also the method onPostExecute that should be called when the asynctask method has finished to execute the instructions right?
So at this point i don't understand why my log RUNNING and my log FINISHED never appear on the log cat.
What i'm doing wrong?
I'm tried to follow this topic Android, AsyncTask, check status? but in my case it isn't working.
Thanks
Problem :
You are creating object like
DownloadWebPageTask webPage = new DownloadWebPageTask();
But you are calling asynctask on different object,
new DownloadWebPageTask().execute(initConfiguration);
Solution :
It should be like
webPage.execute(initConfiguration);
#Override
protected void onResume(){
super.onResume();
new DownloadWebPageTask().execute(initConfiguration);
here do like this
#Override
protected void onResume(){
super.onResume();
webPage.execute(initConfiguration);
You didn't implement webPage.execute(), add it
Most probably the task hasn't finished or even started yet. As you probably know the AsyncTask is doing it's (background) work on a different thread, so your onResume is running in parallel with it. You can either use the task's get() method to wait for it to finish and get the result of the doInBackground() method and then query for it's status or notify your activity from the task's onPostExecute() method to let it know (and log) that it has finished. I don't recommend you the first option because it will actually block the UI thread and will make your usage of AsyncTask pointless.

how to call two different http connections in asynctask

How to call two different network url in asynctask background and call onPostExecute separately? Any idea help me please. Below is my code which works for one network connection. In my App there're two different network connections.
public class TheTask extends AsyncTask<Void, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(Void... arg0) {
try {
String query = URLEncoder.encode("American%20Cheese%20Burger", "utf-8");
String url = "http://198.57.208.46.xyz";
Log.i("url",""+url);
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
HttpEntity resEntity = response.getEntity();
_response=EntityUtils.toString(resEntity);
} catch(Exception e)
{
e.printStackTrace();
}
return _response;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
tv.setText(result);
}
}
Apart from the Java way (Threadpools) there's the Android way with two possibilities.
Call doInBackground() with two parameters (actually as much as you like). This will call onPostExecute() once at the end.
Additionally override AsyncTask.onPostProgress() and call it on every url with publishProgress(_response);. This will then be called on every url and in UI-Thread, so it should fulfill your requirements. The code looks like this:
public class TheTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... urls) {
for(String url : urls) {
Log.i("url", url);
// Work with the URL, like reading the JSON and build _response
publishProgress(_response);
}
return _response;
}
#Override
protected void onProgressUpdate(String _response) {
super.onProgressUpdate(_response);
tv.setText(_response);
}
}
If this is still not exactly, what you need, there's a third thing you can do: Build two AsyncTasks and run them in parallel.

Convert android AsyncTask call to a separate class and call from all activities

I am new to android development. I have a AsyncTask function in my application. Calling http request from all activities. Now in each activity I am using the following class to connect to server, in some activities I even called twice !!.
Basically I am a web developer and in such cases we use a single class which can be accessed from entire application(web) and use the common function to do the same activity. The only difference is input and out put will be changed.
My doubt is in this case can I use ( convert) this to such a function or class ?
My assume is
Create an android class ( which can be accessed from all the activities )
Just make the JSON string we need with specific server ( for process in server )
Just pass the created json to the created class and then made the http connect )
Process the returned data from server
Pass that to the corresponding activity
So that I can use the same function for all the activities and I can avoid duplicate query
Can I convert this code to such a manner ?
My Code
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_main);
LogIN loginUser = new LogIN();
LoginUser.execute("");
}
private class LogIN extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
try {
String path = "http://www.domain_name.com/app/checkSession.php";
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost(path);
json.put("access_token", "123456");
post.setHeader("json", json.toString());
StringEntity se = new StringEntity(json.toString());
se.setContentEncoding((Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/* Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent();
String a = convertStreamToString(in);
JSONObject jsono = stringToJsonobj(a);
String passedStringValue = jsono.getString("result");
if(passedStringValue.equals("1")){
flags=1;
//Log.v("TAGG", "Success");
}
else {
flags=0;
//Log.v("TAGG", "Failed !");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialogue("Login Processing", "Loading");
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
}
#Override
protected void onPostExecute(String result) {
if(flags.equals(1)){
Itent homepage = new Intent(MainActivity.this, RegisterDevice.class);
startActivity(homepage);
finish();
}
else {
Intent homepage = new Intent(MainActivity.this, LoginActivity.class);
startActivity(homepage);
finish();
}
super.onPostExecute(result);
}
}
}
Please any one help/advise
Thanks in advance
Extract your class to a different file and make it public
public class LogIN extends AsyncTask<Object, Integer, String> {
private ILoginListener listener;
#Override
protected String doInBackground(Object... arg0) {
try {
this.listener = (ILoginListener) arg0[0];
//You can also send the url in the obj array
String theUrl = (String) arg0[1];
String path = "http://www.domain_name.com/app/checkSession.php";
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost(path);
json.put("access_token", "123456");
post.setHeader("json", json.toString());
StringEntity se = new StringEntity(json.toString());
se.setContentEncoding((Header) new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/* Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent();
String a = convertStreamToString(in);
JSONObject jsono = stringToJsonobj(a);
String passedStringValue = jsono.getString("result");
if(passedStringValue.equals("1")){
flags=1;
//Log.v("TAGG", "Success");
}
else {
flags=0;
//Log.v("TAGG", "Failed !");
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialogue("Login Processing", "Loading");
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
}
#Override
protected void onPostExecute(String result) {
listener.logInSessionCheckListener(flag.equals(1));
super.onPostExecute(result);
}
}
Regarding your other question, I normally have an interface for that, something like this:
public interface ILoginListener {
public void logInSessionCheckListener(SomeNeeded Value);
}
I implement the interface in the class where i need the postExecute result and in the overriden method you can to what you want with the result of your task.
Your class where you user it will look something like this:
public class SomeClass implements ILoginListener {
//Call it like this from any class:
LogIN loginTask = new LogIn();
Object[] someParams = new Object[2];
//add the listener
someParams[0] = SomeClass.this
//add the url
someParams[1] = someUrlString;
loginTask.execute(someParams);
#Override
public void logInSessionCheckListener(SomeNeeded Value){
//do Stuff with your results
}
}
You can do it like make separate class for everything inside doInBackground() method and called it in all activity with passing parameter to
LogIN loginUser = new LogIN(yourparameter);
LoginUser.execute("");
and check parameter in AsyncTask Class constructor like
public LogIN(Myparameter){
// Your data
}
On the other hand you can use this great framework for android : android-query and the async API.
It allows you to perform asynchroneous network tasks from activities and easily work with the results of your requests.
You should use interfaces to implement a callback to your ui activity.
Have a look at this thread, it might be useful:
android asynctask sending callbacks to ui
And your asyntask class should be in a seperate java file with public acces.
And to pass the parametres you simply have to call a new LogIN async Task like this:
new LogIN().execute(urls);
Hope it helped :)
Remember that you can never know when AsyncTask is going to finish. So if you're using this to authenticate users and then perform task X, task Y, or task Z,
then maybe it's better to create a Login helper class
public class LoginHelper {
public boolean login(params){
// Authenticate user and return true if successfull
}
}
and then have in your Activity classes
private class X extends AsyncTask {
#Override
protected String doInBackground(String... sUrl) {
...
boolean authenticated = LoginHelper.login(params...);
if(authenticated == true) {
// Perform task X here...
} else {
// Inform the user that the login failed...
}
}
First of all
You have to pass the context in which you are calling your async task
Sample Code
Login loginTask = new Long(getContext());
loginTask.execute();
You class Login should have a constructor that accepts the Context
Sample Code
public class Login extends AsyncTask<String, Integer, String> {
private Context mContext ;
private ProgressDialog pd;
private Handler handler = new Handler { };
public Login (Context context){
mContext = context ;
}
.....
Then make sure to create the method showDialog inside Login class to show the progress dialog
Note
You can add what ever Constructors you need to customize the behaviour of your Login task
for example : pass boolean parameter to tell that the Login Task is cancelable....
Hope that help you :)

How to call a URL in background using Android?

I am looking to insert userdata to database by calling URL link to webservice on server:
ex:
this is the link:
http://mydomain.com/AndroidWebService.asmx/nInsertInfo?id=12&lat=23.2222&log=12322
So I want to call this url in hidden mode.
Use android android AsyncTask to post data. It work in android background when application is open.
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
Like
AsyncTask
AsyncTask
AsyncTask
Thanks.
Thanks all for your valuable solutions.
i have did it by creating WebView
WebView myWebView = (WebView) findViewById(R.id.view1);
myWebView.loadUrl(urll);
then i can manage my WebView as i want: hide it, alignment as error or result returns.
Maybe this example will help you :
public class URLConnectionTask <Result> extends AsyncTask<URL, Void, InputStream> {
#Override
protected InputStream doInBackground(URL... params) {
InputStream is;
HttpUriRequest request;
URI uri;
HttpResponse response;
if (params.length == 0)
return null;
is = null;CredentialsProvider credProvider = new BasicCredentialsProvider();
if (userName != null && userName.length() > 0 && password != null && password.length() > 0)
credProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),
new UsernamePasswordCredentials(userName, password));
//
DefaultHttpClient http = new DefaultHttpClient();
http.setCredentialsProvider(credProvider);
//
uri = URI.create(params[0].toString());
if (isPost)
request = new HttpPost(uri);
else
request = new HttpGet(uri);
try {
response = http.execute(request);
is = response.getEntity().getContent();
//Log.d(TAG, "doInBackground() response: "+EntityUtils.toString(response.getEntity()));
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (processingHandler != null && is != null)
processingResult = processingHandler.processResponse(is);// processingHandler is an instance which implements ProcessingHandler interface (ex. VizMarket). processResponse() is implemented on this class.
return is;
}
#Override
protected void onPostExecute (InputStream result) {
input = result;
if (result == null)
return;
//instruction for inserting data on db ....
try {
result.close();
} catch (IOException e) {
}
}
}
You should call URL in AsyncTask. For instance: Return data from AsyncTask class
U have to use a thread to fetch data from server and insert into to DB or in android you can use AsyncTask.
You can have a search :ClickableSpan
And put your insert code into the OnClick body~
Just like:
String yourTextStr;
SpannableString sp = new SpannableString(yourTextStr);
int start;//the start of your url in the text;
int end ;//the end of your url in the text;
sp.setSpan(new ClickableSpan() {
#Override
public void onClick(View widget) {
//Your Insert Code
}
}, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

Categories

Resources