Android App Architecture: Implements user permission in lifecycle - java

I have a LocationListener which is extended LiveData Class. From the Android 6.0, the permission is requested in runtime. Now , when I tried to implements the LiveData Class and it required the permission checking in onActive() function. I have to make the boilerplate code in each activity for the permission requested and result received. Is there any way to move such
onRequestPermissionsResult() and checkSelfPermission() functions to the LocationListener ?
LocationFragment.java
public class LocationFragment extends LifecycleFragment {
private FragmentLocationBinding binding;
public LocationFragment() {
// Required empty public constructor
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (ContextCompat.checkSelfPermission(getActivity(),
permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.ACCESS_COARSE_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.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
200);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
//get the viewmodel from activity
LastLocationViewModel lastLocationViewModel = ViewModelProviders.of(getActivity())
.get(LastLocationViewModel.class);
lastLocationViewModel.getLastKnowLocation().observe(this, location -> {
binding.setLocation(location);
});
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 200: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getActivity(), "Rights Granted", Toast.LENGTH_SHORT).show();
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
binding = DataBindingUtil
.inflate(LayoutInflater.from(getActivity()), R.layout.fragment_location, null, false);
return binding.getRoot();
}
}
LastLocationListener.java
public class LastLocationListener extends LiveData<Location> {
private LocationManager locationManager;
private Context context;
private LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Log.d("Location Msg", location.toString());
setValue(location);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
public LastLocationListener(Context context) {
this.context = context;
locationManager = (LocationManager) context.getSystemService(
Context.LOCATION_SERVICE);
}
#Override
protected void onActive() {
if (ActivityCompat.checkSelfPermission(context, permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(context, 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, 0, 0, listener);
}
#Override
protected void onInactive() {
locationManager.removeUpdates(listener);
}
}

when I tried to implements the LiveData Class and it required the permission checking in onActive() function
No, it does not. What you are seeing is a Lint warning, which you can suppress.
What is required is that you hold the permission before attempting to use this particular bit of LiveData.
Is there any way to move such onRequestPermissionsResult() and checkSelfPermission() functions to the LocationListener ?
No.

Related

How to properly pause app until permission request is finished?

I'm writing an app in which its only function is acting as a receiver for Bluetooth Low Energy. The app is useless if the user does not allow BLE. When the app is started for the first time, I want it to ask the user for Locations Permission (since Android requires it for BLE). I bring the permissions dialog up, but the rest of the app continues while the user is reading the dialog, starting BLEScanner and all that. I want the app to pause while the user is reading the dialog and deciding what to do. Here's my setup:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}
//More UI preparation stuff
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
}
}
}
Where "PermissionDialog" is a different class that uses an DialogFragment to explain why the app needs the permission and then closes/restarts the app. In this case, the rest of the app continues, attempting to do Bluetooth stuff while the user is still reading the permission dialog that has popped up! Naively, I thought I could use a synchronize lock to do it, as below, but in this case, the callback is never called:
private final Object initLock = new Object();
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}
Log.i("Lock", "At the lock!");
try {
synchronized (initLock) {
initLock.wait();
}
}
catch (InterruptedException e) {
//TODO find out what to do here
}
Log.i("Lock", "Past the lock!");
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
synchronized (initLock){
initLock.notify();
}
}
else{
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
}
}
}
}
What's the proper way to do this? I have a few ideas, but they all balloon in scope. Do I need to make another class that inherits AppCompatActivity to do the permissions and I call it as a thread? But then how do I know where the onRequestPermissionResult callback will go? I'm at a loss.
Put the code inside your //More UI preparation stuff to a new method. After the permissions, say 'init()'
private void init(){
//More UI preparation stuff
}
Then inside onCreate, if permission is already granted, call init(); otherwise request permission.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
} else {
init();
}
}
Now handle the user's response inside onRequestPermissionsResult - If user has granted, initialize the UI, otherwise block the feature and/or notify the user about the issue.
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
init();
} else{
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
}
}
}
}
PS: For this same purpose, I have prepared a library which makes this process a lot easier. Have a look at my library.
You can use EasyPermissions and implement EasyPermissions.PermissionCallbacks to resolve it.
And add this annotation:#AfterPermissionGranted before the method you want to run
such as :
AfterPermissionGranted(PERMISSION_REQUESTCODE_BASE)
private void requestPerminssions(){
if(EasyPermissions.hasPermissions(this,PERMISSIONS)){
int hasCityData=config.getInt("isDataEmpty",0);
if(hasCityData==0){
new CountryInfoThread().execute();
}else {
new LocalPositionThread().execute();
}
}
}
I ended up using a private variable:
private boolean readyToStart = false;
In this way:
#Override
protected void onCreate(Bundle savedInstanceState) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);
}
else{
readyToStart = true;
}
}
#Override
protected void onResume() {
super.onResume();
if (readyToStart) {
startBluetooth();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[],
int[] grantResults) {
Log.i("Permission", "Callback made");
switch (requestCode) {
case REQUEST_CODE: {
if (permissions[0].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
PermissionDialog newDialog = new PermissionDialog();
newDialog.show(getSupportFragmentManager(), "Request Location Permission");
}
else{
startBluetooth();
}
}
}
}
}

