Async Task doInBackground Only Being Called Once - android

I am POST-ing the current location of my phone with the press of a button to a local webserver. The webserver receives the POSTs correctly.
However, for some reason, I can only send one location to the server, and after that the Async Task is only called once. EDIT: The Async Task is called, but the doInBackground method is not called. - then with each subsequent button press the task is not reached. I did read in the above link that it can only be called once, but I assume that's only once per object - and for some reason, this was all working just fine before I changed something and it's all screwed up.
I need to be able to send hundreds of these requests within the period of a few minutes from the phone, so any guidance here would be useful. Thanks!
package com.spencer.gps;
import android.app.Activity;
import android.content.Context;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity{
private TextView latituteField;
private TextView longitudeField;
private LocationManager locationManager;
private String provider;
LocationManager mlocManager = null;
LocationListener mlocListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 0, 0, mlocListener);
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
getAndSendLocation();
}
});
/*new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
getAndSendLocation();
}
});
}
}, 0, 1000);*/
}
public void getAndSendLocation() {
final TextView latitudeField = (TextView) findViewById(R.id.lat);
final TextView longitudeField = (TextView) findViewById(R.id.longit);
if (mlocManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
latitudeField.setText("Latitude: " + MyLocationListener.latitude + '\n');
longitudeField.setText("Longitude: " + MyLocationListener.longitude + '\n');
new doPost().execute(MyLocationListener.latitude, MyLocationListener.longitude);
} else {
latitudeField.setText("GPS is not turned on...");
longitudeField.setText("GPS is not turned on...");
}
}
public class doPost extends AsyncTask {
#Override
protected Object doInBackground(Object[] objects) {
double lat = (Double) objects[0];
double longit = (Double) objects[1];
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.1.110:3000/coord");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("lat", Double.toString(lat)));
nameValuePairs.add(new BasicNameValuePair("long", Double.toString(longit)));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
return null;
}
}
/* Request updates at startup */
#Override
protected void onResume() {
super.onResume();
}
/* Remove the locationlistener updates when Activity is paused */
#Override
protected void onPause() {
super.onPause();
}
}

AsyncTask.execute()
As per doc:
Note: this function schedules the task on a queue for a single background thread or pool of threads depending on the platform version. When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting HONEYCOMB, tasks are back to being executed on a single thread to avoid common application errors caused by parallel execution. If you truly want parallel execution, you can use the executeOnExecutor(Executor, Params...) version of this method with THREAD_POOL_EXECUTOR; however, see commentary there for warnings on its use.
So, you should call like this:
new doPost(). executeOnExecutor(AsyncTask. THREAD_POOL_EXECUTOR , MyLocationListener.latitude, MyLocationListener.longitude);
This would execute all threads in parallel, also keep an API 11 check on this method.
Hope that helps. :)

Related

Problem with dynamically updating text view

I have implemented the logs and they are being displayed on the screen. But even after creating the thread, the logs are not being dynamically updated on the screen. New logs should be appended after one second. While the user stays on the screen, the logs should keep displaying on the screen but it is not happening. The thread that I have created works fine as I have tested it with a count variable. But with logs, it does not seem to work.
Help me out, I am stuck here.
package com.example.logreader;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.text.method.ScrollingMovementMethod;
import android.widget.TextView;
public class MainActivity extends Activity {
private int mInterval = 100; // 5 seconds by default, can be changed later
private Handler mHandler;
int count;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView)findViewById(R.id.textView);
Thread t=new Thread(){
#Override
public void run(){
while(!isInterrupted()){
try {
Thread.sleep(1000); //1000ms = 1 sec
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Process process = Runtime.getRuntime().exec("logcat -d");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log=new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
log.append(line);
}
tv.setText(log.toString());
tv.setMovementMethod(new ScrollingMovementMethod());
} catch (IOException e) {
}
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
}
}
Use LiveData and observables it is very powerful and your life becomes easy

Activity closes on button press

