Автоматический ответ на СМС из приложения для Android

Я пытаюсь добиться чего-то похожего на приложение «Найти мой телефон», то есть отправить SMS на мой телефон и получить ответ по SMS с указанием, где находится мой телефон. Требование этого приложения является открытым исходным кодом.

Я видел, что такое приложение уже существует в репозитории F-Droid и называется FindMyPhone. Однако, когда телефон получает SMS, его ответ просто отображается в стандартном приложении для обмена сообщениями в качестве ответа на контакт, но фактически не отправляется. Это не ожидаемое поведение, и я мог видеть в репозитории кода, что автор пытался исправить это, но затем сдался в 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();
            }

(ссылка на код в исходниках)

Этот код выполняется в классе, реализующем LocationListener, вызываемом службой внутри нового потока.

Любая подсказка о причине такого поведения? Почему сообщение просто отображается, но не отправляется? Я просмотрел другое подобное приложение: https://f-droid.org/repository/browse/?fdid=com.teamdc.stephendiniz.autoaway

Это работает нормально и отвечает на SMS, как и ожидалось. Его основное отличие состоит в том, что это приложение работает в службе, постоянно прослушивая новые сообщения и регистрируя получателя на лету, а не объявляя его в манифесте. Для меня это не будет иметь большого значения, но я бы предпочел, чтобы служба не работала постоянно.

Заранее спасибо за любую помощь в этом.


person Antonio Pisano    schedule 27.12.2015    source источник


Ответы (2)


Одной из причин невозможности отправки 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, должно быть коротким.

person fejd    schedule 27.12.2015
comment
Спасибо за ваш ответ, однако я боюсь, что это не причина моей проблемы: AutoAway, приложение, которое правильно отправляет SMS, выполняет тот же самый вызов sendTextMessage, передавая null как центр обслуживания SMS. - person Antonio Pisano; 30.12.2015
comment
FindMyPhone регистрируется, чтобы реагировать на SMS_RECEIVED в манифесте. Реакция на самом деле происходит, но SMS отображается только в моем стандартном приложении для обмена сообщениями и все равно не отправляется. - person Antonio Pisano; 30.12.2015
comment
Я не мог сказать, почему он не отправляется, не просматривая журналы (adb logcat -b radio), но если он отображается в стандартном приложении обмена сообщениями как отправленный (отправленный, поставленный в очередь или не отправленный?), то это означает, что платформа Android сохранил его в базе данных SMS/MMS, и это происходит после того, как сообщение было отправлено (или не удалось отправить) в android.googlesource.com/platform/frameworks/opt/telephony/+/. - person fejd; 30.12.2015

Выяснил, в чем проблема, она не имеет ничего общего с API обмена сообщениями.

В BroadcastReceiver, реагирующем на получение SMS, номер телефона отправителя был передан в Службу, фактически отправляющую ответное SMS по данным Intent, подобным этому

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

Поскольку адрес «от» был закодирован в URI, символ + (плюс) в международном префиксе был утерян. Приложение для обмена сообщениями могло смириться с этим, поэтому оно могло показать сообщение, но оно не было отправлено.

Использование Intent Extras вместо Data сделало свое дело, так как таким образом номер телефона не будет проходить через какую-либо кодировку.

Всего наилучшего

person Antonio Pisano    schedule 30.12.2015