A very long gps location search

I'm writing an app which gets user location with GPS. I added permission to manifest (android.permission.ACCESS_FINE_LOCATION), asked for required runtime permissions and made my app start searching, but this search can take a very long time (about 5 minutes) or last forever not returning any result. But the original Google Maps application determines my location instantly, so the problem is not in the GPS. Maybe someone knows what the problem is?
Here is my code:
public class MainActivity extends AppCompatActivity
implements ActivityCompat.OnRequestPermissionsResultCallback {
private static final int PERMISSION_REQUEST_GPS = 0;
LocationManager manager;
private LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
String lathitude = String.valueOf(location.getLatitude());
String longitude = String.valueOf(location.getLongitude());
Toast.makeText(getApplicationContext(),
"Your Location is - \nLat: " + lathitude + "\nLong: " + longitude,
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Sorry, location unavailable",
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
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btnShowLocation).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
findGPSLocation();
}
});
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == PERMISSION_REQUEST_GPS) {
// Request for camera permission.
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission has been granted.
startGPSSearch();
} else {
// Permission request was denied.
}
}
}
private void findGPSLocation() {
// Check if the Camera permission has been granted
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
// Permission is already available
startGPSSearch();
} else {
// Permission is missing and must be requested.
requestPermission();
}
}
private void requestPermission() {
// Permission has not been granted and must be requested.
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSION_REQUEST_GPS);
}
private void startGPSSearch() {
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
}
}
You request a GPS location, this means android is waiting for a GPS fix from satelites. If you test your code inside building this might not be possible, or might take longer time. Google maps is (most probably) using fused location api which makes use of many different sources of location - but it provides an accurracy of the location so you can make your mind if accurracy is enough for your needs (google maps shows this accurracy with larger / smaller circle around your position).
To use fused location api start here: https://developers.google.com/location-context/fused-location-provider/
You may request network location updates by adding :
manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
see here: https://developer.android.com/guide/topics/location/strategies

App Crashes instantly after asking for location permission

I have looked for question similar to this and all of them did not include the catlog so nobody could really help them. I have made sure to include it here so I hope you can help! Basically as soon as I Open the app it prompts me with a location permission saying will I allow it. As soon as i hit yes, the app crashes!
package com.worden.jason.sample;
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity implements LocationListener {
LocationManager locationManager;
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
String provider;
public void Analysis(View view) {
Intent intent = new Intent(MainActivity.this,Analysis.class);
startActivity(intent);
finish();
}
public void Tips(View view) {
Intent intent = new Intent(MainActivity.this,Tips.class);
startActivity(intent);
finish();
}
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
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.
new AlertDialog.Builder(this)
.setTitle(R.string.TileLocation)
.setMessage(R.string.TextLocation)
.setPositiveButton(R.string.Positive, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.create()
.show();
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[], #NonNull int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
} else {
// permission denied, boo! Disable the
}
return;
}
}
}
#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
protected void onResume() {
super.onResume();
if (checkLocationPermission()) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Request location updates:
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
}
}
}
log for crash
EDIT
public class MainActivity extends AppCompatActivity implements LocationListener {
LocationManager locationManager;
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
**String GPS_PROVIDER;**
public void Analysis(View view) {
Intent intent = new Intent(MainActivity.this,Analysis.class);
startActivity(intent);
finish();
}
public void Tips(View view) {
Intent intent = new Intent(MainActivity.this,Tips.class);
startActivity(intent);
finish();
}
**#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);**
}
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
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.
new AlertDialog.Builder(this)
.setTitle(R.string.TileLocation)
.setMessage(R.string.TextLocation)
.setPositiveButton(R.string.Positive, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.create()
.show();
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[], #NonNull int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
locationManager.requestLocationUpdates(GPS_PROVIDER, 400, 1, this);
}
} else {
// permission denied, boo! Disable the
}
return;
}
}
}
#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
protected void onResume() {
super.onResume();
if (checkLocationPermission()) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Request location updates:
locationManager.requestLocationUpdates(GPS_PROVIDER, 400, 1, this);
}
}
}
}
Two problems here:
You do not initialize the locationManager field. Your call to locationManager.requestLocationUpdates results in a NullPointerException.
You do not initialize the provider field. Your call to locationManager.requestLocationUpdates does not like this.
To fix the first problem, add this override:
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}
To fix the second problem, throw out your provider field and use LocationManager.GPS_PROVIDER (or one of the other providers defined in LocationManager) instead. Or initialize the provider field.
Setting breakpoints and running the program under a debugger is a good way to find such problems. Another approach is to look at logs – I'll bet there's a relevant stack trace in there somewhere.
Also ensure that your manifest mentions the requisite permission:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

