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
相关产品推荐
相关产品推荐

