Как удалить SMS из папки «Входящие» в Android программным способом? - PullRequest
96 голосов
/ 07 января 2009

На телефонах Android SMS-сообщения, зарегистрированные в приложениях, также отправляются в почтовый ящик устройства. Однако, чтобы избежать беспорядка, было бы неплохо иметь возможность удалять специфичные для приложения SMS-сообщения из входящих сообщений, чтобы уменьшить потенциальный переполнение этих сообщений.

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

Итак, сценарий:

  • Запуск приложения для Android.
  • зарегистрировать СМС-сообщения типов X, Y и Z
  • сообщения P, Q, X, Y, Z с течением времени поступают, все хранятся в папке входящих сообщений
  • Приложение Android обнаруживает получение X, Y, Z (предположительно, как часть события прерывания программы)
  • процесс X, Y, Z
  • Желание !!! X, Y, Z удалены из папки входящих сообщений Android

Это было сделано? Можно ли это сделать?

Ответы [ 18 ]

87 голосов
/ 02 июня 2011

"Начиная с Android 1.6, входящие широковещательные SMS-сообщения (android.provider.Telephony.SMS_RECEIVED) доставляются как" заказанная широковещательная передача "- это означает, что вы можете указать системе, какие компоненты должны получать широковещательную передачу в первую очередь."

Это означает, что вы можете перехватить входящее сообщение и в дальнейшем прервать его трансляцию.

В файле AndroidManifest.xml убедитесь, что приоритет установлен на самый высокий:

<receiver android:name=".receiver.SMSReceiver" android:enabled="true">
    <intent-filter android:priority="1000">
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

В вашем BroadcastReceiver, в onReceive() методе, прежде чем выполнять что-либо с вашим сообщением, просто вызовите abortBroadcast();

РЕДАКТИРОВАТЬ: Начиная с KitKat, это больше не работает, по-видимому.

РЕДАКТИРОВАТЬ 2: Подробнее о том, как это сделать на KitKat здесь:

Удалить SMS с Android на 4.4.4 (Затронутые строки = 0 (ноль), после удаления)

27 голосов
/ 13 января 2009

Используя предложения других людей, я думаю, что получил его на работу:

(с использованием SDK v1 R2)

Это не идеально, так как мне нужно удалить весь разговор, но для наших целей это достаточный компромисс, поскольку мы, по крайней мере, будем знать, что все сообщения будут просмотрены и проверены. Нашему потоку, вероятно, потребуется затем прослушать сообщение, захватить нужное нам сообщение, выполнить запрос, чтобы получить thread_id недавно связанного сообщения, и выполнить вызов delete ().

В нашей деятельности:

Uri uriSms = Uri.parse("content://sms/inbox");
Cursor c = getContentResolver().query(uriSms, null,null,null,null); 
int id = c.getInt(0);
int thread_id = c.getInt(1); //get the thread_id
getContentResolver().delete(Uri.parse("content://sms/conversations/" + thread_id),null,null);

Примечание. Мне не удалось удалить содержимое: // смс / входящие / или содержимое: // смс / все /

Похоже, что поток имеет приоритет, что имеет смысл, но сообщение об ошибке только подтолкнуло меня к злости. При попытке удаления на смс / входящие / или смс / все / вы, вероятно, получите:

java.lang.IllegalArgumentException: Unknown URL
    at com.android.providers.telephony.SmsProvider.delete(SmsProvider.java:510)
    at android.content.ContentProvider$Transport.delete(ContentProvider.java:149)
    at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:149)

Для дополнительной справки, обязательно укажите это в своем манифесте для получателя намерений:

<receiver android:name=".intent.MySmsReceiver">
    <intent-filter>
        <action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
    </intent-filter>
</receiver>

Обратите внимание, что тег получателя выглядит не так:

<receiver android:name=".intent.MySmsReceiver" 
    android:permission="android.permission.RECEIVE_SMS">

Когда у меня были эти настройки, android дал мне несколько сумасшедших разрешений, которые не позволяли android.phone передавать полученные SMS моим намерениям. Так что НЕ включайте этот атрибут разрешения RECEIVE_SMS в ваше намерение! Надеюсь, кто-то умнее меня скажет, почему это так.

24 голосов
/ 12 мая 2009

