I am new to Android Studio and am trying to retrieve the co-ordinates of an Android device using Location Service.
I have all the relevant permissions enabled in the manifest (the Coarse and Fine locations, and the Internet).
In my MainActivity.java, I have the following. However, when I run it in Android Studio, for the 3 test cases I have in the activity, the TextView ShowLocation always become "Something else", meaning that it went to the third case where location is null (no location detected?) but permission has been granted properly.
What am I doing wrong here? Is it because I could not test Location Service in Android Studio? How can I test and obtain co-ordinate values in an Android application using Android Studio?
A snippet of MainActivity.java
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION);
}
Location loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {
latitude = String.valueOf(loc.getLatitude());
showLocation.setText("Latitude" + latitude);
}
else {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
showLocation.setText("No GPS Permission granted");
} else
showLocation.setText("Something else");
}
Related
hello i wanna create a attandace online using getlocation
everything works fine until i close the app and forget to turn on the GPS service
everytime i open activity to get geoLocation code is always failed ,
what i ask is how can in get current location using google maps api so everytime i open the apps is works to get location geocodes
Please Help Im struggle to solve this i need this app for my final project
java.lang.NullPointerException: Attempt to invoke virtual method 'double android.location.Location.getLatitude()' on a null object reference
at com.sistemabsensi.online.Absensi.onConnected(Absensi.java:415)
at com.google.android.gms.common.internal.GmsClientEventManager.onConnectionSuccess(Unknown Source:33)
at com.google.android.gms.common.api.internal.zaaw.zab(Unknown Source:292)
at com.google.android.gms.common.api.internal.zaak.zaaq(Unknown Source:125)
at com.google.android.gms.common.api.internal.zaak.onConnected(Unknown Source:105)
at com.google.android.gms.common.api.internal.zabe.onConnected(Unknown Source:101)
at com.google.android.gms.common.api.internal.zaq.onConnected(Unknown Source:6)
at com.google.android.gms.common.internal.zaf.onConnected(Unknown Source:2)
at com.google.android.gms.common.internal.BaseGmsClient$zzf.zzm(Unknown Source:24)
at com.google.android.gms.common.internal.BaseGmsClient$zza.zza(Unknown Source:12)
at com.google.android.gms.common.internal.BaseGmsClient$zzc.zzo(Unknown Source:11)
at com.google.android.gms.common.internal.BaseGmsClient$zzb.handleMessage(Unknown Source:49)
at android.os.Handler.dispatchMessage(Handler.java:107)
at com.google.android.gms.internal.common.zze.dispatchMessage(Unknown Source:8)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7562)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
I/Process: Sending signal. PID: 27425 SIG: 9
Heres My code :
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, (com.google.android.gms.location.LocationListener) this);
}
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
#SuppressLint("MissingPermission") Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double latit = location.getLatitude();
double longit = location.getLongitude();
LatLng kantor = new LatLng(-8.4603894,118.7560158);
LatLng User = new LatLng(latit,longit);
distance=SphericalUtil.computeDistanceBetween(User,kantor);
TextView jarak = findViewById(R.id.jarak);
jarak.setText("Jarak Dari Kantor :" + Math.round(distance) + " Meter");
Log.d(TAG,"Latitude" + String.valueOf(latit) +"Longitude" + String.valueOf(longit));
On Location Change works fine but this not i expected
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraPosition cameraPosition = new CameraPosition.Builder().target(new LatLng(latLng.latitude, latLng.longitude)).zoom(16).build();
latitude = location.getLatitude();
longitude = location.getLongitude();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
#SuppressLint("MissingPermission") Location location1 = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double latit = location.getLatitude();
double longit = location.getLongitude();
float[] results = new float[1];
Location.distanceBetween(latit,longit,-8.4604926,118.7560354,results);
float distance = results[0];
int meter = (int) (distance/10000);
TextView jarak = findViewById(R.id.jarak);
Android 10 introduced new permission called background location:
https://developer.android.com/training/location/permissions#background
For Android 10 devices or above, to get location while app is in background:
You need to declare Background Location permission in manifest.
Users must grant this permission in runtime.
(Update) Location services must be enabled on device.
(Update) Sample code:
Declare fine and background permission in AndroidManifest.xml (in manifest tag):
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
This is how you request these permissions from your Activity class (no permissions before Android 6):
// Android 10+
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION}, REQUEST_CODE);
// Android 6-9
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE);
This is how you check the result from your activity for Android 10+ devices (2 levels of permissions):
// Utility function
#RequiresApi(api = Build.VERSION_CODES.M)
public boolean isPermissionGranted(String permission) {
return checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
// Only fine location granted - no location if app is closed
isPermissionGranted(Manifest.permission.ACCESS_FINE_LOCATION) && !isPermissionGranted(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
// Fine & background location granted - location should (almost) always work:
isPermissionGranted(Manifest.permission.ACCESS_FINE_LOCATION) && isPermissionGranted(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
For Android 6-9 devices you can just check for Manifest.permission.ACCESS_FINE_LOCATION
Is it possible to get the location from NETWORK if GPS is OFF ?
My Demo can get the current user-location from NETWORK and from GPS but only if GPS is ON.
If I try to get the location from LastKnownLocation, I get null too.
#Override
protected void onResume() {
super.onResume();
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) {
startActivity(new Intent(MainActivity.this, Permissions.class));
return;
}
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
isGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPS && !isNetwork) {
Log.d("TAG", "gps and network false");
}else {
if (isGPS) {
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {
Log.i("TAG", "gps loc found");}
}
if (isNetwork) {
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loc != null) {
Log.i("TAG", "network loc found");
}
}
I have tested this code below. it returns the location null too, if I make the device-gps off :
GPSTracker.java
If you are trying to request the location from the network as a fallback to GPS, you will need to have ACCESS_COARSE_LOCATION enabled. Also, even with the permission enabled, you must request a location update, to refresh and update the last network position. Only after that, you'll have the last known location available, otherwise, you'll get null indeed.
To make your code work, you probably just need to call your GPSTracker.getLocation() before your line with
getSystemService(Context.LOCATION_SERVICE);
You can check the documentation for getLastKnownLocation here:
https://developer.android.com/reference/android/location/LocationManager#getLastKnownLocation(java.lang.String)
Gets the last known location from the given provider, or null if there
is no last known location. The returned location may be quite old in
some circumstances, so the age of the location should always be
checked.
👉   This will never activate sensors to compute a new location, and will
only ever return a cached location.
Android 6
I wrote the next code that checks for permissions and if there are no such permissions, it asks a user to give them.
private void checkDiskPermission ()
{
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "no disk access" , Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
else
{
Toast.makeText(this, "disk access - OK" , Toast.LENGTH_LONG).show();
}
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, "no GPS access" , Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0);
}
else
{
Toast.makeText(this, "GPS access - OK" , Toast.LENGTH_LONG).show();
}
}
This code works fine for GPS permissions, but not for WRITE_EXTERNAL_STORAGE permissions. A dialog appears in only one case.
Why can it be so?
Thanks!
Because you are requesting it for 2 times simultaneously.
That's why it is taking last request.
The solution is that you have to ask both permission in one request
Like this-
private void checkDiskPermission ()
{
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& 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, "No Permissions" , Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 0);
}
else
{
Toast.makeText(this, "Has Permissions" , Toast.LENGTH_LONG).show();
}
}
If permission > 1, than it has to combined together at Runtime.
According to Google, beginning with Android 6.0 (API level 23), users can revoke permissions from any app at any time, even if the app targets a lower API level. You should test your app to verify that it behaves properly when it’s missing a needed permission, regardless of what API level your app targets.
Things to keep in mind while asking Multiple Permission:
Number of Permission.
Never Ask Again Checkox
Look at the Source for Multiple Permission Request
your code is working fine. No issue in java code for run time permission. Once check your manifest have you add that line or not?
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
I created my own Java Class to handle the location:
public class MyLocationHandler extends Service implements LocationListener {
......
public Location getLocation() {
try {
locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// getting network status
isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
} else {
this.canGetLocation = true;
// First get location from Network Provider
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
.......
}
And this is an extract from build.gradle:
android {
compileSdkVersion 23
buildToolsVersion "24.0.0"
defaultConfig {
applicationId "com.mobile.appoperator"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
PROBLEM:
The problem is that I need to add checkSelfPermission, but that isn't an activity and plus if I add it, I can't run my app on Android versions older than api lvl 23.
So how can I handle this problem?
I am doing mine inside a service and yes, I currently do not request permission because for some reason, you have to be inside an activity to do that;
Here is what I do instead:
private void updateUserLocation(){
if ( Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission( getApplicationContext(), android.Manifest.permission.ACCESS_FINE_LOCATION )
!= PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission( getApplicationContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
return;
}
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
LocationListener listener = new GpsListener();
Looper.prepare();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
Looper.loop();
}else {
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
LocationListener listener = new GpsListener();
Looper.prepare();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
Looper.loop();
}
}
}
The best approach to actually request a user to grant you permission is to do this early perhaps in the first activity of the app like Login (then they will see some window explaining why you need GPS enabled or such permission in your app.
If the user rejects the request for permission, then you will have to reroute your app - basically feel sad and do what you would do without location features.
SUMMARY
In general, since you only ask the user to grant the permission perhaps once, you can do that when they login (since after they grant the permission, they will then not be asked again), then when actually getting location updates, you can simply check like I do below and move on!
I hope this helps you get somewhere.
I' m in a service, and I just need the latitude and longitude. Just two doubles. So, I did the following:
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double longitude = location.getLongitude();
double latitude = location.getLatitude();
}
For some reason, the latitude and latitude are null. The documentation says this is possible if the information for location is unavailable, but it should be available, since I first check if the permissions are there in the if statement, right? In the phone that I am testing on, I do have location enabled. Why is the latitude and longitude null?
If you try this instead, what is the output?
locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
It's because, even if location is enabled, there is no "lastKnownLocation" available yet. If you go to (for example) google maps app and ask for current location, after location is successfully fetched, go to your app and it will work (lat and lon != null).
EDIT: I don't know the code for android location service API, but for google maps API is something like this (i'm sure is similar):
public void methodThatUseLocation() {
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), PERMISSIONS, MainActivity.REQUEST_LOCATION);
} else {
Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (lastLocation != null) {
Double latitude = lastLocation.getLatitude();
Double longitude = lastLocation.getLongitude();
// do something with latitude and longitude
} else {
requestLocationUpdate();
}
}
}
private void requestLocationUpdate() {
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), PERMISSIONS, MainActivity.REQUEST_LOCATION);
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
}
The reason is, you are checking last known location, and if there were no locations previously fetched by this provider, all corresponding parameters will be null. Method getLastKnownLocation reuses information fetched by other apps/services, and it can happen that there were no information saved.
You can try to make single location update using method requestSingleUpdate, so you won't depend on your device state.