I try to update a string variable with data from a mysql database.
Example:
String str should grab a value from a mysql db using php. This is done and works perfectly.
But str should grab these values every 10 seconds, so it has to run in a loop.
And exactly this is the problem.
Connecting via httppost and getting entities blocks the UI, so it skip frames.
To solve this i used: Services, AsyncTasks and Runnables but always frame skipping.
This is the latest thing i tried:
public class AsyncStatus extends AsyncTask<String, String, String>{
HttpResponse response;
String str;
HttpPost httppost;
HttpClient httpclient;
List<NameValuePair> nameValuePairs;
Handler mHandler=null;
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
//Build the connection only once, to save performance
getStrFirst();
//Loop started
final Runnable mUpdateUI = new Runnable() {
public void run() {
System.out.println("called");
try {
//to avoid "already consumed exceptions"
response = httpclient.execute(httppost);
//get the content
str = EntityUtils.toString(response.getEntity());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
str = str.replaceAll("\\D", "");
mHandler.postDelayed(this, 10000); // 10 seconds
}
};
mHandler.post(mUpdateUI);
return null;
}
public void getStrfirst(){
nameValuePairs = new ArrayList<NameValuePair>();
try
{
httpclient = new DefaultHttpClient();
httppost = new HttpPost("http://lunation.square7.ch/msqlcount.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpclient.execute(httppost);
str = EntityUtils.toString(response.getEntity());
LOGCAT:
09-11 12:12:41.185: I/System.out(10874): called
09-11 12:12:41.975: I/Choreographer(10874): Skipped 51 frames! The application may be doing too much work on its main thread.
09-11 12:12:51.990: I/System.out(10874): called
EDIT:
I call the AsyncTask with:
AsyncStatus assi= new AsyncStatus();
assi.execute("nothing");
Why does this message appear, this isn't the main thread?
Thank you for any advice
Related
Java Code...!
public void saveDB(View v)
{
//BackgroundTask Class Execution
name= ""+output1.getText().toString();
batch_no= ""+output2.getText().toString();
price= ""+output3.getText().toString();
mfg_dt= ""+output4.getText().toString();
exp_dt= ""+output5.getText().toString();
insertintoDB();
onBackPressed();
}
public void insertintoDB()
{
//setting name value pairs
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
//Adding the variables inside the NameValuePairs
nameValuePairs.add(new BasicNameValuePair("name",name));
nameValuePairs.add(new BasicNameValuePair("batch_no",batch_no));
nameValuePairs.add(new BasicNameValuePair("price",price));
nameValuePairs.add(new BasicNameValuePair("mfg_dt",mfg_dt));
nameValuePairs.add(new BasicNameValuePair("exp_dt",exp_dt));
//Setting up the connection inside the try and catch block
try
{
//Setting up the default http client
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://illusion.netau.net/android/saveData.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
//Getting the response
HttpResponse response = httpclient.execute(httppost);
//Setting up the entity
HttpEntity entity = response.getEntity();
//Setting up the content inside the input stream reader
is = entity.getContent();
/* URL url=new URL("http://illusion.netau.net/android/saveData.php");
urlConnection=(HttpURLConnection) url.openConnection();
urlConnection.connect();
is=urlConnection.getInputStream();*/
Toast.makeText(getApplicationContext(), "Data Entered Successfully...",Toast.LENGTH_LONG).show();
Log.e("Conn_Fine", "connection success ");
}catch (ClientProtocolException e)
{
Log.e("Client Protocol","Log_tag");
e.printStackTrace();
}
catch(IOException e)
{
Log.e("Log_tag","IOException");
e.printStackTrace();
Toast.makeText(getApplicationContext(), "No Internet Access",Toast.LENGTH_LONG).show();
}
}
This is my java code where i am saving data into mysql db using httpClient....!
-------------------- LOGCAT Message.---------------------------
04-12 20:56:57.473 2189-2189/com.example.fezimirza.layoutexample I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy#713eb3c time:19721431
04-12 20:57:01.734 2189-2189/com.example.fezimirza.layoutexample E/pass 1: connection success
04-12 20:57:01.743 2189-2189/com.example.fezimirza.layoutexample I/Timeline: Timeline: Activity_launch_request id:com.example.fezimirza.layoutexample time:19725701
04-12 20:57:01.763 2189-2189/com.example.fezimirza.layoutexample I/Choreographer: Skipped 41 frames! The application may be doing too much work on its main thread.
04-12 20:57:02.057 2189-2189/com.example.fezimirza.layoutexample I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy#1932a91 time:19726015
There isn't any code here that's responsible for writing to a database. It looks like you're making an API call to some API (that I'm guessing is responsible for writing to the database). If that's the case, then you should simply be checking to ensure that the API call is successful and was made using the correct POST body and if so, debug your API code to figure out why stuff isn't being written to your database correctly.
As mentioned by zec and Nguyễn Trung Hiếu , server call should happens in secondary thread using AsyncTask . If you are new to android check this ..http://developer.android.com/reference/android/os/AsyncTask.html
The parameter which you send to server . Which format that your server accepts. That server side response could not reflect in android code. Check that php part of receiving the data.
Try it!!!!!
public void saveDB(View v)
{
new insertintoDB().execute();
}
class insertintoDB extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
/*
* pDialog = new ProgressDialog(MainActivity.this);
* pDialog.setMessage("Please wait..."); pDialog.show();
*/
}
#Override
protected String doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://illusion.netau.net/android/saveData.php");
try {
name= ""+output1.getText().toString();
batch_no= ""+output2.getText().toString();
price= ""+output3.getText().toString();
mfg_dt= ""+output4.getText().toString();
exp_dt= ""+output5.getText().toString();
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("name",name));
nameValuePairs.add(new BasicNameValuePair("batch_no",batch_no));
nameValuePairs.add(new BasicNameValuePair("price",price));
nameValuePairs.add(new BasicNameValuePair("mfg_dt",mfg_dt));
nameValuePairs.add(new BasicNameValuePair("exp_dt",exp_dt));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
return null;
}
#Override
protected void onPostExecute(String s) {
/*
* if (pDialog.isShowing()) { pDialog.dismiss();
* Toast.makeText(getApplication(), "Complete",
* Toast.LENGTH_LONG).show(); }
*/
}
}
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
I have a for loop running in the background, and it's uploading an array to my database online. However, it only uploads the first time it goes through, and I can't figure out why.
I can follow the code as it loops through the params.add and the upload, but when I look at my database, only one extra item is added each time. My success int is also set to 0 each time but the first one.
I've looked at similar problems, and tried to fix this, but I can't find anything. I'd appreciate any help on this.
This is the relevant code ( I call it with "new SavePotholeDetails().execute();" ):
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(SensorActivity.this);
pDialog.setMessage("Loading pothole details. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
/**
* Saving product
* */
protected String doInBackground(String... args) {
// TODO: Get data from sensorData
for (int i = 0; i < sensorData.size(); i++) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair(TAG_TIME, Long.toString(sensorData.get(i).getTimestamp())));
params.add(new BasicNameValuePair(TAG_ACCEL_X, Double.toString(sensorData.get(i).getX())));
params.add(new BasicNameValuePair(TAG_ACCEL_Y, Double.toString(sensorData.get(i).getY())));
params.add(new BasicNameValuePair(TAG_ACCEL_Z, Double.toString(sensorData.get(i).getZ())));
params.add(new BasicNameValuePair(TAG_CLIENT_ID, "Epidilius")); //TODO: Make a client ID variable
params.add(new BasicNameValuePair(TAG_GPS_X, Double.toString(sensorData.get(i).getLat())));
params.add(new BasicNameValuePair(TAG_GPS_Y, Double.toString(sensorData.get(i).getLng())));
// sending modified data through http request
// Notice that update product url accepts POST method
JSONObject json = jsonParser.makeHttpRequest(
url_update_pothole, "POST", params);
// check json success tag
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// successfully updated
Intent intent = getIntent();
// send result code 100 to notify about product update
setResult(100, intent);
finish();
} else {
// failed to update product
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute(String file_url) {
// dismiss the dialog once product updated
pDialog.dismiss();
}
EDIT:
Here is the JSONParser class:
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// constructor
public JSONParser() {
}
// function get json from url
// by making HTTP POST or GET mehtod
public JSONObject makeHttpRequest(String url, String method,
List<NameValuePair> params) {
// Making HTTP request
try {
// check for request method
if(method == "POST"){
// request method is POST
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}else if(method == "GET"){
// request method is GET
DefaultHttpClient httpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "UTF-8"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
// try parse the string to a JSON object
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return jObj;
}
}
If you're just running a simple loop and not blocking the loop while your AsyncTasks are executing, then they're just getting fired all at once. I also see that you're sending your web requests through the jsonParser object, but I don't know what that is. If this object is shared between AsyncRequest instances (for example, if all of this stuff is scoped within a single Activity) or if the implementation blocks so that only one request can go out at a time, then everything after the first iteration of the loop is going to fail because your HTTP client is busy.
Without posting more than your AsyncTask code, I can't help much further than that. You might want to think more about how you're executing your loop. You could do something where the loop waits for each AsyncTask instance to call back (from the onPostExecute method) to signal that it's finished. Or, you can do the looping inside of a single AsyncTask instance (probably a more lightweight solution as only a single thread is created).
I have noticed that my http requests tend to take alot of time compared apps communicating with same server. It makes my app feel sluggish and I was wondering if there is a better way of making these requests and updating the UI.
At the moment I use this method to make post requests
public String postRequest(List<NameValuePair> nameValuePairs, String method_name) {
String result = "";
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.mysite.com/api/"+method_name);
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Authorization", "Basic somestuff");
try {
// Add your data
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
BufferedReader rd = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
result = rd.readLine();
return result;
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
return null;
}
And in my UI thread (i.e my Fragment classes) I use this in an Async Task like this
class MakeRequest extends AsyncTask<Integer, Integer, String> {
protected String doInBackground(Integer... counter) {
String result = "";
String method_name = "";
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("id", value));
nameValuePairs.add(new BasicNameValuePair("name", name));
method_name = "petition/setPetition";
result = fixr.postRequest(nameValuePairs, method_name);
JSONObject jsonFile = new JSONObject(result);
if(!jsonFile.has("error")){
//Parse JSON using GSON
return "success";
}else{
return jsonFile.getString("error");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String jsonResult) {
try {
if(jsonResult != null){
//update UI
}else{
//Error message
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
I'd like to optimize this so users can have a really smooth experience on my application. I'm open to using third party http libraries or is there also an argument against using AysncTasks and maybe the runOnUiThread() instead.
Volley Library is better, http, https etc.
https://developers.google.com/live/shows/474338138
very mini sample here:https://github.com/ogrebgr/android_volley_examples/blob/master/src/com/github/volley_examples/Act_SimpleRequest.java
Try Volley mate! I changed from AsyncTasks to Volley library and i am pretty pleased from the overall experience!
Volley Library
This has been asked in different ways so far, but I am unable to find a solution to this particular issue.
Short Version:
I am seeking a way to fetch json from a URL that requires authentication. And rather than authenticating every time, I want it to store the received cookies so that it doesn't have to re-login, and on subsequent connections remain logged in.
Long version:
Basically, I want the app to store the user's username and password (as internal private strings with shared preferences). Then after that, it would call a login url to authenticate and remain logged in(get the cookies). Once this is done, I want the program to fetch json data from different urls (that require a user to be logged in via cookies for example). I want this to remain in place even after the app is paused or destroyed.
It can be considered as an idea similar to a chrome plugin that can simply fetch data from a website once its logged in.
I reckon the solution to this would be useful for many developers who are new to android.
try this it stores username pass and session into shared pref
app_preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
userid=app_preferences.getLong("userid",0);
username=app_preferences.getString("username", "");
password=app_preferences.getString("password", "");
session=app_preferences.getString("session", "");
class task extends AsyncTask<String, integer, Boolean>{
//httpreqclass htrq= new httpreqclass();
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
showProgressDialog();
}
#Override
protected Boolean doInBackground(String... params) {
String usr=params[0];
String p=params[1];
String data[]=new String[2];
String ur= "http://192.168.1.45/Android.asmx/Login";
// TODO Auto-generated method stub
data= postData(usr,p,ur);
boolean sucess=false;
try {
JSONObject jso = new JSONObject(data[0]);
sucess =jso.getBoolean("isSucceeded");
if (sucess) {
SharedPreferences.Editor editor = app_preferences.edit();
JSONObject jsr= jso.getJSONObject("result");
Long a= jsr.getLong("Id");
editor.putLong("userid", a);
editor.putString("username", usr);
editor.putString("password", p);
editor.putString("session", data[1]);
editor.commit(); // Very important
}
}catch (Exception e){
}
return sucess;
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
here put code what you want to do next
}
}
public String[] postData(String u, String p,String url) {
String asp = null,data = null;
String[] rtrn=new String[2];
//Log.e("i entrd here", "");
try {
HttpClient httpclient = new DefaultHttpClient(getHttpParams());
HttpPost httppost = new HttpPost();
HttpResponse response;
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("EmailId", u));
params.add(new BasicNameValuePair("PassWord", p));
UrlEncodedFormEntity ent = new UrlEncodedFormEntity(params,HTTP.UTF_8);
httppost.setEntity(ent);
response = httpclient.execute(httppost);
Header[] headers;
headers = response.getHeaders("Set-Cookie");
//Header atha= respone.getFirstHeader("PHPSESSID");
List<Cookie> cookies = ((AbstractHttpClient) httpclient).getCookieStore().getCookies();
if (cookies.isEmpty()) {
Log.d("TAG","no cookies received");
} else {
for (int i = 0; i < cookies.size(); i++) {
if(cookies.get(i).getName().contentEquals("ASP.NET_SessionId")) {
asp = cookies.get(i).getValue();
}
}
Log.e("this is the cookiee", asp);
}
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
Log.e("", sb.toString());
rtrn[0]=sb.toString();
rtrn[1]=asp;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rtrn;
}
private HttpParams getHttpParams() {
HttpParams htpp = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(htpp, 3000);
HttpConnectionParams.setSoTimeout(htpp, 5000);
return htpp;
}
you can refer the code and make the application as per your logic
and note when the next time onwards when you send a request to the server do not forget to add the session/cookie in the header
Just to not leave the question unanswered and explain how I solved the problem, here is my answer.
I resorted to use the Loopj Android Async Http Client library, which is being used by major apps like Instagram and Pinterest.
Keeping the cookies persistent is pretty simple this way. All you need is:
AsyncHttpClient myClient = new AsyncHttpClient(); // a client instance
PersistentCookieStore myCookieStore = new PersistentCookieStore(this);
myClient.setCookieStore(myCookieStore); // setting the cookie store