Request runtime permissions on android - android

I am trying to get runtime permissions on my app. However the app is not displaying the dialog to request the specific permission. The code below only works when the GPS is turned on on the phone manually.
I am running the app on Android 5.0.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_location = findViewById(R.id.get_location);
txt_latitude = findViewById(R.id.latitude);
txt_longitude = findViewById(R.id.longitude);
txt_timestamp = findViewById(R.id.timestamp);
btn_map = findViewById(R.id.map);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
btn_location.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getLocation();
}
});
}
private void getLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {
Manifest.permission.ACCESS_FINE_LOCATION
}, REQUEST_LOCATION_PERMISSION);
} else {
mFusedLocationClient.getLastLocation().addOnSuccessListener(new OnSuccessListener < Location > () {
#Override
public void onSuccess(Location location) {
if (location != null) {
mLastLocation = location;
txt_latitude.setText(getString(R.string.location_latitude, mLastLocation.getLatitude()));
txt_longitude.setText(getString(R.string.location_longitude, mLastLocation.getLongitude()));
txt_timestamp.setText(getString(R.string.timestamp, mLastLocation.getTime()));
} else {
txt_latitude.setText(R.string.no_latitude);
txt_longitude.setText(R.string.no_longitude);
txt_timestamp.setText(R.string.no_timestamp);
}
}
});
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_LOCATION_PERMISSION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLocation();
} else {
Toast.makeText(this, R.string.location_permission_denied, Toast.LENGTH_SHORT).show();
}
}
}
}

Since you are run on Android 5.0 the Android runtime permission won't be shown. As runtime permission is only be shown starting from Android 6 (Marshmellow).
Please check the official documentation for the runtime permission details.

Related

android - GPS app crashes on location update request

I have tried to follow a tutorial to the fullest. Even tried to make few changes. I admit I am very new to Android. Pardon the n00b and unprepared question.
This app crashes as soon as I open. I have tried to comment the updateGPS() call. Which made the app open but crashes again if I touch the "Location Updates" (sw_locationsupdates) switch which calls updateGPS().
`
tv_lat = findViewById(R.id.tv_lat);
tv_lon = findViewById(R.id.tv_lon);
tv_address = findViewById(R.id.tv_address);
tv_altitude = findViewById(R.id.tv_altitude);
tv_accuracy = findViewById(R.id.tv_accuracy);
tv_speed = findViewById(R.id.tv_speed);
tv_sensor = findViewById(R.id.tv_sensor);
tv_updates = findViewById(R.id.tv_updates);
tv_address = findViewById(R.id.tv_address);
sw_locationsupdates = findViewById(R.id.sw_locationsupdates);
sw_gps = findViewById(R.id.sw_gps);
locationRequest = new LocationRequest();
locationRequest.setInterval(1000 * DEFAULT_UPDATE_INTERVAL);
locationRequest.setFastestInterval(1000 * FAST_UPDATE_INTERVAL);
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationCallBack = new LocationCallback() {
#Override
public void onLocationResult(#NonNull LocationResult locationResult) {
super.onLocationResult(locationResult);
// save the location
updateUIValues(Objects.requireNonNull(locationResult.getLastLocation()));
}
};
sw_gps.setOnClickListener(new View.OnClickListener() {
#SuppressLint("SetTextI18n")
#Override
public void onClick(View v) {
if (sw_gps.isChecked()) {
// most accurate - use GPS
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
tv_sensor.setText("Using GPS sensors");
}
else {
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
tv_sensor.setText("Using Towers + WiFi");
}
}
});
sw_locationsupdates.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View w) {
if(sw_locationsupdates.isChecked()) {
// turn on lcation tracking
startLocationUpdates();
}
else {
// turn off tracking
stopLocationUpdates();
}
}
});
updateGPS(); // tried to comment this.
} //end of onCreate method
#SuppressLint("SetTextI18n")
private void startLocationUpdates() {
tv_updates.setText("Location is being tracked");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fsdLocationProviderClient.requestLocationUpdates(locationRequest, locationCallBack, null);
updateGPS();
}
}
#SuppressLint("SetTextI18n")
private void stopLocationUpdates() {
tv_updates.setText("Location is NOT being tracked");
tv_lat.setText("Not tracking location");
tv_lon.setText("Not tracking location");
tv_speed.setText("Not tracking location");
tv_address.setText("Not tracking location");
tv_accuracy.setText("Not tracking location");
tv_sensor.setText("Not tracking location");
fsdLocationProviderClient.removeLocationUpdates(locationCallBack);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISSION_FINE_LOCATION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
updateGPS();
}
else {
Toast.makeText(this, "This app requires permission to be granted to function", Toast.LENGTH_SHORT).show();
finish();
}
break;
}
}
private void updateGPS () {
// get permission from user to track GPS
// get the current location from the fused API
// update the UI - i.e set all properties in their associated text view items
fsdLocationProviderClient = LocationServices.getFusedLocationProviderClient(MainActivity.this);
try {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// user provided the permission
fsdLocationProviderClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// we got permission. Put the values of location, into the UI components.
updateUIValues(location);
}
});
} else {
// permission required
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_FINE_LOCATION);
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
#SuppressLint("SetTextI18n")
private void updateUIValues(Location location) {
// update all of the text view objects with a new location
tv_lat.setText(String.valueOf(location.getLatitude()));
tv_lon.setText(String.valueOf(location.getLongitude()));
tv_accuracy.setText(String.valueOf(location.getAccuracy()));
if (location.hasAltitude()) {
tv_altitude.setText(String.valueOf(location.getAltitude()));
}
else {
tv_altitude.setText("Not available");
}
if (location.hasSpeed()) {
tv_speed.setText(String.valueOf(location.getAltitude()));
}
else {
tv_speed.setText("Not available");
}
Geocoder geocoder = new Geocoder(MainActivity.this);
try {
List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
tv_address.setText(addresses.get(0).getAddressLine(0));
}
catch (Exception e) {
tv_address.setText("Unable to get street address");
}
}
}
`
I am following this youtube video.
Android Studio Tutorial - Build a GPS App
build.gradle has
implementation 'com.google.android.gms:play-services-location:21.0.0
AndroidManifest.xml has
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
Tried to use
locationRequest = new LocationRequest.Builder();
LocationRequest.Builder.setIntervalMillis(Priority.PRIORITY_PASSIVE);
LocationRequest.Builder.setMinUpdateIntervalMillis(Priority.PRIORITY_HIGH_ACCURACY);
LocationRequest.Builder.setPriority(Priority.PRIORITY_BALANCED_POWER_ACCURACY);
Didn't get very far.
Tried to use Try and catch updateGPS(). No luck

