0

I'm working on an android project that requires location permission. I followed the documentation and everything works fine for the permission itself. But my app heavily depends on that permission so nothing will work if not granted. anyway, my problem is that I have a function that requests the permission as follows (knowing that the function hasPermission() just checks if permission was granted before or not):

public void requestPermission() {
    if(!hasPermission()){
        ActivityCompat.requestPermissions(MainActivity.this, new String[] {ACCESS_FINE_LOCATION}, REQUEST_CODE);
        Toast.makeText(this, "Here", Toast.LENGTH_SHORT).show();
    }
}

I handled my onRequestPermissionsResult as follows :

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "Location Permission Granted", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "Location Permission Denied", Toast.LENGTH_SHORT).show();
        }
    }
}

and my onCreate() is :

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    requestPermission();
    Toast.makeText(this, "In main", Toast.LENGTH_SHORT).show();
}

How can I make the Toast in my onCreate() method wait until the user finishes from choosing from the permission dialog box, because if I directly try to use my hasPermission() function it will check even before the user chooses?

------------------------Edit----------------------------------

the onRequestPermissionsResult is deprecated so i used this :

private ActivityResultLauncher<String> permission = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> {
    if(result){
        Toast.makeText(this, "Granted", Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(this, "Denied", Toast.LENGTH_SHORT).show();
    }
});

and my onCreate() :

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    permission.launch(Manifest.permission.ACCESS_FINE_LOCATION);
    Toast.makeText(this, "In main", Toast.LENGTH_SHORT).show();
}

and still the toast after permission. launch() ran before completing the permission dialog box.

moustafa
  • 27
  • 5
  • `onRequestPermissionsResult` is deprecated; please check [here](https://stackoverflow.com/questions/66551781/android-onrequestpermissionsresult-is-deprecated-are-there-any-alternatives) – Zain Jun 18 '22 at 11:19
  • @Zain i just implemented it and still the toast under my permission.launch() ran before completing it – moustafa Jun 18 '22 at 11:42
  • @moustafa Try Dexter library its best for permission handler !! – Rahul Pandey Jun 18 '22 at 11:55

1 Answers1

0

how can i make the Toast in my onCreate() method wait until the user finish from choosing from the permission dialog box

This is normal because requesting the permission takes some time to check if the system already granted this permission to my app or not. And this is done asynchronously; so the onCreate() will go ahead and continue executing by showing the Toast and returning.

Generally speaking, you shouldn't seize the main thread in Android to avoid Application Not Responding (ANR); so, pausing the onCreate() until it checks there is a granted permission or not will cause ANR.

until the user finish from choosing

How could we know that the user will immediately choose an option or waits one hour later on?

So, the right way to do this is in the ActivityResultLauncher callback which waits for the user reaction asynchronously:

private ActivityResultLauncher<String> permission = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> {
    if(result){
        Toast.makeText(this, "Granted", Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(this, "Denied", Toast.LENGTH_SHORT).show();
    }

    // The permission dialog gone; show the Toast
    Toast.makeText(this, "In main", Toast.LENGTH_SHORT).show();
});

Or probably you can fire another listener callback or update a LiveData object. But all this will also go in the ActivityResultLauncher callback.

Zain
  • 37,492
  • 7
  • 60
  • 84
  • its my first time using callbacks so sorry for asking how can i make it wait for the user reaction asynchronously – moustafa Jun 18 '22 at 12:00
  • @moustafa you don't have to do much as the `ActivityResultLauncher` handles that for you using its callback in the second argument of the `registerForActivityResult`.. This callback get triggered asynchronously whenever the user closes the permission dialog. So, you can just show the Toast there – Zain Jun 18 '22 at 12:07
  • i cant get my head over it. like after i get my permission granted i want to show another dialog box for some other thing and then goes the actual code of the app. If i understood it correctly i should do it all in the callback ? – moustafa Jun 18 '22 at 13:28
  • Yes that's right, within the grating `if(result)` branch you can do whatever you want. – Zain Jun 18 '22 at 13:30
  • okay and i can update the UI and all right ? like switching fragments and all ? – moustafa Jun 18 '22 at 13:37
  • Absolutely; why not? Did you find obstacles on it? – Zain Jun 18 '22 at 13:42
  • no i just tried it and worked out fine thank alot for the help – moustafa Jun 18 '22 at 14:03