Итак, у меня была игра, и можно удалить удаленное полученное SMS. К сожалению, не все так просто: (

У меня есть приемник, который принимает входящие SMS-сообщения. Теперь способ входящей маршрутизации Android SMS состоит в том, что часть кода, ответственная за декодирование сообщений, отправляет широковещательную рассылку (она использует метод sendBroadcast() - который, к сожалению, НЕ является версией, которая позволяет просто вызывать abortBroadcast()) всякий раз, когда сообщение прибывает.

Мой приемник может вызываться или не вызываться до получения системного SMS-сообщения, и в любом случае полученная широковещательная рассылка не имеет свойства, которое могло бы отражать столбец _id в таблице SMS.

Однако, будучи не тем, кого можно остановить, я легко отправляю (через обработчик) отложенное сообщение с сообщением SmsMessage в качестве прикрепленного объекта. (Полагаю, вы тоже можете разместить себе Runnable ...)

handler.sendMessageDelayed(handler.obtainMessage(MSG_DELETE_SMS, msg), 2500);

Задержка существует для того, чтобы к тому времени, когда сообщение прибыло, все получатели Broadcast завершили свои работы и сообщение было безопасно помещено в таблицу SMS.

Когда сообщение (или Runnable) получено, вот что я делаю:

case MSG_DELETE_SMS:
    Uri deleteUri = Uri.parse("content://sms");
    SmsMessage msg = (SmsMessage)message.obj;

    getContentResolver().delete(deleteUri, "address=? and date=?", new String[] {msg.getOriginatingAddress(), String.valueOf(msg.getTimestampMillis())});

Я использую поле исходного адреса и отметки времени, чтобы обеспечить очень высокую вероятность удаления ТОЛЬКО интересующего меня сообщения. Если бы я хотел быть еще более параноиком, я мог бы включить содержимое msg.getMessageBody() в качестве части запроса.

Да, сообщение удалено (ура!). К сожалению, панель уведомлений не обновляется: (

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

Для меня это не совсем хорошо - я хочу, чтобы все следы сообщения исчезли - я не хочу, чтобы пользователь думал, что TXT существует, когда его нет (это может привести только к сообщениям об ошибках) .

Внутренне в ОС звонит MessagingNotification.updateNewMessageIndicator(Context), но я этот класс был скрыт от API, и я не хотел копировать весь этот код только ради точности индикатора.

11 голосов
/ 15 декабря 2012
public boolean deleteSms(String smsId) {
    boolean isSmsDeleted = false;
    try {
        mActivity.getContentResolver().delete(Uri.parse("content://sms/" + smsId), null, null);
        isSmsDeleted = true;

    } catch (Exception ex) {
        isSmsDeleted = false;
    }
    return isSmsDeleted;
}

используйте это разрешение в AndroidManizest

<uses-permission android:name="android.permission.WRITE_SMS"/>
6 голосов
/ 16 августа 2011

Лучше использовать _id и thread_id для удаления сообщения.

Thread_id - это то, что присваивается сообщениям, приходящим от одного и того же пользователя. Поэтому, если вы используете только thread_id, все сообщения от отправителя будут удалены.

Если вы используете комбинацию _id, thread_id, то он удалит именно то сообщение, которое вы хотите удалить.

Uri thread = Uri.parse( "content://sms");
int deleted = contentResolver.delete( thread, "thread_id=? and _id=?", new String[]{String.valueOf(thread_id), String.valueOf(id)} );
5 голосов
/ 09 января 2009

Вам необходимо найти URI сообщения. Но как только вы это сделаете, я думаю, что вы должны иметь возможность android.content.ContentResolver.delete (...).

Вот еще немного info .

2 голосов
/ 15 марта 2014

Используйте эту функцию для удаления определенной цепочки сообщений или изменения в соответствии с вашими потребностями:

public void delete_thread(String thread) 
{ 
  Cursor c = getApplicationContext().getContentResolver().query(
  Uri.parse("content://sms/"),new String[] { 
  "_id", "thread_id", "address", "person", "date","body" }, null, null, null);

 try {
  while (c.moveToNext()) 
      {
    int id = c.getInt(0);
    String address = c.getString(2);
    if (address.equals(thread)) 
        {
     getApplicationContext().getContentResolver().delete(
     Uri.parse("content://sms/" + id), null, null);
    }

       }
} catch (Exception e) {

  }
}

Вызовите эту функцию просто ниже:

delete_thread("54263726");//you can pass any number or thread id here

Не забудьте добавить разрешение Android Mainfest ниже:

<uses-permission android:name="android.permission.WRITE_SMS"/>
2 голосов
/ 12 июня 2009

Я не смог заставить его работать, используя решение dmyung, это дало мне исключение при получении либо идентификатора сообщения, либо идентификатора потока.

В конце я использовал следующий метод для получения идентификатора потока:

private long getThreadId(Context context) {
    long threadId = 0;

    String SMS_READ_COLUMN = "read";
    String WHERE_CONDITION = SMS_READ_COLUMN + " = 0";
    String SORT_ORDER = "date DESC";
    int count = 0;

    Cursor cursor = context.getContentResolver().query(
                    SMS_INBOX_CONTENT_URI,
          new String[] { "_id", "thread_id", "address", "person", "date", "body" },
                    WHERE_CONDITION,
                    null,
                    SORT_ORDER);

    if (cursor != null) {
            try {
                count = cursor.getCount();
                if (count > 0) {
                    cursor.moveToFirst();
                    threadId = cursor.getLong(1);                              
                }
            } finally {
                    cursor.close();
            }
    }


    return threadId;
}

Тогда я мог бы удалить это. Однако, как сказал Дуг, уведомление все еще там, даже сообщение отображается при открытии панели уведомлений. Только нажав на сообщение, я смог увидеть, что оно пустое.

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

2 голосов
/ 08 июня 2009

Я думаю, что это не может быть идеально сделано в настоящее время. Есть 2 основных проблемы:

  1. Как вы можете убедиться, что смс уже находится в папке "Входящие", когда вы пытаетесь удалить его?
    Обратите внимание, что SMS_RECEIVED не является заказанной трансляцией.
    Так что решение Дмьюнга - это попытка удачи. даже задержка с ответом Дуга не является гарантией.

  2. SmsProvider не является потокобезопасным (см. http://code.google.com/p/android/issues/detail?id=2916#c0)
    Тот факт, что более одного клиента запрашивают удаление и вставку в него одновременно, приведет к повреждению данных или даже к немедленному исключению времени выполнения.

1 голос
/ 03 июля 2012

Теперь метод abortBroadcast(); может использоваться для ограничения входящего сообщения на входящие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...