I need to do some HTTP requests from my android app.
I use AsyncTask as needed, with the network part in doInBackground.
Here is my request class :
public class AsyncRequest extends AsyncTask<Void, Integer, HttpResponse>{
private ProgressDialog dialog;
private Activity activity;
private HttpUriRequest query;
private HttpClient client;
private HttpResponse response;
private String dialogMsg;
private String uri;
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public AsyncRequest(Activity a, HttpUriRequest q, HttpClient c, String m) {
query = q;
client = c;
activity = a;
dialog = new ProgressDialog(a);
dialogMsg = m;
}
#Override
protected void onPostExecute(HttpResponse res) {
if (dialog.isShowing())
dialog.dismiss();
}
protected void onPreExecute() {
this.dialog.setMessage(dialogMsg);
this.dialog.show();
}
#Override
protected HttpResponse doInBackground(Void... arg0) {
try {
response = client.execute(query);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
protected HttpResponse getResponse() {
return response;
}
}
And, in my UI thread, I use it this way :
AsyncRequest request;
HttpClient httpClient = new DefaultHttpClient();
HttpGet getQuery = new HttpGet("Here goes my url");
HttpResponse response = null;
String rt = "Null";
getQuery.setHeader("Authorization", getIntent().getExtras().getString("token"));
request = new AsyncRequest(this, getQuery, httpClient, "Loading events...");
try {
response = request.execute().get(3, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
HttpEntity entity = response.getEntity();
try {
rt = EntityUtils.toString(entity);
} catch (Exception e) {
e.printStackTrace();
return ;
}
So, I'm an android beginner, but I guess this exception is caught when network related code is executed in main thread. But I run client.execute() in my doInBackground() method. Is it the call to execute().get() (in ui thread) that causes the problem ?
You have this
response = request.execute().get(3, TimeUnit.SECONDS);
Calling get() makes AsyncTask no more Asynchronous. It blocks the ui thread waiting for the response. This leads to NetworkOnMainThreadException.
Get rid of get(3, TimeUnit.SECONDS);
Just use request.execute(). You can update ui in onPostExecute. You can also use interface as a callback to the Activity.
Check the answer by blackbelt in the below link
How do I return a boolean from AsyncTask?
Related
I am uploading an image on server by using async task and in the end I want to return value of uploaded file url. How can I do that
I am calling asynctask as
new Config.UploadFileToServer(loginUserInfoId, uploadedFileURL).execute();
and my asynctask function is as:
public static final class UploadFileToServer extends AsyncTask<Void, Integer, String> {
String loginUserInfoId = "";
String filePath = "";
long totalSize = 0;
public UploadFileToServer(String userInfoId, String url){
loginUserInfoId = userInfoId;
filePath = url;
}
#Override
protected void onPreExecute() {
// setting progress bar to zero
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... progress) {
// Making progress bar visible
// updating progress bar value
}
#Override
protected String doInBackground(Void... params) {
return uploadFile();
}
#SuppressWarnings("deprecation")
private String uploadFile() {
String responseString = null;
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(Config.HOST_NAME + "/AndroidApp/AddMessageFile/"+loginUserInfoId);
try {
AndroidMultiPartEntity entity = new AndroidMultiPartEntity(
new AndroidMultiPartEntity.ProgressListener() {
#Override
public void transferred(long num) {
publishProgress((int) ((num / (float) totalSize) * 100));
}
});
File sourceFile = new File(filePath);
// Adding file data to http body
entity.addPart("file", new FileBody(sourceFile));
totalSize = entity.getContentLength();
httppost.setEntity(entity);
// Making server call
HttpResponse response = httpclient.execute(httppost);
HttpEntity r_entity = response.getEntity();
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
// Server response
responseString = EntityUtils.toString(r_entity);
} else {
responseString = "Error occurred! Http Status Code: "
+ statusCode;
}
} catch (ClientProtocolException e) {
responseString = e.toString();
} catch (IOException e) {
responseString = e.toString();
}
responseString = responseString.replace("\"","");
return responseString;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
Try my code as given below.
public Result CallServer(String params)
{
try
{
MainAynscTask task = new MainAynscTask();
task.execute(params);
Result aResultM = task.get(); //Add this
}
catch(Exception ex)
{
ex.printStackTrace();
}
return aResultM;//Need to get back the result
}
You've almost got it, you should do only one step. As I can see, you are returning the result at the doInBackground method (as a result of calling uploadFile). Now, this value is passed to the onPostExecute method, which is executed on the main thread. In its body you should notify components, which are waiting for result, that result is arrived. There are a lot of methods to do it, but if you don't want to used 3rd party libs, the simplest one should be to inject listener at the AsyncTask constructor and call it at the onPostExecute. For example, you can declare the following interface:
public interface MyListener {
void onDataArrived(String data);
}
And inject an instance implementing it at the AsyncTask constructor:
public UploadFileToServer(String userInfoId, String url, MyListener listener){
loginUserInfoId = userInfoId;
filePath = url;
mListener = listener;
}
Now, you can simply use it at the onPostExecute:
#Override
protected void onPostExecute(String result) {
listener.onDataArrived(result);
super.onPostExecute(result); //actually `onPostExecute` in base class does nothing, so this line can be removed safely
}
If you are looking for a more complex solutions, you can start from reading this article.
I have web services and I want to create a class that should takes an email and password from server after authentication in hash table, and then saves email and password in shared preferences.
Try this class to call webservice in your app, i am sharing get and post both methods you can use any one as per your need.
public class CallService {
String url;
HttpEntity str1;
String str;
Context context;
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public CallService(String url1) {
this.url = url1;
}
public String getResponceWithPost() {
try {
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters,5000000);
HttpConnectionParams.setSoTimeout(httpParameters,500000);
HttpConnectionParams.setTcpNoDelay(httpParameters,true);
HttpClient hc = new DefaultHttpClient(httpParameters);
HttpPost post= new HttpPost (url);
HttpResponse rp = hc.execute(post);
// //////////////
if (rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
str = EntityUtils.toString(rp.getEntity());
Log.e("Calling service", str);
return str;
}
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
public int getResponceWithGet() {
int code = 0;
try {
HttpClient hc = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse rp = hc.execute(get);
code= rp.getStatusLine().getStatusCode();
return code;
} catch (IOException e) {
Log.e("calling service", e.toString());
e.printStackTrace();
}
catch(Exception e)
{
Log.e("calling service", e.toString());
}
return code;
}}
this will return response from server like email password or other details.
and you can save these details in sharedpreference .
for shared preference follow this -
http://developer.android.com/guide/topics/data/data-storage.html#pref
and in your activity call your url using my call service class like this-
declare your hashTable in activity like this
Hashtable hashtable = new Hashtable();
call this method
new checkForLogin().execute();
and your async class
class checkForLogin extends AsyncTask<Void, Void,String>
{
#Override
protected void onPreExecute() {
progress= ProgressDialog.show(LoginScreen.this,"Authenticating !","Please Wait");
}
#Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
Parse your json data here that will be in data
CallService cl2=new CallService("your server url here");
Log.e("login url is",""+Urls.loginurl);
data=cl2.getResponceWithPost();
Log.e("server response data","data = "+data);
hashtable.put(“email″, data.getString("email"));
hashtable.put(“pass″, data.getString("pass"));
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
progress.dismiss();
}
i hope this ll help you.
I am creating an android app that depends on data that the app gets from the database. To get this data I have the following class (this class gets data from the database in JSON, translates it and returns it):
public class Json {
public String jsonResult;
private Activity activity;
private String url = "http://json.example.org/json.php";
private String db, query;
public Json(Activity activity) {
this.activity = activity;
}
public String accessWebService(String db, String query) {
JsonReadTask task = new JsonReadTask();
this.db = db;
this.query = query;
task.execute(new String[] { url });
try {
task.get();
} catch (InterruptedException e) {
Toast.makeText(activity.getApplicationContext(), "FATAL ERROR: The thread got interrupted",
Toast.LENGTH_LONG).show();
} catch (ExecutionException e) {
Toast.makeText(activity.getApplicationContext(), "FATAL ERROR: The thread wasn't able to execute",
Toast.LENGTH_LONG).show();
}
return jsonResult;
}
// Async Task to access the web
private class JsonReadTask extends AsyncTask<String, Void, String> {
private final ProgressDialog dialog = new ProgressDialog(activity);
protected String doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(params[0]);
try {
// add post data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("db", db));
nameValuePairs.add(new BasicNameValuePair("query", query));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
jsonResult = inputStreamToString(response.getEntity().getContent()).toString();
if (jsonResult.isEmpty()) {
Toast.makeText(activity.getApplicationContext(),
"Error, connection is up but didn't receive data. That's strange...", Toast.LENGTH_LONG)
.show();
this.cancel(true);
}
} catch (ClientProtocolException e) {
// Toast.makeText(activity.getApplicationContext(),
// "Error, Client Protocol Exception in JSON task",
// Toast.LENGTH_LONG).show();
Log.i("Json", "Error, Client Protocol Exception in JSON task");
this.cancel(true);
} catch (IOException e) {
// Toast.makeText(activity.getApplicationContext(),
// "Error, Please check your internet connection",
// Toast.LENGTH_LONG).show();
Log.i("Json", "Error, Please check your internet connection");
this.cancel(true);
}
return null;
}
private StringBuilder inputStreamToString(InputStream is) {
String rLine = "";
StringBuilder answer = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((rLine = rd.readLine()) != null) {
answer.append(rLine);
}
} catch (IOException e) {
Toast.makeText(activity.getApplicationContext(), "Error..." + e.toString(), Toast.LENGTH_LONG).show();
}
return answer;
}
}// end async task
}
I noticed that my app freezes while accessing the database. After some googling, I found out it was the .get() method in the accessWebService() method caused this. I tried to implement a progressDialog like so (I also deleted the .get() method):
private final ProgressDialog dialog = new ProgressDialog(activity);
protected void onPreExecute() {
super.onPreExecute();
this.dialog.setMessage("Loading...");
this.dialog.setCancelable(false);
this.dialog.show();
}
protected void onPostExecute(String result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
}
but the dialog didn't show up and I got NullPointerException because the app only works when there is data:
result = json.accessWebService(db, query);
(maybe an important thing to mention: I also use this method in for loops)
So now my question is: How can I change my app so that I get a ProgressDialog while accessing the database and without getting NullPointerException? I fear that I have to rearchitect my whole app and if I have to do this, how do I do this? I hope you guys understand my question and have a fix for this because I really need help. Thanks in advance.
P.S. Sorry if my English is not that good, I'm not a native speaker.
... I found out it was the .get() method in the accessWebService() method caused this. I tried to implement a progressDialog...
That is right. get() is a blocking call and simply adding a ProgressDialog won't fix it. You need to remove .get() and that will probably fix the issue of your ProgressDialog not showing.
An AsyncTask must be executed on the main Thread so make sure you are doing that.
Another problem you have is Toast.LENGTH_LONG).show(); runs on the UI and you have it in doInBackground() which cannot happen. You need to send the result to onPostExecute() and you can display your Toast there if need. This could also be done in onProgressUpdate().
This null pointer exception happens because of result value was null. put the condition before
if(result != null ) {
// CODE FOR PARSING
} else {
return;
}
You can start showing progress bar before asyncTask is started and finish showing when asyncTask is finished.
Pass handler to asyncTask and sendMessage onPostExecute method. Then handle message on UI thread and hide progress bar
For example there is handler field in UI (mainActivity). There you should handle hiding progress bar:
public Handler refreshChannelsHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case EPGManager.ERROR_MESSAGE:
//do some stuff
break;
case EPGManager.SUCCESS_MESSAGE:
//do some stuff
break;
}
super.handleMessage(msg);
}
};
Then you can call asyncTask with your handler
epgManager.loadChannels(refreshChannelsHandler);
AsyncTask is inside the method so it looks like this:
public void loadChannels(Handler handler) {
AsyncTask task = new AsyncTask() {
#Override
protected Object doInBackground(Object[] params) {
try {
//do AsyncTask Job
} catch (Exception e) {
return new LoadingResult((Handler) params[0], false);
}
return new LoadingResult((Handler) params[0], false);
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
LoadingResult loadingResult = ((LoadingResult)o);
sendMessageToHandler(loadingResult.handler, loadingResult.isSuccess);
}
};
task.execute(handler);
}
Here is method:
private void sendMessageToHandler(Handler handler, boolean isSuccess) {
handler.sendEmptyMessage(isSuccess ? SUCCESS_MESSAGE : ERROR_MESSAGE);
}
And finally inner class
private class LoadingResult {
private Handler handler;
private boolean isSuccess;
public LoadingResult(Handler handler, boolean isSuccess) {
this.handler = handler;
this.isSuccess = isSuccess;
}
public Handler getHandler() {
return handler;
}
public void setHandler(Handler handler) {
this.handler = handler;
}
public boolean isSuccess() {
return isSuccess;
}
public void setSuccess(boolean isSuccess) {
this.isSuccess = isSuccess;
}
}
Ow, and don't forget constants
public static final int SUCCESS_MESSAGE = 1;
public static final int ERROR_MESSAGE = -1;
Hope it helps :)
This is my function that is in LoginActivity.java.So onclick of button i am calling this function.
public void postHttpRequest(String userId,String pass,TextView error){
RequestClient reqClient = new RequestClient(LoginActivity.this);
String AppResponse = null;
try {
url = "myurl";
Log.d("URL", url);
AppResponse = reqClient.execute().get();
String status = ValidateLoginStatus.checkLoginStatus(AppResponse);
Log.d("Status recived", status);
if(status.equals("200")){
saveInformation(userId,pass);
startingActivity(HOST_URL);
}else{
error.setText("Incorrect UserName or Password");
}
} catch (Exception e) {
Log.e("Exception Occured", "Exception is "+e.getMessage());
}
}
From this function i am calling a AsynkTask for Http Communication.So onclick of button when i am geeting the response then my processDialog in opening just for one sec.I want as i click the buttoon my processDialog should get open utill i got the response
public class RequestClient extends AsyncTask<String, Void, String>{
ProgressDialog pDialog;
Context context;
public RequestClient(Context c) {
context = c;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Authenticating user...");
pDialog.show();
}
#Override
protected String doInBackground(String... aurl){
String responseString="";
DefaultHttpClient httpClient=new DefaultHttpClient();
try {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(LoginActivity.url);
HttpResponse responseGet = client.execute(get);
HttpEntity resEntityGet = responseGet.getEntity();
if (resEntityGet != null) {
responseString = EntityUtils.toString(resEntityGet);
Log.i("GET RESPONSE", responseString);
}
} catch (Exception e) {
Log.d("ANDRO_ASYNC_ERROR", "Error is "+e.toString());
}
Log.d("ANDRO_ASYNC_ERROR", responseString);
httpClient.getConnectionManager().shutdown();
return responseString;
}
#Override
protected void onPostExecute(String response) {
super.onPostExecute(response);
if(pDialog!=null)
pDialog.dismiss();
}
}
So please suggest me what changes i have to make so that processDialog should display properly in the center of the device
//add style in your progressbialog
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDialog.setMessage("Authenticating user...");
if (pDialog != null && !pDialog.isShowing()) {
pDialog.show();
}
}
AsyncTask return value only after using get() method
Drawing from the above link
Calling the get() method of AsyncTask will block the main thread and wait for the result to be returned. This effectively makes using an AsyncTask become a synchronous operation in which case there's no point in using an AsyncTask.
The only reason I can think of to use the get() method would be from a thread other than the main (UI) thread although I can't think of many reasons to do that.
On Button click
RequestClient reqClient = new RequestClient(LoginActivity.this,new TheInterface() {
#Override
public void theMethod(String result) {
Log.i("Result =",result);
}
});
reqClient.execute(url); // no get(). pass url to doInBackground()
In your activity class
public interface TheInterface {
public void theMethod(String result);
}
}
AsyncTask
public class RequestClient extends AsyncTask<String, Void, String>{
ProgressDialog pDialog;
Context context;
TheInterface listener;
public RequestClient(Context c,TheInterface listen) {
context = c;
listener = listen;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Authenticating user...");
pDialog.show();
}
#Override
protected String doInBackground(String... aurl){
String responseString="";
HttpClient client;
try {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(aurl[0]); // url
HttpResponse responseGet = client.execute(get);
HttpEntity resEntityGet = responseGet.getEntity();
if (resEntityGet != null) {
responseString = EntityUtils.toString(resEntityGet);
Log.i("GET RESPONSE", responseString);
}
} catch (Exception e) {
Log.d("ANDRO_ASYNC_ERROR", "Error is "+e.toString());
}
Log.d("ANDRO_ASYNC_ERROR", responseString);
client.getConnectionManager().shutdown();
return responseString;
}
#Override
protected void onPostExecute(String response) {
super.onPostExecute(response);
pDialog.dismiss();
if (listener != null)
{
listener.theMethod(result);
}
}
}
It seems that your button code is not correct, because it's async, but you are trying to use it as standart sync code.
Try to move this code into onPostExecute:
String status = ValidateLoginStatus.checkLoginStatus(response);
Log.d("Status recived", status);
if(status.equals("200")){
saveInformation(userId,pass);
startingActivity(HOST_URL);
}else{
error.setText("Incorrect UserName or Password");
}
and make this button click code:
public void postHttpRequest(String userId,String pass,TextView error){
RequestClient reqClient = new RequestClient(LoginActivity.this);
String AppResponse = null;
try {
url = "myurl";
Log.d("URL", url);
reqClient.execute();
} catch (Exception e) {
Log.e("Exception Occured", "Exception is "+e.getMessage());
}
}
I'm working on one project and I need to call one AsyncTask, but the onPostExecute method is not called.
This is my class:
public class WebService extends AsyncTask<String, String, String> {
private ArrayList<SimpleObserver> listeners;
private int responseCode;
private String message;
private String response;
private String URL;
public WebService() {
listeners = new ArrayList<SimpleObserver>();
}
public void addListener(SimpleObserver obs) {
listeners.add(obs);
}
public void removeListener(SimpleObserver obs) {
listeners.remove(obs);
}
public void notifyListener(String s) {
for (SimpleObserver listener : listeners)
listener.onChange(s);
}
public String getResponse() {
return response;
}
public String getErrorMessage() {
return message;
}
public int getResponseCode() {
return responseCode;
}
#Override
protected void onPreExecute() {
//notifyListener("A calcular");
}
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
HttpParams my_httpParams = new BasicHttpParams();
final String proxyHost = android.net.Proxy.getDefaultHost();
final int proxyPort = android.net.Proxy.getDefaultPort();
if(proxyPort != -1)
{
my_httpParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, new HttpHost(proxyHost, proxyPort));
}
DefaultHttpClient client = new DefaultHttpClient(my_httpParams);
HttpGet httpGet = new HttpGet(url);
Log.d("URL serviço HttpGet", url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
Log.d("RESPOSTA do web service", response);
} catch (Exception e) {
e.printStackTrace();
response = e.getMessage();
Log.e("ERRO de respota", e.getMessage());
}
}
return response;
}
#Override
protected void onPostExecute(String result) {
Log.d("onPostExecute Serviço", result);
notifyListener(result);
}
}
I have created this method:
public void executeService(String param) {
try {
Log.d("Entrar", "no serviço");
s.execute(new String [] {URL+param});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("Erro ao aceder ao web service", e.getMessage());
}
}
to call the task.
these are the results of Log
08-28 17:47:21.936: D/URL serviço HttpGet(2055): http://192.168.56.1:8080/pt.Agile21.Acerola.WebService/rest/acerola?id=g;ana#eu.com
08-28 17:47:22.456: D/RESPOSTA do web service(2055): ana;ana#eu.com;pass;0
08-28 17:47:22.456: D/RESPOSTA do web service(2055): ana;ana#eu.com;pass;0
As you can see I have all the results of doInBackground(). :S
Someone can help me to understand which is the problem?
Something that I saw now looking for the Log files.. my onPostExeute method returns when I finish my app on purpose.. it is not normal.. :S can someone help me?