I'm having trouble finding an error, that I obviously should have somewhere. Probably a logic error that I'm not aware of.
I'm having a button, which starts a locationManager locating my position, upon click. While scanning for my location, I want my button to be disabled. I managed to do that (Yay), though after retrieving the location for the first time and clicking the button for the second time, to receive the location for a second time, the button does NOT get disabled anymore. This enables me to tap the button multiple times, starting more and more locationListeners listening for locations. That is just what I tried to prevent by disabling the button while scanning.
Here's my code. Explanation follows.
MainActivity:
public class MainActivity extends FragmentActivity {
// Setting layout dependent variables
...
private Button btn_scan;
// Setting several variables
...
// Setting default values
...
private boolean locationReceived = false;
private boolean gsmReceived = false;
private boolean isBusy = false;
private int counter = 0;
private Handler handler;
private Runnable runnable = new Runnable() {
public void run() {
counter ++;
handler.postDelayed(runnable, 1000);
if (locationReceived && gsmReceived) {
// SAVE DATA TO DB HERE! //
displayInformation();
handler.removeCallbacks(runnable);
} else if (counter >= (TIME_TO_WAIT_FOR_RESPONSE+1)) {
displayInformation();
handler.removeCallbacks(runnable);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Application context
context = getApplicationContext();
// Handler
handler = new Handler();
// initializing layout dependent variables
...
btn_scan = (Button) findViewById(R.id.btn_scan);
// Initialize GoogleMap
...
// Get the LocationManager for checking, if providers are enabled
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
// Get the PhoneStateListener and telephony service to receive the signal strength
myListener = new MyPhoneStateListener();
tel = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
// Ask for the current location in here.
locationResult = new LocationResult() {
@Override
public void gotLocation(final Location location) {
// If location given, do something with it. If not, return some message.
if (location != null) {
updateGeoData(location);
}
}
};
btn_scan.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
if (!isBusy) {
toogleButton();
// if GPS is enabled in phone settings
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
postGPSAlert();
toogleButton();
} else {
// If GPS enabled, get info
getInformation();
}
}
}
});
}
/*
* wrapper method for getting informations
*/
private void getInformation() {
// start informationfetcher.
runnable.run();
// get geo location, longitude & latitude
getGeoLocation();
// get signal strength and its' other parameters
getSignalStrength();
// get internet connectivity quality string
getConnectivityQuality();
// get internet connectivity type
getConnectivityType();
}
/*
* get signal strength. only starts the listener, which does the rest of the job.
*/
public void getSignalStrength() {
tel.listen(myListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
/*
* get connectivity type and update the variable internetType
*/
private void getConnectivityType() {
... nothing important
}
/*
* Gets internet quality string
*/
private void getConnectivityQuality() {
... nothing important
}
/*
* Gets the geo location
*/
public void getGeoLocation() {
MyLocation myLocation = new MyLocation(context, TIME_TO_WAIT_FOR_RESPONSE);
if (!myLocation.getLocation(locationResult)) {
String message = "To make use of localization, please enable GPS or mobile networking.";
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
}
/*
* Updates retrieved GeoData
*/
private void updateGeoData(Location location) {
latitude = location.getLatitude();
longitude = location.getLongitude();
locationReceived = true;
}
/*
* Updates GUI with all received values
*/
private void displayInformation() {
... only updating textViews here
if (gsmReceived) {
... only updating textViews here
}
if (locationReceived) {
... only updating textViews here and moving googleMapCamera to some spot
}
// Post Error messages, if location and/or GSM could not be obtained.
... just Toasting some error messages, if no signal or GPS received.
toogleButton();
}
/*
* Posts an alert saying u gotta enable GPS
*/
private void postGPSAlert() {
// Prompt alert
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
// Title and message values
alert.setTitle(getString(R.string.prompt_titleProviderFail));
alert.setMessage(getString(R.string.prompt_messageProviderFail));
// If OK was clicked, redirect to settings to enable GPS
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
});
// If ABORT was clicked, redirect back to activity
alert.setNegativeButton("Abort", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
// Show dialog
alert.show();
}
/*
* Method for disabling and enabling the button on pressure/update
*/
private void toogleButton() {
if (btn_scan.isEnabled()) {
isBusy = true;
btn_scan.setText("SCANNING ...");
btn_scan.setEnabled(false);
} else if (!btn_scan.isEnabled()) {
isBusy = false;
btn_scan.setText("SCAN");
btn_scan.setEnabled(true);
}
}
/*
* (non-Javadoc)
* Listener, to listen on signalStrength of your phone. It'll set all the variables declared above and update the info you'll see.
*/
private class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
... just updating some String variables here
gsmReceived = true;
tel.listen(myListener, PhoneStateListener.LISTEN_NONE);
}
}
}
Now to the explanation: As soon as I click the button, I'm checking if I'm already having an operation running and I'm disabling the button via the method toogleButton(). So, several methods are triggered to gather some information about the network, signalStrength and my location. Gathering my location usually requires most time, but that's not important. I'm using a handler+runnable to check every second for 60 seconds, if all informations were gathered. If so, I'm displaying all information via displayInformation() on the UserInterface and enabling the button again via toogleButton(). Also, I'm setting the variable isBusy = true. If I did not gather all information and 60 seconds passed, I'm still displaying all (till then) gathered information and toogle the button again (to the enabled state).
All of this works fine, for the first time. When I push the button for the second time AFTER I received all information, the button does not get disabled anymore, though the app still gathers information as it should. The only problem here is that I can now push the button multiple times and start multiple requests to gather the information. That is not what I want. I want it one by one.
Do you know what I did wrong here?
Use Asynctask thread - disable button in onPreExecute , write location search code inside doInBackground() & enable button inside onPostExecude.