Android API 发送短信技术文档

Android API 发送短信技术文档

概述

本文档介绍如何使用 Android 系统 API 发送短信。提供了 SmsUtils 工具类和 SmsUtilsExample 示例类,简化短信发送功能的实现。

功能特性

  • 简单短信发送
  • 带回调结果的短信发送
  • 长短信自动分段发送(超过 160 字符)
  • 发送状态和送达状态监听
  • 运行时权限处理
  • 设备支持检测

权限要求

AndroidManifest.xml 配置

xml 复制代码
<uses-permission android:name="android.permission.SEND_SMS" />

Android 6.0+ 运行时权限

需要在代码中动态申请 SEND_SMS 权限。


SmsUtils 工具类

SmsUtils 是一个 Kotlin object 单例,封装了所有短信发送相关的方法。

方法 1:简单发送短信

功能:最简单的短信发送方法,不关心发送结果。

源码

kotlin 复制代码
@Deprecated("建议使用 sendSmsWithCallback 以获取发送结果")
fun sendSms(context: Context, phoneNumber: String, message: String): Boolean {
    return try {
        val smsManager = SmsManager.getDefault()
        smsManager.sendTextMessage(phoneNumber, null, message, null, null)
        Log.d(TAG, "短信发送请求已提交: $phoneNumber")
        true
    } catch (e: Exception) {
        Log.e(TAG, "短信发送失败", e)
        false
    }
}

参数说明

  • context: 应用上下文
  • phoneNumber: 目标手机号
  • message: 短信内容

返回值

  • true: 发送请求已成功提交
  • false: 发送失败

注意 :此方法已废弃,推荐使用 sendSmsWithCallback

原理说明

  • 调用 SmsManager.getDefault() 获取短信管理器
  • 调用 sendTextMessage() 方法发送短信
  • 最后两个 null 参数分别表示不监听发送状态和送达状态

方法 2:带回调的短信发送

功能:发送短信并通过回调函数通知发送结果。

源码

