0

我正在尝试实现类似于“查找我的手机”应用程序的功能,即向我的手机发送短信并通过短信接收回复,告诉我手机的位置。此应用程序的要求是开源的。

我已经看到这种应用程序已经存在于 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();
            }

(链接到 sourceforge 中的代码)

此代码在实现 LocationListener 的类中执行,由 Service 在新线程内调用。

关于这种行为原因的任何提示?为什么消息只显示但没有发送?我查看了另一个类似的应用程序:https ://f-droid.org/repository/browse/?fdid=com.teamdc.stephendiniz.autoaway

这工作正常,可以按预期回复短信。它的主要区别在于,这个应用程序运行在一个服务中,不断地监听新消息并动态注册接收者,而不是在清单中声明它。对我来说,这没什么大不了的,但我宁愿不让服务始终运行。

提前感谢您对此的任何帮助。

4

2 回答 2

0

找出问题所在,它与消息传递 API 无关。

在对 SMS 到达做出反应的 BroadcastReceiver 中,发送者的电话号码被传递给服务,实际上通过 Intent 数据发送回复 SMS,如下所示

locationIntent.setData(Uri.parse("?destinationAddress=" + from));

由于“发件人”地址是 URI 编码的,因此国际前缀中的 +(加号)字符丢失了。消息应用程序可以忍受这一点,因此它能够显示消息,但这不会被发送。

使用 Intent Extras 而不是 Data 就可以了,因为这样电话号码就不会通过任何编码。

一切顺利

于 2015-12-30T12:38:40.680 回答
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;
}

参考:https ://android.googlesource.com/platform/packages/apps/Messaging/+/master/src/com/android/messaging/datamodel/BugleDatabaseOperations.java#917

您应该在清单中注册监听 SMS_RECEIVED 的广播接收器 - 无需即时注册接收器。接收者应该将工作卸载到服务上,比如 IntentService,因为在 onReceive 中花费的执行时间应该很短。

于 2015-12-27T22:57:49.530 回答