2016-12-19 14 views
2

У меня установлена ​​служба фона registerContentObserver, чтобы получать уведомления при отправке SMS. Получив это событие, я увеличил бы переменную, чтобы узнать количество отправленных сообщений. Это работает как ожидалось.Обнаружение нескольких SMS-сообщений, отправленных из-за длины содержимого

Когда кто-то отправляет SMS с более чем 140 символами, оператор мобильной связи будет рассматривать это как несколько SMS, но кажется, что я получаю только один обратный вызов для отправленного сообщения. Это заставляет мое приложение пропускать подсчет некоторых сообщений.

Есть ли правильный способ узнать, сколько сообщений было отправлено?

ответ

1

Когда приложение несет ответственность за то, что оно написало свои собственные сообщения Поставщику, скорее всего, он будет писать все сообщение за один раз, независимо от того, должно ли сообщение отправляться как multipart. Вот почему ваш наблюдатель часто стреляет только один раз для каждого полного сообщения, независимо от того, насколько он большой.

С момента установки KitKat система автоматически сохранит исходящие сообщения для любых приложений, отличных от по умолчанию, и для многостраничных сообщений каждая часть будет сохранена индивидуально, каждый раз запуская ваш наблюдатель. Конечно, это ничего не помогает до KitKat, или если приложение по умолчанию сохраняет свои собственные сообщения в более поздних версиях.

Одна из возможностей - получить тело сообщения в вашем ContentObserver и определить, сколько частей сообщений было бы разделено на. Метод SmsMessage.calculateLength() может сделать это для нас. Он возвращает массив int, первый элемент которого будет иметь количество сообщений для данного текста.

Например, используя старый onChange(boolean) метод для поддержки API < 16:

private class SmsObserver extends ContentObserver { 
    private static final Uri SMS_SENT_URI = Uri.parse("content://sms/sent"); 
    private static final String COLUMN_ID = "_id"; 
    private static final String COLUMN_BODY = "body"; 
    private static final String[] PROJECTION = {COLUMN_ID, COLUMN_BODY}; 

    // You might want to persist this value to storage, rather than 
    // keeping a field, in case the Observer is killed and recreated. 
    private int lastId; 

    public SmsObserver(Handler handler) { 
     super(handler); 
    } 

    @Override 
    public void onChange(boolean selfChange) { 
     Cursor c = null; 
     try { 
      // Get the most recent sent message. 
      c = getContentResolver().query(SMS_SENT_URI, PROJECTION, null, 
              null, "date DESC LIMIT 1"); 
      if (c != null && c.moveToFirst()) { 

       // Check that we've not already counted this one. 
       final int id = c.getInt(c.getColumnIndex(COLUMN_ID)); 
       if (id == lastId) { 
        return; 
       } 
       lastId = id; 

       // Get the message body, and have the SmsMessage 
       // class calculate how many parts it would need. 
       final String body = c.getString(c.getColumnIndex(COLUMN_BODY)); 
       final int numParts = SmsMessage.calculateLength(body, false)[0]; 

       // Add the number of parts to the count, 
       // however you might be doing that. 
       addToCount(numParts); 
      } 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
     } 
     finally { 
      if (c != null) { 
       c.close(); 
      } 
     } 
    } 
} 

вы должны быть поддержкой API 16 и выше, мы можем использовать перегрузку onChange(boolean, Uri), и все становится немного проще, так как мы не обязательно должны отслеживать последний идентификатор сообщения.

+0

Благодарим за обмен решением с кодом. Я вижу, что вы столкнулись с такими же проблемами, как и я в отношении lastMessageId, и поскольку мое приложение поддерживает API 8 и выше, я бы проверил первый вариант. +1 для подробного объяснения. Мой код приложения находится по адресу https://github.com/midhunhk/message-counter – midhunhk

+1

Да, для обработки API <16 требуется немного больше работы, но я вижу, что вы уже это знаете. :-) Я заметил, что вы используете столбец 'protocol', чтобы определить, является ли сообщение отправленным сообщением. Вместо этого вы можете использовать столбец 'type'. Тип 2 - _sent_, тип 1 - _inbox_. Вы можете просмотреть все типы сообщений на этой странице (https://developer.android.com/reference/android/provider/Telephony.TextBasedSmsColumns.html). Они не стали официальными до API 19, но значения всегда были одинаковыми. Лемме знаю, могу ли я что-нибудь прояснить. Надеюсь, это сработает для вас. Ура! –

+1

Приветствия! Это хорошая информация, чтобы знать. Это было очень сложно сделать, поскольку документация по API-интерфейсу SMS не была общедоступной. Большое спасибо за подробный и быстрый ответ. – midhunhk