安卓APP发送短信失败求助:已配置SEND_SMS权限仍无法发送
Hey there! Let's troubleshoot why your SMS sending feature isn't working, based on the code snippets and info you've shared. I'll walk through the most common issues and fixes step by step:
First off, make sure your SEND_SMS permission is declared outside the <application> tag in your AndroidManifest.xml—this is a super common mistake. Here's the correct structure:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.your.app.package"> <!-- Permission goes HERE, not inside <application> --> <uses-permission android:name="android.permission.SEND_SMS" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" ...> <!-- Your activities, services, etc. --> </application> </manifest>
You're already requesting permissions, but adding a pre-check ensures you only request when needed, and avoids edge cases. Update your code to check if the permission is already granted before requesting:
// Call this when you want to send an SMS public void attemptSendSMS(String phoneNumber, String message) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) { // Permission not granted, request it ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SEND_SMS}, 1); } else { // Permission already granted, send immediately sendSMS(phoneNumber, message); } }
sendSMS Method Implementation This is likely the root cause—you mentioned calling sendSMS but didn't share its code. Android has two main ways to send SMS; here's the reliable, recommended approach using SmsManager:
private void sendSMS(String phoneNumber, String message) { SmsManager smsManager = SmsManager.getDefault(); // Handle long SMS messages by splitting them automatically ArrayList<String> messageParts = smsManager.divideMessage(message); // Send the split parts (works for short messages too) smsManager.sendMultipartTextMessage(phoneNumber, null, messageParts, null, null); }
If you're using an implicit Intent to open the system SMS app instead, ensure your Intent is set up correctly:
private void sendSMSWithIntent(String phoneNumber, String message) { Intent smsIntent = new Intent(Intent.ACTION_SENDTO); smsIntent.setData(Uri.parse("smsto:" + Uri.encode(phoneNumber))); smsIntent.putExtra("sms_body", message); // Only launch if there's an app to handle the Intent if (smsIntent.resolveActivity(getPackageManager()) != null) { startActivity(smsIntent); } }
Your onRequestPermissionsResult is missing edge case handling (like when the user cancels the request). Update it to cover all scenarios:
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case 1: { // If user cancels the request, grantResults will be empty if (grantResults.length == 0) { Toast.makeText(this, "Permission request cancelled", Toast.LENGTH_SHORT).show(); return; } if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission granted—send your SMS here sendSMS(phoneNumberTo, smsMessage); } else { // Permission denied—inform the user Toast.makeText(this, "SMS permission denied, can't send messages", Toast.LENGTH_SHORT).show(); // Optional: Guide user to app settings to enable permission } return; } // Handle other request codes if needed } }
To pinpoint exactly why sending fails, add broadcast receivers to listen for SMS send/delivery statuses. This will tell you if it's a network issue, radio problem, or something else:
private void sendSMSWithStatus(String phoneNumber, String message) { SmsManager smsManager = SmsManager.getDefault(); ArrayList<String> messageParts = smsManager.divideMessage(message); // Create intents to track send/delivery status Intent sentIntent = new Intent("SMS_SENT_ACTION"); PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, sentIntent, PendingIntent.FLAG_IMMUTABLE); Intent deliveredIntent = new Intent("SMS_DELIVERED_ACTION"); PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0, deliveredIntent, PendingIntent.FLAG_IMMUTABLE); // Register receiver for send status registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { switch (getResultCode()) { case Activity.RESULT_OK: Toast.makeText(context, "SMS sent successfully!", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_NO_SERVICE: Toast.makeText(context, "No network service available", Toast.LENGTH_SHORT).show(); break; case SmsManager.RESULT_ERROR_RADIO_OFF: Toast.makeText(context, "Radio is turned off", Toast.LENGTH_SHORT).show(); break; default: Toast.makeText(context, "SMS send failed: " + getResultCode(), Toast.LENGTH_SHORT).show(); } unregisterReceiver(this); } }, new IntentFilter("SMS_SENT_ACTION")); // Register receiver for delivery status (optional) registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (getResultCode() == Activity.RESULT_OK) { Toast.makeText(context, "SMS delivered to recipient", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "SMS not delivered", Toast.LENGTH_SHORT).show(); } unregisterReceiver(this); } }, new IntentFilter("SMS_DELIVERED_ACTION")); // Send the SMS with status tracking smsManager.sendMultipartTextMessage(phoneNumber, null, messageParts, Collections.nCopies(messageParts.size(), sentPI), Collections.nCopies(messageParts.size(), deliveredPI)); }
- Avoid emulators: Some Android emulators don't support SMS sending—test on a physical device if possible.
- Verify network status: Ensure your device has cellular service and isn't in airplane mode.
- Check carrier restrictions: Make sure your plan allows SMS sending, and there are no account issues (like unpaid bills).
内容的提问来源于stack exchange,提问作者omriman12




