来自 Android 个应用的自动短信回复

Automatic SMS reply from Android App

我正在尝试实现类似于 "Find my phone" 应用程序的功能,即向我的 phone 发送短信并通过短信接收回复,告知我的 phone 所在位置.此应用程序的要求是开源。

我看到F-Droid库中已经存在这种应用程序,叫做FindMyPhone。然而,当phone收到短信时,其回复只是作为对联系人的回复显示在股票短信应用程序中,但并未有效发送。这不是预期的行为,我可以在代码存储库中看到作者尝试更正此问题,然后在 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)

此代码在 class 实现 LocationListener 中执行,由服务在新线程中调用。

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

这一切正常,可以按预期回复短信。它的主要区别在于,此应用程序在服务中运行,不断侦听新消息并即时注册接收者,而不是在清单中声明它。对我来说这没什么大不了的,但我宁愿不要总是有服务 运行.

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

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 中花费的执行时间应该保持较短。

找到问题所在,与消息无关API。

在 BroadcastReceiver 对 SMS 到达做出反应时,phone 发送者的号码被传递给服务,实际上通过 Intent 数据发送回复 SMS

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

由于 "from" 地址是 URI 编码的,国际前缀中的 +(加号)字符丢失了。消息传递应用程序可以接受,因此它能够显示消息,但不会发送。

使用 Intent Extras 而不是 Data 就成功了,因为这样 phone 数字将不会通过任何编码。

祝一切顺利