How pass method in AsyncTask? - java

I've class with methods
class Wrapper {
public static String AuthIn(String Login, String Password){
String response = HTTPRequest.POST(client, GetAuthUrl(), RequestBuilder.AuthInVk(login, password));
System.out.println(response);
}
public static String GetInfoUser(){
String response = HTTPRequest.GET(client, "http://site1.com");
System.out.println(response);
}
}
When i call this methods in MainActivity class and get error message "Main thread ..... etc"
How write Wrapper class in AsyncTask ?

Here is a nice example taken from codexpedia, for more details please check their site.
public class MainActivity extends AppCompatActivity {
TextView tvWeatherJson;
Button btnFetchWeather;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvWeatherJson = (TextView) findViewById(R.id.tv_weather_json);
btnFetchWeather = (Button) findViewById(R.id.btn_fetch_weather);
btnFetchWeather.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new FetchWeatherData().execute();
}
});
}
private class FetchWeatherData extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String forecastJsonStr = null;
try {
// Construct the URL for the OpenWeatherMap query
// Possible parameters are avaiable at OWM's forecast API page, at
// http://openweathermap.org/API#forecast
URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7&appid=2de143494c0b295cca9337e1e96b00e0");
// Create the request to OpenWeatherMap, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
forecastJsonStr = buffer.toString();
return forecastJsonStr;
} catch (IOException e) {
Log.e("PlaceholderFragment", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
}
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
tvWeatherJson.setText(s);
Log.i("json", s);
}
}
}
If you want to pass data into the async task doInBackground or onPostExcute and more check this stackoverflow comment : what-arguments-are-passed-into-asynctaskarg1-arg2-arg3
Keep in mind that your AsyncTask won't stop even when the activity has destroyed. A better way to create a network call from an activity is with an Handler Or just use an asyncHttp client lib such as ok-http , google volley :)

You always must perform network request form other thread than UI thread. So you can create abstarct class (network dispatcher) which extend AsyncTask or Thread or Runnable and add abstarct method which will be called in run/doInBackground/etc. Next implement abstarct method in your method. But it a little improvement to your boilerplate code. Also you can use JavaRx (AndroidRx) to perform networking method. Also you can use Retrofit with JavaRx.
EDIT
I see you edit your question. If you want use AsyncTask you should implement it and perform request in doInBackgroud

Related

How to access HttpResponse returned by HttpURLConnection InputStream in Android?

I have adopted the code in this Stack Overflow answer to successfully POST JSON from my Android app to a Python/Django server. Here is my (very close) adaptation of the POST code:
// In my activity's onCreate method
try {
JSONObject obj = new JSONObject(strJSON);
new postJSON().execute("https://www.placeholder.com/generate_json", obj.toString());
} catch (Throwable t) {
Log.e("JSON Error", "Could not parse malformed JSON: " + strJSON);
}
// Outside onCreate
private class postJSON extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String data = "";
HttpURLConnection httpURLConnection = null;
try {
httpURLConnection = (HttpURLConnection) new URL(params[0]).openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
wr.writeBytes("PostData=" + params[1]);
wr.flush();
wr.close();
InputStream in = httpURLConnection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(in);
int inputStreamData = inputStreamReader.read();
while (inputStreamData != -1) {
char current = (char) inputStreamData;
inputStreamData = inputStreamReader.read();
data += current;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.e("TAG", result);
}
}
I now want to access the HttpResponse returned by the server, which I think is contained in data (but I'm not sure about this). If data does contain the HttpResponse, I would like to print it in a Toast.
Does data already contain the HttpResponse from the server or do I need to take additional steps to get it from InputStream? If it is already there, where should I put my Toast.makeText code to print the HttpResponse (i.e. data) in a Toast?
The variable data is a String containing the response body from the server and will be available to you on your UI thread as the variable result in the method onPostExecute
There are many patterns for getting the result from an async task. Here is one simple way to do it, try this approach to get a toast.
Write your execution of the task as such:
// In your activity's onCreate method
try {
JSONObject obj = new JSONObject(strJSON);
new postJSON() {
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
}
}.execute("https://www.placeholder.com/generate_json", obj.toString());
} catch (Throwable t) {
Log.e("JSON Error", "Could not parse malformed JSON: " + strJSON);
}

Suggestion about AsyncTask

