Java get result from Thread and Runnable - java

in this below code i can not get result from getValue from Foo class and thats return null but that must be return value. result is correct and this function could not return that. for example this is my class:
public class JsonService {
private JSONObject json = new JSONObject();
public JsonService(final String username, final String password) throws Exception{
json.put("username", username);
json.put("password", password);
}
public class Foo implements Runnable {
private String result;
#Override
public void run() {
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
try {
HttpPost post = new HttpPost("http://www.example.com/json_android.php");
StringEntity se = new StringEntity( json.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
if(response!=null){
InputStream stream = response.getEntity().getContent();
result = convertToString(stream);
/*
I can Log result with below line
*/
Log.e("response is: ", result);
/*
result is {"username = ":"Hello"}
*/
}
} catch(Exception e) {
e.printStackTrace();
Log.e("Error", String.valueOf(e));
}
}
public String getValue() {
/*
return in this fucntion not working
*/
return result;
}
}
public String request() throws ExecutionException, InterruptedException {
Foo foo = new Foo();
new Thread(foo).start();
return foo.getValue();
}
How to get result correctly from Foo and return that from reauest() ? please help me. thanks

Use a FutureTask and implement a Callable.
public class Foo implements Callable<String> {
#Override
public String call() {
String result = null;
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
HttpResponse response;
try {
HttpPost post = new HttpPost("http://www.example.com/json_android.php");
StringEntity se = new StringEntity( json.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
if(response!=null){
InputStream stream = response.getEntity().getContent();
result = convertToString(stream);
/*
I can Log result with below line
*/
Log.e("response is: ", result);
/*
result is {"username = ":"Hello"}
*/
}
} catch(Exception e) {
e.printStackTrace();
Log.e("Error", String.valueOf(e));
}
return result;
}
}
and than use it with the FutureTask
public String request() throws ExecutionException, InterruptedException {
Foo foo = new Foo();
FutureTask<String> fooFuture = new FutureTask<String>(foo);
new Thread(fooFuture).start();
return fooFuture.get();
}

the method of get from class FutureTask (at the above answer return fooFuture.get();) is a blocking function that means when you call it from UI thread it blocks the UI thread so cause your app sends you ANR error. My suggestion to solve it is using LocalBroadCastManager and when the computation finished it sends a local broadcast and in your UI you will get the result at the onReceive from the Extra that is embedded in the intent.
another solution is using ruOnUiThread or passing the handler from UI thread. and last one is using post method of widgets.

Related

Cannot get http response when intervally requesting a new http request

I have a class called App which is this one:
public class App{
public static void main(String[] args){
StreamingData dataStream = new StreamingData("urlString");
dataStream.StreamHttpRequest();
}
}
and this class called StreamingData that has two methods, the StreamHttpRequest that intervally calls the httpRequest every 1 second as shown below:
public class StreamingData {
private String url;
private JSONObject httpResponse;
public StreamingData(String url){
this.url = url;
}
public void httpRequest() throws Exception{
try {
URL obj = new URL(this.url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
BufferedReader in = new BufferedReader(new
InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
setHttpResponse(new JSONObject(response.toString()));
} catch (ConnectException e){
e.printStackTrace
}
}
public void setHttpResponse(JSONObject httpResponse) {
this.httpResponse = httpResponse;
}
public JSONObject getHttpResponse() {
System.out.println(this.httpResponse.toString());
return this.httpResponse;
}
public void StreamHttpRequest() {
final long timeInterval = 1000;
Runnable runnable = new Runnable() {
public void run() {
while(true){
try {
httpRequest();
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(timeInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
Whenever I call the getHttpResponse from the httpRequest method, or pretty much every method from the StreamingData class it returns the whole json response, but when I try to retrieve it from the App class like this
// code as shown above
StreamingData netDataStream = new StreamingData("urlString");
JSONObject netDataHttpResponse = netDataStream.getHttpResponse();
it returns Exception in thread "main" java.lang.NullPointerException and the json is empty.
How can I get the json response to another class (e.g. the App)? Because for now I cannot use it outside the StreamingData class.
Thank you very much for your help,
csymvoul
You're working with threads. That means that the httpResponse field value will be set once the http request performs (async).
here:
StreamingData netDataStream = new StreamingData("urlString");
JSONObject netDataHttpResponse = netDataStream.getHttpResponse();
You're asking for the response immediatelly (when the http response is not ready).
You could add some kind of listener to your StreamingData class , so that you can call on some method when the response is ready:
public class HttpResponseListener {
void onResponse(JSONObject httpResponse){...}
}
Then you could do something like...
StreamingData netDataStream = new StreamingData("urlString" , new HttpResponseListener());
And call httpResponseListener.onResponse when the httpResponse object is set.
public void setHttpResponse(JSONObject httpResponse) {
this.httpResponse = httpResponse;
httpResponseListener.onResponse(httpResponse);
}
That is if you still want to use Http request / reponses with threads.

How can I make an httppost request in Android?

I know this should have been easy to find online but none of the articles addressed my issue so I am coming to SO for some help.I am trying to make an httppost request in android to a wcf restful web service. I want to create an xml and then I want to post that to the service and get a response from the service.
I have created a WCF Rest service and it has a method to accept the xml and respond back.Here is the code for the method:
[OperationContract]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "DoWork1/{xml}",
BodyStyle = WebMessageBodyStyle.Wrapped)]
XElement DoWork1(string xml);
public XElement DoWork1(string xml)
{
StreamReader reader = null;
XDocument xDocRequest = null;
string strXmlRequest = string.Empty;
reader = new StreamReader(xml);
strXmlRequest = reader.ReadToEnd();
xDocRequest = XDocument.Parse(strXmlRequest);
string response = "<Result>OK</Result>";
return XElement.Parse(response);
}
Here is android code to post xml :
String myXML = "<? xml version=1.0> <Request> <Elemtnt> <data id=\"1\">E1203</data> <data id=\"2\">E1204</data> </Element> </Request>";
HttpClient httpClient = new DefaultHttpClient();
// replace with your url
HttpPost httpPost = new HttpPost("http://192.168.0.15/Httppost/Service1.svc/DoWork1/"+myXML);
This code crasehes throwing an illegal character in the path exception.
How can I make post an xml file to this service from android. Any suggestions would be really appreciated.
public class HTTPPostActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
makePostRequest();
}
private void makePostRequest() {
HttpClient httpClient = new DefaultHttpClient();
// replace with your url
HttpPost httpPost = new HttpPost("www.example.com");
//Post Data
List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(2);
nameValuePair.add(new BasicNameValuePair("username", "test_user"));
nameValuePair.add(new BasicNameValuePair("password", "123456789"));
//Encoding POST data
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair));
} catch (UnsupportedEncodingException e) {
// log exception
e.printStackTrace();
}
//making POST request.
try {
HttpResponse response = httpClient.execute(httpPost);
// write response to log
Log.d("Http Post Response:", response.toString());
} catch (ClientProtocolException e) {
// Log exception
e.printStackTrace();
} catch (IOException e) {
// Log exception
e.printStackTrace();
}
}
}
To connect to WCF service on android you have to use external library like ksoap.
enter link description here
Then you can adapt for your needs this class:
public abstract class SoapWorker extends AsyncTask<SoapWorker.SoapRequest,Void,Object> {
public static class SoapRequest{
private LinkedHashMap<String,Object> params;
private String methodName;
private String namespace;
private String actionName;
private String url;
public SoapRequest(String url, String methodName,String namespace){
this.methodName = methodName;
this.params = new LinkedHashMap<>();
this.namespace=namespace;
this.actionName=this.namespace + "IService/" + methodName;
this.url=url;
}
public void addParam(String key,Object value){
this.params.put(key,value);
}
}
#Override
protected Object doInBackground(SoapRequest input) {
try {
SoapObject request = new SoapObject(input.namespace, input.methodName);
for(Map.Entry<String, Object> entry : input.params.entrySet()){
request.addProperty(entry.getKey(),entry.getValue());
}
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(input.url);
androidHttpTransport.call(input.actionName, envelope);
input.params.clear();
return parseResponse(envelope.getResponse());
} catch (Exception e) {
Log.e("SoapWorker", "error " + e);
return e;
}
}
#WorkerThread
public abstract Object parseResponse(Object response);
}
Use this class like:
SoapWorker.SoapRequest request = new SoapWorker.SoapRequest(URL,METHOD_NAME,NAMESPACE);
request.addParam(KEY,VALUE);
....
request.addParam(KEY,VALUE);
SoapWorker worker = new SoapWorker(){
#Override
public Object parseResponse(Object response) {
if(response==null)
return null;
//parse response
// this is background thread
return response;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
// this is ui thread
//update your ui
}
};
worker.execute(request);
Use this asynck task only in application context.Pass data to Activity / fragment only using EventBus from green roboot or otto.

Android - HTTP GET on separate thread

Background:
I am new to android programming. I want to simply do an http get request to a local server.
I want to pass this request a name as a parameter and want to get a return in json. This issue that I cannot execute it on the main thread. How can I do this?
Here is what I tried:
main class:
itemsAdapter.add(get.getName(device.getName()));
Seperate class in same file:
private class httpGet extends AsyncTask<Editable, Void, Integer> {
protected String doInBackground(Editable... params) {
Editable editable = params[0];
return getName(editable.toString());
}
final String getName(String btName) {
HttpResponse response = null;
String result = "";
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
URI website = new URI("http://192.168.1.105/getName.php?q=" + btName);
request.setURI(website);
response = client.execute(request);
// Convert String to json object
JSONObject json = new JSONObject(response.toString());
// get LL json object
JSONObject json_Name = json.getJSONObject("Name");
// get value from LL Json Object
name = json_Name.getString("value"); //<< get value here
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
// Do something to recover ... or kill the app.
}
return result;
}
protected void onPostExecute(Integer result) {
// here you have the result
}
I am not sure if this is even a good way to do this task. I also have no idea how I would call it.
AsyncTask allows you to perform a background operation in a different thread without manipulating threads/handlers.
It should be this way:
private class httpGet extends AsyncTask<ParamForDoInBackground, ParamForOnProgressUpdate, ParamForOnPostExecute> {
protected Long doInBackground(ParamForDoInBackground... urls) {
// do the request here
}
protected void onProgressUpdate(ParamForOnProgressUpdate progress) {
// if you need to show any progress of the
// request from doInBackground
}
protected void onPostExecute(ParamForOnPostExecute result) {
// this method will run when doInBackground
// is done executing
}
}
Then you can execute an AsyncTask:
new httpGet().execute(ParamForDoInBackground);
You can use the following as a reference: AndroidBackgroundProcessing and Android Developer AsyncTask
You should learn how the asyncTask work. Inside DoInBackground you should to put the code referent to the HTTPRequest. I recommend to use methods to improve the understanding of code. Here is an example of one of my apps:
public String query(String uri) {
HttpClient cliente = new DefaultHttpClient();
HttpContext contexto = new BasicHttpContext();
HttpPost httpPost = new HttpPost(uri);
HttpResponse response = null;
String resultado=null;
try {
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("dato", cod_restaurante));
httpPost.setEntity(new UrlEncodedFormEntity(params));
response = cliente.execute(httpPost, contexto);
HttpEntity entity = response.getEntity();
resultado = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e) {
// TODO: handle exception
}
return resultado;
}
private class MyAsyncTask extends AsyncTask<String, Integer, String>{
#Override
protected String doInBackground(String... params)
{
result=query(params[0]);
return result;
}
protected void onPostExecute(final String resultadoDoInBackground)
{
//here put the code to modify the UI
}
}
Then in your activity onCreate() method you execute the Asynktask.
new MyAsyncTask().execute(" ");
You can read more about AsyncTask here:
AsyncTask Android Developer

How to send cookies with AsyncTask?

I have a web server, where i log in in my android Application, after that loging i recive as an XML the user who logged with a field named token.
This token is used to keep open the session during next calls to webService, and it works sendidnt the token as a cookie named "acrsession" but it seems not working because everytime i tried to check if im logged in (using a get call named currentUser) it returns me forbidden, so i think it isnt working good.
Here is my AsyncTask class who do the calls to server.
public String getFileName() {
return FileName;
}
public void setFileName(String fileName) {
FileName = fileName;
}
private String Response;
private URI uriInfo;
private String FileName;
public WebServiceTask(int taskType, Context mContext, String processMessage,String token) {
this.taskType = taskType;
this.mContext = mContext;
this.processMessage = processMessage;
this.token=token;
}
public void addNameValuePair(String name, String value) {
params.add(new BasicNameValuePair(name, value));
}
public void showProgressDialog() {
pDlg = new ProgressDialog(mContext);
pDlg.setMessage(processMessage);
pDlg.setProgressDrawable(mContext.getWallpaper());
pDlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDlg.setCancelable(false);
pDlg.show();
}
#Override
protected void onPreExecute() {
//hideKeyboard();
showProgressDialog();
}
protected String doInBackground(String... urls) {
String url = urls[0];
String result = "";
HttpResponse response = doResponse(url);
if (response == null) {
return result;
} else {
try {
result = inputStreamToString(response.getEntity().getContent());
} catch (IllegalStateException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
} catch (IOException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
}
}
return result;
}
#Override
protected void onPostExecute(String response) {
this.Response=response;
pDlg.dismiss();
}
// Establish connection and socket (data retrieval) timeouts
private HttpParams getHttpParams() {
HttpParams htpp = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(htpp, CONN_TIMEOUT);
HttpConnectionParams.setSoTimeout(htpp, SOCKET_TIMEOUT);
return htpp;
}
private HttpResponse doResponse(String url) {
// Use our connection and data timeouts as parameters for our
// DefaultHttpClient
HttpClient httpclient = new DefaultHttpClient(getHttpParams());
int responseCode=0;
// Create a local instance of cookie store
//CookieStore cookieStore = new BasicCookieStore();
// Create local HTTP context
//HttpContext localContext = new BasicHttpContext();
// Bind custom cookie store to the local context
//localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
//CookieManager cookieManager= CookieManager.getInstance();
this.getLocalContext();
this.cookieStore.addCookie(new BasicClientCookie("acrsession", this.token));
HttpResponse response = null;
try {
switch (taskType) {
case POST_TASK:
HttpPost httppost = new HttpPost(url);
// Add parameters
httppost.setEntity(new UrlEncodedFormEntity(params));
int executeCount = 0;
do
{
pDlg.setMessage("Logging in.. ("+(executeCount+1)+"/5)");
// Execute HTTP Post Request
executeCount++;
response = httpclient.execute(httppost,localContext);
responseCode = response.getStatusLine().getStatusCode();
// If you want to see the response code, you can Log it
// out here by calling:
// Log.d("256 Design", "statusCode: " + responseCode)
} while (executeCount < 5 && responseCode == 408);
uriInfo = httppost.getURI();
break;
case GET_TASK:
HttpGet httpget = new HttpGet(url);
response = httpclient.execute(httpget,localContext);
responseCode = response.getStatusLine().getStatusCode();
httpget.getRequestLine();
uriInfo = httpget.getURI();
break;
case PUT_TASK:
HttpPut httpput = new HttpPut(url);
File file = new File(this.FileName);
InputStreamEntity reqEntity = new InputStreamEntity(new FileInputStream(file), -1);
reqEntity.setContentType("binary/octet-stream");
reqEntity.setChunked(true); // Send in multiple parts if needed
httpput.setEntity(reqEntity);
response = httpclient.execute(httpput,localContext);
responseCode = response.getStatusLine().getStatusCode();
httpput.getRequestLine();
uriInfo = httpput.getURI();
break;
}
} catch (Exception e) {
Log.e(TAG, e.getLocalizedMessage(), e);
}
return response;
}
private String inputStreamToString(InputStream is) {
String line = "";
StringBuilder total = new StringBuilder();
// Wrap a BufferedReader around the InputStream
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
// Read response until the end
while ((line = rd.readLine()) != null) {
total.append(line);
}
} catch (IOException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
}
// Return full string
this.Response=total.toString();
return total.toString();
}
public String getResponse(){
return this.Response;
}
public HttpContext getLocalContext()
{
if (localContext == null)
{
localContext = new BasicHttpContext();
cookieStore = new BasicCookieStore();
localContext.setAttribute(ClientContext.COOKIE_ORIGIN, cookieStore);
localContext.setAttribute(ClientContext.COOKIE_SPEC, cookieStore);
localContext.setAttribute(ClientContext.COOKIESPEC_REGISTRY, cookieStore);
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);// to make sure that cookies provided by the server can be reused
}
return localContext;
}
Plesae tell me what im doing bad.
Thanks in advance.
Well, finally i found the solution, everything was ok but i fortgot to set cookie Domain and path, so onced i putted it it worked.
Now cookie creation looks like this:
this.localContext=this.getLocalContext();
BasicClientCookie cookie = new BasicClientCookie("acrsession", this.token);
cookie.setDomain(this.Domain);
cookie.setPath(this.path);
this.cookieStore.addCookie(cookie);
localContext.setAttribute(ClientContext.COOKIE_STORE, this.cookieStore);
Hope it will help someone else.

NullPointerException in android AsyncTask class

I'm trying to get data through web services, So that I'm using below shown asynctask calls. It gives me a null point exception as shown in the below screen shot. What can be the issue?
Activity class
new PickupAsyncTask(getApplicationContext(), null).execute();
Asynctask class
public class PickupAsyncTask extends AsyncTask<String, Integer, JSONArray> {
private OnTaskCompleted listener;
private JSONArray responseJson = null;
private Context contxt;
private Activity activity;
public PickupAsyncTask(Context context, OnTaskCompleted listener) {
// API = apiURL;
this.contxt = context;
this.listener = listener;
}
// async task to accept string array from context array
#Override
protected JSONArray doInBackground(String... params) {
String path = null;
String response = null;
HashMap<String, String> request = null;
JSONObject requestJson = null;
DefaultHttpClient httpClient = null;
HttpPost httpPost = null;
StringEntity requestString = null;
ResponseHandler<String> responseHandler = null;
try {
path = "http://xxxxxxxxxxxxxxx/LocationService.svc/StreetDetails";
new URL(path);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
// set the API request
request = new HashMap<String, String>();
request.entrySet().iterator();
// Store locations in JSON
requestJson = new JSONObject(request);
httpClient = new DefaultHttpClient();
httpPost = new HttpPost(path);
requestString = new StringEntity(requestJson.toString());
// sets the post request as the resulting string
httpPost.setEntity(requestString);
httpPost.setHeader("Content-type", "application/json");
// Handles the response
responseHandler = new BasicResponseHandler();
response = httpClient.execute(httpPost, responseHandler);
responseJson = new JSONArray(response);
System.out.println("*****JARRAY*****" + responseJson.length());
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
return responseJson;
}
#Override
protected void onPostExecute(JSONArray result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
listener.onTaskCompleted(responseJson); //line 101
}
}
OnTaskCompleted.java
public interface OnTaskCompleted {
void onTaskCompleted(JSONArray responseJson);
}
listener is null. Introduce a check to verify that listener is not null before calling any methods on it.
Edit
If you want to handle the task completion, pass an anonymous object of OnTaskCompleted to PickupAsyncTask constructor as follows:
new PickupAsyncTask(context, new OnTaskCompleted() {
#Override
public void onTaskCompleted(JsonArray response) {
//Handle the task completion
}
}).execute();

Categories

Resources