How to get the user's location using GPS

I have an activity in which I have a text view where I want to display the distance between the user's current location and a specific address. I have the Latitude and Logitude of the address but my issue is getting the user's location. My target is when the activity is created that's when I want to get his location' without pressing any button. I have tried multiple ways: getLastKnownLocation, onLocation changed etc, but the value returned is always null.
It's important to note that I am running the app on an emulator.
Sample code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_business_list);
Bundle bundleUser = getIntent().getExtras();
final String owneruser = bundleUser.getString("username");
Bundle bundleType = getIntent().getExtras();
String type = bundleType.getString("type");
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
final TextView t = (TextView) findViewById(R.id.textView2);
listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
longitude = location.getLongitude();
latitude = location.getLatitude();
t.append("\n " + location.getLongitude() + " " + location.getLatitude());
}
#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);
startActivity(i);
}
};
final Location userLocation = new Location("");
userLocation.setLatitude(latitude);
userLocation.setLongitude(longitude);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode){
case 10:
update();
break;
default:
break;
}
}
void update(){
// first check for permissions
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_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.INTERNET}
,10);
}
}
else {
locationManager.requestLocationUpdates("gps", 5000, 0, listener);
}
}
implement your activity to LocationListener :
public class MyActivity extends AppCompatActivity implements LocationListener {
private Location userLocation = new Location("");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
}
#Override
public void onLocationChanged(Location location) {
if(location != null){
userLocation.setLatitude(location.getLatitude());
userLocation.setLongitude(location.getLongitude());
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
TRY this to grant permission:
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an expanation 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.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, RC_ACCESS_FINE_LOCATION);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an app-defined int constant. The callback method gets the result of the request.
}
}
and add this in your manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

onResult() callback from ResultCallback<LocationSettingsResult> is never called

I am trying to check the user's Location settings before retrieving their location but I cannot get the onResult callback to fire. I first initialized the GoogleClientApi object in onCreate() and tried debugging, it says "No such instance field" at the result.setResultCallback() breakpoint. I have spent numerous hours on this, please help me out!
public class MainActivity extendsAppCompatActivity
implements,OnConnectionFailedListener{
private static final int PERMISSION_CODE = 23;
private static final int RESOLUTION_CODE = 0x1;
public GoogleApiClient googleClient;
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
checkLocationSettings();
}
public void checkLocationSettings() {
googleClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
.addOnConnectionFailedListener(this)
.build();
LocationSettingsRequest.Builder locationSettingsBuilder = new LocationSettingsRequest.Builder()
.addLocationRequest(new LocationRequest().setInterval(5000)).setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleClient
, locationSettingsBuilder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult locationSettingsResult) {
Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
checkLocationPermission();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
status.startResolutionForResult(MainActivity.this, RESOLUTION_CODE);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Toast.makeText(MainActivity.this, "Location is missing", Toast.LENGTH_LONG).show();
}
}
});
}
private void checkLocationPermission() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_CODE);
} else {
googleClient.connect();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case RESOLUTION_CODE:
switch (resultCode) {
case RESULT_OK:
checkLocationPermission();
break;
case RESULT_CANCELED:
Toast.makeText(MainActivity.this, "Location is required, turn it on", Toast.LENGTH_SHORT).show();
break;
}
break;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSION_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
googleClient.connect();
} else {
Toast.makeText(MainActivity.this, "Error Activty", Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (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;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(googleClient);
textView.setText(location.getLatitude() + location.getLongitude() + "");
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
protected void onStop() {
super.onStop();
if(googleClient.isConnected()){
googleClient.disconnect();
}
}
}
From these SO threads, No such instance field and Initialize boolean value "no such instance field", if there wasn't a problem with the code, try restarting Android Studio. Maybe it's using an incorrect file from the previous version. This thread: Why is LocationSettingsResult startResolutionForResult not calling onActivityResult? might also help on how to connect to GoogleApiClient for getting the user's location.

Categories

Resources