java - 如何在权限请求完成之前正确暂停应用程序?

标签 java android asynchronous android-permissions

我正在编写一个应用程序,其中它的唯一功能是充当低功耗蓝牙的接收器。如果用户不允许 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 来解释为什么应用程序需要权限,然后关闭/重新启动应用程序。在这种情况下,应用程序的其余部分继续,尝试在用户仍在阅读弹出的权限对话框时执行蓝牙操作!天真地,我以为我可以使用同步锁来做到这一点,如下所示,但在这种情况下,永远不会调用回调:

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 回调会去哪里呢?我很茫然。

最佳答案

将代码放入您的//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.

关于java - 如何在权限请求完成之前正确暂停应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52378583/

相关文章:

android - Flutter 中的 rxdart 用法未被识别

android - 在 Android 中,无尽滚动在 fragment 中不起作用

android - Kotlin/anko 多个异步任务

iOS 在 vi​​ewDidLoad 中预加载 AlertView : Any nicer way to code this?

java - Java 中的 Scanner 会阻止文件输入吗?

java - java.util.Objects.equals 和 com.google.common.base.Objects.equals 有什么区别?

java - 按钮操作监听器在 Java 窗口中添加新的文本字段

java - 在传递给 JSP 标记处理程序之前评估变量

Android工作室终端不显示

java - 异步 session 方法是否/可以比 servlet 调用的生存时间更长