In this topic:
About task onPostExecute
I asked about onPostExecute to dismiss a process, the friend #inner_class7 give me the way to resolve the error, but the friend #Doug Stevenson said that using this way the code will blocking the uithread, I tested and this is true, my uithraed was blocked. So He said that I need to use onPostExecute to get the result. I read about and created a code and I would like suggestion about.
I changed the code and do it:
protected ArrayList<String> doInBackground(String... params) {
try {
final String POST_PARAMS = params[1];
URL obj = new URL(params[0]);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
// For POST only - START
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write(POST_PARAMS.getBytes());
os.flush();
os.close();
// For POST only - END
int responseCode = con.getResponseCode();
System.out.println("POST Response Code :: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) { //success
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// print result
System.out.println(response.toString());
JSONArray myListsAll= new JSONArray(response.toString());
for(int i=0;i<myListsAll.length();i++){
JSONObject jsonObject = myListsAll.getJSONObject(i);
this.stringArray.add(jsonObject.toString());
}
} else {
System.out.println("POST request not worked");
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return this.stringArray;
}
#Override
protected void onPostExecute(ArrayList<String> result)
{
this.obj.setFeedsData(result);
if(setProgress){ progress.dismiss(); }
}
So call in my mainactivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
String[] itensUrl = {links.feedsList(),"iduser=2&offset=0"};
new JsonRequest(this,this,true).execute(itensUrl);
}
public void setFeedsData(ArrayList<String> obj){
createListView(obj);
}
So what Do you think about? This way that a use is a good way?
What you have should be working just fine. You are correctly executing and parsing the results of the request off the UI thread. However, there are a couple minor things you can do to make it clearer.
stringArray looks like a field on the AsyncTask. This is not necessary the way you have the AsyncTask defined since you are already passing the stringArray directly into the onPostExecute() method. You should instead declare stringArray directly in the doInBackground() method.
Other thing I noticed is it looks like you might be keeping a reference to your Activity in the AsyncTask based on what you are doing in onPostExecute(). You are calling this.obj.setFeedsData(result);. If your AsyncTask is an inner class of the Activity using it you can call setFeedsData(result); directly instead.
If your AsyncTask is not an inner class it is usually best to pass the results back to the object interested in them through an interface in case you need to reuse the AsyncTask elsewhere.

How to load XML feed data into user interface with an splitted "getData" and "MainActivity" without freeze UI

I'am new with android an read a lot about the life cycles and so on on developer.android.com Now i wanna build an app that gets data from an online XML feed.
I created an XmlManager class which extends the aSyncTask<...>
Here i download the XML from the URL and put it in an string, this works!
Now i will invoke the download from the main activity in the onCreate so it downloads the XML in the background. The user needs to see an tekst, "loading" or something(in an TextView). When the download (the aSync proces) is ready it need needs to fire an event or something and push?/send? the data to the activity so the activity can replace the loadingtext by the XMl string.
When i know how to do this i can find out by my self how to parse the xml and put it in an nice userinterface. I tryed to implement this but i cant get it done.
Is there anyone who can help me ? A sample code will be nice!
An simple user interface (Textview and button) and when i click the button the the background proces is started an downloads the xml and replace the current text in the textview by the XML would be GREAT!!!
The code i use for download the XML is:
public class XmlManager extends AsyncTask<String, String, String> {
String xml = null;
#Override
protected String doInBackground(String... inputUrl) {
Log.i("Status", "ASync proces started");
getStream(inputUrl[0]);
Log.i("Status", "ASync proces finished");
return xml;
}
private void getStream(String urlString) {
URL url = null;
HttpURLConnection urlConnection = null;
InputStream is = null;
try {
url = new URL(urlString);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
Log.i("Status", "Connection opened");
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line);
}
Log.i("Status", "XML loaded into string");
} catch (Exception e) {
Log.e("Error", e.getMessage().toString());
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
Log.i("Status", "Connection disconnected");
}
}
}
}
Thanks in advance!
The important part that you are missing is this (from the Android docs):
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
You need to parse your XML and add it to your UI in the above function. Since onPostExecute runs on the UI Thread.
It might be that you need to pass a callback interface into the AsyncTask constructor to be able to send the parsed data back to your Activity.
For example:
public class XmlManager extends AsyncTask<String, String, String> {
private MyCallback mCallback = null;
public XmlManager(MyCallback callback) {
mCallback = callback;
}
...
protected void onPostExecute(String result) {
mCallback.onResult(result);
}
}

AsyncTask.getStatus() does not return Status.FINISHED

