Как правильно приостановить приложение, пока запрос разрешения не будет завершен? - PullRequest
0 голосов
/ 18 сентября 2018

Я пишу приложение, в котором его единственная функция - приемник Bluetooth Low Energy. Приложение бесполезно, если пользователь не разрешает BLE. Когда приложение запускается в первый раз, я хочу, чтобы оно запрашивало у пользователя разрешение на размещение (так как Android требует его для BLE). Я открываю диалог разрешений, но остальная часть приложения продолжается, пока пользователь читает диалог, запускает BLEScanner и все такое. Я хочу, чтобы приложение сделало паузу, пока пользователь читает диалог и решает, что делать. Вот мои настройки:

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

Где "PermissionDialog" - это другой класс, который использует DialogFragment, чтобы объяснить, почему приложению требуется разрешение, а затем закрывает / перезапускает приложение. В этом случае остальная часть приложения продолжает работу, пытаясь выполнить Bluetooth, пока пользователь все еще читает диалоговое окно с разрешениями, которое появилось! Наивно, я думал, что мог бы использовать синхронизирующую блокировку, чтобы сделать это, как показано ниже, но в этом случае обратный вызов никогда не вызывается:

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

Как правильно это сделать? У меня есть несколько идей, но все они раздуваются. Нужно ли создавать другой класс, который наследует AppCompatActivity для выполнения разрешений, и я вызываю его как поток? Но тогда как мне узнать, куда пойдет обратный вызов onRequestPermissionResult? Я в растерянности.

Ответы [ 3 ]

0 голосов
/ 18 сентября 2018

Вы можете использовать EasyPermissions и реализовать EasyPermissions.PermissionCallbacks, чтобы решить его.И добавьте эту аннотацию: @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();
        }
    }
}
0 голосов
/ 20 сентября 2018

Я использовал закрытую переменную:

private boolean readyToStart = false;

Таким образом:

@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();
                    }
                }
            }
        }
    }
0 голосов
/ 18 сентября 2018

Поместите код внутри //More UI preparation stuff в новый метод.После разрешений произнесите 'init()'

private void init(){
    //More UI preparation stuff
}

Затем внутри 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 String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_CODE);

    } else {
        init();
    }
}

Теперь обработайтеответ пользователя внутри 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: для этой же цели я подготовилбиблиотека, которая делает этот процесс намного проще.Взгляните на мою библиотеку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...