I'm having a bit of trouble with a simple app I'm making.
I'll include the code:
import android.app.ProgressDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import java.net.URL;
public class login extends AppCompatActivity {
EditText user;
EditText pass;
boolean result_back;
private ProgressDialog pDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Button log = (Button) findViewById(R.id.btLogIn2);
log.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
login(v);
}
});
}
public void login(View v)
{
HttpClient client = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpResponse response = null;
user = (EditText) findViewById(R.id.eTUser);
String usuario = user.toString();
pass = (EditText) findViewById(R.id.eTPass);
String passw = pass.toString();
String parametros = "?usuario=" + usuario + "&password=" + passw;
HttpGet httpGet = new HttpGet("http://gie.byethost.com/acces.php" + parametros);
Toast toast2 = Toast.makeText(getApplicationContext(), "Enviando datos", Toast.LENGTH_SHORT);
toast2.show();
try
{
response = client.execute(httpGet, localContext);
toast2 = Toast.makeText(getApplicationContext(), response.toString(), Toast.LENGTH_SHORT);
toast2.show();
}
catch (Exception e)
{
}
// response.toString();
if (response.toString().equalsIgnoreCase("1"))
{
Toast toast1 = Toast.makeText(getApplicationContext(), "Login correcto", Toast.LENGTH_SHORT);
toast1.show();
} else
if (response.toString().equalsIgnoreCase("0"))
{
Toast toast1 = Toast.makeText(getApplicationContext(), "Error de login", Toast.LENGTH_SHORT);
toast1.show();
}
}
}
There's only one button here and neither toast is showing, so I don't see where the app is crashing. Also, I'm a bit new in Android programming, so this may have an obvious solution.
Any comments will be appreciated!
You're doing a network transaction on the main thread. Never do that (or any blocking behavior) on the main thread. Your app might be crashing with an error in logcat related to "StrictMode".
Instead, you need to put all your blocking work on another thread. Android has very specific patterns about how to do that. It's not like you would expect in a normal java app.
You might want to consider doing a search for "android asynchronous programming" and learn about things like AsyncTask, Loader, and Service. There are a lot of great tutorials out there on how to use them. Please don't use Thread directly, as that will only cause you pain.

android os network on main thread exception