kotlin 复制代码
fun sendSmsWithCallback(
    context: Context,
    phoneNumber: String,
    message: String,
    onResult: ((success: Boolean, errorMessage: String?) -> Unit)? = null
) {
    try {
        val smsManager = SmsManager.getDefault()

        // 创建发送状态 PendingIntent
        val sentIntent = Intent(SMS_SENT_ACTION).let { intent ->
            intent.putExtra("phone_number", phoneNumber)
            PendingIntent.getBroadcast(
                context,
                System.currentTimeMillis().toInt(),
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
        }

        // 创建送达状态 PendingIntent
        val deliveredIntent = Intent(SMS_DELIVERED_ACTION).let { intent ->
            intent.putExtra("phone_number", phoneNumber)
            PendingIntent.getBroadcast(
                context,
                (System.currentTimeMillis() + 1).toInt(),
                intent,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
        }

        // 注册广播接收器(建议在 Activity/Fragment 中注册,这里为简化逻辑)
        // 实际使用时,应该在发送前注册广播接收器来监听结果

        smsManager.sendTextMessage(phoneNumber, null, message, sentIntent, deliveredIntent)
        Log.d(TAG, "短信发送请求已提交: $phoneNumber")

        onResult?.invoke(true, null)
    } catch (e: Exception) {
        Log.e(TAG, "短信发送失败: ${e.message}", e)
        onResult?.invoke(false, e.message)
    }
}

参数说明

  • context: 应用上下文
  • phoneNumber: 目标手机号
  • message: 短信内容
  • onResult: 发送结果回调函数

原理说明

  • 创建两个 PendingIntent:一个用于监听发送状态,一个用于监听送达状态
  • 使用 SMS_SENT_ACTIONSMS_DELIVERED_ACTION 作为广播 action
  • 通过 putExtra() 将手机号存入 Intent,方便后续识别
  • 使用 FLAG_UPDATE_CURRENT 更新已存在的 PendingIntent
  • 使用 FLAG_IMMUTABLE (Android 12+ 要求) 标记 PendingIntent 为不可变

方法 3:发送长短信(自动分段)

功能:处理超过 160 字符的长短信,自动分段发送。

源码

kotlin 复制代码
fun sendLongSms(
    context: Context,
    phoneNumber: String,
    message: String,
    onProgress: ((current: Int, total: Int) -> Unit)? = null,
    onResult: ((success: Boolean, errorMessage: String?) -> Unit)? = null
) {
    try {
        val smsManager = SmsManager.getDefault()

        // 分割短信
        val parts = smsManager.divideMessage(message)

        if (parts.isEmpty()) {
            onResult?.invoke(false, "短信内容为空")
            return
        }

        // 如果只有一段,直接发送
        if (parts.size == 1) {
            sendSmsWithCallback(context, phoneNumber, parts[0], onResult)
            return
        }

        // 多段短信发送
        val sentIntents = ArrayList<PendingIntent>()
        val deliveredIntents = ArrayList<PendingIntent>()

        for (i in parts.indices) {
            val sentIntent = Intent(SMS_SENT_ACTION).let { intent ->
                intent.putExtra("phone_number", phoneNumber)
                intent.putExtra("part_index", i)
                intent.putExtra("total_parts", parts.size)
                PendingIntent.getBroadcast(
                    context,
                    (System.currentTimeMillis() + i).toInt(),
                    intent,
                    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
                )
            }
            sentIntents.add(sentIntent)

            val deliveredIntent = Intent(SMS_DELIVERED_ACTION).let { intent ->
                intent.putExtra("phone_number", phoneNumber)
                intent.putExtra("part_index", i)
                intent.putExtra("total_parts", parts.size)
                PendingIntent.getBroadcast(
                    context,
                    (System.currentTimeMillis() + i + 100).toInt(),
                    intent,
                    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
                )
            }
            deliveredIntents.add(deliveredIntent)

            onProgress?.invoke(i + 1, parts.size)
        }

        // 发送多段短信
        smsManager.sendMultipartTextMessage(
            phoneNumber,
            null,
            parts,
            sentIntents,
            deliveredIntents
        )

        Log.d(TAG, "长短信发送请求已提交: $phoneNumber, 共 ${parts.size} 段")
        onResult?.invoke(true, null)

    } catch (e: Exception) {
        Log.e(TAG, "长短信发送失败: ${e.message}", e)
        onResult?.invoke(false, e.message)
    }
}

参数说明

  • context: 应用上下文
  • phoneNumber: 目标手机号
  • message: 短信内容(可长可短)
  • onProgress: 发送进度回调(当前段/总段数)
  • onResult: 发送结果回调

原理说明

  • 调用 smsManager.divideMessage(message) 自动分割短信
  • 如果只有一段,调用 sendSmsWithCallback 单独处理
  • 如果多段,为每段创建独立的 PendingIntent
  • 使用 part_indextotal_parts 标记当前段的序号和总段数
  • 调用 sendMultipartTextMessage() 批量发送多段短信
  • 使用不同的 requestCode (System.currentTimeMillis() + i) 确保 PendingIntent 不冲突

方法 4:设备支持检测

功能:检查设备是否支持发送短信功能。

源码

kotlin 复制代码
fun isSmsSupported(context: Context): Boolean {
    return try {
        SmsManager.getDefault() != null
    } catch (e: Exception) {
        Log.e(TAG, "设备不支持发送短信", e)
        false
    }
}

参数说明

  • context: 应用上下文

返回值

  • true: 设备支持发送短信
  • false: 设备不支持

原理说明

  • 尝试获取 SmsManager 实例
  • 如果获取失败或抛出异常,说明设备不支持(如平板设备或不支持移动网络的设备)

方法 5:获取短信最大长度

功能:返回单条短信最大字符数。

源码

kotlin 复制代码
fun getSmsMaxLength(): Int {
    return try {
        SmsManager.getDefault() // GSM: 160, CDMA: 70
        160 // 默认返回 GSM 标准长度
    } catch (e: Exception) {
        Log.e(TAG, "获取短信长度限制失败", e)
        160
    }
}

返回值

  • 通常返回 160 字符(GSM 标准)
  • CDMA 网络可能是 70 字符

原理说明

  • GSM 网络标准:单条短信最多 160 字符
  • CDMA 网络标准:单条短信最多 70 字符
  • 该方法默认返回 160,实际使用时可根据网络类型调整

方法 6:计算短信分段数

功能:根据消息长度计算短信会被分成多少段。

源码

kotlin 复制代码
fun calculateSmsParts(message: String): Int {
    val maxLength = getSmsMaxLength()
    return if (message.length <= maxLength) 1 else (message.length + maxLength - 1) / maxLength
}

参数说明

  • message: 短信内容

返回值

  • 段数

原理说明

  • 如果消息长度 ≤ 160,返回 1
  • 否则使用公式 (长度 + 159) / 160 向上取整
  • 例如:161 字符 → (161+159)/160 = 320/160 = 2 段

方法 7:获取意图过滤器

功能:返回用于注册广播接收器的 IntentFilter。

源码

kotlin 复制代码
fun getSentIntentFilter(): IntentFilter {
    return IntentFilter(SMS_SENT_ACTION)
}

fun getDeliveredIntentFilter(): IntentFilter {
    return IntentFilter(SMS_DELIVERED_ACTION)
}

原理说明

  • 用于在 Activity/Fragment 中注册广播接收器
  • SMS_SENT_ACTION 监听发送状态
  • SMS_DELIVERED_ACTION 监听送达状态

方法 8:短信发送结果广播接收器

功能:抽象类,用于监听短信发送结果。

源码

kotlin 复制代码
abstract class SmsSentReceiver : android.content.BroadcastReceiver() {
    abstract fun onResult(
        phoneNumber: String,
        success: Boolean,
        errorCode: Int,
        errorMessage: String?
    )

    override fun onReceive(context: Context?, intent: Intent?) {
        val phoneNumber = intent?.getStringExtra("phone_number") ?: ""
        val partIndex = intent?.getIntExtra("part_index", 0) ?: 0
        val totalParts = intent?.getIntExtra("total_parts", 1) ?: 1

        val success = resultCode == android.app.Activity.RESULT_OK
        val errorCode = if (!success) resultCode else 0
        val errorMessage = getErrorMessage(errorCode)

        onResult(phoneNumber, success, errorCode, errorMessage)
    }

    private fun getErrorMessage(errorCode: Int): String? {
        return when (errorCode) {
            SmsManager.RESULT_ERROR_GENERIC_FAILURE -> "通用错误"
            SmsManager.RESULT_ERROR_RADIO_OFF -> "无线电关闭"
            SmsManager.RESULT_ERROR_NULL_PDU -> "PDU 为空"
            SmsManager.RESULT_ERROR_NO_SERVICE -> "无服务"
            SmsManager.RESULT_ERROR_LIMIT_EXCEEDED -> "超出限制"
            else -> null
        }
    }
}

使用方式

继承此抽象类并实现 onResult() 方法:

kotlin 复制代码
val receiver = object : SmsUtils.SmsSentReceiver() {
    override fun onResult(
        phoneNumber: String,
        success: Boolean,
        errorCode: Int,
        errorMessage: String?
    ) {
        if (success) {
            Log.d("SMS", "发送成功: $phoneNumber")
        } else {
            Log.e("SMS", "发送失败: $errorMessage")
        }
    }
}
context.registerReceiver(receiver, SmsUtils.getSentIntentFilter())

错误码说明

  • RESULT_ERROR_GENERIC_FAILURE: 通用错误
  • RESULT_ERROR_RADIO_OFF: 无线电关闭(飞行模式)
  • RESULT_ERROR_NULL_PDU: PDU 为空
  • RESULT_ERROR_NO_SERVICE: 无服务
  • RESULT_ERROR_LIMIT_EXCEEDED: 超出限制

原理说明

  • 从 Intent 中提取之前存储的 phone_numberpart_indextotal_parts
  • 检查 resultCode 判断是否成功
  • resultCode == Activity.RESULT_OK 表示成功
  • 其他值表示失败,通过错误码匹配错误信息

SmsUtilsExample 示例类

示例 1:简单发送短信

功能:最基础的使用示例,不关心发送结果。

源码

kotlin 复制代码
fun example1(context: Context) {
    val phoneNumber = "183XXXXXXXX"
    val message = "这是一条测试短信"

    val success = SmsUtils.sendSms(context, phoneNumber, message)
    if (success) {
        Toast.makeText(context, "短信发送请求已提交", Toast.LENGTH_SHORT).show()
    } else {
        Toast.makeText(context, "短信发送失败", Toast.LENGTH_SHORT).show()
    }
}

使用场景

  • 测试环境
  • 不关心发送结果的场景
  • 快速验证功能

示例 2:发送短信并获取结果

功能:使用回调函数获取发送结果。

源码

kotlin 复制代码
fun example2(context: Context) {
    val phoneNumber = "183XXXXXXXX"
    val message = "这是一条测试短信2"

    SmsUtils.sendSmsWithCallback(
        context = context,
        phoneNumber = phoneNumber,
        message = message
    ) { success, errorMessage ->
        if (success) {
            Log.d(TAG, "短信发送请求成功")
        } else {
            Log.e(TAG, "短信发送失败: $errorMessage")
        }
    }
}

使用场景

  • 需要知道是否提交成功
  • 记录日志
  • 显示发送状态

示例 3:发送长短信

功能:发送超过 160 字符的长短信,并监听发送进度。

源码

kotlin 复制代码
fun example3(context: Context) {
    val phoneNumber = "183XXXXXXXX"
    val message = """
        这是一条很长的短信内容,用来测试分段发送功能。
        当短信内容超过160个字符时,SmsUtils会自动将其分割成多条发送。
        这样可以确保长内容也能完整送达。
        继续添加内容以达到测试目的...
    """.trimIndent()

    // 计算会被分成多少段
    val parts = SmsUtils.calculateSmsParts(message)
    Log.d(TAG, "短信将被分成 $parts 段发送")

    SmsUtils.sendLongSms(
        context = context,
        phoneNumber = phoneNumber,
        message = message,
        onProgress = { current, total ->
            Log.d(TAG, "发送进度: $current / $total")
        },
        onResult = { success, errorMessage ->
            if (success) {
                Log.d(TAG, "长短信发送请求成功")
            } else {
                Log.e(TAG, "长短信发送失败: $errorMessage")
            }
        }
    )
}

使用场景

  • 发送验证码(可能较长)
  • 发送通知消息
  • 需要知道分段进度的场景

示例 4:在 Activity 中完整使用(包括权限申请和结果监听)

功能:完整的 Activity 集成示例,包括运行时权限申请、广播接收器注册和注销。

权限申请和发送源码

kotlin 复制代码
fun requestAndSendSms(
    activity: Activity,
    phoneNumber: String,
    message: String,
    onResult: ((success: Boolean, errorMessage: String?) -> Unit)? = null
) {
    // 检查权限
    if (ContextCompat.checkSelfPermission(
            activity,
            Manifest.permission.SEND_SMS
        ) == PackageManager.PERMISSION_GRANTED
    ) {
        // 已有权限,直接发送
        SmsUtils.sendSmsWithCallback(
            activity,
            phoneNumber,
            message,
            onResult
        )
    } else {
        // 申请权限
        ActivityCompat.requestPermissions(
            activity,
            arrayOf(Manifest.permission.SEND_SMS),
            REQUEST_SEND_SMS_PERMISSION
        )
        // 保存发送参数,在权限结果回调中使用
        savePendingSms(activity, phoneNumber, message, onResult)
    }
}

处理权限结果源码

kotlin 复制代码
fun handlePermissionResult(
    requestCode: Int,
    grantResults: IntArray,
    onPermissionResult: ((granted: Boolean) -> Unit)? = null
) {
    if (requestCode == REQUEST_SEND_SMS_PERMISSION) {
        val granted = grantResults.isNotEmpty() &&
                grantResults[0] == PackageManager.PERMISSION_GRANTED

        onPermissionResult?.invoke(granted)
    }
}

注册广播接收器源码

kotlin 复制代码
fun registerSmsReceiver(
    context: Context,
    onResult: (phoneNumber: String, success: Boolean, errorCode: Int, errorMessage: String?) -> Unit
): BroadcastReceiver {
    val receiver = object : SmsUtils.SmsSentReceiver() {
        override fun onResult(
            phoneNumber: String,
            success: Boolean,
            errorCode: Int,
            errorMessage: String?
        ) {
            onResult(phoneNumber, success, errorCode, errorMessage)
        }
    }

    context.registerReceiver(receiver, SmsUtils.getSentIntentFilter())
    return receiver
}

注销广播接收器源码

kotlin 复制代码
fun unregisterSmsReceiver(context: Context, receiver: BroadcastReceiver) {
    try {
        context.unregisterReceiver(receiver)
    } catch (e: IllegalArgumentException) {
        Log.w(TAG, "广播接收器未注册")
    }
}

保存待发送短信源码(权限申请期间使用):

kotlin 复制代码
private fun savePendingSms(
    context: Context,
    phoneNumber: String,
    message: String,
    onResult: ((success: Boolean, errorMessage: String?) -> Unit)?
) {
    // 使用 SharedPreferences 保存
    val prefs = context.getSharedPreferences("sms_pending", Context.MODE_PRIVATE)
    prefs.edit()
        .putString("phone_number", phoneNumber)
        .putString("message", message)
        .putBoolean("has_callback", onResult != null)
        .apply()

    Log.d(TAG, "已保存待发送短信,等待权限结果")
}

获取并清除待发送短信源码

kotlin 复制代码
fun getPendingSms(context: Context): Triple<String, String, Boolean>? {
    val prefs = context.getSharedPreferences("sms_pending", Context.MODE_PRIVATE)
    val phone = prefs.getString("phone_number", null)
    val msg = prefs.getString("message", null)
    val hasCallback = prefs.getBoolean("has_callback", false)

    return if (phone != null && msg != null) {
        // 清除保存的数据
        prefs.edit().clear().apply()
        Triple(phone, msg, hasCallback)
    } else {
        null
    }
}

完整的 Activity 使用示例

kotlin 复制代码
class MainActivity : AppCompatActivity() {

    private var smsReceiver: BroadcastReceiver? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 检查设备支持
        checkDeviceSupport()

        // 注册短信结果监听
        smsReceiver = SmsUtilsExample.registerSmsReceiver(this) { phone, success, code, error ->
            runOnUiThread {
                if (success) {
                    Toast.makeText(this, "发送成功: $phone", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(this, "发送失败: $error", Toast.LENGTH_SHORT).show()
                }
            }
        }

        // 发送短信(带权限检查)
        sendSmsWithPermissionCheck(this, "183XXXXXXXX", "测试短信")
    }

    private fun sendSmsWithPermissionCheck(activity: Activity, phone: String, msg: String) {
        SmsUtilsExample.requestAndSendSms(activity, phone, msg) { success, error ->
            runOnUiThread {
                Toast.makeText(this, if (success) "发送成功" else "发送失败: $error", Toast.LENGTH_SHORT).show()
            }
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        SmsUtilsExample.handlePermissionResult(requestCode, grantResults) { granted ->
            if (granted) {
                // 权限已授予,发送待发送的短信
                val pending = SmsUtilsExample.getPendingSms(this)
                pending?.let { (phone, msg, _) ->
                    SmsUtils.sendSmsWithCallback(this, phone, msg) { success, error ->
                        Log.d("SMS", if (success) "发送成功" else "发送失败: $error")
                    }
                }
            } else {
                Toast.makeText(this, "需要短信权限才能发送", Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun checkDeviceSupport() {
        val supported = SmsUtils.isSmsSupported(this)
        val maxLength = SmsUtils.getSmsMaxLength()

        Log.d("SMS", "设备支持发送短信: $supported")
        Log.d("SMS", "单条短信最大长度: $maxLength 字符")
    }

    override fun onDestroy() {
        smsReceiver?.let { SmsUtilsExample.unregisterSmsReceiver(this, it) }
        super.onDestroy()
    }
}

示例 5:检查设备支持

功能:检查设备是否支持发送短信。

源码

kotlin 复制代码
fun checkDeviceSupport(context: Context) {
    val supported = SmsUtils.isSmsSupported(context)
    val maxLength = SmsUtils.getSmsMaxLength()

    Log.d(TAG, "设备支持发送短信: $supported")
    Log.d(TAG, "单条短信最大长度: $maxLength 字符")
}

使用场景

  • 应用启动时检测
  • 适配不支持短信的设备(如某些平板)

核心概念解释

1. SmsManager

Android 系统提供的短信管理器,用于发送短信、彩信等。

kotlin 复制代码
val smsManager = SmsManager.getDefault()

2. PendingIntent

PendingIntent 是一种特殊的 Intent,可以让其他应用(如系统)代表你的应用执行操作。

在短信发送中用于:

  • 监听发送状态(SMS_SENT_ACTION
  • 监听送达状态(SMS_DELIVERED_ACTION

3. BroadcastReceiver

广播接收器,用于接收系统发送的广播。

短信发送成功/失败时,系统会发送广播,通过注册 BroadcastReceiver 可以接收这些广播。

4. FLAG_IMMUTABLE

Android 12+ 要求创建 PendingIntent 时必须指定可变性标志:

kotlin 复制代码
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
  • FLAG_UPDATE_CURRENT: 如果已存在相同 requestCode 的 PendingIntent,则更新其 Extras
  • FLAG_IMMUTABLE: 标记 PendingIntent 为不可变,提高安全性

注意事项

1. 权限申请

  • Android 6.0(API 23)及以上版本需要在运行时申请 SEND_SMS 权限
  • 必须在 AndroidManifest.xml 中声明权限

2. 发送结果

  • sendSms 方法返回 true 仅表示发送请求已提交,不代表短信已送达
  • 如需监听实际发送和送达状态,需要使用 sendSmsWithCallback 并注册广播接收器

3. 长短信处理

  • 单条短信最大长度通常为 160 字符(GSM 标准)
  • 超过限制的短信会被自动分段发送
  • 长短信会消耗多条短信配额

4. 设备兼容性

  • 部分平板设备或不支持移动网络的设备可能无法发送短信
  • 使用 isSmsSupported() 检查设备支持情况

5. 广播接收器

  • 必须在不需要时注销广播接收器(通常在 onDestroy() 中)
  • 使用 PendingIntent.FLAG_IMMUTABLE 标志以适应 Android 12+ 的安全要求

6. 短信费用

  • 发送短信会产生运营商费用
  • 应用商店可能审核要求用户确认后才能发送短信

最佳实践

  1. 始终检查权限:发送前先检查权限,未授权则申请
  2. 使用回调监听结果:不要依赖简单的返回值,使用回调获取真实状态
  3. 处理长短信 :使用 sendLongSms 自动处理分段发送
  4. 检查设备支持 :使用 isSmsSupported() 避免在不支持的设备上报错
  5. 及时注销监听器:在 Activity/Fragment 生命周期结束时注销广播接收器
  6. 提供用户反馈:使用 Toast 或 UI 显示发送状态

常见问题

Q: 为什么发送请求成功但收不到短信?

A: sendSms 返回成功仅表示请求已提交到系统,实际发送可能因以下原因失败:

  • 设备无信号或无服务
  • 目标号码错误
  • 运营商网络问题
  • 短信被拦截

建议使用 sendSmsWithCallback 并注册广播接收器监听实际发送结果。

Q: 如何获取短信送达确认?

A: 使用 sendSmsWithCallback 时,第二个 PendingIntent 会接收送达确认。需要额外注册监听 SMS_DELIVERED_ACTION 的广播接收器。

Q: 长短信为什么分成多段?

A: 短信协议限制单条短信最大长度(GSM 为 160 字符)。超过此长度的内容会被分成多条发送。使用 sendLongSms 可自动处理此过程。

Q: Android 12+ 报错 FLAG_IMMUTABLE 相关错误?

A: 代码中已正确使用 PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,请确保使用最新版本的示例代码。


更新日志

v2.0 (当前版本)

  • 完善文档,添加每个方法的源码解释
  • 增加详细的使用示例
  • 添加核心概念解释

v1.0

  • 基础短信发送功能
  • 长短信分段发送
  • 发送结果回调
  • 设备支持检测
  • 运行时权限处理

相关推荐
周周不一样2 小时前
Android基础笔记1
android·笔记·gitee
取码网2 小时前
影视APP源码 SK影视 安卓+苹果双端APP 反编译详细视频教程+源码
android
musk12122 小时前
android webview 黑屏问题 , 页面加载时间有点长的情况下
android
夏沫琅琊2 小时前
Android 彩信导出技术文档
android·kotlin
sp42a2 小时前
安卓原生 MQTT 通讯 Java 实现
android·java·mqtt
Mr Lee_2 小时前
Apktool 反编译与回编译详解:enableOnBackInvokedCallback 属性缺失问题分析与解决
android
高梦轩8 小时前
MySQL高可用
android·运维·数据库
RATi GORI12 小时前
MySQL中的CASE WHEN语句:用法、示例与解析
android·数据库·mysql
MoFe112 小时前
【Mysql】创建IP授权用户并授权
android