1

I'd like for a user who starts the application for the first time on a device to be able to access GPS data in that session. Currently, the user must close and then restart the application after providing location permission for the location data to show in the application. I have tried a variety of methods to resolve this. Most recently, I have moved requestPermission into Fragment1 which is also where locationManager is located.

public class Fragment1 extends Fragment {
public static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.data_capture, container, false);
    requestPermission(v);
    permissionAssessment(v);
...
return (v);
}


public void requestPermission(View v) {//This works, only poulates after restart...
    int permissionCheck = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION);

    if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION);
        //conditional here so that if conditionals granted do below, if refused, go away...
    }else{
        mGpsLocationListener = new GpsLocationListener();
        lm = (LocationManager) getActivity().getSystemService(getActivity().LOCATION_SERVICE);
        mGpsStatus = lm.getGpsStatus(mGpsStatus);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, mGpsLocationListener);
    }
}   

In addition, I took the caveman approach, and created "permissionAssessment()" that would run immediately following requestPermission() assuming that perhaps since permissions were likely granted by the user in requestPermission(), I could run checkSelfPermission and force location services to start that way. No cigar. See below.

  public void permissionAssessment(View v){
    int permissionCheck = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION);
    if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
        mGpsLocationListener = new GpsLocationListener();
        lm = (LocationManager) getActivity().getSystemService(getActivity().LOCATION_SERVICE);
        mGpsStatus = lm.getGpsStatus(mGpsStatus);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, mGpsLocationListener);
    }
}

Note that permissionAssessment() works fine if the device already has ACCESS_FINE_LOCATION permissions granted. It just does not work following the newly installed permissions from requestPermission() when that is used and there were no pre-existing permissions on the device.

Furthermore, fyi this application starts on the tab associated with Fragment1 and has constantly updated gps satellite time displayed. Satellite/GPS data shows fine AFTER the application has been restarted following the session where the user granted location permissions. I'd strongly prefer that the GPS "go-live" in the session where the user sets permissions. Constructive suggestions would be appreciated. Thanks in advance.

Update, 5/14/2021: This is what ended up working for me,

public class MainActivity extends AppCompatActivity {
...
private boolean requestPermissions() {
    int iExtStorage = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    int iCoarseLocation = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION);
    int iFineLocation = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION);
    List<String> listPermissionsNeeded = new ArrayList<>();

   if (iExtStorage != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }
    if (iFineLocation != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
    }
    if (iCoarseLocation != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
    }
    if (!listPermissionsNeeded.isEmpty())
    {
       ActivityCompat.requestPermissions(this,listPermissionsNeeded.toArray
                (new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
        return false;
    }
    getLocation();
    return true;
} 

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case REQUEST_ID_MULTIPLE_PERMISSIONS: {
             if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // location-related task you need to do.
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) {
                    getLocation();
                }
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        == PackageManager.PERMISSION_GRANTED) {
                }
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        != PackageManager.PERMISSION_GRANTED) {
                }
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
                }
            }
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            return;
        }
    }
  }
...
}

Update #2, 5/14/2021: Per Sasaki's additional comment. This is from the fragment.

public class dataCapture extends Fragment {
...
private boolean requestPermission(View v) {
    int iExtStorage = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    int iCoarseLocation = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_COARSE_LOCATION);
    int iFineLocation = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION);
    List<String> listPermissionsNeeded = new ArrayList<>();

    if (iExtStorage != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }
    if (iFineLocation != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
    }
    if (iCoarseLocation != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
    }
    if (!listPermissionsNeeded.isEmpty())
    {
        requestPermissions(listPermissionsNeeded.toArray
                (new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
        return false;
    }
    getLocation();
    return true;
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case REQUEST_ID_MULTIPLE_PERMISSIONS: {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (ContextCompat.checkSelfPermission(getActivity(),
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) {
                    getLocation();
                }
                if (ContextCompat.checkSelfPermission(getActivity(),
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        == PackageManager.PERMISSION_GRANTED) {
                }
                if (ContextCompat.checkSelfPermission(getActivity(),
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        != PackageManager.PERMISSION_GRANTED) {
                }
                if (ContextCompat.checkSelfPermission(getActivity(),
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
                }
            }
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            return;
        }
    }
  }
...
}
portsample
  • 1,986
  • 4
  • 19
  • 35
  • "Currently, user must close and then restart the application after providing permission for the GPS hardware to be accessed and location data to show in the application" -- not normally. My guess is that you are trying to use `Fragment1` before you have obtained permission. You need to postpone trying to do something that needs permission until you have that permission. – CommonsWare May 10 '21 at 22:10

1 Answers1

0

In addition, I took the caveman approach, and created "permissionAssessment()" that would run immediately following requestPermission() assuming that perhaps since permissions were likely granted by the user in requestPermission().

This approach will not work the first time when the permissions are granted by user. This is because a prompt is shown to user for requesting permission using ActivityCompat.requestPermissions(...). The actual granting/denial of permission would be done on a later stage when the user interacts with the prompt.

This means that the function permissionAssessment(...) which is being immediately run after the ActivityCompat.requestPermission(...) will not have the permissions hence wont run successfully for the first time and will require a Fragment "reload".

To ensure a successful run, you'll have to call the permissionAssessment(...) in the "success" callback of ActivityCompat.requestPermission(...). This is done using the function onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults).

Here's my implementation :-

public class Fragment1 extends Fragment {
public static final int REQUEST_FINE_LOCATION_CODE = 1;
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.data_capture, container, false);

    permissionAssessment(v);

...
return (v);
}


public void permissionAssessment(View v){
    int permissionCheck = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION);

    if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
        // Permission is granted, proceed to get location.
        getLocation()
    } else {
        // Permission is not granted, request permissions.
        // Only the prompt is shown here, nothing else will happen.
        ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_FINE_LOCATION_CODE);
    }
}
    
/**
 * This Function is responsible for handling what happens when permissions are granted by the user.
 */
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    
    if (requestCode == REQUEST_FINE_LOCATION_CODE) {

        if (grantResults.length > 0) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                
                // Permissions Granted!
                // Get Location as soon as the permissions are granted.
                getLocation();
            }
        } else {
                
            // Permission Denied by the user
            // Show a prompt or do nothing as per your use case.
        }
    }

    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}


public void getLocation() {
    mGpsLocationListener = new GpsLocationListener();
    lm = (LocationManager) getActivity().getSystemService(getActivity().LOCATION_SERVICE);
    mGpsStatus = lm.getGpsStatus(mGpsStatus);
    lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, mGpsLocationListener);
}

Please refer to this

Sasaki
  • 118
  • 9
  • 1
    Thank you for posting a suggested solution as well as an explanation. However- onRequestPermissionsResult may not be engaging as anticipated. Immediately following permission acceptance in the popup boxes, the gps does not become active, not until after the application is restarted. I did insert a diagnostic Toast message in onRequestPermissions,(oRP) above getLocation(), however it did not display. Hence my conclusion that oRP may not be running. Thanks again. – portsample May 12 '21 at 15:37
  • 1
    Moving the location manager from the fragment to the MainActivity resolved the issue with onRequestPermissionsResult. – portsample May 12 '21 at 19:27
  • Ah! That's my bad. the oRP is not receiving the result in fragment but in the activity. This is because we should use `requestPermissions` instead of `ActivityCompat.requestPermissions`. Please refer to this for more details - https://stackoverflow.com/questions/35989288/onrequestpermissionsresult-not-being-called-in-fragment-if-defined-in-both-fragm . – Sasaki May 14 '21 at 09:50