Android Marshmallow及以上设备SmsManager失效致应用崩溃问题排查
解决Android 6.0+系统中短信发送应用崩溃的问题
嘿,我一眼就看出问题所在了——你的APP在Android 4.3上正常,但到Marshmallow(6.0)及以上就崩溃,核心原因是Android 6.0引入的动态权限机制。在API 23之前,权限只需要在Manifest里声明就行,但从6.0开始,像SEND_SMS这种「危险权限」必须在运行时向用户主动申请,用户同意后才能使用。
你的代码里已经做了权限检查和请求的第一步,但漏掉了最关键的权限回调处理——如果用户拒绝权限后你还是尝试发送短信,必然会触发崩溃。下面是完整的修复方案:
第一步:确认Manifest权限声明
先确保你已经在AndroidManifest.xml里添加了短信权限(这步你大概率已经做了,但还是确认下):
<uses-permission android:name="android.permission.SEND_SMS" />
第二步:完善短信发送逻辑
把你的sendSMS方法改成带权限判断和回调的完整逻辑:
首先定义一个权限请求码(放在你的Activity类里):
private static final int MY_PERMISSION_REQUEST_SEND_SMS = 1001; // 数值可以自定义 // 用来保存请求权限前的短信内容和手机号,避免用户重新输入 private String mPendingPhoneNumber; private String mPendingMessage;
然后修改sendSMS方法:
private void sendSMS(String phoneNumber, String message) { // 先保存要发送的内容,后续回调里要用 mPendingPhoneNumber = phoneNumber; mPendingMessage = message; // 检查是否已获得短信发送权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) { // 权限未授予,向用户申请 ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.SEND_SMS}, MY_PERMISSION_REQUEST_SEND_SMS ); } else { // 权限已授予,直接执行发送 performSMSDelivery(phoneNumber, message); } }
第三步:处理权限请求回调
必须重写onRequestPermissionsResult方法,处理用户的权限选择结果:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == MY_PERMISSION_REQUEST_SEND_SMS) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 用户同意了权限,执行发送 performSMSDelivery(mPendingPhoneNumber, mPendingMessage); } else { // 用户拒绝了权限,给个友好提示 Toast.makeText(this, "没有短信权限无法发送消息哦", Toast.LENGTH_SHORT).show(); } } }
第四步:实现真正的短信发送逻辑
把发送短信的核心逻辑抽成单独方法,避免重复代码:
private void performSMSDelivery(String phoneNumber, String message) { SmsManager smsManager = SmsManager.getDefault(); try { smsManager.sendTextMessage(phoneNumber, null, message, null, null); Toast.makeText(this, "短信发送成功!", Toast.LENGTH_SHORT).show(); } catch (Exception e) { Toast.makeText(this, "发送失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); e.printStackTrace(); } }
额外提示
如果用户之前已经拒绝过权限请求,下次申请时可以弹出一个对话框,解释为什么需要这个权限(比如「我们需要短信权限来帮你发送验证码」),引导用户授予权限,提升用户体验。
内容的提问来源于stack exchange,提问作者Dylan
相关产品推荐
相关产品推荐

