I'm trying to add an AsyncTask to the following class but I'm not sure where to start. I would like to encapsulate the entire class if possible. I'm new to Android and Java so I really have no idea about what I'm doing. The following class works, and I can send all the information to my database properly. Each time the user's location is updated, the program first checks a table in the database for the user ID; if it does not exist in the table the GPS coordinates are sent, but if the user ID is in the table, the coordinates are not sent and the program stops sending location updates. This works like it should, but it locks up my UI and throws an ANR error when attempting to interact. I know that I need to implement an AsyncTask, but I need some guidance. Below is the complete code for the class. Any help would be great!
public class FindLocation {
protected static final Context SendLocation = null;
private LocationManager locManager;
private LocationListener locListener;
Context ctx;
public FindLocation(Context ctx) {
this.ctx = ctx;
}
public void startLocation(final Context context, String usr_id2) {
final String usr = usr_id2;
//get a reference to the LocationManager
locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//checked to receive updates from the position
locListener = new LocationListener() {
public void onLocationChanged(Location loc) {
String lat = String.valueOf(loc.getLatitude());
String lon = String.valueOf(loc.getLongitude());
JSONArray jArray;
String result = null;
InputStream is = null;
StringBuilder sb = null;
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("id", usr));
//http post
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.example.com/test/example.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
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() + "\n");
String line="0";
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}
catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
try{
jArray = new JSONArray(result);
JSONObject json_data=null;
for(int i=0;i<jArray.length();i++){
json_data = jArray.getJSONObject(i);
String ct_name = json_data.getString("phoneID");
if(ct_name == usr) {
locManager.removeUpdates(locListener);
}
}
}
catch(Exception e){
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://example.com/test/example.php");
try {
List<NameValuePair> nameValuePairs1 = new ArrayList<NameValuePair>(2);
nameValuePairs1.add(new BasicNameValuePair("lat", lat));
nameValuePairs1.add(new BasicNameValuePair("lon", lon));
nameValuePairs1.add(new BasicNameValuePair("id", usr));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs1));
httpclient.execute(httppost);
}
catch (ClientProtocolException g) {
// TODO Auto-generated catch block
} catch (IOException f) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void onProviderDisabled(String provider){
}
public void onProviderEnabled(String provider){
}
public void onStatusChanged(String provider, int status, Bundle extras){
}
};
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 6000, 0, locListener);
}
}
All you should have to do is:
modify FindLocation class by extending asynctask
change startLocation for an override of doInBackground.
Then call the execute method of your asynctask instead of startLocation.
Also, in your case, an asynctask may not be the best. Usually you use an asynctask because you want to do something in the background and then, when the task is done, update some ui components with the result of the background operation. Here, as you just want something in the background but no UI update, you could be better using a normal thread :
make you class extend thread
change startLocation for an override of run
start your thread instead of calling startLocation
--Update with details --
This could be simpler but the idea to get more familiar with asyncTask ia a good one too.
public class LocationFinder extends Thread {
public LocationFinder( Context ctx ) {
this.ctx = ctx;
}
public void start( String userId ) {
this.userId = userId;
super.start();
}
//defensive programming : prevent your thread from beeing started in an undesired way
#Override
public void start() {
throw new IllegalStateException( "LocationFinder can't be started using start(). Prefer start( int )." );
}
public void run() {
//remaining of the code of startLocation except the first line.
}
}
to use your thread then do in an activity :
new LocationFinder( this ).start( userId );
private class BackgroundLoader extends AsyncTask<Void, Void, Void> {
private ProgressDialog dialog;
protected Long doInBackground() {
dialog = new ProgressDialog(ctx);
dialog.show();
}
protected void doInBackground() {
// do all your stuff here that doesn't modify the UI
}
protected void onPostExecute(Long result) {
// do what you need to to the UI
dialog.dismiss();
}
Then to create an instance call new BackgroundLoader().execute(); in your onCreate() method
Related
I am trying to get the response code for the HttpReponse.
I have changed the method for getting the response but it is not working.
Before I used this try & catch:
(url is parameter for function)
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost method = new HttpPost(url);
if (params != null) {
method.setEntity(new UrlEncodedFormEntity(params));
}
HttpResponse response = httpclient .execute(method);
InputStream inputStream = response.getEntity().getContent();
String result = convertInputStreamToString(inputStream);
return result;
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
But this code gave me a runtime error in HttpResponse response = httpclient .execute(method);
So I changed my code:
public class RegisterActivity extends Activity {
String username;
String password;
InputStream is = null;
String result = null;
String line = null;
int code;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.register);
final EditText usernamefield = (EditText) findViewById(R.id.username_reg);
final EditText passwordfield = (EditText) findViewById(R.id.password_reg);
Button reg_btn = (Button) findViewById(R.id.reg_btn);
reg_btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
username = usernamefield.getText().toString();
password = passwordfield.getText().toString();
insert();
ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("username", usernamefield.getText().toString()));
params.add(new BasicNameValuePair("password", passwordfield.getText().toString()));
params.add(new BasicNameValuePair("action", "insert"));
}
});
}
public void insert()
{
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("username", username));
nameValuePairs.add(new BasicNameValuePair("password", password));
nameValuePairs.add(new BasicNameValuePair("action", "insert"));
try
{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.1.10/ferdos/service.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
Log.e("pass 1", "connection success ");
}
catch (Exception e)
{
Log.e("Fail 1", e.toString());
Toast.makeText(getApplicationContext(), "Invalid IP Address",
Toast.LENGTH_LONG).show();
}
try
{
BufferedReader reader = new BufferedReader
(new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
is.close();
result = sb.toString();
Log.e("pass 2", "connection success ");
}
catch (Exception e)
{
Log.e("Fail 2", e.toString());
}
try
{
JSONObject json_data = new JSONObject(result);
code = (json_data.getInt("code"));
if (code == 1)
{
Toast.makeText(getBaseContext(), "Inserted Successfully",
Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(getBaseContext(), "Sorry, Try Again",
Toast.LENGTH_LONG).show();
}
}
catch (Exception e)
{
Log.e("Fail 3", e.toString());
}
}}
Please help me with this code to solve my problem.
Thats what Google says.
To avoid creating an unresponsive UI, don't perform network operations on the UI thread. By default, Android 3.0 (API level 11) and higher requires you to perform network operations on a thread other than the main UI thread; if you don't, a NetworkOnMainThreadException is thrown.
You need to execute your HTTP requests in separate thread. This can be done in a AsyncTask.
In your case you need to update UI after the downloading is finished. Use a listener to notify the UI thread
public interface ResultsListener {
public void onResultsSucceeded(String result);
}
This is an example from Google developers guide. I edited it and it calls the listener when the result is finished.
private class HttpRequestTask extends AsyncTask<URL, Integer, String> {
public void setOnResultsListener(ResultsListener listener) {
this.listener = listener;
}
protected String doInBackground(URL... urls) {
int count = urls.length;
for (int i = 0; i < count; i++) {
String httpResult = // Do your HTTP requests here
// Escape early if cancel() is called
if (isCancelled()) break;
}
return httpResult;
}
// use this method if you need to show the progress (eg. in a progress bar in your UI)
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
// this method is called after the download finished.
protected void onPostExecute(String result) {
showDialog("Downloaded " + result);
listener.onResultsSucceded(result);
}
}
Now you can execute the task by calling new HttpRequestTask().execute(url) in your Activity. Your activity needs to implement the ResultsListener. Inside the onResultsSucceeded method you can update your UI elements.
You see, you can use the AsyncTask in your example pretty well. You just need some reformatting of your code.
I use AsyncTask but dont working again
please check my code
public class RegisterActivity extends Activity {
EditText editusername;
EditText editpassword;
String username;
String password;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.register);
editusername = (EditText) findViewById(R.id.username_reg);
editpassword = (EditText) findViewById(R.id.password_reg);
Button reg_btn = (Button) findViewById(R.id.reg_btn);
reg_btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
username = editusername.getText().toString();
password = editpassword.getText().toString();
new RegisterAsyncTask().execute();
}
});
}
class RegisterAsyncTask extends AsyncTask<Void, Void, Boolean> {
private void postData(String username, String password) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("myurl");
try {
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
nameValuePairs.add(new BasicNameValuePair("username", username));
nameValuePairs.add(new BasicNameValuePair("password", password));
nameValuePairs.add(new BasicNameValuePair("action", "insert"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
}
catch (Exception e)
{
Log.e("log_tag", "Error: " + e.toString());
}
}
#Override
protected Boolean doInBackground(Void... params) {
postData(username, password);
return null;
}
}}
I am having trouble with my code where i have my Activity which i use to call google api's and retrieve jsons, deserialize them and use it's Polylines to draw on the map.
The problem is that getMapAsync() which sends the callback for onMapReady() (which is used to create the map) is executed immediately after executing my Async Tasks which retrieves necessary data to create the map.
How can i make this happen without stopping the UI thread? I tried doing this calling .execute.get() which freeze the UI thread. But if i do that, i won't be able to use ProgressDialog to inform the users about the delay for fetching data from the servers, which they will be exposed to a frozen UI until the task is complete. How can i do this?
public class RouteAssistantActivity extends Activity implements OnMapReadyCallback{
public GoogleMapsDirectionsResponse dirRes;
public GoogleMapsDistanceResponse disRes;
public String jsonString;
private String mapsAPIKey;
private String directionsBaseURL;
private String distanceBaseURL;
MapFragment mapFragment;
private ProgressDialog progress;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ra_route_assisstant);
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.ra_map);
progress = new ProgressDialog(RouteAssistantActivity.this);
progress.setTitle("Please Wait");
progress.setMessage("Retrieving Data from the Server");
progress.setIndeterminate(true);
try {
ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
if (appInfo.metaData != null) {
mapsAPIKey = appInfo.metaData.getString("com.google.android.maps.v2.API_KEY");
directionsBaseURL = appInfo.metaData.getString("com.google.android.maps.directions.baseURL");
distanceBaseURL = appInfo.metaData.getString("com.google.android.maps.distance.baseURL");
}
} catch (PackageManager.NameNotFoundException e) {
Log.e("Meta Error", "Meta Data not found. Please check the Manifest and the Meta Data Package Names");
e.printStackTrace();
}
//Test
String directionsURL = directionsBaseURL+"origin=6.948109,79.858191&destination=6.910176,79.894347&key="+mapsAPIKey;
String distanceURL = distanceBaseURL+"units=metric&origins=6.948109,79.858191&destinations=6.910176,79.894347&key="+mapsAPIKey;
Log.e("CA Debug","URL : " + directionsURL);
Log.e("CA Debug","URL : " + distanceURL);
new configurationSyncTask().execute(distanceURL,"distance");
new configurationSyncTask().execute(directionsURL, "direction");
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
LatLng rajagiriya = new LatLng(6.910176, 79.894347);
String points = dirRes.getRoutes().get(0).getOverviewPolyline();
List<LatLng> list = PolyUtil.decode(points);
googleMap.setMyLocationEnabled(true);
googleMap.getUiSettings().setRotateGesturesEnabled(true);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(rajagiriya, 13));
googleMap.addMarker(new MarkerOptions()
.title("Rajagiriya")
.snippet("My Place")
.position(rajagiriya));
googleMap.addPolyline(new PolylineOptions()
.geodesic(false)
.addAll(list)
.color(Color.RED)
.width(25));
}
private class configurationSyncTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
progress.show();
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
String type = params[1];
Log.d("CA Debug", getClass().getSimpleName() + " --> Real URL : " + url);
Log.d("CA Debug", getClass().getSimpleName() + " --> doInBackground requesting content");
jsonString = requestContent(url);
// if the output is null, stop the current task
if (jsonString == null) {
Log.d("CA Debug", getClass().getSimpleName() + " --> Stopping Async Task");
this.cancel(true);
Log.d("CA Debug", getClass().getSimpleName() + " --> Async Task Stopped");
}
return type;
}
#Override
protected void onPostExecute(String types) {
if (types.equalsIgnoreCase("distance")) {
disRes = GMapsDistanceResponseJSONDeserializer.deserialize(jsonString);
} if (types.equalsIgnoreCase("directions")) {
dirRes = GMapsDirectionsResponseJSONDeserializer.deserialize(jsonString);
}
progress.dismiss();
}
}
public String requestContent(String url) {
Log.d("CA Debug",getClass().getSimpleName()+" --> URL : "+url);
try {
URL urlObj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) urlObj.openConnection();
con.setChunkedStreamingMode(0);
con.setRequestMethod("GET");
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null,null, new SecureRandom());
con.setSSLSocketFactory(sc.getSocketFactory());
InputStream clientResponse;
String jsonString;
int status = con.getResponseCode();
if(status >= HttpURLConnection.HTTP_BAD_REQUEST){
Log.d("CA Debug", getClass().getSimpleName()+" --> Bad Request");
jsonString = null;
} else {
Log.d("CA Debug", getClass().getSimpleName()+" --> converting Stream To String");
clientResponse = con.getInputStream();
jsonString = convertStreamToString(clientResponse);
}
Log.d("CA Debug", getClass().getSimpleName()+" --> JSON STRING : " + jsonString);
return jsonString;
} catch (IOException | NoSuchAlgorithmException | KeyManagementException e) {
Log.d("CA Debug", getClass().getSimpleName()+" --> Error when creating an Input Stream");
e.printStackTrace();
}
return null;
}
public String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
} finally {
try {
is.close();
} catch (IOException e) {
}
}
return sb.toString();
}
}
Quick and somewhat dirty solution would be to execute both AsyncTasks on a single AsyncTask and then on its onPostExecute code invoke getMapAsync. this way you will be sure your tasks finished before you dealing with map's readyness.
Firstly, run tasks after onMapReady because you will get rid of
concern of ready map.
Your async tasks are not parallel, they working on background but second one will be executed after first one completed, check this link
Move some parts of onMapReady to onPostExecute, something like below
Move
#Override
protected void onPostExecute(String types) {
if (types.equalsIgnoreCase("distance")) {
disRes = GMapsDistanceResponseJSONDeserializer.deserialize(jsonString);
}if (types.equalsIgnoreCase("directions")) {
dirRes = GMapsDirectionsResponseJSONDeserializer.deserialize(jsonString);
String points = dirRes.getRoutes().get(0).getOverviewPolyline();
List<LatLng> list = PolyUtil.decode(points);
googleMap.addPolyline(new PolylineOptions()
.geodesic(false)
.addAll(list)
.color(Color.RED)
.width(25)
);
}
}
AsyncTask.SERIAL_EXECUTOR is used to force AsyncTask to execute in Serial Fashion.
More over for your case a little trick will do the job.
Create call back for same AsyncTask and pass different parameters to differentiate the functions.
Now in the second call back initiate mapFragment.getMapAsync(this);
public class MainFragment ...
{
DataDownloader dataDownloader;
int processCount=1;
void initiateProcessFirst(){
new DataDownloader(this,processCount ).execute();
}
public void initiateSecondProcess(){
processCount++;
new DataDownloader(this,processCount ).execute();
}
public void secondProcessCompleted(){
mapFragment.getMapAsync(this);
}
}
AsyncTask Logic goes like the below
public class DataDownloader extends AsyncTask<Void,Void,Boolean> {
MainFragment context;
int processCount;
public DataDownloader(MainFragment context ,int processCount){
this.context=context;
this.processCount=processCount;
}
#Override
protected Boolean doInBackground(Void... params) {
boolean status=false;
// Do logic according to the Process Count
return status;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if(processCount==1)
context.initiateSecondProcess();
else
context.secondProcessCompleted();
}
}
I have to hit a service and if the response came true than I have to verify the user & save the user entered variables in shared preference. my url is: http://a.nextput.com/apps/init/4/a/9fe2d2cbaa8332a4633be17b79208181-2y-10-ELVM4HwkaYaCVu6203Zjfus-G/o?aff_id and the response it is giving is {"success":true}. For this I have made a class and declared a static method. Inside the static method I have to do parsing.
my class:
public class InitializeSDK {
/*String json = "";
URL url;
HttpURLConnection connection = null;*/
public static void init(final Context ctx, int offerwall_id, String offerwall_public_key) {
new AsyncTask<Void, Void, Void>() {
protected void onPreExecute() {
super.onPreExecute();
}
protected Void doInBackground(Void... arg0) {
//TODO: add code to read http request and store the json data in json variable
String json = "";
//URL url;
HttpURLConnection connection = null;
InputStream is = null;
final String MyPREFERENCES = "MyPrefs" ;
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://a.nextput.com/apps/init/4/a/9fe2d2cbaa8332a4633be17b79208181-2y-10-ELVM4HwkaYaCVu6203Zjfus-G/o?aff_id");//YOUR URL
HttpResponse httpResponse = httpClient.execute(httpPost);
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, "iso-8859-1"), 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 {
JSONObject jObj = new JSONObject(json);
boolean isSuccess = jObj.getBoolean("success");
System.out.println("success : " + isSuccess);
// SharedPreferences sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
/*SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(Context ctx);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("isSuccess",isSuccess);
editor.commit();*/
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
/* JSONObject jsonObject = new JSONObject(json);
boolean state = jsonObject.getBoolean("success");*/
return null;
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}.execute();
}
my MainActivity is:
public class MainActivity extends AppCompatActivity {
final Context context = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
}
How to save the variables in sharedpreference and connect the class with MainActivity? Please help
Do the below changes.
Step1: Change Return type Void to Boolean
new AsyncTask<Void, Void, Boolean>() {}
Step2: In doInBackground return "isSuccess"
Step3: Change the onPostExecute() below
protected void onPostExecute(boolean result) {
super.onPostExecute(result);
if(result){
PreferenceManager.getDefaultSharedPreferences(this)
.edit()
.putInt"offerwall_id", offerwall_id)
.putString("offerwall_public_key",offerwall_public_key)
.apply();
}
}
Step4: Call from MainActivity
public class MainActivity extends AppCompatActivity {
final Context context = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InitializeSDK.init(this,val1,val2);
}
}
}
Make InitializeSDK class extend AsyncTask
like
public class InitializeSDK extends AsyncTask<Void, Integer, String> {
Context ctx;
int offerwall_id;
String offerwall_public_key;
public InitializeSDK (Context ctx, int offerwall_id, String offerwall_public_key){
this.ctx = ctx;
this.offerwall_id = offerwall_id;
this.offerwall_public_key = offerwall_public_key;
}
//rest of the asynctask code
}
and in your MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int id = //your id;
String offerwall_public_key = //your key;
new IntializeSDK(this,id,offerwall_public_key).execute();
}
Your shared preference code is correct, use it in OnPostExecute
Semi-noob with Java here.
I am trying to set a TextView inside my doInBackground() inside of my Async task. According to my research, I can not modify the main thread doing this so messing around with TextViews is out of the question here. So what I would like to do instead is use a string. I need this string to be accessible in the main class.
How can I do this?
I tried String loginresult = "Login Successful! Please Wait..."; but I am not able to access that string anywhere. I tried marking it as public but that is an illegal modifier inside a doInBackground().
Maybe strings is not the best way to go about doing this, if so, what would all you geniuses out there suggest?
Here is my async code, I put arrows in the areas I am having an issue. Any help would be appreciated for this noob :)
class PostTask extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("username", username));
nameValuePairs.add(new BasicNameValuePair("password", password));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
Log.w("SENCIDE", "Execute HTTP Post Request");
//Executes link, login.php returns true if username and password match in db
HttpResponse response = httpclient.execute(httppost);
String str = inputStreamToString(response.getEntity().getContent()).toString();
Log.w("SENCIDE", str);
if(str.toString().equalsIgnoreCase("true"))
{
Log.w("SENCIDE", "TRUE");
-----> result.setText("Login Successful! Please Wait...");
}else
{
Log.w("SENCIDE", "FALSE");
------> result.setText(str);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// Dummy code
for (int i = 0; i <= 100; i += 5) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
}
return "All Done!";
}//end doinbackground
StringBuilder inputStreamToString(InputStream is) {
String line = "";
StringBuilder total = new StringBuilder();
// Wrap a BufferedReader around the InputStream
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
// Read response until the end
try {
while ((line = rd.readLine()) != null) {
total.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
// Return full string
return total;
}//end StringBuilder
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// turns the text in the textview "Tbl_result" into a text string called "tblresult"
TextView tblresult = (TextView) findViewById(R.id.tbl_result);
// If "tblresult" text string matches the string "Login Successful! Please Wait..." exactly, it will switch to next activity
if (tblresult.getText().toString().equals("Login Successful! Please Wait...")) {
Intent intent = new Intent(NewAndroidLogin.this, Homepage.class);
//take text in the username/password text boxes and put them into an extra and push to next activity
EditText uname2 = (EditText)findViewById(R.id.txt_username);
String username2 = uname2.getText().toString();
EditText pword2 = (EditText)findViewById(R.id.txt_password);
String password2 = pword2.getText().toString();
intent.putExtra("username2", username2 + "&pword=" + password2);
startActivity(intent);
}
}//end onPostExecute
}//end async task
Change your AsyncTask to use String as progress parameter type:
AsyncTask<String, String, String>
Change onProgressUpdate() to update progress
#Override
protected void onProgressUpdate(String... values) {
result.setText(values[0]);
}
And then report the progress:
if(str.toString().equalsIgnoreCase("true"))
{
Log.w("SENCIDE", "TRUE");
publishProgress("Login Successful! Please Wait...");
}else
{
Log.w("SENCIDE", "FALSE");
publishProgress(str);
}
Make String loginresult = "Login Successful! Please Wait..."; as global and
runOnUiThread(new Runnable() {
#Override
public void run() {
str = inputStreamToString(response.getEntity().getContent()).toString();
if(str.toString().equalsIgnoreCase("true"))
{
Log.w("SENCIDE", "TRUE");
result.setText("Login Successful! Please Wait...");
}
else
{
Log.w("SENCIDE", "FALSE");
result.setText(str);
}
}
} );
Declare Handler at class level:
Handler handler;
Initialize Handler in onCreate() method of Activity:
// Doing this inside the onCreate() method of Activity
// will help the handler to hold the reference to this Activity.
handler = new Handler();
Call it within the background thread:
#Override
protected String doInBackground(String... params) {
handler.post(new Runnable(){
public void run(){
// SET UI COMPONENTS FROM HERE.
}
});
}
I have a thread that sends GPS coordinates to a database every six seconds and I have a check that verifies that the user is within a defined area. If the user is not within the location, I want an alert dialog that notifies them that they are out of range, and if they are within the area I want a dialog that tells them they are within range. I have the checks working properly, but I have tried and I'm pretty sure that I can't add the dialog on the background thread. I have read a bit about using handlers but I'm not sure how to implement one. If you have any suggestions I would appreciate it! Thanks.
This is how I call FindLocation.java from my main activity (MainActivity.java):
new FindLocation(getBaseContext()).start(usr_id1); //sends a user id with it
Below is FindLocation.java
public class FindLocation extends Thread {
public boolean inJurisdiction;
public boolean AlertNotice = false;
private LocationManager locManager;
private LocationListener locListener;
Context ctx;
public String userId;
public FindLocation(Context ctx) {
this.ctx = ctx;
}
public void start(String userId) {
this.userId = userId;
super.start();
}
#Override
public void run() {
Looper.prepare();
final String usr = userId;
//get a reference to the LocationManager
locManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
//checked to receive updates from the position
locListener = new LocationListener() {
public void onLocationChanged(Location loc) {
String lat = String.valueOf(loc.getLatitude());
String lon = String.valueOf(loc.getLongitude());
Double latitude = loc.getLatitude();
Double longitude = loc.getLongitude();
if (latitude >= 39.15296 && longitude >= -86.547546 && latitude <= 39.184901 && longitude <= -86.504288 || inArea != false) {
Log.i("Test", "Yes");
inArea = true;
JSONArray jArray;
String result = null;
InputStream is = null;
StringBuilder sb = null;
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("id", usr));
//http post
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://www.example.com/test/example.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
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() + "\n");
String line="0";
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}
catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
try{
jArray = new JSONArray(result);
JSONObject json_data=null;
for(int i=0;i<jArray.length();i++){
json_data = jArray.getJSONObject(i);
String ct_name = json_data.getString("phoneID");
Log.i("User ID", ct_name);
if(ct_name == usr) {
locManager.removeUpdates(locListener);
}
else{
locManager.removeUpdates(locListener);
Log.i("User ID", "NONE");
}
}
}
catch(Exception e){
//Log.e("log_tag", "Error converting result "+e.toString());
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://example.com/test/example.php");
try {
List<NameValuePair> nameValuePairs1 = new ArrayList<NameValuePair>(2);
nameValuePairs1.add(new BasicNameValuePair("lat", lat));
nameValuePairs1.add(new BasicNameValuePair("lon", lon));
nameValuePairs1.add(new BasicNameValuePair("id", usr));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs1));
httpclient.execute(httppost);
Log.i("SendLocation", "Yes");
}
catch (ClientProtocolException g) {
// TODO Auto-generated catch block
} catch (IOException f) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
else {
Log.i("Test", "No");
inArea = false;
}
}
public void onProviderDisabled(String provider){
}
public void onProviderEnabled(String provider){
}
public void onStatusChanged(String provider, int status, Bundle extras){
}
};
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 6000, 0, locListener);
Looper.loop();
}
}
It is a little difficult to read the entire code, but I will show you how to display an AlertDialog from a background Thread:
Create a handler inside onCreate(), or onResume()... something that runs on the UI-Thread:
...onCreate(){
//...
mHandler=new Handler();
}
Then inside your Thread() just use:
mHandler.post(new Runnable() {
public void run(){
//Be sure to pass your Activity class, not the Thread
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
//... setup dialog and show
}
});
runOnUiThread(new Runnable() {
public void run() {
//your alert dialog here..
}
});
new Handler().post(new Runnable{
public void run(){
//create your AlertDialog here..
}
});
see more here