You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio开发APP短信权限适配及发送前校验方案咨询

Android短信权限正确处理方案及发送前检查逻辑

嘿,这个短信权限的问题我太熟了,不同Android版本的权限规则差异确实容易踩坑,我来给你梳理下正确的处理方式,解决你在API26上失效的问题。

首先得明确:SEND_SMS属于危险权限,从Android 6.0(API23)开始,危险权限不能只靠Manifest声明,必须动态申请用户授权。API13的时候还没有动态权限机制,所以你当时登录时申请能生效,但到了API26(Android8.0),必须严格遵循动态权限的流程。

一、基础准备:Manifest声明权限

不管哪个Android版本,第一步都要在AndroidManifest.xml里声明权限,这是前提:

<uses-permission android:name="android.permission.SEND_SMS" />

二、完整权限处理流程

1. 发送前先检查权限

每次准备发送短信前,都要先检查权限是否已授予,这是核心步骤:

private boolean hasSendSmsPermission() {
    return ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS)
            == PackageManager.PERMISSION_GRANTED;
}

2. 无权限时发起申请

如果权限未授予,分两种情况处理:

  • 如果用户之前拒绝过权限但没勾选“不再询问”,先弹出对话框解释权限用途,再申请;
  • 如果是第一次申请或用户之前没拒绝过,直接发起权限申请。

代码示例:

private static final int REQUEST_CODE_SEND_SMS = 100;

private void requestSendSmsPermission() {
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.SEND_SMS},
            REQUEST_CODE_SEND_SMS);
}

private void prepareSendSms() {
    if (hasSendSmsPermission()) {
        // 已有权限,直接执行发送逻辑
        sendSms();
    } else {
        // 判断是否需要向用户解释权限用途
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS)) {
            // 弹出对话框说明为什么需要这个权限,提升用户授权意愿
            new AlertDialog.Builder(this)
                    .setTitle("需要短信权限")
                    .setMessage("为了能正常发送通知/验证码短信,请授予我们短信权限")
                    .setPositiveButton("确定", (dialog, which) -> requestSendSmsPermission())
                    .setNegativeButton("取消", null)
                    .show();
        } else {
            // 直接发起权限申请
            requestSendSmsPermission();
        }
    }
}

3. 处理权限申请回调

必须在Activity/Fragment里重写回调方法,处理用户的授权结果:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_CODE_SEND_SMS) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 用户授权成功,执行发送短信
            sendSms();
        } else {
            // 用户拒绝授权
            if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS)) {
                // 用户拒绝且勾选了“不再询问”,需要引导用户去设置页开启权限
                Toast.makeText(this, "短信权限已被拒绝,请前往应用设置开启", Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                Uri uri = Uri.fromParts("package", getPackageName(), null);
                intent.setData(uri);
                startActivity(intent);
            } else {
                // 用户只是拒绝,没勾选“不再询问”,可以提示后续还能申请
                Toast.makeText(this, "需要短信权限才能发送短信", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

4. 发送短信的核心逻辑

权限没问题后,就可以调用SmsManager发送短信了(支持长短信拆分):

private void sendSms() {
    String phoneNumber = "目标手机号";
    String message = "短信内容";
    SmsManager smsManager = SmsManager.getDefault();
    // 如果短信内容过长,自动拆分发送
    if (message.length() > 160) {
        ArrayList<String> parts = smsManager.divideMessage(message);
        smsManager.sendMultipartTextMessage(phoneNumber, null, parts, null, null);
    } else {
        smsManager.sendTextMessage(phoneNumber, null, message, null, null);
    }
}

三、为什么你之前API26的尝试失败?

大概率是这几个原因:

  • 没有正确重写onRequestPermissionsResult回调,导致授权结果没被处理;
  • 忽略了shouldShowRequestPermissionRationale的判断,用户拒绝后没有引导逻辑;
  • 申请权限时的权限数组写错了,比如漏了SEND_SMS。

四、最佳实践建议

  • 不要在登录页一次性申请所有权限,按需申请(比如用户点击“发送短信”按钮时再申请),用户更容易理解权限用途,授权率更高;
  • 处理好用户拒绝权限的场景,尤其是“不再询问”的情况,避免用户后续无法使用功能;
  • 测试时要覆盖不同Android版本(API23+),确保权限逻辑在各版本都能正常工作。

内容的提问来源于stack exchange,提问作者MidnightP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:07:01