Как программно удалить SMS из папки "Входящие" на Android?

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

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

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

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

Это сделано? Это можно сделать?

Ответ 1

"Начиная с 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();

EDIT: По сравнению с KitKat, это больше не работает.

EDIT2: больше информации о том, как это сделать на KitKat:

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

Ответ 2

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

(используя 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);

Примечание. Я не смог удалить содержимое://sms/inbox/content://sms/all/

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

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">

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

Ответ 3

Итак, у меня была игра, и можно удалить полученное 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())});

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

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

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

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

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

Ответ 4

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;
}

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

<uses-permission android:name="android.permission.WRITE_SMS"/>

Ответ 5

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

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

Если u использует комбинацию _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)} );

Ответ 6

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

Здесь еще информация.

Ответ 7

Я думаю, что это пока невозможно сделать. Есть две основные проблемы:

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

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

Ответ 8

Я не мог заставить его работать с использованием решения 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 до его доставки в систему, прежде чем он даже попадет в папку "Входящие". Однако я очень сомневаюсь, что это выполнимо. Пожалуйста, поправьте меня, если я ошибаюсь.

Ответ 9

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

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

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

<uses-permission android:name="android.permission.WRITE_SMS"/>

Ответ 10

Просто отключите уведомления для приложения sms по умолчанию. Обработайте свои собственные уведомления для всех текстовых сообщений!

Ответ 11

Просто взгляните на эту ссылку, это даст вам краткое представление о логике:

https://gist.github.com/5178e798d9a00cac4ddb
Просто вызовите функцию deleteSMS() с некоторой задержкой, потому что есть небольшая разница между временем уведомления и фактическим сохранением...., подробности см. на этой ссылке также..........

http://htmlcoderhelper.com/how-to-delete-sms-from-inbox-in-android-programmatically/

Спасибо..........

Ответ 12

Также обновите файл манифеста, чтобы удалить sms, необходимые для разрешения записи.

<uses-permission android:name="android.permission.WRITE_SMS"/>

Ответ 13

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

Ответ 14

Вы просто попробуете следующий код. Он удалит все sms, которые все в телефоне (получено или отправлено).

Uri uri = Uri.parse("content://sms");

ContentResolver contentResolver = getContentResolver();

Cursor cursor = contentResolver.query(uri, null, null, null,
  null);



while (cursor.moveToNext()) {

 long thread_id = cursor.getLong(1);
 Uri thread = Uri.parse("content://sms/conversations/"
   + thread_id);
 getContentResolver().delete(thread, null, null);
}

Ответ 15

Образец для удаления одного SMS, а не для разговора:

getContentResolver().delete(Uri.parse("content://sms/conversations/" + threadID), "_id = ?", new String[]{id});

Ответ 16

Используйте один из этих методов, чтобы выбрать последнее полученное SMS и удалить его, здесь в этом случае я получаю верхнюю часть sms и собираюсь удалить с помощью значения потока и id sms,

try {
    Uri uri = Uri.parse("content://sms/inbox");
    Cursor c = v.getContext().getContentResolver().query(uri, null, null, null, null);
    int i = c.getCount();

    if (c.moveToFirst()) {
    }
} catch (CursorIndexOutOfBoundsException ee) {
    Toast.makeText(v.getContext(), "Error :" + ee.getMessage(), Toast.LENGTH_LONG).show();
}

Ответ 17

Попробуйте это, я на 100% уверен, что это сработает нормально: // просто поместите здесь адрес конверсии для удаления целого преобразования по адресу (не забывайте добавлять чтение, разрешение на запись в mainfest) Вот код:

String address="put address only";

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(address)){
        getApplicationContext().getContentResolver().delete(Uri.parse("content://sms/" + id), null, null);}
    }
} catch(Exception e) {

}

Ответ 18

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    SMSData sms = (SMSData) getListAdapter().getItem(position);
    Toast.makeText(getApplicationContext(), sms.getBody(),
            Toast.LENGTH_LONG).show();
    Toast.makeText(getApplicationContext(), sms.getNumber(),
            Toast.LENGTH_LONG).show();

    deleteSms(sms.getId());

}

public boolean deleteSms(String smsId) {
    boolean isSmsDeleted = false;
    try {
        MainActivity.this.getContentResolver().delete(
                Uri.parse("content://sms/" + smsId), null, null);
        isSmsDeleted = true;

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