The requirement is : I have a background service and in that service I am doing a REST call to get a JSON data. I want to send the JSON data to UI and update contents.
One method I can use i.e. store the entire JSON string in SharedPreferences and retrieve in UI but I don't think that's efficient.
Any idea guys ? I have added a Handler in UI to update elements but I am not that familiar in using it.
Sample REST call code :
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(DATA_URL);
httpPost.setHeader("Content-Type", "application/json");
//passes the results to a string builder/entity
StringEntity se = null;
try {
se = new StringEntity(RequestJSON.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//sets the post request as the resulting string
httpPost.setEntity(se);
//Handles what is returned from the page
ResponseHandler responseHandler = new BasicResponseHandler();
try {
HttpResponse response = (HttpResponse) httpClient.execute(httpPost, responseHandler);
// response will have JSON data that I need to update in UI
//Show notification
showNotification("Update Complete");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// httpClient = null;
}
On UI activity
Handler myHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
Bundle Recevied = msg.getData();
String resp = Recevied.getString("Mkey");
}
};
messenger = new Messenger(myHandler);
}
pass the messanger to service and once result ready:
Message msg = Message.obtain();
Bundle data = new Bundle();
data.putString("Mkey",
Smsg);
msg.setData(data);
try {
// Send the Message back to the client Activity.
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
Something like that may be suitable for you. TL;DR: Create a listener in the service that updates the activity.
In the service, make a static function and a static field:
private static BlaBlaService _instance;
public static BlaBlaService getInstance() {
return _instance;
}
Populate the _instance field on the onCreate function:
public void onCreate() {
super.onCreate();
_instance = this;
...
}
public void addRESTCompleteListener(RESTCompleteListener l) {...}
Once a REST call is complete call:
listener.RESTCompleted(JSON.whatever)
Now in your activity, simply add the listener to the service once it starts:
BlaBlaService.getInstance().addRESTCompleteListener(listener)
Don't forget to dispose all the pointers when needed.
Hope this helps :)
Related
This code shows the exception when it reach the get sentence (line commented on the code).
The code is the next, consist on get a comments list from Http get Request:
public class ObtencionComentariosPerfil extends AsyncTask<String, Integer, List<Comment>>{
#Override
protected List<Comment> doInBackground(String... params) {
// TODO Auto-generated method stub
HttpClient httpClient = new DefaultHttpClient();
URI url;
List<Comment> listaComentarios = new ArrayList<Comment>();
try {
url = new URI(params[1]);
HttpGet del = new HttpGet(url);
del.setHeader("content-type", "application/json");
del.setHeader("X-Auth-Token", params[0]);
System.out.println("El token params es: "+params[0]);
HttpResponse resp = httpClient.execute(del);// THE EXCEPTION shows here
StatusLine estatus = resp.getStatusLine();
if (estatus.getStatusCode() == 200) {
InputStream is = resp.getEntity().getContent();
CommentsParser parser= new CommentsParser();
listaComentarios = parser.parseoComentarios(is.toString());
} else {
System.out.println("Error");
listaComentarios = null;
}
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return listaComentarios;
}
#Override
protected void onPostExecute(List<Comment> lista){
}
}
Here is called from main code:
public List<Comment> obtieneComentariosPerfil(long idUsuario, String aut){
List<Comment> listaComentarios = new ArrayList<Comment>();
String url= "http://"+ip+":8080/api/users/"+idUsuario+"/comments";
String[] params= new String[2];
params[0]=aut;
params[1]=url;
ObtencionComentariosPerfil du = new ObtencionComentariosPerfil();
listaComentarios = du.doInBackground(params);
return listaComentarios;
}
I think it have to be a stupid failure but i cant find the error. Thanks.
Because you call du.doInBackground(params);
you should call du.excute(params) instead
listaComentarios = du.doInBackground(params);
You submit async tasks for execution in a background thread by calling execute(), not by directly calling the doInBackground() callback in the current thread.
Communicate the result back to UI thread in onPostExecute().
I am trying to get an HttpResponse in xml but Im not getting the whole response, what is courious is that if I loop the request the response ends in different parts but is never full.
I use the same code to request things from different Urls but I only get problems with one.
Here is the code of the AsyncTask:
public class NetworkTask extends AsyncTask<String, Void, HttpResponse> {
private AsyncTaskListener listener;
#Override
protected HttpResponse doInBackground(String... params) {
String link = params[0];
HttpGet request = new HttpGet(link);
AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
try {
HttpResponse httpResponse = client.execute(request).;
return httpResponse;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
client.close();
}
}
#Override
protected void onPostExecute(HttpResponse result) {
if (result != null){
try {
String sRes = EntityUtils.toString(result.getEntity());
listener.onNTCompleted(sRes);
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public NetworkTask(AsyncTaskListener listener){
this.listener=listener;
}
}
I am not sure if this helps you but you have a problem because EntityUtils.toString() reads data from the network stream, which should not be done on UI thread (onPostExecute). Try moving EntityUtils.toString() to doInBackground() first. This may not help solve your problem, but it is the right thing to do.
I am using httppost method in doinbackground and I am also getting the the response. Now when I pass the data to webservice I get a Jsonobject which I have to parse. and that jsonobject is stored in responsebody below. I have putted the return statement as "res". but in onpost execute I get a nullpointer exception.
I want to use the String responseBody in onpostexecute method?
class Thread extends AsyncTask<String, Void , String>{
private String responseBody;
private String res;
#Override
protected String doInBackground(String... params) {
HttpClient client = new DefaultHttpClient();
HttpResponse response;
JSONObject json=new JSONObject();
HttpPost post = new HttpPost(url1);
try {
json.put("URL",getqrcode());
json.put("EmailID", getuseremail());
StringEntity stringEntity = new StringEntity(json.toString());
stringEntity.setContentEncoding("UTF-8");
stringEntity.setContentType("application/json");
post.setEntity(stringEntity);
response = client.execute(post);
Log.e("RESPONSE", response.toString());
String responseBody = EntityUtils
.toString(response.getEntity());
String res= responseBody.toString();
Log.e("RESPONSE BODY", responseBody);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
return res;
}
#Override
protected void onPostExecute(String res) {
Log.e("response is", res);
// TODO Auto-generated method stub
super.onPostExecute(res);
}
Make a Global variable of response
String res;
and use in onpostExecute() method:
and just replace
String res= responseBody.toString();
with
res= responseBody.toString();
only
Your global res is masking the local res defined in the try block.
Since the res variable you populate is local to the scope of the try block, it cannot be seen outside, and your compiler doesn't complain because of the global res.
You can simply affect the res member without re-declaring it:
res = responseBody;
Technically, it is not useful to declare the res variable globally, you can simply declare it in the method, but in the same scope as the return, that is, outside the try block (before it).
(also, the toString is not useful, as it will only return itself in the case of a String)
(the same goes for responseBody, the local scope hide the global scope. In this case, the global scope is useless)
Just insert this statement in the end of your doInBackground method :
return res;
This will return response to onPostExecute(String oString) wrap-up in oString
I have a simple program that aks questions then call a php file saying if the answer was a yes or a no.
Right now it works but there is a slight pause when the information is being send. I would like some kind message or indicator to come up showing the computer is busy.
Now when I chnage the text of a textvue, before I send the data, the textView does not change, I allso tried to call it's update methed
code
case R.id.butYes:
mSend .setText("Sending your vote to server");
mSend.invalidate();
TalkToServer( mYes[mPes-1] );
UpdateScreen();
mSend .setText("");
break;
String TalkToServer( String addr)
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(addr);
HttpResponse response;
String responseBody=new String("");
try {
response = httpclient.execute(httppost);
responseBody = EntityUtils.toString(response.getEntity());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return responseBody;
}
use AsyncTask to avoid hanging of UI when sending data to server just change your code as:
case R.id.butYes:
new SendTextOperation().execute("");
break;
private class SendTextOperation extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
//Update UI here
mSend.setText("Sending your vote to server");
mSend.invalidate();
}
#Override
protected String doInBackground(String... params) {
// Talk to server here to avoid Ui hanging
TalkToServer( mYes[mPes-1] );
return null;
}
#Override
protected void onPostExecute(String result) {
// Update screen here after talk to server end
UpdateScreen();
mSend .setText("");
}
}
i want to run the script behind the button of Google search that means...posting a form to google server and getting the response in the form of html string and finally i put that string on webview to display result....
then i run the code ...
some times it shows correct result (like someone click on google search button) but some times it shows me message to "force to close" without any changes i do in to code....that means prediction about output is unexpected...
My code is like this......
public class url extends Activity
{
HttpResponse end = null;
String endResult = null;
WebView mWebView;
Intent myWebViewIntent;
public static final int TIMEOUT_MS=10000;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), TIMEOUT_MS);
HttpConnectionParams.setSoTimeout(client.getParams(), TIMEOUT_MS);
HttpPost post = new HttpPost("http://www.google.com/m");
List<NameValuePair> pairs = new ArrayList<NameValuePair>();
pairs.add(new BasicNameValuePair("hl", "en"));
pairs.add(new BasicNameValuePair("gl", "us"));
pairs.add(new BasicNameValuePair("source", "android-launcher-widget"));
pairs.add(new BasicNameValuePair("q", "persistent"));
try {
post.setEntity(new UrlEncodedFormEntity(pairs));
/* Uri uri = Uri.parse(post.toString());
TextView t1=new TextView(this);
t1.setText(post.getRequestLine().getUri());
this.setContentView(t1);*/
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Toast msg = Toast.makeText(url.this, "Message", Toast.LENGTH_LONG);
msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2);
msg.show();
HttpResponse response = client.execute(post);
end = response;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
//Toast.makeText(url.this, "problem in execute....", 20).show();
// TODO Auto-generated catch block
//put the balance is empty dialog box here.
e.printStackTrace();
}
BasicResponseHandler myHandler = new BasicResponseHandler();
try {
// Log.i("file tag","we are out of url");
endResult = myHandler.handleResponse(end);
} catch (HttpResponseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
WebView engine = (WebView)findViewById(R.id.webview);
engine.loadDataWithBaseURL(post.getRequestLine().getUri(), endResult, "text/html", "UTF-8", null);
//engine.loadData(endResult, "text/html", "UTF-8");
engine.requestFocus(View.FOCUS_DOWN);
//engine.loadUrl(endResult);
}
}
so is there any problem in emulator or installation of SDk or program itself....? becoz it seems to be the connection with the internet is done but i use the proper permission..
thank you..
The ANR you get is because you're making a blocking call on the UI thread. To perform a blocking action without blocking the UI thread you have to use a thread and a handler, or (recommended) an AsyncTask.
See Painless Threading.