I want to start programming Android apps that can communicate with a server to receive/send data and store it on the server.
I have been reading about this and I think I only need to send the data to the server with POST request (perhaps a XML file since I may need to send images), then parse the XML on the server side, and do whatever I need.
To start I'm just trying to send some text through my app.
This is my Post class, for the AsyncTask use:
public class Post extends AsyncTask<String, Void, Boolean> {
Context context;
String response;
public Post (Context ctx){
context = ctx;
}
#Override
protected Boolean doInBackground(String... params) {
URL url;
HttpURLConnection conn;
try {
url = new URL("http://192.168.1.40/index.php");
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(5000);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "text/xml; charset=\"utf-8\"");
conn.setDoInput(true);
conn.setDoOutput(false);
conn.connect();
String body = "<test>\"some testing\"</test>";
//Send POST
OutputStreamWriter output = new OutputStreamWriter(conn.getOutputStream(),"UTF8");
output.write(body);
output.flush();
output.close();
//Get response
String line = "";
InputStream is = conn.getInputStream();
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) sb.append(line);
response = sb.toString();
br.close();
is.close();
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public String getResponse(String s)
{
}
Using a button to send the request:
public class MainActivity extends ActionBarActivity {
Context ctx;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ctx = this;
Button b = new Button(this);
b.setText("Send POST");
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Post p = new Post(ctx);
p.execute();
while(p.getStatus() != AsyncTask.Status.FINISHED);
Toast.makeText(ctx,p.getResponse(),Toast.LENGTH_LONG).show();
}
});
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
params.topMargin = 0;
params.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
addContentView(b,params);
}
And this is my server side php code:
<?php print_r($_POST);?>
I know there are a lot of posts about this stuff, I went through many of them but I can't figure out this problem.
The HttpURLConnection response code is 200 which means HTTP_OK.
In the index.php page the only output is: "Array ()".
When I debug, the response string is also "Array ()", the problem is that the status of the AsyncTask is "RUNNING" all the time.
P.S - I'm using wampserver as webserver
Thanks in advance.
EDIT: I followed Pawel advice and tried this before the Toast:
while(p.getStatus() != AsyncTask.Status.FINISHED);
The app crashed, so I guess it never gets the FINISHED status.
Also tried the AsyncTask.get() method, like this:
try {
Toast.makeText(ctx, p.get().toString(), Toast.LENGTH_LONG).show();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Got a "false" in the Toast text wich means my p.doInBackground() completed the execution. Why do I still don't have any results?
LAST EDIT: I'm not giving up yet! After a lot of debugging and frustration I think I have found the problem. It was the PHP code! I was expecting it to show me in the browser the post request but It does not work that way apparently.
I changed it to this:
<?php file_put_contents('test.txt', file_get_contents('php://input')); ?>
Now I can see the file with the content.
My only problem with this is that if I remove the code to read the response from the server, it does not create the file. Is there something wrong or it's just normal behavior?
You should read this:
http://developer.android.com/reference/android/os/AsyncTask.html
You know that Post is Asynchronous operation since it extends AsyncTask ? Which means that it can be completed after your invoke Toast.makeText(ctx,p.getResponse(),Toast.LENGTH_LONG).show();
Small hint:
Check in above linked documentation about methods:
public final Result get () and public final AsyncTask.Status getStatus ().
Now you should have your results availabe when it is done.

How do I access the returned value from a Web API Method in Android?

After being confused about how to do so (as can be seen here and here, I am now successfully connecting to my server app and the appropriate RESTful method with this code:
public void onFetchBtnClicked(View v){
if(v.getId() == R.id.FetchBtn){
Toast.makeText(getApplicationContext(), "You mashed the button, dude.", Toast.LENGTH_SHORT).show();
new CallAPI().execute("http://10.0.2.2:28642/api/Departments/GetCount?serialNum=4242");
}
}
public static class CallAPI extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
String urlString=params[0]; // URL to call
String resultToDisplay = "";
InputStream in = null;
// HTTP Get
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream());
} catch (Exception e ) {
System.out.println(e.getMessage());
return e.getMessage();
}
return resultToDisplay;
}
protected void onPostExecute(String result) {
Log.i("FromOnPostExecute", result);
}
} // end CallAPI
I realize I need to assign something (other than an empty string at initialization) to resultToDisplay, but what? What part of "in" do I need to access/covert to a string?
UPDATE
The "manual" way is working for me, but the fancypants apache io utils "not so much" (well, it compiles...). This is my code:
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
in = new BufferedInputStream(urlConnection.getInputStream());
resultToDisplay = getStringFromInputStream(in);
total = IOUtils.toString(in);
resultToDisplay's assignment works (I get, "18"). total's assignment does not (I get, "").
Note: The "getStringFromInputStream()" method is from Raghunandan's link.
UPDATE 2
This works just dandy (using WIllJBD's idea to use apache commons' IOUtils):
new CallWebAPI().execute("http://10.0.2.2:28642/api/Departments/GetCount?serialNum=4242");
. . .
private class CallWebAPI extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
String urlString=params[0]; // URL to call
String result = "";
// HTTP Get
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection =
(HttpURLConnection)url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
if (null != inputStream)
result= IOUtils.toString(inputStream);
} catch (Exception e ) {
System.out.println(e.getMessage());
return e.getMessage();
}
return result;
}
#Override
protected void onPostExecute(String result) {
Log.i("RenameTheWashingtonFootballTeamTheRedskinPeanuts", result);
}
}
...and so apparently it is not necessary to add anything like "compile files('libs/commons-io-2.4.jar')" to the dependencies section of build.gradle, as seemingly was at least necessary at one time, according to this. If anybody can verify such a[m,pp]endments to build.gradle are no longer needed, I'd be gradleful.
UPDATE 4
I just noticed that I inadvertently removed the "#Override" from the onPostExecute() method, but it made no difference - it worked fine without it, and it works fine once I restored it. So what's the advantage of [not] having it - is it just superfluous fluff?
why not use something like IOUtils?
InputStream inputStream = urlConnection.getInputStream();
if (inputStream != null)
String content = IOUtils.toString(inputStream);
http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/IOUtils.html
now you can parse the string into Json or XML, using one of many libraries.

Categories

Resources