Android开发求助:如何向已保存联系人发送含位置信息的短信
实现向已保存联系人发送含位置信息的短信
一、添加必要权限
在AndroidManifest.xml中声明以下权限,确保应用能发送短信、获取位置及读取联系人:
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.READ_CONTACTS" />
二、完善联系人模型(修正原代码逻辑问题)
原ContactModel的手机号验证存在逻辑错误,以下是优化后的版本,确保手机号格式统一:
public class ContactModel { private int id; private String phoneNo; private String name; // 构造方法 public ContactModel(int id, String name, String phoneNo) { this.id = id; this.phoneNo = validatePhoneNumber(phoneNo); this.name = name; } // 验证并格式化手机号:过滤无效字符,统一添加区域码前缀 private String validatePhoneNumber(String phone) { StringBuilder formattedPhone = new StringBuilder(); // 保留数字和+号,过滤其他字符 for (char c : phone.toCharArray()) { if (Character.isDigit(c) || c == '+') { formattedPhone.append(c); } } // 无+号前缀时,默认添加+212(可根据需求修改区域码) if (!formattedPhone.toString().startsWith("+")) { formattedPhone.insert(0, "+212"); } return formattedPhone.toString(); } // Getter和Setter方法 public String getPhoneNo() { return phoneNo; } public int getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
三、实现当前位置获取功能
使用Google推荐的FusedLocationProviderClient获取设备当前经纬度:
private FusedLocationProviderClient fusedLocationClient; private double currentLatitude; private double currentLongitude; private static final int MY_PERMISSIONS_REQUEST_LOCATION = 2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); // 其他初始化代码... } // 获取当前位置 private void getCurrentLocation() { // 检查位置权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION); return; } // 获取最后已知位置 fusedLocationClient.getLastLocation() .addOnSuccessListener(this, location -> { if (location != null) { currentLatitude = location.getLatitude(); currentLongitude = location.getLongitude(); // 获取位置后触发联系人选择 selectContactAndSendSms(); } else { Toast.makeText(this, "无法获取当前位置,请检查定位设置", Toast.LENGTH_SHORT).show(); } }); }
四、整合联系人选择与短信发送逻辑
将联系人选择、位置信息、短信发送功能整合,修正原短信代码的权限处理和内容填充:
private static final int MY_PERMISSIONS_REQUEST_SEND_SMS = 1; private static final int PICK_CONTACT_REQUEST = 3; private ContactModel selectedContact; Button sendBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sendBtn = findViewById(R.id.btnSendSMS); sendBtn.setOnClickListener(view -> { // 点击按钮先获取位置,再选择联系人 getCurrentLocation(); }); } // 调用系统联系人选择器 private void selectContactAndSendSms() { Intent pickContactIntent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI); startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST); } // 处理联系人选择结果 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_CONTACT_REQUEST && resultCode == RESULT_OK) { Uri contactUri = data.getData(); String[] projection = {ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME}; Cursor cursor = getContentResolver().query(contactUri, projection, null, null, null); if (cursor != null && cursor.moveToFirst()) { int numberIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER); int nameIndex = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME); String phoneNumber = cursor.getString(numberIndex); String contactName = cursor.getString(nameIndex); // 用ContactModel格式化手机号 selectedContact = new ContactModel(0, contactName, phoneNumber); // 开始发送短信 sendSMSMessage(); cursor.close(); } } } // 权限检查与短信发送触发 protected void sendSMSMessage() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS)) { Toast.makeText(this, "需要短信权限才能发送位置信息", Toast.LENGTH_SHORT).show(); } ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SEND_SMS}, MY_PERMISSIONS_REQUEST_SEND_SMS); } else { sendSmsImpl(); } } // 权限请求结果处理 @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_SEND_SMS: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { sendSmsImpl(); } else { Toast.makeText(getApplicationContext(), "未授予短信权限,无法发送短信", Toast.LENGTH_LONG).show(); } break; } case MY_PERMISSIONS_REQUEST_LOCATION: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { getCurrentLocation(); } else { Toast.makeText(getApplicationContext(), "未授予位置权限,无法获取当前位置", Toast.LENGTH_LONG).show(); } break; } } } // 实际发送短信逻辑 private void sendSmsImpl() { // 校验联系人与位置是否有效 if (selectedContact == null || currentLatitude == 0 || currentLongitude == 0) { Toast.makeText(this, "请先选择联系人并确保位置获取成功", Toast.LENGTH_SHORT).show(); return; } // 构建带位置链接的短信内容 String locationLink = String.format("https://www.google.com/maps/search/?api=1&query=%f,%f", currentLatitude, currentLongitude); String smsContent = String.format("我现在的位置:%s", locationLink); SmsManager smsManager = SmsManager.getDefault(); // 拆分长短信(超过短信字数限制时自动拆分) ArrayList<String> smsParts = smsManager.divideMessage(smsContent); smsManager.sendMultipartTextMessage(selectedContact.getPhoneNo(), null, smsParts, null, null); Toast.makeText(getApplicationContext(), "短信已发送", Toast.LENGTH_LONG).show(); }
五、关键注意事项
- 权限处理:Android 6.0及以上版本必须动态申请短信、位置、读取联系人权限,不能仅依赖Manifest声明。
- 位置可靠性:
getLastLocation()可能返回null,建议添加位置更新监听,确保获取到实时有效位置。 - 长短信处理:短信内容过长时,必须用
divideMessage拆分后发送,避免发送失败。 - 联系人来源:示例使用系统联系人选择器,若你有自定义联系人列表,直接传入对应的
ContactModel对象即可。
内容的提问来源于stack exchange,提问作者youna kim
相关产品推荐
相关产品推荐