i make this code in single application working, but if join with other application , show this dialog "android os network on main thread exception"
package com.kelompok2.bissmilahpulsa;
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;
public class coba extends Activity {
EditText nm,nmr;
RadioGroup prov,nom,pem;
TextView error;
Button ok;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mulaitransaksi);
nm=(EditText)findViewById(R.id.et_nama);
nmr=(EditText)findViewById(R.id.et_nomor);
prov=(RadioGroup)findViewById(R.id.provider);
nom=(RadioGroup)findViewById(R.id.nominal);
error=(TextView)findViewById(R.id.error);
pem=(RadioGroup)findViewById(R.id.pembayaran);
ok=(Button)findViewById(R.id.btn_ok);
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
String type=null;
String type1=null;
String type2=null;
switch (prov.getCheckedRadioButtonId())
{
case R.id.rb_as:
type="As";
break;
case R.id.rb_axis:
type="Axis";
break;
case R.id.rb_im3:
type="Im3";
break;
case R.id.rb_telkomsel:
type="Telokmsel";
break;
case R.id.rb_xl:
type="Xl";
break;
}
switch (nom.getCheckedRadioButtonId())
{
case R.id.rb_5:
type1="5";
break;
case R.id.rb_10:
type1="10";
break;
case R.id.rb_20:
type1="20";
break;
case R.id.rb_50:
type1="50";
break;
}
switch (pem.getCheckedRadioButtonId())
{
case R.id.rb_cash:
type2="Cash";
break;
case R.id.rb_hutang:
type2="Hutang";
break;
}
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("nama", nm.getText().toString()));
postParameters.add(new BasicNameValuePair("nomor", nmr.getText().toString()));
postParameters.add(new BasicNameValuePair("provider", type));
postParameters.add(new BasicNameValuePair("nominal", type1));
postParameters.add(new BasicNameValuePair("jenis_pembayaran", type2));
String response = null;
try {
response = CustomHttpClient.executeHttpPost("http://appmob.pusku.com/save.php", postParameters);
String res = response.toString();
res = res.trim();
res = res.replaceAll("\\s+","");
error.setText(res);
if (res.equals("1")) error.setText("Data Tersimpan");
else error.setText("Data Tersimpan Ke server");
}
catch (Exception e) {
error.setText(e.toString());
}
String nama1 = nm.getText().toString();
String nama2 = nmr.getText().toString();
String nama3 = type;
String nama4 = type1;
String nama5 = type2;
String sms = nama1+"#"+nama2+"#"+nama3+"#"+nama4+"#"+nama5;
Intent i = new Intent (Intent.ACTION_SENDTO,Uri.parse("sms:5556"));
i.putExtra("sms_body", sms);
startActivity(i);
nm.setText(null);
nmr.setText(null);
}
});
}
}
in permission i active that <uses-permission android:name="android.permission.INTERNET"/>
and still not working
You need to run internet activities on a thread separate from main (UI) thread, you can do that by wrapping your code in the following block:
new Thread() {
#Override
public void run() {
//your code here
}
}.start();
Execute your Network related operation in AsyncTask
You can also refer here Android AsyncTask
public class ExcuteNetworkOperation extends AsyncTask<Void, Void, String>{
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
/**
* show dialog
*/
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
/**
* Do network related stuff
* return string response.
*/
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
/**
* update ui thread and remove dialog
*/
super.onPostExecute(result);
}
}
first method
you can create an AsynTask .. Your code should run in background in order to be responsive.. otherwise it will show Not Responding ..
Second Method
You can create a seperate thread for it .. using multitasking.
Third
Right the code in the onCreate after setContentView
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
While all of the answers posted in this thread is correct, asynctasks are not really considering to be a good tool to user for network transactions anymore. The main reasons for this is that the asynctasks are very closely tied to activities so alot issues arise like..."what happens if the activity is destroyed before the network call returns?".
If you really want to implement android best practices (and not to mention impress your fellow Android devs) then why not perform a network task in a service?
I would suggest looking at the Path FOSS project android-prioriy-queue. They make it ridiculously easy to perform task in a service.

Force Close by using Async Task

I want to display a progressdialog when a client sends request to the server..the request should be done in background...but i am getting a force close when i use the AsyncTask..Please help ..Thank you
package com.example.client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
public static ProgressDialog Dialog;
String s1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// sendreq();
new SendUserTask().execute();
}
});
}
public String sendreq() {
try {
// TODO Auto-generated method stub
SocketAddress sockaddr = new InetSocketAddress("192.168.7.116",
9011);
Socket serversocket = new Socket();
serversocket.connect(sockaddr, 10000);
serversocket.setSoTimeout(10000);
DataOutputStream out = new DataOutputStream(
serversocket.getOutputStream());
out.flush();
DataInputStream in = new DataInputStream(
serversocket.getInputStream());
out.flush();
String msg = "";
msg = "hi";
out.writeBytes(msg);
out.flush();
byte[] message = new byte[100];
in.read(message);
s1 = new String(message);
Toast.makeText(getApplicationContext(), s1, Toast.LENGTH_LONG)
.show();
((TextView) findViewById(R.id.textView1)).setText(s1);
in.close();
out.close();
serversocket.close();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), String.valueOf(e),
Toast.LENGTH_LONG).show();
}
return null;
}
private class SendUserTask extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
Dialog = ProgressDialog.show(MainActivity.this, "",
"Logging In....", true);
super.onPreExecute();
}
protected void onPostExecute(String s) {
if (Dialog.isShowing())
Dialog.dismiss();
}
#Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
try {
return sendreq();
} catch (Exception e) {
Toast.makeText(getApplicationContext(), String.valueOf(e),
Toast.LENGTH_SHORT).show();
}
return null;
}
}
}
this ((TextView) findViewById(R.id.textView1)).setText(s1); is executed from the background thread. you cannot access UI elements outside the UI thread.
You need to move that part to either onProgressUpdate or onPostExecute, or to run it in a runOnUiThread Runnable.
doInBackgorund() is a non-UI thread and you cannot access UI elements inside it. The code inside doInBackground() runs on a separate non-ui thread which does not have access to the UI elements defined in your layout. Also, since you are calling another Activity via intents, you should always keep in mind that an Activity runs on the UI thread and hence you should never start another Activity from inside a non-ui thread.
So, remove the code " ((TextView) findViewById(R.id.textView1)).setText(s1); " accessing the UI elements from inside of doInBackground() and instead put it inside onPostExecute(), which is a UI thread and is called after doInBackground() finishes the background processing.
Ok.... After googling a lot i finally came to understand that you cant access UI elements from main thread into a new non-UI thread....So you cant use elements like textview or even getApplicationContext mtd tht v use for toast in the dobackground mtd or even in anyother mts that the dobackground is calling....This also applies for the new Thread() using runnable..Thank you njzk2 for your help :)