last known location is always 0 [duplicate]

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.

How do I get started on manipulating android GPS?

So I've been trying to learn more about Android GPS applications (specifically offline) and I've come to notice a LocationManager might be able to solve my issues. Problem is that it requires API 23 in order to function and I'd like to target API 19 devices for a specific reason. Is there any other way to manipulate the GPS function to get coordinates without internet access on a lower level API?
Please help!
#Edit: I've added a sample application that I made (and is working just fine - the only problem here is that it requires API 23 in order to run) This piece of code describes an application that displays decimal coordinates every 5 seconds.
button = (Button) findViewById(R.id.button);
textView = (TextView) findViewById(R.id.textView);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
textView.append("\n "+ location.getLatitude() + " "+ location.getLongitude());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent (Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
};
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
}, 10 );
}
return;
}
else {
configureButton();
}
} //onCreate
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 10:
if (grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
configureButton();
return;
}
}
private void configureButton() {
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
locationManager.requestLocationUpdates("gps", 5000, 0, locationListener);
}
});
}

Adding location permissions on marshmallow

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);
}

location.getSpeed() not coming for Marshmallow, using Fused Location API

I'm using Fused Location API in my app ( getLatitude(), getLongitude(), getSpeed(), getElevation(), and distanceTo() ). It was working fine until I updated my phone (Moto X2 2014) to Marshmallow.
Now I don't receive speed in the location object in my app, rest methods are responding normally. However, if I run navigation on google maps in the background, I seem to receive speed inside my app as well.
Also, my app seems to work without any issues on Nexus 5X (Marshmallow) and other below API 23 phones.
What could be the problem? Has anyone faced something similar before?
On devices running Android 6.0 (API level 23) and higher, you need to validate the permission programmatically.
Youd could be something like this:
public class YourActivity extends AppCompatActivity implements
LocationListener, ActivityCompat.OnRequestPermissionsResultCallback{
private static final int REQUEST_LOCATION = 0;
private static final String[] PERMISSION_LOCATION = {Manifest.permission.ACCESS_FINE_LOCATION};
private LocationManager locManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
//Check if the Location permission is already available.
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
//Permission not granted.
requestLocationPermission();
} else {
//Permission granted.
initLocManager();
}
}
}
/**
* Requests the permission.
*/
private void requestLocationPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
//Permission has been previously denied.
//Show message...
} else {
//Permission has not been granted yet. It is requested directly.
ActivityCompat.requestPermissions(this, PERMISSION_LOCATION, REQUEST_LOCATION);
}
}
/**
* Callback.
*/
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == REQUEST_LOCATION) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Permission granted.
initLocManager();
} else {
//Permission not granted.
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
public void initLocManager(){
//Sample code...
map.setMyLocationEnabled(true);
locManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
if(locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) ||
locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission("android.permission.ACCESS_FINE_LOCATION") == PackageManager.PERMISSION_GRANTED) {
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
}else{
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
} else{
Toast.makeText(this, "No location services", Toast.LENGTH_LONG).show();
}
}
#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 onLocationChanged(Location location) {
map.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(),
location.getLongitude()), 16));
removeUpdatesLocListener();
}
private void removeUpdatesLocListener(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission("android.permission.ACCESS_FINE_LOCATION") == PackageManager.PERMISSION_GRANTED) {
if(locManager!=null)
locManager.removeUpdates(this);
}
}else{
if(locManager!=null)
locManager.removeUpdates(this);
}
}
#Override
protected void onStop() {
super.onStop();
removeUpdatesLocListener();
}
}
Good luck!
And if you need more information, look this

Categories

Resources