如何在基于Fused Location API的校园APP中集成SMS Manager发送位置URL
集成SMS Manager并发送位置URL的完整方案
嘿,很高兴你已经搞定了Fused Location API的位置获取部分!接下来把位置转成可点击的地图URL并通过SMS发送,其实只需要几步就能完成,我给你梳理清楚:
1. 先搞定必要的权限
首先得确保你的应用拥有发送短信的权限,在AndroidManifest.xml里添加:
<uses-permission android:name="android.permission.SEND_SMS" /> <!-- 你已经添加的位置权限可以保留,比如ACCESS_FINE_LOCATION -->
注意:从Android 6.0(API 23)开始,SEND_SMS属于危险权限,所以你需要在运行时请求权限,不能只靠清单文件。可以在启动发送功能前先检查权限:
// 以Kotlin为例,Java写法逻辑一致 private const val SMS_PERMISSION_REQUEST_CODE = 1001 private fun checkSmsPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.SEND_SMS), SMS_PERMISSION_REQUEST_CODE) } else { // 权限已授予,直接执行发送逻辑 sendLocationSms() } } // 处理权限请求结果 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == SMS_PERMISSION_REQUEST_CODE) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { sendLocationSms() } else { // 用户拒绝了权限,可以提示需要权限才能发送短信 Toast.makeText(this, "需要短信权限才能发送位置", Toast.LENGTH_SHORT).show() } } }
2. 把位置坐标转成可点击的地图URL
当你通过Fused Location API获取到Location对象后,可以把经纬度拼接成通用的地图URL(接收方点击就能直接打开地图定位):
private fun getLocationUrl(location: Location): String { val latitude = location.latitude val longitude = location.longitude // 这个格式兼容大部分地图应用,安卓/iOS用户点击都能直接跳转 return "https://www.google.com/maps?q=$latitude,$longitude" }
3. 用SMS Manager发送短信
接下来就是核心的发送逻辑,获取SmsManager实例,然后发送包含位置URL的短信:
// 先定义一个全局变量存储获取到的位置 private var currentLocation: Location? = null private fun sendLocationSms() { currentLocation?.let { location -> val locationUrl = getLocationUrl(location) val phoneNumber = "目标手机号" // 这里可以改成用户输入的号码或预设号码 val smsContent = "我的当前位置:$locationUrl" val smsManager = SmsManager.getDefault() // 可选:监听短信发送状态 val sentIntent = PendingIntent.getBroadcast(this, 0, Intent("SMS_SENT"), PendingIntent.FLAG_IMMUTABLE) val deliveredIntent = PendingIntent.getBroadcast(this, 0, Intent("SMS_DELIVERED"), PendingIntent.FLAG_IMMUTABLE) smsManager.sendTextMessage(phoneNumber, null, smsContent, sentIntent, deliveredIntent) } ?: run { Toast.makeText(this, "无法获取当前位置", Toast.LENGTH_SHORT).show() } }
如果需要监听发送是否成功,可以注册一个广播接收器:
private val smsSentReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { when (resultCode) { Activity.RESULT_OK -> { Toast.makeText(context, "位置短信发送成功", Toast.LENGTH_SHORT).show() } SmsManager.RESULT_ERROR_GENERIC_FAILURE -> { Toast.makeText(context, "发送失败:未知错误", Toast.LENGTH_SHORT).show() } SmsManager.RESULT_ERROR_NO_SERVICE -> { Toast.makeText(context, "发送失败:无信号", Toast.LENGTH_SHORT).show() } // 其他错误码可按需扩展 } } } // 在onCreate里注册接收器 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ...其他初始化代码 registerReceiver(smsSentReceiver, IntentFilter("SMS_SENT")) } // 在onDestroy里注销接收器 override fun onDestroy() { super.onDestroy() unregisterReceiver(smsSentReceiver) }
4. 结合你现有的位置获取逻辑
把上面的代码和你已经实现的“点击按钮获取位置”功能结合起来:
// 假设你的获取位置按钮点击事件 findViewById<Button>(R.id.btn_get_location).setOnClickListener { // 这里是你已有的Fused Location获取逻辑 fusedLocationClient.lastLocation.addOnSuccessListener { location -> currentLocation = location // 获取到位置后,检查权限并发送 checkSmsPermission() }.addOnFailureListener { Toast.makeText(this, "获取位置失败", Toast.LENGTH_SHORT).show() } }
一些实用提示
- 测试一定要用真实安卓设备,模拟器通常无法发送真实短信。
- 如果需要发送给多个号码,可以循环调用
sendTextMessage,长短信可使用sendMultipartTextMessage(咱们这个场景基本用不上)。 - 记得处理位置为null的情况(比如用户关闭了位置服务)。
内容的提问来源于stack exchange,提问作者LJ Ca-ong




