I want to save certain information via http. This information is continuously stored in a local database (sqlite) and just keep it in the server (HttpPost) every so often.
How I can save that information releasing tasks individually by each data from my table? If possible an orderly manner.
Thus I launch a task and works perfectly (the code is generic, of course)
(I hope my english is right)
void SaveDataOnServer()
{
String data = db.getFirstData();
task = new SaveItemTask();
task.execute(data);
//if I have, say, 5 data, it would be nice to launch 5 row consecutive (for, while...)?
}
public class SaveItemTask extends AsyncTask<String, Void, Boolean>
{
protected Boolean doInBackground(String... param)
{
...
HttpClient client = new DefaultHttpClient();
HttpPost consult = new HttpPost(url + "?x=" + param[0]);
//making an HTTP POST request
try
{
HttpResponse response = client.execute(consult);
HttpEntity entity = response.getEntity();
...
}
catch...
}
....
#Override
protected void onPostExecute(final Boolean success)
{
...
if (success)
{
//Update row (set saved onserver=true)
}
...
}
http://developer.android.com/reference/android/os/AsyncTask.html
The task can be executed only once (an exception will be thrown if a
second execution is attempted.)
So either you re-create your SaveItemTask object every time, either you modify SaveItemTask in order to perform the HttpPost a target number of times.
Related
I have a strange problem in my application.
I have an activity that fetches 2 or 3 things in parallel using AsyncTasks
When I simply do the following
new getMessages().execute("someID");
new getNotifications().execute("someID");
and the both AsyncTasks has code as follows:
(Both of them are identical except that the URL requested by each method is different).
Notice: I modified this code a little bit just to remove any unneeded extras like extra parameters sent in the http request
// in the other Async task "notifications" is changed with "messages"
public class getNotifications extends AsyncTask<String, Void, String> {
ProgressDialog dialog;
Integer verified = 0;
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... args) {
// getRequestsCount just perfomrs http request and grabs JSON data
String result = getRequestsCount(args[0] , "notifications");
return result;
}
protected void onPostExecute(String result) {
// This is just a method that handles the result
// When I log result I found that results are exchanged.
displayResults(result);
}
}
public String getRequestsCount(String id, String type){
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new
HttpPost(GlobalSettings.apiURL + "/getcount/" + type );
Log.i("will contact",GlobalSettings.apiURL + "/getcount/" + type);
HttpResponse response = httpclient.execute(httppost);
BufferedReader reader = new BufferedReader(new InputStreamReader( response.getEntity().getContent(), "UTF-8"));
String responseMessage = reader.readLine().toString().trim();
// Response is always 1 line of JSON data
Log.i("Response for "+type,responseMessage);
return responseMessage;
}
Now my problem is that sometimes results are exchanged.
i.e. getMessages recives the JSON data requested from getNotifications
and vice versa.
I am developing an android application which aim is to send some datas to the server. However, sometimes there may not have wifi connection, so I would like to ask if it is possible to create a cache to store multiple sets of data, say maybe 3 sets, and then the app will send those datas automatically when a connection is available.
Here is the way I send my datas to server recently:
private class GrabURL extends AsyncTask<String, Void, Void>{
//ArrayList object for storing the string pairs
ArrayList<NameValuePair> nameValuePairs;
public GrabURL() {
//constructor of the class
nameValuePairs = new ArrayList<NameValuePair>();
}
protected void onPreExecute(String key, String value) {
//store the pair of values into the ArrayList
nameValuePairs.add(new BasicNameValuePair(key,value));
}
#Override
protected Void doInBackground(String... urls) {
// TODO Auto-generated method stub
//Operation being executed in another thread
try{
//set up the type of HTTPClient
HttpClient client = new DefaultHttpClient();
//set up the location of the server
HttpPost post = new HttpPost(urls[0]);
//translate form of pairs to UrlEncodedFormEntity
UrlEncodedFormEntity ent = new UrlEncodedFormEntity(nameValuePairs,HTTP.UTF_8);
//set up the entity being sent by post method
post.setEntity(ent);
//execute the url and post the values
//client.execute(post);
HttpResponse responsePOST = client.execute(post);
HttpEntity resEntity = responsePOST.getEntity();
line = EntityUtils.toString(resEntity);
} catch (Exception e) {
//catch the exception
line = "Can't connect to server";
}
return null;
}
protected void onPostExecute(Void unused) {
Toast.makeText(getApplicationContext(), "Value updated", Toast.LENGTH_SHORT).show();
}
}
I think Cache data is simple, you can store it in memory or store them as files. You can listen the network state change events to be notified when there is a connection available.
Here is the Sample Code.
this may be helpful in having abstract caching lib for object+image caching;
generic-store-for-android >>
To store primitive things, you can simply use SharedPreferences, and as soon as network becomes available, you can check if something with a specific key exist in SharedPreferences. If you don' t write the data inside a persistent environment(like SharedPreferences, Sqlite, file inside SD card or internal storage, etc.) closing the application will cause your data to be loss.
I am developing an android application where in each activity i need to pass some data onto the server and get back the responses before going to the next activity. The application works fine if the internet is fast enough. But as the speed goes down the application force closes. How to deal with slow internet connection so that it might not lead to force close of application?????
Here is some part of code
public void onClick(View v) {
// TODO Auto-generated method stub
UserFunctions userFunction = new UserFunctions();
if(userFunction.isNetworkAvailable(getApplicationContext()))
{
answer="";
for(int check1=0;check1<counter2;check1++){
int check2=0;
answer=answer+option4[check1]+"|";
while(check2<counter1){
if(edTxt[check1][check2].getText().toString().equals("")){
answer="";
break;
}
else{
answer=answer+edTxt[check1][check2].getText().toString()+"|";
}
check2++;
}
if(answer.equals("")){
break;
}
else{
answer=answer+"||";
}
}
if(answer.equals("")){
Toast.makeText(this, "Please fill all fields", 600).show();
}
else{
userFunction.form1(surveyId,userId , quesNo, answer);
if(total>0){
draw(temp);
}
else{
ques_no++;
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("quesNo", Integer.toString(ques_no)));
params.add(new BasicNameValuePair("surveyId", surveyId));
count = getJsonFromURL22(surveyCond, params);
j=Integer.parseInt(result);
if(j==22)
{
Toast.makeText(this, "Survey Completed", 600).show();
Intent home=new Intent(Format16.this, SurveyCompleted.class);
UserFunctions userFunctions = new UserFunctions();
userFunctions.full(surveyId);
Bundle d=new Bundle();
d.putString("userId", userId);
home.putExtras(d);
startActivity(home);
}
public String getJsonFromURL22(String url, List<NameValuePair> params){
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
httppost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection"+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
sb = new StringBuilder();
sb.append(reader.readLine());
String line="0";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
return result;
}
Since you have not shown any code, I am guessing you are targeting Android API level 10 or lower, and you are doing all the networking in the UI thread, resulting in the dreaded App Not Responding(ANR) error. One way to fix the problem would be to use AsyncTask and move all your networking code in there. When done right, AsyncTask's doInBackground() will process all your networking in a separate thread, allowing the UI to remain responsive.
It usually works something like this:
private class NetworkTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
// Do all networking here, this will work away in a background thread.
// In your case:
// HttpResponse response = httpclient.execute(httppost);
// Must happen here
}
#Override
protected void onPostExecute(String result) {
// dismiss progress dialog if any (not required, runs in UI thread)
}
#Override
protected void onPreExecute() {
// show progress dialog if any, and other initialization (not required, runs in UI thread)
}
#Override
protected void onProgressUpdate(Void... values) {
// update progress, and other initialization (not required, runs in UI thread)
}
}
If you enable StrictMode, or target api versions 11 and higher, Android will throw a NetworkOnMainThreadException when you try to do this.
The application works fine if the internet is fast enough. But as the
speed goes down the application force closes.
It clearly indicates that you are doing network operation on UI Thread.As per Google Docs if the Asynchronous operation is performed on Main thread and if it is taking more than 5 seconds then your application will show force close dialog which is very unpleasent for end user.
In-fact if you try to run such application on latest android version (i.e 4.0 or later) It will not allow you to run application it will crash at start as soon as it detects that the asynchronous operation is performed on main thread.
You must use AsyncTask or Handlers to perform long running application.
Go through following blog to know more.
http://android-developers.blogspot.in/2010/07/multithreading-for-performance.html
That must be ANR issue not the Force Close issue.
You can use StrictMode to help find potentially long running operations such as network that you might accidentally be doing your main thread.
Or else try to put progress bar.
use setConnectionTimeout or setSoTimeout for handling connection timeout.
HttpGet httpGet = new HttpGet(url);
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
and use AsyncTask or Handler or HandlerThread or runOnUiThread anyone for getting data from Server(to perform long running task in background).
You should take a look at this tool that allows you to see what is causing the slow down in your application. The ARO tool is designed to diagnose these sorts of network problems http://developer.att.com/developer/forward.jsp?passedItemId=9700312
I am relatively a new Android developer and I am not able to understand how to do this. I have been looking through all the forums, I made some advance but still here I am.
So, what I want to do is a common function that send a POST request to a webpage (it only sends one POST argument) and returns the result as a string.
I have the main thread here
public class AppActivity extends Activity {
HTTPPostData PostData = new HTTPPostData("id");
PostData.execute();
txtLabel.setText(PostData.Result);
}
and I have my HTTPPostData asynchronous class
public class HTTPPostData extends AsyncTask<String, Long, Object> {
String Value = null;
String Result = null;
public HTTPPostData(String query) {
Value = query;
}
#Override
protected String doInBackground(String... params) {
byte[] Bresult = null;
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://www.mypage.com/script.php");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("cmd", Value));
post.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
HttpResponse response = client.execute(post);
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpURLConnection.HTTP_OK){
Bresult = EntityUtils.toByteArray(response.getEntity());
Result = new String(Bresult, "UTF-8");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
}
return Result;
}
}
I want to use this function several times (inside the same Activity or share it with other Activities of the same application). I am a little bit messed up at this moment so I need your help. What I understand is that I am asking for the result before the doInBackground() is done, and I get an empty result.
Thanks in advance for your help
Regarding this:
HTTPPostData PostData = new HTTPPostData("id");
PostData.execute();
txtLabel.setText(PostData.Result);
Your problem is that you're treating asynctask like it's just a regular function. It's good that you move webpage loading off the main thread, but if you depend on the result for the very next instruction, then it's not doing you much good, you're still blocking the main program waiting for the result. You need to think of AsyncTask like a 'fire and forget' operation, in which you don't know when, if ever, it will come back.
The better thing to do here would be something like:
HTTPPostData PostData = new HTTPPostData("id");
PostData.execute();
txtLabel.setText("Loading...");
and then in the asynctask:
protected void onPostExecute(String result) {
txtLabel.setText(result);
}
This lets your main thread get on with doing it's business without knowing the result of the asynctask, and then as soon as the data is available the asynctask will populate the text label with the result.
I am having difficulties understanding AsyncTask, even after reading everything about it on Developer.Android. I am looking for some insight in how I should proceed. This is the situation :
I have an Activity which, on an onClick event calls the LoginCheck() method of an underlying LoginController class. The LoginController class then proceeds to fetch whatever information is nescesarry from a UserInfo class or from the Activity(User and Password) and creates an instance of a RestClient which then makes the call to the web service and attempts to log in. RestClient has a private class CallServiceTask that extends AsyncTask.
I have a few design problems here that I hope you can be of assistance with.
Am I doing it right? Is this a proper way to make sure that any calls to the web service are being done asynchronously?
How do use onProgressUpdate or whatever to notify the user that the application is in the process of logging in?
How would I go about getting the data that is saved in DoinBackground() ?
Below you'll find snippets of the project in question :
RestClient
// From the constructor...
rtnData = new Object[]{ new JSONObject() , Boolean.TRUE };
public void ExecuteCall(RequestMethod method) throws Exception
{
Object[] parameters = new Object[]{ new HttpGet() , new String("") };
switch(method) {
case GET:
{
//add parameters
String combinedParams = "";
if(!params.isEmpty()){
combinedParams += "?";
for(NameValuePair p : params)
{
String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue());
if(combinedParams.length() > 1)
{
combinedParams += "&" + paramString;
}
else
{
combinedParams += paramString;
}
}
}
HttpGet request = new HttpGet(url + combinedParams);
//add headers
for(NameValuePair h : headers)
{
request.addHeader(h.getName(), h.getValue());
}
parameters[0] = request;
parameters[1] = url;
new CallServiceTask().execute(request, url);
jsonData = ((JSONObject) rtnData[0]).optJSONObject("data");
connError = (Boolean) rtnData[1];
break;
}
case POST: ....
}
}
private Object[] executeRequest(HttpUriRequest request, String url)
{
HttpClient client = new DefaultHttpClient();
client = getNewHttpClient();
HttpResponse httpResponse;
try {
httpResponse = client.execute(request);
HttpEntity entity = httpResponse.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
String response = convertStreamToString(instream);
try {
rtnData[0] = new JSONObject(response);
rtnData[1] = false;
} catch (JSONException e1) {
rtnData[1] = true;
e1.printStackTrace();
}
// Closing the input stream will trigger connection release
instream.close();
}
} catch (ClientProtocolException e) {
client.getConnectionManager().shutdown();
e.printStackTrace();
} catch (IOException e) {
client.getConnectionManager().shutdown();
e.printStackTrace();
}
return rtnData;
}
CallServiceTask
private class CallServiceTask extends AsyncTask<Object, Void, Object[]>
{
protected Object[] doInBackground(Object... params)
{
HttpUriRequest req = (HttpUriRequest) params[0];
String url = (String) params[1];
return executeRequest(req, url);
}
#Override
protected void onPostExecute(Object[] result)
{
rtnData = result;
}
}
It's absolutely right that any possibly long running operations should be executed in separate threads. And the AsyncTask is a good way to solve this kind of problems, since it also gives you an easy way to synchronize your task with the UI thread. This is the answer to your first question.
Now, concerning the UI thread updating to show your users that your application is not stuck. Since an AsyncTask's onPreExecute() and onPostExecute() methods are running inside the UI thread, you can easily create, run and stop ProgressDialogs or ProgressBars there. If you want to show the current progress of the task, you should call publishProgress(int) method inside the doInBackground(), and then make use of it inside the AsyncTask's onProgressUpdate() method. There you can, for example, update your ProgressDialog.
And to get the result out of your AsyncTask you can either call its get() method (this a synchronous call), or implement some kind of callback interface that will tell the activity that the task has finished.
I hope the answer is clear enough, if no - feel free to ask more questions. Hope this helps.
EDIT
Create an interface called, for example, onFetchFinishedListener with one method - void onFetchFinished(String). Your activity, that starts the AsyncTask, must implement this interface. Now create a constructor inside your AsyncTask that takes an OnFetchFinishedListener object as an argument, and when instantiating the AsyncTask inside your activity send a reference to the Activity as the argument (since it implements OnFetchFinishedListener). Then when your task is finished inside doInBackground() call onFetchFinished() on the activity. Now inside the onFetchFinished(String) method of your Activity you can make use of the String (or another object) that's brought with the callback. Again, hope I was clear enough.