I am new to JAVA and I have to create an app that plot a route between where I am (found by GPS) and some pre-specified destination. I followed online tutorials such as http://androidexample.com/GPS_Basic__-__Android_Example/index.php?view=article_discription&aid=68&aaid=93 to learn how to read my own location.
I want my app to act differently when the GPS is turned on and off. To read the GPS status I used an LocationManager object as line below:
boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
I can manually turn the GPS off in Genymortion emulator by right clicking the GPS tab. The picture below shows how I turned on the GPS.
However, my app always say either isGPSEnabled = true all the time or isGPSEnabled = false all the time even though I change the GPS status. Can anyone tells me what I am missing? I attached most of my code below if that helps.
public class MapDisplayActivity extends Activity implements LocationListener {
private MapDisplayFragment fragment;
private DrawerLayout sideDrawerMenu;
private ListView sideDrawerMenuList;
private LocationManager locationManager;
private boolean isGPSEnabled;
private final static String LOG_TAG = "MapDisplayActivity";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.side_drawer_menu);
// some codes come here...
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isGPSEnabled) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
5000, // 5 sec
10, this);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
#Override
public void onLocationChanged(Location location) {
if (isGPSEnabled) {
String str = "Latitude: " +
location.getLatitude()
+ "Longitude: " + location.getLongitude();
Toast.makeText(getBaseContext(), str, Toast.LENGTH_LONG).show();
}else{
gpsLatlon = null;
}
}
#Override
public void onProviderDisabled(String provider) {
Toast.makeText(getBaseContext(), "Gps turned off ", Toast.LENGTH_LONG).show();
}
#Override
public void onProviderEnabled(String provider) {
Toast.makeText(getBaseContext(), "Gps turned on ", Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
// ~~~~~~~~~~ to imeplement LocationListener ~~~~~~~~~~~~~~
private class SideDrawerClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
selectItem(position);
}
}
// some more methods definitions....
}
It looks like you just need to set the isGPSEnabled flag in the callbacks:
#Override
public void onProviderDisabled(String provider) {
if(provider.equals(LocationManager.GPS_PROVIDER)){
isGPSEnabled = false;
}
Toast.makeText(getBaseContext(), "Gps turned off ", Toast.LENGTH_LONG).show();
}
#Override
public void onProviderEnabled(String provider) {
if(provider.equals(LocationManager.GPS_PROVIDER)){
isGPSEnabled = true;
}
Toast.makeText(getBaseContext(), "Gps turned on ", Toast.LENGTH_LONG).show();
}
One thing to note is that these callbacks will only be called if you currently have the Activity registered as a location listener.
So, as you have it now, only the onProviderDisabled() callback will be called if the Activity starts with GPS on and then GPS is disabled with the Activity still running.
One way to go would be to register for NETWORK_PROVIDER callbacks when GPS is disabled.
That way you would still have a location listener registered, and you would get the onProviderEnabled() callback for GPS. At that point you could unregister for NETWORK callbacks and register for GPS callbacks.
Related
I think I know the issue for why when running my code the gps tracking only works on emulated devices. It has something to do with the location listener being inside the onCreate() function. I just don't know how I would be able to edit my existing code so Locationlistener still works when placed outside of the onCreate() function.
I want to test the code on a mobile device because the getSpeed() function does not work when emulating.
Here is the code that fetches the location:
private LocationListener listener;
private LocationManager location;
private Float speedStr;
private Boolean boolSpeed;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#SuppressLint("MissingPermission")
#Override
public void onCreate() { //Get coords and send to main activity. Also get speed.
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Intent i = new Intent("location update");
i.putExtra("coords",location.getLatitude());
i.putExtra("coords2",location.getLongitude());
sendBroadcast(i);
Toast.makeText(GPS_Service.this,"reading",Toast.LENGTH_SHORT).show();
speedStr = location.getSpeed();
boolSpeed = location.hasSpeed();
Log.i("speed",speedStr.toString());
Log.i("speed",boolSpeed.toString());
}
#Override
public void onProviderDisabled(String s) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
location = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
location.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,200,listener); //set min distance proper units
}
#SuppressLint("MissingPermission")
#Override
public void onDestroy() {
super.onDestroy();
if(location != null) {
location.removeUpdates(listener);
}
}
}
I recently began developing an app, and I've spent the last few days working on the GPS part to obtain the user's address.
The issue is that if I run the app in Android Studio Emulator and change the address on the map, it appears correctly on a Toast and in the String variable I created to store the address, as shown in the screenshot below, but if I build the APK and run it on a Smartphone, the Toast does not appear and the String variable remains empty.
Is there something in my code that I'm forgetting? I'll paste the code for someone to review below.
public class FragmentT1_Agora extends Fragment {
View view;
LocationManager locationManager;
String moradaAtual; // Current Address
private Button btEnviar;
public FragmentT1_Agora() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_t1_agora, container, false);
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 100);
}
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 3, mLocationListener);
return view;
}
private final LocationListener mLocationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Toast.makeText(getContext(), "" + location.getLatitude() + "," + location.getLongitude(), Toast.LENGTH_LONG).show();
try {
Geocoder geocoder = new Geocoder(getContext(), Locale.getDefault());
List<Address> moradas = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
moradaAtual = moradas.get(0).getAddressLine(0);
Toast.makeText(getContext(), "Morada: " + moradaAtual, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
}
I've left out the code that isn't related to the GPS.
Screenshot:
I have an issue, I need to get the latitude and longitude of one specific moment like taking a picture. I get the Double values, the problem is that they're always 0. I receive no exceptions, and the coordinates are uploaded successfully to Firebase Database, but when I check them in the JSON, they are always zero (I took like 20 pictures).
This is my sections code of "location" stuffs and the uploading to Firebase Database.
My Main Activity is like this.
public class MainActivity extends AppCompatActivity implements LocationListener
Global variables related to Location
double latitude;
double longitude;
This goes inside onCreate():
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
String networkProvider = LocationManager.NETWORK_PROVIDER;
String gpsProvider = LocationManager.GPS_PROVIDER;
final Location location= new Location(networkProvider);
onLocationChanged(location);{
latitude=location.getLatitude();
longitude=location.getLongitude();
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
locationManager.requestLocationUpdates(gpsProvider, 5000, 10, this);
This goes in a button onClickListener(), also inside onCreate() method.
//Insert coordinates to JSON Firebase database...
Coordinates coordinates = new Coordinates();
coordinates.setLatitude(location.getLatitude());
coordinates.setLongitude(location.getLongitude());
testReference.push().setValue(coordinates);
Toast.makeText(MainActivity.this, "Coordinates uploaded!", Toast.LENGTH_LONG).show();
Also I have these methods inside MainActivity:
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
Try this:
locationManager = (LocationManager) getApplicationContext()
.getSystemService(Context.LOCATION_SERVICE);
Criteria locationCritera = new Criteria();
String providerName = locationManager.getBestProvider(locationCritera,
true);
if(providerName!=null)
location = locationManager.getLastKnownLocation(providerName);
locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, locationListener);
and Implement Your Location Listener class:
private class MyLocationListener implements LocationListener {
public void onLocationChanged(Location loc) {
if (loc != null) {
location = loc;
latitude=location.getLatitude();
longitude=location.getLongitude();
}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
check null value for getLastKnownLocation() method..
I am currently making an application where I need to get the user's location when a button is clicked. I am using this sample and it works great as a sample application. My question is, how would I implement it into my application button's onClick event? I don't need it to refresh often, I just need it so that when the user clicks the button, it gets the user's latitude and longitude and saves them to two variables. What would be the best way to do this? I didn't post my own code because all I have is a button with an onClick event.
Follow these steps to get the location on button click:
Implement LocationListener in your activity like:
public class MainActivity Extends AppCompactActivity implements LocationListener
Then create an Instance For LocationManager, longitude, and latitude as below:
LocationManager locationManager; // create global outside all methods
Double currentLattitude, currentLongitude;
Set click event on your button as below:
btnLocation.setOnClickListner( new View.onClickListner
{
#Override
public void onClick(View v)
{
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
});
Now implement method for LocationListener as below:
#Override
public void onLocationChanged(Location location) {
currentLattitude = location.getLatitude();
currentLongitude = location.getLongitude());
}
#Override
public void onProviderDisabled(String provider) {
Log.d("Latitude","disable");
}
#Override
public void onProviderEnabled(String provider) {
Log.d("Latitude","enable");
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d("Latitude","status");
}
With this, you can get your location via on click of your button.
Main thing to don't forget is to set permission (in your Manifest) as below:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission. ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
Use fused location API this is the fastest from all others.
public class LocationActivity extends Activity implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "LocationActivity";
private static final long INTERVAL = 1000 * 10;
private static final long FASTEST_INTERVAL = 1000 * 5;
Button btnFusedLocation;
TextView tvLocation;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mCurrentLocation;
String mLastUpdateTime;
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate ...............................");
//show error dialog if GoolglePlayServices not available
if (!isGooglePlayServicesAvailable()) {
finish();
}
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
setContentView(R.layout.activity_main);
tvLocation = (TextView) findViewById(R.id.tvLocation);
btnFusedLocation = (Button) findViewById(R.id.btnShowLocation);
btnFusedLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
updateUI();
}
});
}
#Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart fired ..............");
mGoogleApiClient.connect();
}
#Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop fired ..............");
mGoogleApiClient.disconnect();
Log.d(TAG, "isConnected ...............: " + mGoogleApiClient.isConnected());
}
private boolean isGooglePlayServicesAvailable() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (ConnectionResult.SUCCESS == status) {
return true;
} else {
GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
return false;
}
}
#Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
startLocationUpdates();
}
protected void startLocationUpdates() {
PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "Connection failed: " + connectionResult.toString());
}
#Override
public void onLocationChanged(Location location) {
Log.d(TAG, "Firing onLocationChanged..............................................");
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateUI();
}
private void updateUI() {
Log.d(TAG, "UI update initiated .............");
if (null != mCurrentLocation) {
String lat = String.valueOf(mCurrentLocation.getLatitude());
String lng = String.valueOf(mCurrentLocation.getLongitude());
tvLocation.setText("At Time: " + mLastUpdateTime + "\n" +
"Latitude: " + lat + "\n" +
"Longitude: " + lng + "\n" +
"Accuracy: " + mCurrentLocation.getAccuracy() + "\n" +
"Provider: " + mCurrentLocation.getProvider());
} else {
Log.d(TAG, "location is null ...............");
}
}
#Override
protected void onPause() {
super.onPause();
stopLocationUpdates();
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
Log.d(TAG, "Location update stopped .......................");
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
Log.d(TAG, "Location update resumed .....................");
}
}
}
LocationListener provides call back for location change through onLocationChanged.
GoogleApiClient.ConnectionCallbacks provides call back for GoogleApiClient onConnected.
GoogleApiClient.OnConnectionFailedListener provides call back for GoogleApiClient onConnectionFailed.
Source: http://javapapers.com/android/android-location-fused-provider/
I have provide a GPS reminder in my app, but when i enable my gps and return to my mainactivty, my gps reminder ask me again, again and a agin when i press the googlemaps button. It only works when I close the program and restart the app
This is my MainActivityClass.
GPSTracker gps;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gps = new GPSTracker(MainActivity.this);
}
My button to googlemaps.
public void googlemaps(View view) {
if (gps.canGetLocation()) {
Intent intent = new Intent(this, GoogleMaps.class);
startActivity(intent);
} else {
gps.showSettingsAlert();
}
}
this is my GPS tracker class
public class GPSTracker extends Service implements LocationListener {
private final Context mContext;
// flag for GPS status
boolean isGPSEnabled = false;
// flag for GPS status
boolean canGetLocation = false;
Location location; // location
public LocationManager locationManager;
public GPSTracker(Context context) {
this.mContext = context;
getLocation();
}
public Location getLocation() {
try {
locationManager = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!isGPSEnabled) {
} else {
this.canGetLocation = true;
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 10, 2000, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
/**
* Function to show settings alert dialog On pressing Settings button will
* lauch Settings Options
* */
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog
.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing Settings button
alertDialog.setPositiveButton("Settings",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
#Override
public void onLocationChanged(Location loc) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
You need to retest if the GPS has been enabled after you show your dialog. From the looks of it, you set your canGetLocation variable once when you create the class (via a call to getLocation(). Adding a call to 'getLocation()inonResume()` should solve your problem. I would recommend breaking the logic to see if the GPS is enabled into its own method.