代码之家  ›  专栏  ›  技术社区  ›  MW2023

如何正确暂停应用程序直到权限请求完成?

  •  1
  • MW2023  · 技术社区  · 7 年前

    我正在写一个应用程序,它唯一的功能就是充当蓝牙低能量接收器。如果用户不允许使用BLE,那么应用程序就没用了。当应用程序第一次启动时,我希望它向用户请求Locations权限(因为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来解释应用程序为什么需要权限,然后关闭/重新启动应用程序。在这种情况下,应用程序的其余部分继续,试图在用户仍在阅读弹出的权限对话框时执行蓝牙操作!天真地说,我以为可以使用同步锁来完成,如下所示,但在本例中,从不调用回调:

    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 回复  |  直到 7 年前
        1
  •  2
  •   Nabin Bhandari    7 年前

    把密码放在你的电脑里 //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 -如果用户已授权,则初始化UI,否则阻止该功能和/或将问题通知用户。

    @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:出于同样的目的,我准备了一个库,使这个过程更容易。看一看 my library.

        2
  •  1
  •   Seraph Gabriel    7 年前

    并添加此注释 @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();
            }
        }
    }
    
        3
  •  1
  •   MW2023    7 年前

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