How to kill a TimerTask created from an IntentService with a button

I'm making a Cloud Service that uses a standard HTTP get to get commands. I use a service (extending class IntentService as opposed to Service) to keep things in sync. I have the checking going on in a TimerTask firing off every 3 seconds. The problem is that when the user goes back to the activity to turn it off if they want, they press a toggle button. How do I tell the TimerTask (or the IntentService running a timer task) to stop and start it?
The service itself is getting destroyed after it handles the intent and creates the task, so would a Service be more appropriate for this than an IntentService? Even if thats the case, the question about stopping and starting the TimerTask remains.
Here's the code to the intentservice:
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.*;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.widget.*;
public class syncservice extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public syncservice() {
super("syncservice");
}
public static final String PREFS_NAME = "prefcs";
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String uid = intent.getExtras().get("uid").toString();
final String dvname = intent.getExtras().get("dvname").toString();
final long period = intent.getExtras().getLong("period");
final Context ctx = getApplicationContext();
final Toast toast = Toast.makeText(ctx,"An error occured with the service. It will automatically turn off.", 0);
final Handler handler = new Handler();
TimerTask timertask = new TimerTask () {
#Override
public void run() {
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
if (settings.getBoolean("doservice", false)) {
String command = netread("url here");
//TODO Parse command from Pulling
if (command.contains("<")) {
//TODO what to do if an error occurred (exceptions already caught
Runnable showerrormessage = new Runnable() {
public void run() {
toast.makeText(ctx,"new text",0);
toast.show();
}
};
handler.post(showerrormessage);
}
}
}
};
Timer timer = new Timer();
timer.schedule(timertask,0,period);
return super.onStartCommand(intent,flags,startId);
}
public void onDestroy() {
Toast.makeText(getApplicationContext(), "The Service has died", Toast.LENGTH_SHORT).show();
return;
}
#Override
protected void onHandleIntent(Intent intent) {
Toast.makeText(getApplicationContext(), "Intent Handled", 0).show();
}
public final String netread(String url) {
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
ResponseHandler<String> resHandler = new BasicResponseHandler();
String page = httpClient.execute(httpGet, resHandler);
return page;
} catch (ClientProtocolException e) {
//Toast.makeText(getApplicationContext(),"Client Protocol Exception! Try again.",0).show();
return "<";
} catch (IOException e) {
//Toast.makeText(getApplicationContext(),"IO Exception! Make sure you are connected to the internet and try again.", 0).show();
return "<";
}
}
}
Thanks a bunch for helping me out!
For what you're trying to do, Handler may be more useful. That link BTW shows also how to stop it from the UI.

Categories

Resources