How to properly pause app until permission request is finished?

Clash Royale CLAN TAG#URR8PPP
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 StringManifest.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 StringManifest.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.
3 Answers
3
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
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();
Put the code inside your //More UI preparation stuff to a new method. After the permissions, say 'init()'
//More UI preparation stuff
init()
private void init()
//More UI preparation stuff
Then inside onCreate, if permission is already granted, call init(); otherwise request permission.
onCreate
init();
@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 StringManifest.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.
onRequestPermissionsResult
@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.
No, showing a doalog does not affect activity life cycle. Why don't you just try it?
– Nabin Bhandari
yesterday
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 StringManifest.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();
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I had thought about that, but in this case, once the Permission dialog is up, the app lifecycle will chug ahead to onStart() and onResume() potentially while the user is still reading the dialog, right?
– Eric
yesterday