注册CallStateListener时出现错误的权限对话框。

huangapple go评论96阅读模式
英文:

Wrong permission dialog when registering CallStateListener

问题

我的应用程序希望在手机接到电话时停止音频处理。

当应用程序启动时,Android 认为应用程序想要拨打和管理电话,这是错误的。

// 在构造函数中
requestPermissionLauncher = activity.registerForActivityResult(
    new ActivityResultContracts.RequestPermission(), 
    this::registerTelephonyCallback);

// 在初始化过程中
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    if(ActivityCompat.checkSelfPermission(activity.getContext(), Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED){
        registerTelephonyCallback(true);
    } else {
        requestPermissionLauncher.launch(Manifest.permission.READ_PHONE_STATE);
    }
} else {
    //noinspection deprecation
    // 使用已弃用的 TelephonyManager.listen()
}

这是 registerTelephonyCallback() 方法:

private void registerTelephonyCallback(boolean phoneStateCanBeRead){
    if (!phoneStateCanBeRead){
        return;
    }
    TelephonyManager telephonyManager = (TelephonyManager) activity.getContext().getSystemService(Context.TELEPHONY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        Executor mainExecutor = ContextCompat.getMainExecutor((Activity)activity);
        telephonyManager.registerTelephonyCallback(INCLUDE_LOCATION_DATA_NONE, mainExecutor, new PhoneCallback());
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        Executor mainExecutor = ContextCompat.getMainExecutor((Activity)activity);
        telephonyManager.registerTelephonyCallback(mainExecutor, new PhoneCallback());
    }
}

这是我的 TelephonyCallback 实现:

@RequiresApi(api = Build.VERSION_CODES.S)
private class PhoneCallback extends TelephonyCallback implements TelephonyCallback.CallStateListener {
    @Override
    public void onCallStateChanged(int state) {
        if (!audioServiceIsRegistered()) {
            return;
        }
        if (state == TelephonyManager.CALL_STATE_IDLE) {
            if (isExternallyPaused) {
                playAudio();
            }
            isExternallyPaused = false;
        } else {
            pauseAudio();
            isExternallyPaused = true;
        }
    }
}
英文:

My app wants to stop audio processing when the phone receives a call.

When the app starts, Android thinks, that the app wants to make and manage phone calls, which is wrong.注册CallStateListener时出现错误的权限对话框。

// in constructor
requestPermissionLauncher = activity.registerForActivityResult(
    new ActivityResultContracts.RequestPermission(), 
    this::registerTelephonyCallback);

// during init
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    if(ActivityCompat.checkSelfPermission(activity.getContext(), Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED){
        registerTelephonyCallback(true);
    } else {
        requestPermissionLauncher.launch(Manifest.permission.READ_PHONE_STATE);
    }
} else {
    //noinspection deprecation
    // use deprecated TelephonyManager.listen()
}

Here is the method registerTelephonyCallback():

private void registerTelephonyCallback(boolean phoneStateCanBeRead){
    if (!phoneStateCanBeRead){
        return;
    }
    TelephonyManager telephonyManager = (TelephonyManager) activity.getContext().getSystemService(Context.TELEPHONY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        Executor mainExecutor = ContextCompat.getMainExecutor((Activity)activity);
        telephonyManager.registerTelephonyCallback(INCLUDE_LOCATION_DATA_NONE, mainExecutor, new PhoneCallback());
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        Executor mainExecutor = ContextCompat.getMainExecutor((Activity)activity);
        telephonyManager.registerTelephonyCallback(mainExecutor, new PhoneCallback());
    }
}

This is my TelephonyCallback implementation:

@RequiresApi(api = Build.VERSION_CODES.S)
private class PhoneCallback extends TelephonyCallback implements TelephonyCallback.CallStateListener {
    @Override
    public void onCallStateChanged(int state) {
        if (!audioServiceIsRegistered()) {
            return;
        }
        if (state == TelephonyManager.CALL_STATE_IDLE) {
            if (isExternallyPaused) {
                playAudio();
            }
            isExternallyPaused = false;
        } else {
            pauseAudio();
            isExternallyPaused = true;
        }
    }
}

答案1

得分: 1

根据文档,某些权限具有权限组,当您请求权限时,向用户显示的确认对话框仅与该组相关。

在您的情况下,android.permission.READ_PHONE_STATE 的权限组是 android.permission-group.PHONE,因此当您请求权限时,详细信息将包含 Phone 权限组的详细信息。

根据谷歌的说法,其目的是最小化可能的对话框数量:

权限组帮助系统在应用请求密切相关的权限时最小化向用户呈现的系统对话框数量。当用户被提示为应用授予权限时,属于同一组的权限将在同一界面中呈现。但是,请注意,权限可以在不通知的情况下更改组,因此不要假设某个权限与任何其他权限分组。

我正在开发一个只请求接收短信的应用程序,但对话框显示该应用程序想要发送和接收短信。

似乎这就是系统的设计方式。

英文:

According to documentation, some permissions have permission groups, and when you request permission, the confirmation dialog shown to the user only relates to group.

In your case, the group of android.permission.READ_PHONE_STATE is android.permission-group.PHONE. so when you request permission, the details will contain the details of Phone permission group.

According to google, the purpose is to minimize the number of possible dialog:

> Permission groups help the system minimize the number of system dialogs that are presented to the user when an app requests closely related permissions. When a user is presented with a prompt to grant permissions for an application, permissions belonging to the same group are presented in the same interface. However, permissions can change groups without notice, so don't assume that a particular permission is grouped with any other permission.

I work on an app that only requests receiving SMS, and the dialog said the app wants to send and receive SMS.

Seems like it's just how the system is built.

huangapple
  • 本文由 发表于 2023年7月17日 20:12:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76704346.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定