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().
Related
I am working on an android app, and am running into some troubles with registering users. I want to post a JSON object to my server and receive one back. I can successfully create a JSON object with the right information but when I go to post it I get a NetworkOnMainThreadException or my HttpClient class returns null when it should be returning a JSONObject and I am very confident that my web server works correctly. I understand that you cannot connect to the network on the main thread and have created an HttpClient class that uses AsnycTask (although probably not correctly). I have been working on this for quite a while and would appreciate any guidance in the right direction.
//Main activity
#Override
public void onClick(View arg0) {
if(!(isEmpty(name) || isEmpty(username) || isEmpty(password) || isEmpty(email))) {
user = new JSONObject();
try {
user.put("username", username.getText().toString());
user.put("name", name.getText().toString());
user.put("email", email.getText().toString());
user.put("password", password.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
jRegister = new JSONObject();
try {
jRegister.put("apiToken", Utilities.apiToken);
jRegister.put("user", user);
Log.i("MainActivity", jRegister.toString(2));
} catch (JSONException e) {
e.printStackTrace();
}
//
HttpClient client = new HttpClient(url, jRegister);
result = client.getJSONFromUrl();
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}else {
tv.setText("");
}
}
HttpClient Class
public class HttpClient extends AsyncTask<Void, Void, JSONObject>{
private final String TAG = "HttpClient";
private String URL;
private JSONObject jsonObjSend;
private JSONObject result = null;
public HttpClient(String URL, JSONObject jsonObjSend) {
this.URL = URL;
this.jsonObjSend = jsonObjSend;
}
public JSONObject getJSONFromUrl() {
this.execute();
return result;
}
#Override
protected JSONObject doInBackground(Void... params) {
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
StringEntity se;
se = new StringEntity(jsonObjSend.toString());
// Set HTTP parameters
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
// convert content stream to a String
String resultString= convertStreamToString(instream);
instream.close();
resultString = resultString.substring(1,resultString.length()-1); // remove wrapping "[" and "]"
JSONObject jsonObjRecv = new JSONObject(resultString);
// Raw DEBUG output of our received JSON object:
Log.i(TAG,"<JSONObject>\n"+jsonObjRecv.toString()+"\n</JSONObject>");
return jsonObjRecv;
}
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(JSONObject jObject) {
result = jObject;
}
private static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}
I understand that you cannot connect to the network on the main thread
and have created an HttpClient class that uses AsnycTask (although
probably not correctly).
You are right you have not implemented it the right way.
In your onClick events (still on Main thread) you performed a network activity causing the error:
HttpClient client = new HttpClient(url, jRegister);
result = client.getJSONFromUrl();
Instead you should run the network operation inside of the AsnycTask
public class GetJsonTask extends AsyncTask<Void, Void, JSONObject >{
private String URL;
private JSONObject jsonObjSend;
public GetJsonTask(String URL, JSONObject jsonObjSend) {
this.URL = URL;
this.jsonObjSend = jsonObjSend;
}
#Override
protected JSONObject doInBackground(Void... params) {
JSONObject jsonObjRecv;
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
StringEntity se;
se = new StringEntity(jsonObjSend.toString());
// Set HTTP parameters
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
long t = System.currentTimeMillis();
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
// convert content stream to a String
String resultString= convertStreamToString(instream);
instream.close();
resultString = resultString.substring(1,resultString.length()-1); // remove wrapping "[" and "]"
jsonObjRecv = new JSONObject(resultString);
// Raw DEBUG output of our received JSON object:
Log.i(TAG,"<JSONObject>\n"+jsonObjRecv.toString()+"\n</JSONObject>");
}
}
catch (Exception e) {
e.printStackTrace();
}
return jsonObjRecv;
}
protected void onPostExecute(JSONObject result) {
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}else {
tv.setText("");
}
}
}
Then you call your async in onclik method like this:
public void onClick(View arg0) {
//.......
GetJsonTask client = new GetJsonTask(url, jRegister);
client.execute();
}
One problem in your code is that your expectations of AsyncTask aren't quite right. In particular this function:
public JSONObject getJSONFromUrl() {
this.execute();
return result;
}
AsyncTask runs the code in the doInBackground() function in a separate thread. This means that once you call execute() you have two parallel lines of execution. You end up with what's called a Race Condition. When you reach the return result line, a couple of things can be happening:
doInBackground() hasn't run and therefore result is still has the default value. In this case null.
doInBackground() can be in the middle of the code. In your particular case because it doesn't modify result then this doesn't affect you much. But it could be on any line (or middle of a line sometimes if operations aren't atomic) when that return happens.
doInBackground() could've finished, but since onPostExecute() runs on the UI thread it has to wait until your onClick handler is finished. By the time onPostExecute() has a chance to run onClick already tried to update tv with whatever it was that getJSONFromUrl returned, most likely null.
The way to set up tasks with AsyncTask is to give it the information it needs to do it's work, start it up with execute, and since you can't know how long it will take to complete, let it handle the finishing steps of the task.
This means that after calling execute you don't wait around for it's result to update views (like in your case), but rather rely on the AsyncTask's onPostExecute or related methods to take over the next steps.
For your case this would mean that your onPostExecute should look something like:
protected void onPostExecute(JSONObject result) {
try {
if(result != null)
tv.setText(result.toString(2));
else
tv.setText("null");
} catch (JSONException e) {
e.printStackTrace();
}
}
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 !!
I am working on android application and I need to parse my json object with data. How you can see I create JSONParser class and try to use asynctask but there is something wrong and I can't understand where is the problem. Every time I use it resultJSON is null. Hope that you can give me an advice!
public class JSONParser {
private String resultJSON;
public JSONArray getJSON(String url) throws JSONException {
Parser parser = new Parser();
parser.execute(url);
return json;
}
private class Parser extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
for (String url : urls) {
StringBuilder builder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
resultJSON = builder.toString();
} else {
Log.e(JSONParser.class.toString(), "Failed to download file");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultJSON;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
json = new JSONArray(result);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
Why don't you JSONArray json = new JSONArray(resultJSON); do this on post execute method of async task .
And i will not suggest varevarao way , as it will create extra burden of one thread .
You should use the get() method of the AsyncTask class to retrieve the result of the task. It waits for the task to complete and gets the result (which means it'd be best if you enclose it within a separate thread with a progress dialog or just a background thread).
public JSONArray getJSON(String url) throws JSONException {
Parser parser = new Parser();
parser.execute(url);
resultJSON = parser.get(); // Probably put this in a Thread to avoid spending too much time waiting for a result on the main thread
JSONArray json = new JSONArray(resultJSON);
return json;
}
The problem is fixed. It's an awful workaround but it works. Add this line
while(json==null) {}
after calling the execute method.
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.
I have a method that I'm calling but, for newer versions of Android it fails. Apparently, this is due to the lack of threading. My method is to send a message to my server. This is the code (sans threading)
public String sendMessage(String username, Editable message){
BufferedReader in = null;
String data = null;
try{
DefaultHttpClient client = new DefaultHttpClient();
URI website = new URI("http://abc.com/user_send.php?username="+username+"&message="+message);
HttpPost post_request = new HttpPost();
post_request.setURI(website);
HttpGet request = new HttpGet();
request.setURI(website);
//executing actual request
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);
}
in.close();
data = sb.toString();
return data;
}catch (Exception e){
return "ERROR";
}
}
Now, just trying to put a thread around it:
public String sendMessage(String username, Editable message){
BufferedReader in = null;
String data = null;
Thread sendThread = new Thread(){
try{
DefaultHttpClient client = new DefaultHttpClient();
URI website = new URI("http://thenjtechguy.com/njit/gds/user_send.php?username="+username+"&message="+message);
HttpPost post_request = new HttpPost();
post_request.setURI(website);
HttpGet request = new HttpGet();
request.setURI(website);
//executing actual request
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);
}
in.close();
data = sb.toString();
return data;
}catch (Exception e){
return "ERROR";
}
} sendThread.start();
}
But that doesn't work. What am I doing wrong? Also, if you notice I'm breaking any fundamental rules in android regarding the HttpClient, please let me know.
Your implementation is not correct - you did not override run() method
class SendThread extends Thread {
public void run(){
//add your implementation here
}
}
Tow start the thread
SendThread sendThread = new SendThread();
sendThread.start();
Better to a head and use AsyncTask concept.
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.
Refer this LINK for sample implementation