我正在努力实现与“查找我的手机”应用程序类似的功能,即将短信发送到我的手机并通过短信接收回复,告诉我手机的位置。该应用程序的要求是开源的。
我已经看到这种应用程序已经存在于F-Droid存储库中,被称为FindMyPhone。但是,当手机收到短信时,其回复只会在股票信息应用中显示为对联系人的回复,但无法有效发送。这不是预期的行为,我可以在代码库中看到作者试图纠正这个然后在2013年放弃。
我查看了代码并看到它使用的技术是直截了当的:
try {
SmsManager smsManager = SmsManager.getDefault();
// ********* SENDING SMS HERE *******
smsManager.sendTextMessage(currentFromAddress, null, txt, null, null);
// ********* SENDING SMS HERE *******
Log.d(FindMyPhoneHelper.LOG_TAG, "Sent SMS");
Thread.sleep(5000);
Log.d(FindMyPhoneHelper.LOG_TAG, "Slept 5000ms");
} catch(Exception e) {
Log.d(FindMyPhoneHelper.LOG_TAG, "Failed SMS: " + e.getMessage());
e.printStackTrace();
}
(link to the code in sourceforge)
此代码在实现LocationListener的类中执行,该类在服务的新线程内调用。
有关此行为原因的任何暗示?为什么消息刚刚显示但未发送?我查看了另一个类似的应用程序:https://f-droid.org/repository/browse/?fdid=com.teamdc.stephendiniz.autoaway
这是正常的,并按预期答复短信。它的主要区别在于这个应用程序在一个服务中运行,不断地监听新消息并在运行中注册接收器,而不是在清单中声明它。对我而言,这不会有什么大不了的,但我宁愿不让服务一直在运行。
提前感谢您提供任何帮助。
答案 0 :(得分:0)
SMS无法发送的一个原因可能是应用程序将null作为SMS服务中心传递给sendTextMessage,而应该从SMS提供程序获取它,如下所示:
public static String getSmsServiceCenterForConversation(final DatabaseWrapper dbWrapper,
final String conversationId) {
Assert.isNotMainThread();
Cursor cursor = null;
try {
cursor = dbWrapper.query(DatabaseHelper.CONVERSATIONS_TABLE,
new String[] { ConversationColumns.SMS_SERVICE_CENTER },
ConversationColumns._ID + "=?",
new String[] { conversationId },
null, null, null);
Assert.inRange(cursor.getCount(), 0, 1);
if (cursor.moveToFirst()) {
return cursor.getString(0);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
您应该在清单中注册收听SMS_RECEIVED的广播接收器 - 无需动态注册接收器。接收器应该将工作卸载到服务,就像IntentService一样,因为onReceive中的执行时间应该保持很短。
答案 1 :(得分:0)
发现问题所在,它与消息传递API无关。
在BroadcastReceiver对SMS到达作出反应时,发送者的电话号码被传递给服务实际上通过Intent数据发送回复短信
locationIntent.setData(Uri.parse("?destinationAddress=" + from));
由于“from”地址是URI编码的,因此国际前缀中的+(加号)字符丢失。消息应用程序可以使用它,因此它能够显示消息,但不会发送。
使用Intent Extras代替Data可以解决问题,因为这种方式的电话号码不会通过任何编码。
一切顺利