Hey I am trying to get a phone location using GPS and I tried this code but it doesn't show anything (I am running it on the simulator and changing the location there) but it seems that it doesn't even enter the location change method..
Here is the activity code:
private BroadcastReceiver broadcastReceiver;
#Override
protected void onResume() {
super.onResume();
if(broadcastReceiver==null)
{
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(getApplicationContext(),"cor",Toast.LENGTH_LONG).show();
// Log.d("cors:",""+intent.getExtras().get("cordinates"));
}
};
}
registerReceiver(broadcastReceiver,new IntentFilter("location_update"));
}
#Override
protected void onDestroy() {
super.onDestroy();
if(broadcastReceiver!=null)
unregisterReceiver(broadcastReceiver);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
Log.d("oncraet","oncreate");
setSize();
if(!runtime_permissions())
{
enable_buttons();
}
}
private boolean runtime_permissions() {
if (Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}
,100);
return true;
}
return false;
}
public void enable_buttons()
{
Intent i =new Intent(getApplicationContext(), GPS_Service.class);
startService(i);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 100) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
enable_buttons();
} else {
runtime_permissions();
}
}
}
and here is the Service class code:
public class GPS_Service extends Service {
private LocationListener listener;
private LocationManager locationManager;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Intent i = new Intent("location_update");
i.putExtra("coordinates",location.getLongitude()+" "+location.getLatitude());
sendBroadcast(i);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
//noinspection MissingPermission
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,3000,0,listener);
}
#Override
public void onDestroy() {
super.onDestroy();
if(locationManager != null){
//noinspection MissingPermission
locationManager.removeUpdates(listener);
}
}
}
the manifest is all good..
what is the problem? and how can I make the app get the first location without it has to move first?
look at my example here
private LocationManager locationManager;
private double lastKnownStartLatitude, lastKnownStartLongtitude;
locationManager = (LocationManager) getSystemService(serviceString);
String serviceString = Context.LOCATION_SERVICE;
locationManager = (LocationManager) getSystemService(serviceString);
String provider = LocationManager.GPS_PROVIDER;
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
// if lastKnownLocation is not null
lastKnownLocation = locationManager.getLastKnownLocation(provider);
if (lastKnownLocation != null) {
lastKnownStartLatitude = lastKnownLocation.getLatitude();
lastKnownStartLongtitude = lastKnownLocation.getLongitude();
}
// if lastKnownLocation is null
LocationListener myLocationListener = new LocationListener() {
public void onLocationChanged(Location locationListener) {
Location location;
// using gps
if (isGPSEnabled(YourClassName.this)) {
if (locationListener != null) {
if (ActivityCompat.checkSelfPermission(YourClassName.this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(TestWithLocationListener.this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
System.out.println("Hello isGPSEnabled");
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
} else if (isInternetConnected(TestWithLocationListener.this)) {
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
Hope this helps
Try to use Google's fused location provider API as it is now the new best practice to fetch location.
You get updates for best location available from all sources according to your location request.
This tutorial on developer's site is really good.
Related
I want to get current location in background every 15 mins. I have created a background service with Timer. But it stops at some point of time.
Please correct me, how to run this all time in background without stopping?
public class BackgroundService extends Service implements LocationListener {
public static String str_receiver = "app.BackgroundService.Locationreceiver";
boolean isGPSEnable = false;
boolean isNetworkEnable = false;
double latitude, longitude;
LocationManager locationManager;
Location location;
long notify_interval = 600000;
Intent intent;
private Handler mHandler = new Handler();
private Timer mTimer = null;
public BackgroundService() {
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(BackgroundService.this, "Getting Location", Toast.LENGTH_SHORT).show();
mTimer = new Timer();
mTimer.schedule(new TimerTaskToGetLocation(), 60000, notify_interval);
intent = new Intent(str_receiver);
}
#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) {
}
private void fn_getlocation() {
locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
isGPSEnable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnable && !isNetworkEnable) {
Toast.makeText(BackgroundService.this, "GPS disabled", Toast.LENGTH_LONG).show();
} else {
if (isNetworkEnable) {
location = null;
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000000, 20, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
Log.e("latitude", location.getLatitude() + "");
Log.e("longitude >>", location.getLongitude() + "");
latitude = location.getLatitude();
longitude = location.getLongitude();
fn_update(location);
}
}
}
if (isGPSEnable) {
location = null;
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000000, 20, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
Log.e("latitude>>", location.getLatitude() + "");
Log.e("longitude", location.getLongitude() + "");
latitude = location.getLatitude();
longitude = location.getLongitude();
fn_update(location);
}
}
}
}
}
private void fn_update(Location location) {
intent.putExtra("latutide", location.getLatitude() + "");
intent.putExtra("longitude", location.getLongitude() + "");
sendBroadcast(intent);
}
private class TimerTaskToGetLocation extends TimerTask {
#Override
public void run() {
mHandler.post(new Runnable() {
#Override
public void run() {
fn_getlocation();
}
});
}
}
In Manifest
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
The thing is location services are expensive for android. Thus, android os stops heavy background services when the apps go in the background. That is why you do not get the location or in some cases, you might get the Old location itself.
Please take a look at this, Background Execution Limit in android for having idea about the problem.
https://medium.com/exploring-android/exploring-background-execution-limits-on-android-oreo-ab384762a66c
So, you should use ForegroundService which generates a Notification while the service is running.
Its onCreate() is somewhat like
override fun onCreate() {
super.onCreate()
log("The service has been created".toUpperCase())
var notification = createNotification()
startForeground(1, notification)
}
And it should be started as
context.startForegroundService(it)
Here, is an article regarding its detailed implementation.
This should help you I hope.
I'm trying to develop an application for Android Automotive
As you know, we can't use Google Play Services for Android Auto apps, so I m looking for a solution to get last position. The Location object.
You need to add permission to your manifest file
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
then you can create your custom LocationUtil class like below;
public class LocationUtil {
private final LocationListener locationListener;
private Context mContext;
private Location currentLocation;
private LocationManager mLocationManager;
private static LocationUtil INSTANCE;
public LocationUtil(Context context, final LocationListener listener) {
mContext = context;
mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
locationListener = listener;
}
public synchronized static LocationUtil getInstance(Context context, final LocationListener listener) {
if (INSTANCE == null) {
INSTANCE = new LocationUtil(context, listener);
}
return INSTANCE;
}
public void startLocationUpdate() {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
criteria.setAltitudeRequired(false);
criteria.setSpeedRequired(false);
criteria.setPowerRequirement(Criteria.POWER_MEDIUM);
criteria.setCostAllowed(false);
String provider = mLocationManager.getBestProvider(criteria, true);
if (provider == null) {
List<String> providers = mLocationManager.getAllProviders();
for (String temp : providers) {
if (mLocationManager.isProviderEnabled(temp)) {
provider = temp;
}
}
}
long distanceChage = 20;
long updateTime = 1000 * 50;
if (provider != null && Build.VERSION.SDK_INT >= 23
&& ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationManager.requestLocationUpdates(provider, updateTime, distanceChage, locationListener);
currentLocation = mLocationManager.getLastKnownLocation(provider);
} else if (provider != null && Build.VERSION.SDK_INT < 23) {
mLocationManager.requestLocationUpdates(provider, updateTime, distanceChage, locationListener);
currentLocation = mLocationManager.getLastKnownLocation(provider);
}
}
public void stopLocationUpdate() {
if (mLocationManager != null) {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationManager.removeUpdates(locationListener);
}
}
}
public Location getLocation() {
return currentLocation;
}
}
then you can create an instance of this class whereever you want to initiate.
LocationUtil manager = LocationUtil.getInstance(context, YourActivity.class);
manager.startLocationUpdate();
#Override
public void onLocationChanged(final Location location) {
//Do your work here
}
#Override
public void onStatusChanged(final String provider, final int status, final Bundle extras) {
}
#Override
public void onProviderEnabled(final String provider) {
}
#Override
public void onProviderDisabled(final String provider) {
}
I have Fused Location Api class which extends AppCompatActivity right now. I want to make it non-activity class and call it in MainActivity or in any other activity class. How can i do that? I am a newbie . So please any constructive criticism would be really appreciated.
public class GpsLocation extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private Location location;
private TextView locationTv;
private GoogleApiClient googleApiClient;
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private LocationRequest locationRequest;
private static final long UPDATE_INTERVAL = 5000, FASTEST_INTERVAL = 5000; // = 5 seconds
// lists for permissions
private ArrayList<String> permissionsToRequest;
private ArrayList<String> permissionsRejected = new ArrayList<>();
private ArrayList<String> permissions = new ArrayList<>();
// integer for permissions results request
private static final int ALL_PERMISSIONS_RESULT = 1011;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_hotkey_navigation);
locationTv = findViewById(R.id.location);
// we add permissions we need to request location of the users
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
permissionsToRequest = permissionsToRequest(permissions);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (permissionsToRequest.size() > 0) {
requestPermissions(permissionsToRequest.toArray(
new String[0]), ALL_PERMISSIONS_RESULT);
}
}
// we build google api client
googleApiClient = new GoogleApiClient.Builder(this).
addApi(LocationServices.API).
addConnectionCallbacks(this).
addOnConnectionFailedListener(this).build();
}
private ArrayList<String> permissionsToRequest(ArrayList<String> wantedPermissions) {
ArrayList<String> result = new ArrayList<>();
for (String perm : wantedPermissions) {
if (!hasPermission(perm)) {
result.add(perm);
}
}
return result;
}
private boolean hasPermission(String permission) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
return true;
}
#Override
protected void onStart() {
super.onStart();
if (googleApiClient != null) {
googleApiClient.connect();
}
}
#Override
protected void onResume() {
super.onResume();
if (!checkPlayServices()) {
locationTv.setText("You need to install Google Play Services to use the App properly");
}
}
#Override
protected void onPause() {
super.onPause();
// stop location updates
if (googleApiClient != null && googleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
googleApiClient.disconnect();
}
}
private boolean checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST);
} else {
finish();
}
return false;
}
return true;
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
// Permissions ok, we get last location
location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
locationTv.setText("Latitude : " + location.getLatitude() + "\nLongitude : " + location.getLongitude());
}
startLocationUpdates();
}
private void startLocationUpdates() {
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(UPDATE_INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "You need to enable permissions to display location !", Toast.LENGTH_SHORT).show();
}
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
if (location != null) {
locationTv.setText("Latitude : " + location.getLatitude() + "\nLongitude : " + location.getLongitude());
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch(requestCode) {
case ALL_PERMISSIONS_RESULT:
for (String perm : permissionsToRequest) {
if (!hasPermission(perm)) {
permissionsRejected.add(perm);
}
}
if (permissionsRejected.size() > 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(permissionsRejected.get(0))) {
new AlertDialog.Builder(GpsLocation.this).
setMessage("These permissions are mandatory to get your location. You need to allow them.").
setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
requestPermissions(permissionsRejected.
toArray(new String[0]), ALL_PERMISSIONS_RESULT);
}
}).setNegativeButton("Cancel", null).create().show();
return;
}
}
} else {
if (googleApiClient != null) {
googleApiClient.connect();
}
}
break;
}
}
}
I need to get its gps coordinates and send it to MainActivity class.So please help me. Any help would be much really appreciated.
why are you extending AppCompat at all if you want a regular class? Create a normal class and instantiate it in your activity.
What exactly are you trying to do in this class, that it cant be a method in your Activity?
The fused Location Client can me created anywhere by calling
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
I'm using this What is the simplest and most robust way to get the user's current location on Android? to get my current location and list nearby restaurants when i click on swith button.It works before i remove the app and install it again.
this is my implementation of gotLocation method
switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
MyLocationManager.LocationResult locationResult= new MyLocationManager.LocationResult() {
#Override
public void gotLocation(final Location location) {
//Got the location!
currentLocation = location;
browseNearbyBusinessesList(currentLocation);
}
};
MyLocationManager myLocationManager = new MyLocationManager();
myLocationManager.getLocation(getBaseContext(), locationResult);
}else {
searchDefaultList();
}
}
});
I got not null LocationResult Object but the gotLocation method was not executed . Can any one tell me where is exactly the problem please?
this is the code of MyLocationManager Class
public class MyLocationManager {
public LocationResult locationResult;
public Context context;
Timer timer1;
LocationManager lm;
boolean gps_enabled = false;
boolean network_enabled = false;
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerGps);
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
private boolean isPermessed = false;
public MyLocationManager() {
}
public MyLocationManager(boolean isPermessed) {
this.isPermessed = isPermessed;
}
public boolean getLocation(Context context, LocationResult result) {
//I use LocationResult callback class to pass location value from MyLocation to user code.
this.context = context;
locationResult = result;
if (lm == null)
lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//exceptions will be thrown if provider is not permitted.
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
//don't start listeners if no provider is enabled
if (!gps_enabled && !network_enabled)
return false;
if (gps_enabled) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
isPermessed = false;
return false;
} else {
isPermessed = true;
}
if (isPermessed)
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
}
if (network_enabled) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
isPermessed = false;
return false;
} else {
isPermessed = true;
}
if (isPermessed)
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
}
timer1 = new Timer();
timer1.schedule(new GetLastLocation(), 4000);
return true;
}
public static abstract class LocationResult {
public abstract void gotLocation(final Location location);
}
class GetLastLocation extends TimerTask {
#Override
public void run() {
lm.removeUpdates(locationListenerGps);
lm.removeUpdates(locationListenerNetwork);
Location net_loc = null, gps_loc = null;
if (gps_enabled) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
isPermessed = false;
return;
} else {
isPermessed = true;
}
if (isPermessed)
gps_loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
if (network_enabled) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
isPermessed = false;
return;
} else {
isPermessed = true;
}
if (isPermessed)
net_loc = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
System.out.println(isPermessed);
//if there are both values use the latest one
if (gps_loc != null && net_loc != null) {
if (gps_loc.getTime() > net_loc.getTime())
locationResult.gotLocation(gps_loc);
else
locationResult.gotLocation(net_loc);
return;
}
if (gps_loc != null) {
locationResult.gotLocation(gps_loc);
return;
}
if (net_loc != null) {
locationResult.gotLocation(net_loc);
return;
}
locationResult.gotLocation(null);
}
}
}
The problem was isPermissed returns always false. I created a method getLocationPermissions() to grant permissions.
private final static String FINE_LOCATION= Manifest.permission.ACCESS_FINE_LOCATION;
private final static String COARSE_LOCATION= Manifest.permission.ACCESS_COARSE_LOCATION;
private final static int LOCATION_PERMISSION_REQUEST_CODE=1234;
--------------------------------------
if (gps_enabled) {
getLocationPermission();
if (((ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) && (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED))) {
isPermessed = true;
Log.i("isPermessed = ", isPermessed+"");
} else {
isPermessed = false;
Log.i("isPermessed = ", isPermessed+"");
return false;
}
--------------------------------------
private void getLocationPermission() {
String[] permissions = {android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION};
if (ContextCompat.checkSelfPermission(context,
FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(context,
COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
} else {
ActivityCompat.requestPermissions((Activity) context,
permissions,
LOCATION_PERMISSION_REQUEST_CODE);
}
} else {
ActivityCompat.requestPermissions((Activity) context,
permissions,
LOCATION_PERMISSION_REQUEST_CODE);
}
}
Hi I am creating an android map application that will get the user location, but when users open their map sometimes the location is not accurate and will slowly pinpoint your location.
I have tried this. But It still calls the handler and the TOASTS won't stop.
private LocationManager locationManager;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps_page);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
handler.postDelayed(runnable,3000);
}
#Override
public void onProviderDisabled(String provider) {
handler.removeCallbacks(runnable);
}
});
private Runnable runnable = new Runnable() {
#Override
public void run() {
getCurrentLocation();
Toast.makeText(mapsPage.this, "GETTING LOCATION", Toast.LENGTH_SHORT).show();
handler.postDelayed(this, 3000);
}
};
private void getCurrentLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
longitude = location.getLongitude();
latitude = location.getLatitude();
moveMap();
Integer loc = Math.round(location.getAccuracy());
textings.setText(Integer.toString(loc));
if(loc <= 100)
{
handler.removeCallbacks(runnable);
Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show();
}
}
}
//Function to move the map
private void moveMap() {
LatLng latLng = new LatLng(latitude, longitude);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(17));
mMap.addMarker(new MarkerOptions().position(latLng).draggable(false));
}
I have added a handler that will run every 5 seconds checking the users location, and when the getAccuracy data is either equal or lesser than 100 it will stop. How would I do this?
getCurrentLocation may call handler.removeCallbacks(runnable);, but then the runnable will always call handler.postDelayed(this, 3000); right after.
To fix this there has to be some condition for the Runnable to check to see if it should post itself again.
A solution would be to make getCurrentLocation return a boolean indicating if it was successful (enough):
private boolean getCurrentLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
longitude = location.getLongitude();
latitude = location.getLatitude();
moveMap();
Integer loc = Math.round(location.getAccuracy());
textings.setText(Integer.toString(loc));
if(loc <= 100) {
handler.removeCallbacks(runnable);
Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show();
return true;
}
}
return false;
}
Then in your Runnable check if you need to have another run:
#Override
public void run() {
if(!getCurrentLocation()) {
handler.postDelayed(this, 3000);
}
}
However, all of that being said, you should just check the Location in onLocationChanged of your LocationListener and do something if that location is accurate enough. Then you don't need the Runnable at all.
You should definitely accept RobCo's answer as the correct one because it addresses your question directly and also offers an additional key insight (i.e. you don't really need the Runnable at all).
But, I was curious what RobCo's approach would look like, so I created one possible implementation of it.
It turns out that if we avoid the Runnable and rely on Google's callbacks instead, we can get away with using only the newer location provider API (LocatonServices.FusedLocationApi). The older LocationManager API can just be eliminated.
So, in this implementation, I let the Google location service trigger callbacks if/when the location changes (instead of using a periodic poll from the client):
public class MainActivity extends AppCompatActivity implements
ActivityCompat.OnRequestPermissionsResultCallback, GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks,
com.google.android.gms.location.LocationListener {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int PERMISSION_REQUEST_CODE = 10001;
public static final int LOCATION_UPDATE_INTERVAL = 5000; // milliseconds
private GoogleApiClient googleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
googleApiClient = new GoogleApiClient.Builder(this, this, this)
.enableAutoManage(this, this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
}
private void requestPermission() {
ActivityCompat.requestPermissions(this,
new String[]{ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_CODE);
}
private void initLocationServices() {
try {
// make initial, synchronous request for current location
Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
moveMap(location);
}
// request future location updates which will come in as callbacks later, when available
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(LOCATION_UPDATE_INTERVAL);
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
} catch (SecurityException se) {
Log.w(TAG, "App does not have sufficient permission to request location. " +
"Requesting permission now...");
requestPermission();
}
}
private void moveMap(Location location) {
Log.v(TAG, "moveMap");
// TODO: actual map moving code goes here
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e(TAG, "Connection failed:" + connectionResult.getErrorMessage());
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED) {
Log.v(TAG, "User granted permission. Will request current location.");
initLocationServices();
} else {
Log.w(TAG, "User did not grant permission. Cannot request location. Cannot proceed.");
}
}
#Override
public void onLocationChanged(Location newLocation) {
Log.v(TAG, "onLocationChanged:" + newLocation.toString());
moveMap(newLocation);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if ((ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED)
&& (ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED)) {
initLocationServices();
} else {
Log.w(TAG, "onCreate: requesting sufficient permission from user");
requestPermission();
}
}
#Override
public void onConnectionSuspended(int i) {
Log.v(TAG, "onConnectionSuspended");
}
}
A downside of this particular implementation is that the MainActivity implements several interfaces and that adds some confusion (what are all these methods doing here?, etc)
Dunno. Maybe it's useful. In any event, good luck with your app.