I'm implementing a class which extends AsyncTask and I perform an http request within this class. The class is not an Activity and is located in a seperate java file because I want to use this class several times.
I instantiate an object of this class in my Activity, to execute the http request in a separate thread. When the thread executes, I want to call a method of my Activity.
How do I implement this? I need the result of the http request in my Activity but I can't handle this so far.
This is the code for the thread task...
public class PostRequest extends AsyncTask<String, Void, String> {
public String result = "";
#Override
protected String doInBackground(String... urls) {
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://bla/index.php?" + urls[0]);
// httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
// convert response to string
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result = sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(String result) {
}
}
And this is part of my Activity code that creates the thread class...
public class ListActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list);
PostRequest task = new PostRequest();
task.execute(new String[] { "action=getUsers" });
task.onPostExecute(task.result) {
}
}
public void Display(String result) {
try {
JSONArray jArray = new JSONArray(result);
JSONObject json_data = jArray.getJSONObject(0);
String value = json_data.getString("name");
TextView text = (TextView) findViewById(R.id.value);
text.setText(value);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
pass the activity reference in constructor......
as
public class PostRequest extends AsyncTask<String, Void, String> {
public String result = "";
private Activity mActivity;
public PostRequest(Activity activity){
super();
mActivity = activity;
}
......
You don't have to do a onPostExecute() as this is called after the process doInBackground has completed and then you can use the reference of the activity passed into the constructor of the AsyncTask to run any time of method on your UI.
Just remember that onPostExecute() method runs on a UI thread so here from this method you can try to modify your view if needed.
See this question...can-i-put-asynctask-in-a-separate-class-and-have-a-callback and the accepted answer. If you want a re-usable AysncTask as a stand-alone class then using a listener as a callback for all of your activities is the best way to do it.
Related
I am trying to create a function to make a request, but it is giving some error, I already put permission to the internet, but still
This is my code:
public String request(String Url,JSONObject Data){
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(Url);
InputStream inputstream;
String content = "";
try {
httppost.setEntity(new StringEntity(Data.toString()));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
while(true){
if(entity != null){
inputstream = entity.getContent();
content = inputstream.toString();
break;
}
}
} catch (Exception ex) {
return ex.toString();
}
return content;
}
Input:
JSONObject data = new JSONObject();
data.put("teste","teste");
String response = request('urlExample',data);
Toast.makeText(getApplicationContext(),response,Toast.LENGTH_SHORT).show();
Output:
android.os.NetworkOnMainThreadExecption
I suggest you to use AsyncTask as I mentioned in the comment :
private class LongOperation extends AsyncTask<Void, Void, String> {
private String mUrl;
private JSONObject mData;
public LongOperation(String url, JSONObject data) {
mUrl = url;
mData = data;
}
#Override
protected String doInBackground(Void... params) {
return request(mUrl, mData);
}
#Override
protected void onPostExecute(String response) {
Toast.makeText(getApplicationContext(),response,
Toast.LENGTH_SHORT).show();
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
You can start your AsyncTask as follow:
JSONObject data = new JSONObject();
data.put("teste","teste");
new LongOperation('urlExample', data).execute();
Network operation does not be launched on Main Thread. You can create another Thread for running it.
Thread thread = new Thread(new Runnable(){
#Override public void run(){
// Run request here !!!!
}
});
thread.start();
I recomend you to use **Volley**, it's a side client library which helps you with the Http-Request.
Search for StringRequest.
I want to make constructor take url for use the class in many activity but it does not work.
There is my code:
class BackgroundTask extends AsyncTask<Void, Void, String> {
String url1;
//
// there i want to take url from oncreate in main but not work
//
public BackgroundTask(String json_url) {
super();
this.url1=json_url;
}
#Override
protected String doInBackground(Void... voids) {
try {
URL url =new URL(url1);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
while ((JSON_STRING_Doctor = bufferedReader.readLine()) != null) {
stringBuilder.append(JSON_STRING_Doctor + "\n");
}
bufferedReader.close();
inputStream.close();
httpURLConnection.disconnect();
return stringBuilder.toString().trim();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String res) {
json_string = res;
}
}
and in oncreate I call first a new backgroudTask with url and after I call execute method but no result, json_string is null.
after I call execute method but no result, json_string is null.
Your constructor is fine, but this is not how you use an AsyncTask to get the result
task = new BackgroundTask(url);
task.execute();
// use json_string
You need to wait for the response. The json string is never available before the call to onPostExecute, and even then, it could still be null because that's what you have within doInBackground when there's an exception.
Any code that requires the result of the task needs to be called following onPostExecute (so within that method, call other methods that take the json string), which should be easy to do if the AsyncTask is an inner class of where ever you need it.
When I run the AsyncTask below, I can see the log messages. However progress bar wont change visibility.
Below, is my AsyncTask code.
class test extends AsyncTask<String, Void, String> {
private Context mContext;
public PostWav(Context context) {
mContext = context;
}
protected String doInBackground(String... params ) {
URL url= null;
try {
url = new URL(params[0]);
} catch (MalformedURLException e) {
e.printStackTrace();
}
InputStream inputStream;
DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams());
JSONObject object = new JSONObject();
try {
object.put("provider_id",1);
String message = object.toString();
HttpPost httppost = new HttpPost(url.toString());
httppost.setEntity(new StringEntity(message, "UTF8"));
httppost.setHeader("Content-type", "application/json");
httppost.setHeader("Accept", "application/json");
String boundary = "-------------" + System.currentTimeMillis();
httppost.setHeader("Content-type", "multipart/form-data; boundary="+boundary);
File file = getDir("test", Context.MODE_PRIVATE);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
File wavFile = new File(file.getPath() + "/" + params[3]);
ContentType contentType = ContentType.create("audio/x-wav");
FileBody cbFile = new FileBody(wavFile,contentType,"sample");
builder.addPart("sample", cbFile);
builder.setBoundary(boundary);
httppost.setEntity(builder.build());
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
Header[] header = response.getHeaders("Location");
String location = String.valueOf(header[0].getValue());
inputStream = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
return location;
} catch (JSONException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute() {
Log.i("Async-Example", "onPreExecute Called");
loading.setVisibility(View.VISIBLE);
record.setVisibility(View.INVISIBLE);
super.onPreExecute();
}
#Override
protected void onPostExecute(String feed) {
Log.i("Async-Example", "onPostExecute Called");
loading.setVisibility(View.INVISIBLE);
record.setVisibility(View.VISIBLE);
}
}
I am uploading a .wav file to a my API. I did not included whole code this is basically all that I'm doing.
#greenapps Thanks mate your hint was more than enough for me to understand the problem.
Basically when I imported this class from another project I completely forgot the reason she was programmed like that.
I just had to remove .get() from the execute command and passed the methods to the post execute on the Task and everything when smoothly.
I am sorry for taking everyone's time, I really appreciated the help!
Here is the result i was looking for:
You would like to show the progress bar while the task is being completed, so you need to work around this statement.
Try to do the work in the following method(s):
doInBackground(int Progress)
OnProgressUpdate() to update the progress bar according to your ideas
For more read the following documentation.
Normally AsyncTask runs on the UI Thread, but I have the strong assumption that you are calling this from somewhere else than the UI Thread since you are passing the Context as a Parameter.
So you can use that.
#Override
protected void onPostExecute(String feed) {
Log.i("Async-Example", "onPostExecute Called");
activity.runOnUiThread(new Runnable(){
loading.setVisibility(View.INVISIBLE);
record.setVisibility(View.VISIBLE);
});
}
Also remove super.onPreExecute(); you dont need that
You have to change your constructor parameter from Context to Activity or it will be a bit more complicated.
I am trying to retrieve a string from a server using HTTPGet, then I want to set that string to a TextView in my MainActivity class. Here is the class I am trying to use to accomplish this. (I didn't include the imports here, but they are in the actual class. I also withheld the URL I am using here, but the actual URL is in my class)
public class GetFromServer {
public String getInternetData() throws Exception {
BufferedReader in = null;
String data = null;
try{
HttpClient client = new DefaultHttpClient();
URI website = new URI("URL withheld");
HttpGet request = new HttpGet();
request.setURI(website);
HttpResponse response = client.execute(request);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String l = "";
String nl = System.getProperty("line.separator");
while ((l = in.readLine()) !=null){
sb.append(l + nl);
}
in.close();
data = sb.toString();
return data;
}finally {
if (in != null){
try{
in.close();
return data;
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}
Then to use it in my MainActivity class:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
GetFromServer test = new GetFromServer();
String returned = null;
try {
returned = test.getInternetData();
textView.setText(returned);
} catch (Exception e) {
e.printStackTrace();
}
}
This doesn't work because I get the android.os.NetworkOnMainThreadException, which means I have to use an AsyncTask. What I am asking is how do I turn this class into an AsyncTask so that it will work? Once it is an AsyncTask, how do I use it in my MainActivity class?
There's a pretty thorough explanation of AsyncTask over at the developer documentation.
Basically, you subclass AsyncTask, defining the types of parameters you will be working with. Your HTTPGet code will go into the doInBackground() method. To run it, you create a new instance of your AsyncTask class and call execute().
I'm trying to POST data in JSON format to a script I have running PHP on my webserver. I have found this post: How to send data to a website using httpPost, app crashes.
Using the code he wrote (putting it on a separate thread first) I am able to post data to the PHP script, which accesses it by the $_POST variable. However, I wish to post my data in JSON format. I am guessing it would require me to post a raw stream of data to the server. What functions are available to achieve this? I would also need to post images as a stream of data to the PHP script so I think this solution will also help me in that area.
Additionally, what are the advantages of posting JSON to the server rather than using the method he used?
I am programming the client side in Java in conjunction with the Android SDK.
Any help would be appreciated.
I have a sample example for posting json data .
Have a look at this:
public class LoginActivity extends Activity {
private static final String TAG = "LoginActivity";
private Context mContext;
private Intent mIntent;
private ProgressDialog pdLoading;
private class LoginTask extends AsyncTask<Void, Void, String>
{
private ArrayList<NameValuePair> mParams = new ArrayList<NameValuePair>();
private JSONArray mJArray = new JSONArray();
private JSONObject mJobject = new JSONObject();
private String jsonString = new String();
#Override
protected void onPreExecute() {
super.onPreExecute();
pdLoading.show();
}
#Override
protected String doInBackground(Void... params) {
try {
mJobject.put("userName", "test");
mJobject.put("password", "test");
mJArray.put(mJobject);
mParams.add(new BasicNameValuePair("message", mJArray.toString()));
jsonString = WebAPIRequest.postJsonData("http://putyoururlhere.com/login.php?", mParams);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
return jsonString;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
pdLoading.dismiss();
if(result!=null)
{
/* try {
mJobject = new JSONObject(jsonString);
if(mJobject.getString("Success").equals("True"))
{
mJArray = mJobject.getJSONArray("user");
JSONObject mUser = mJArray.getJSONObject(0);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
Log.e(TAG, jsonString);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initialization();
new LoginTask().execute();
}
private void initialization() {
mContext = this;
mIntent = new Intent();
pdLoading = new ProgressDialog(mContext);
pdLoading.setMessage("loading...");
}
}
and
public class WebAPIRequest {
public static String convertStreamToString(InputStream is)
throws IOException {
if (is != null) {
StringBuilder sb = new StringBuilder();
String line;
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, "UTF-8"));
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
} finally {
is.close();
}
return sb.toString();
} else {
return "";
}
}
public static String postJsonData(String url, List<NameValuePair> params) {
String response_string = new String();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
httppost.addHeader("Content-Type", "application/x-www-form-urlencoded");
try {
httppost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
String paramString = URLEncodedUtils.format(params, HTTP.UTF_8);
String sampleurl = url + "" + paramString;
Log.e("Request_Url", "" + sampleurl);
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
if (response != null) {
InputStream in = response.getEntity().getContent();
response_string = WebAPIRequest.convertStreamToString(in);
}
} catch (Exception e) {
e.printStackTrace();
}
return response_string;
}
}
EDIT :
try,
print_r(json_decode($_POST['message'], true);
or
$data = file_get_contents('php://input');
$json = json_decode($data,true);
I hope it will be helpful !!