This question already has answers here:
Location is empty at the start
(5 answers)
Closed 3 years ago.
Inspite of my best effort, I am unable to get my location correct. This is my main.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
//new SecondFragment();
//TabLayout tabs = findViewById(R.id.tabs);
//tabs.setupWithViewPager(viewPager);
FloatingActionButton fab = findViewById(R.id.fab);
FontDrawable drawable = new FontDrawable(this, R.string.fa_plus_solid, true, false);
drawable.setTextColor(ContextCompat.getColor(this, android.R.color.white));
fab.setImageDrawable(drawable);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
//Check permission
if (ContextCompat.checkSelfPermission(getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(getApplicationContext(),
android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
latlang.Lat =location.getLatitude();
latlang.Lang =location.getLongitude();
}
}
});
}
}
}
the latlang is defined in another file as:
public class latlang {
public static double Lat;
public static double Lang;
}
If I hardcode the value here in latlang, everything is fine. But, of course I want the value of last known location.
Kindly help.
The problem is that you try to get the location before the permission is granted.
After calling requestPermissions() you immediately try to get location while the permission dialog is being displayed which means that the code that gets the location is being executed while you are seeing the permission dialog. This is why there is onRequestPermissionsResult function in activity that reports only after the user is done with permissions dialog.
You will need to get the location in onRequestPermissionsResult().
Second problem in your code is that you are only getting location when the permission is not granted. Your code does not handle the case when permission is already granted.
Here is how you would solve this:
#Override
protected void onCreate(Bundle savedInstanceState) {
if (ContextCompat.checkSelfPermission(getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(getApplicationContext(),
android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[] {
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION
}, 101);
} else {
fetchLocation();
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
switch (requestCode) {
case 101:
{
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 &&
(grantResults[0] == PackageManager.PERMISSION_GRANTED ||
grantResults[1] == PackageManager.PERMISSION_GRANTED)) {
// permission was granted
fetchLocation()
} else {
Show some error
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
public void fetchLocation() {
FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener < Location > () {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
latlang.Lat = location.getLatitude();
latlang.Lang = location.getLongitude();
}
}
});
}
Basically, Create a separate function that gets the location. You will call this function from 2 places. First is in onCreate when the permission is granted, and second in onPermissionResult. Don't forget to handle permission errors.
Related
I am new to Android and in my current project I am trying to retrieve location using GPS. The code for obtaining the location is in a separate non-activity class, because the fragment where I display the coordinates is crammed.
I have tried to use the guidelines from developer.android.com but I can't get any permission prompt, and when I press the button in the fragment, I only get the default 0-values for latitude and longitude.
I have provided the permissions in the manifest:
<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" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
The GPS locator class:
public class LocationProvider implements ActivityCompat.OnRequestPermissionsResultCallback {
private static final int PERMISSION_REQUEST_LOCATION = 1;
private Activity activity;
Location gps_loc;
Location final_loc;
double longitude;
double latitude;
private LocationManager locationManager;
public LocationProvider(Activity activity) {
this.activity =activity;
locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_LOCATION) {
// Request for permission.
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLocation();
} else {
requestLocationPermission();
}
}
}
private void getLocation() {
// Check if the permission has been granted
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
gps_loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (gps_loc != null) {
Log.v("Loc_provider",gps_loc.toString());
final_loc = gps_loc;
latitude = final_loc.getLatitude();
longitude = final_loc.getLongitude();
}
} else {
requestLocationPermission();
}
}
private void requestLocationPermission() {
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_LOCATION);
}
public String getCoordinates() {
return latitude + " "+ longitude;
}
}
The code in the fragment:
FloatingActionButton fab=view.findViewById(R.id.floatingActionButton);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
locProvider=new LocationProvider(requireActivity());
gpsCoordinates.setText(locProvider.getCoordinates());
}
});
Tips and solutions for fixing the code are most welcome.
UPDATE 1:
I moved the code in the fragment instead, so that it looks like below:
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!checkIfAlreadyhavePermission()) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else {
gps_loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
gpsCoordinates.setText(getCoordinates());
}
}
});
private String getCoordinates() {
if (gps_loc != null) {
Log.v("Loc_provider", gps_loc.toString());
final_loc = gps_loc;
latitude = gps_loc.getLatitude();
longitude = gps_loc.getLongitude();
}
return latitude + " " + longitude;
}
private boolean checkIfAlreadyhavePermission() {
int result = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION);
return result == PackageManager.PERMISSION_GRANTED;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Log.v("Grant_Results", String.valueOf(grantResults[0]));
Toast.makeText(getActivity(), "permission granted", Toast.LENGTH_LONG).show();
gpsCoordinates.setText(getCoordinates());
} else {
Toast.makeText(getActivity(), "permission denied", Toast.LENGTH_LONG).show();
}
break;
}
}
}
I now get the permission prompt, but the location still doesn't update (I get 0).
Please note:
Saving an Activity object is not recommended this may cause memory leaks. Activity may be destroyed and recreated (for example when screen orientation changes). Holding a reference to the old activity will cause you problems.
Implementing the ActivityCompat.OnRequestPermissionsResultCallback interface does nothing. Your method will never be called. You will have to call it explicitly from the activity.
You have not requested permission, so your permission prompt will never be shown and the default value of double that is 0 will get returned. You need to call your getLocation() method so that the control falls on the else block and your permission prompt is shown
I recommend you handle permission in the activity. Have the activity get the coordinates for the location. You can have the activity implement an interface, say LocationFetcher, with a method getCoordinates(). You can then call this in the fragment like so:
LocationFetcher locationFetcher = (LocationFetcher) activity;
gpsCoordinates.setText(locationFetcher.getCoordinates());
Fixed by implementing LocationListener in Fragment and then adding
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 400, 1, this);
in onRequestPermissionsResult().
I am using FusedLocationProviderClient to get latitude and longitude on a button click. But when I click the button it shows nothing. Just the app keeps loading for eternity. Can any show me where I am doing wrong in the code?
This is the code:
public class MainActivity extends AppCompatActivity {
Button showLocation;
TextView getLat, getLong;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showLocation = findViewById(R.id.btnShowLocation);
getLat = findViewById(R.id.getLat);
getLong = findViewById(R.id.getLong);
}
public void getlocation(View v) {
final ProgressDialog progressDialog=new ProgressDialog(MainActivity.this);
progressDialog.setMessage("Getting Location");
progressDialog.setCancelable(false);
progressDialog.show();
FusedLocationProviderClient fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(MainActivity.this);
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) {
// 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;
}
Task<Location> task = fusedLocationProviderClient.getLastLocation();
task.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if(location!=null)
{
String lati=String.valueOf(location.getLatitude());
getLat.setText(lati);
String longi=String.valueOf(location.getLongitude());
getLat.setText(longi);
Toast.makeText(MainActivity.this,"Location Found !!!",Toast.LENGTH_LONG).show();
progressDialog.cancel();
}
else
Toast.makeText(MainActivity.this,"Please Enable GPS And Internet !!!",Toast.LENGTH_LONG).show();
}
});
}
}
I have used FusedLocation in one of my Kotlin project , i will post the method below.
Make sure that , your location service is enable also the permission for accessing location is already asked from user, else last location cannot be detected.
fun getLocation(): Task<Location>? {
val mFusedLocationProviderClient: FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(dashboardActivity)
if (ActivityCompat.checkSelfPermission(dashboardActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(dashboardActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
}
val location = mFusedLocationProviderClient.lastLocation
location.addOnCompleteListener { task ->
if (task.isSuccessful) {
val currentLocation = task.result
if (currentLocation != null) {
latitude = currentLocation.latitude
longitude = currentLocation.longitude
dashboardActivity.getLatLong(latitude.toString(), longitude.toString()) //this methods calls the collector geo-location service
} else {
val builder = AlertDialog.Builder(dashboardActivity)
builder.setTitle("Location On")
builder.setPositiveButton("Yes") { dialog, which ->
val viewIntent = Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)
dashboardActivity.startActivity(viewIntent)
}
builder.setNegativeButton("No") { dialog, which ->
Toast.makeText(dashboardActivity, "Please enable location service", Toast.LENGTH_SHORT).show()
}
val dialog: AlertDialog = builder.create()
dialog.show()
}
}
}
return location
}
Instead of using addOnSuccessListener() i have instead used addOnCompleteListener() , i think that might be the issue.
When I run my Maps activity and accept the location permissions for the first time, if I press on "My Location" button nothing happens.
However, if i close the activity and go back to it, the button works fine after that! So, The problem is only after I accept the permissions for the first time of activity launch.
If I recreate the activity after accepting permissions the problem is solved, but I do not like that solution, plus I want to understand the cause of the problem.
What is causing this bug?
public class MapsActivity extends FragmentActivity implements` OnMapReadyCallback {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
GoogleMapOptions options = new GoogleMapOptions();
options.mapType(GoogleMap.MAP_TYPE_NORMAL);
mapFragment.newInstance(options);
mapFragment.getMapAsync(this);
}
#
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
requestLocationPermissions();
mMap.getUiSettings().setMapToolbarEnabled(true);
}
#
public void requestLocationPermissions() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) !=
PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
15);
}else{
mMap.setMyLocationEnabled(true);//needs location permission
mMap.getUiSettings().setMyLocationButtonEnabled(true);
}
}
#SuppressLint("MissingPermission")
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 15) {
if (grantResults.length == 0) {
requestLocationPermissions();
} else {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED ) {
Toast.makeText(this, "You have to accept all Permissions!", Toast.LENGTH_SHORT).show();
Log.e("Permission refused","Permission refused");
requestLocationPermissions();
} else {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED ) {
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
}
}
}
}
}
Debug your code to check what values from latitude and longitude you receive when you first grant the permission. The location might not be set at that moment. If the GPS is not already turned on, acquiring fine location takes sometimes a little more time. I've had the same issue on some of the devices used for testing.
I've been struggling with this issue and at the minute the only workaround I've found is to use the fuse location client to retrieve the location of the device and add a custom behavior for "my location" button.
In this way it works all times without reloading the activity.
private void getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (hasLocationPermission()) {
fusedLocationClient
.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
lastLocation = location;
// Logic to handle location object
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(location.getLatitude(),
location.getLongitude()), DEFAULT_ZOOM));
mMap.setOnMyLocationButtonClickListener(MapsActivity.this);
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
} else {
mMap.setMyLocationEnabled(false);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
}
});
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
MapsActivity is a listener of GoogleMap.OnMyLocationButtonClickListener and then have this code
#Override
public boolean onMyLocationButtonClick() {
// I've tried just setting the default behavior of the button, but just works after reloading
// the activity, then I've managed the click event to latest location; now it works for
// all cases.
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(lastLocation.getLatitude(),
lastLocation.getLongitude()), DEFAULT_ZOOM));
return false;
}
This is the code of onMapReady
#SuppressLint("MissingPermission")
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
mMap.getUiSettings().setZoomControlsEnabled(true);
getMuseums();
if (!hasLocationPermission()) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_PERMISSION_LOCATION);
return;
}
getDeviceLocation();
}
And my actual DEFAULT_ZOOM value is 10.
I am using fused location provider for fetching current location and update my marker to my current location via that. I am giving app permission and then it does nothing after that. Though i have written code for that to fetch and update location on map. I have previously given Access_COARSE_LOCATION as well, but nothing changes. this is my code :-
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private FusedLocationProviderClient mFusedLocationClient;
private static final int LOCATION_PERMISSION_REQUEST_CODE = 537;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
// Initializing Objects...
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
if (mapFragment != null) {
mapFragment.getMapAsync(this);
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
// onMapReady check Permission and load map...
// If Permission not granted ask for permission...
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mMap = googleMap;
MoveCameraToCurrentPosition();
} else {
AskUserPermission();
}
}
public void AskUserPermission() {
// Show Explanation and show permission dialog...
// Permission is not granted
// Show Explanation...
// shouldShowRequestPermissionRationale returns true if permission has previously
// denied by user..
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Why we need Location Permission?");
builder.setMessage("we want to forecast the weather alert like storms, Flood," +
"Hurricanes, etc. to you before hand based on your farm location, so that " +
"we can save your crops :).");
builder.setNeutralButton("Got it.", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
RequestLocationPermission();
}
});
builder.show();
RequestLocationPermission();
} else {
// No Explanation Needed Request Permission...
RequestLocationPermission();
}
}
// Show Alert Dialog for permission...
private void RequestLocationPermission() {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission
.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
// Fetch Request Permission result and update current location...
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case LOCATION_PERMISSION_REQUEST_CODE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// This code is not executing even after giving permission..
MoveCameraToCurrentPosition();
}
break;
}
}
// Move camera to current location...
private void MoveCameraToCurrentPosition(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Add a marker in Sydney, Australia, and move the camera.
LatLng sydney = new LatLng(location.getLatitude(), location.getLongitude());
mMap.addMarker(new MarkerOptions().position(sydney).icon(BitmapDescriptorFactory.fromResource(R.drawable.barley)).title("Your Location"));
CameraPosition cameraPosition = new CameraPosition(sydney, 10, 0, 0);
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition);
mMap.animateCamera(cameraUpdate);
}
}
});
} else {
AskUserPermission();
}
}
}
Okay so my problem was i was getting not calling getMapAsync after i allow location permission, which was making my Google Map Object null and so that was not ablw to move my camera to my current location. I have updated my code and now it works fine.
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap googleMap;
private String TAG = this.getClass().getSimpleName();
private FusedLocationProviderClient mFusedLocationClient;
private SupportMapFragment mapFragment;
private static final int LOCATION_PERMISSION_REQUEST_CODE = 537;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
if (mapFragment != null) {
mapFragment.getMapAsync(this);
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (googleMap != null) {
this.googleMap = googleMap;
MoveCameraToCurrentPosition();
} else {
Toast.makeText(this, "Null Object...OnMapReady", Toast.LENGTH_SHORT).show();
}
} else {
AskUserPermission();
}
}
public void AskUserPermission() {
// Show Explanation and show permission dialog...
// Permission is not granted
// Show Explanation...
// shouldShowRequestPermissionRationale returns true if permission has previously
// denied by user..
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Why we need Location Permission?");
builder.setMessage("we want to forecast the weather alert like storms, Flood," +
"Hurricanes, etc. to you before hand based on your farm location, so that " +
"we can save your crops :).");
builder.setNeutralButton("Got it.", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
builder.show();
}
RequestLocationPermission();
}
private void RequestLocationPermission() {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission
.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case LOCATION_PERMISSION_REQUEST_CODE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (googleMap != null) {
MoveCameraToCurrentPosition();
} else {
if (mapFragment != null) {
mapFragment.getMapAsync(this);
}
}
}
break;
}
}
private void MoveCameraToCurrentPosition() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Add a marker in Sydney, Australia, and move the camera.
LatLng sydney = new LatLng(location.getLatitude(), location.getLongitude());
googleMap.addMarker(new MarkerOptions().position(sydney).icon
(BitmapDescriptorFactory.fromResource(R.drawable.barley)).title("Your Location"));
CameraPosition cameraPosition = new CameraPosition(sydney, 10, 0, 0);
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition);
googleMap.animateCamera(cameraUpdate);
}
}
});
} else {
AskUserPermission();
}
}
}
I am writing a code to get lastknownlocation from location manager and this prompted me to add runtime permissions.
Here is my code:
public class MainActivity extends AppCompatActivity implements LocationListener {
LocationManager locationManager;
String provider;
private final int MY_PERMISSIONS_REQUEST_CODE=1;
Location location;
Boolean isPermissionGranted=false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
provider = locationManager.getBestProvider(new Criteria(), false);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION},MY_PERMISSIONS_REQUEST_CODE);
}
// return;
}
}
public void getlastknownposition()
{
}
#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) {
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == MY_PERMISSIONS_REQUEST_CODE)
{
if(grantResults[0]==PackageManager.PERMISSION_GRANTED && grantResults[1]==PackageManager.PERMISSION_GRANTED){
Toast.makeText(MainActivity.this," granted "+grantResults[0]+"granted2"+grantResults[1], Toast.LENGTH_SHORT).show();
location = locationManager.getLastKnownLocation(provider);}
}
}
}
I am still getting an error "Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException
in onRequestPermissionsResult on line location = locationManager.getLastKnownLocation(provider);
Put some braces around the second if in onPermissionsResult =)
if(requestCode == MY_PERMISSIONS_REQUEST_CODE){
if(grantResults[0]==PackageManager.PERMISSION_GRANTED && grantResults[1]==PackageManager.PERMISSION_GRANTED){
Toast.makeText(MainActivity.this," granted "+grantResults[0]+"granted2"+grantResults[1], Toast.LENGTH_SHORT).show();
location = locationManager.getLastKnownLocation(provider);
} else {
//TODO handle user saying NO! :)
}
}
Tip: if you request FINE_LOCATION you don't need COARSE, it already includes it.
Replace the line
location = locationManager.getLastKnownLocation(provider);
with
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
location = locationManager.getLastKnownLocation(provider);
}