Як видалити SMS з папки "Вхідні" в Android програмно?


98

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

Питання інших груп Google щодо отримання остаточної відповіді на програмний спосіб видалення SMS-повідомлень з папки "Вхідні" Android, здається, не є нагальним.

Отже сценарій:

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

Це було зроблено? Чи можна це зробити?


4
Я вважаю, що робити щось корисне з можливостями телефону Android є дуже неприємним досвідом.
BobbyShaftoe

1
хороший товариш. я шукав щось подібне: D cheers
Harsha MV

3
Найкраще було б у першу чергу запобігти надходженню SMS-повідомлень у папку "Вхідні": stackoverflow.com/questions/1741628/…
Крістофер Орр

Відповіді:


87

"Станом на 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 (нульовий), після видалення)


3
І переконайтесь, що бачите stackoverflow.com/questions/1741628/…
Майкл Леві

Чи можете ви побачити тут stackoverflow.com/questions/25988574/… ?
Gangadhar Nimballi

Найкраща відповідь на це = D
Майк Брайан Олівера

27

Користуючись пропозиціями інших осіб, я думаю, що я працював так:

(за допомогою SDK v1 R2)

Це не ідеально, оскільки мені потрібно видалити всю розмову, але для наших цілей це достатній компроміс, оскільки ми принаймні знаємо, що всі повідомлення будуть розглянуті та перевірені. Нашому потоку, ймовірно, потрібно буде прослухати повідомлення, захопити для потрібного повідомлення, зробити запит, щоб отримати nit_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 / вхідні / або вміст: // sms / all /

Схоже, що нитка має перевагу, що має сенс, але повідомлення про помилку лише посилило мене, щоб збитись. Спробувавши видалити sms / вхідні / або 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">

Коли у мене були ці налаштування, андроїд дав мені певні винятки з дозволів, які не дозволяли android.phone передавати отримані SMS на мій намір. Отже, НЕ вкладайте атрибут дозволу RECEIVE_SMS у свій намір! Сподіваюся, хтось мудріший за мене може сказати мені, чому так було.


Чи можете ви побачити тут stackoverflow.com/questions/25988574/… ?
Гангадхар Німбаллі

24

Отже, у мене була гра, і це можна видалити отримав SMS. На жаль, це не все звичайне плавання :(

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

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

Однак, не будучи зупиненим, я легко розміщую (через обробник) повідомлення із запізненням із доданим об'єктом SmsMessage. (Я гадаю, ви могли б також розмістити себе Runnable ...)

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

Затримка існує для того, щоб до моменту надходження повідомлення всі приймачі широкомовної програми закінчили свої дані, і повідомлення буде надійно укладено в таблиці 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, і я не хотів копіювати весь цей код лише для того, щоб зробити індикатор точним.


Дуг, це чудово. Як питання, чи знаєте ви, чи потрібно робити посаду Обробнику? Цікаво, чи вводиться SMS в системну базу даних SMS до того, як приймачі мовлення будуть викликані? Ймовірно, мені доведеться зазирнути в ОС, щоб побачити, де відбувається вставка, але я б припустив, що вставлення SMS у якусь базу даних відбувається ще до того, як приймачі мовлення будуть повідомлені. Чи розумієте це чи ви вже це перевіряли?
Хемі

Чи можете ви побачити тут stackoverflow.com/questions/25988574/… ?
Gangadhar Nimballi

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

1
Як ми отримуємо sms id?
Dev01


@ Dev01i якщо ви хочете видалити певний смс, ви маєте мати його id? а якщо ні, вам не доведеться запитувати ідентифікатор з адресою чи smsbody
д-р aNdRO

6

Для видалення повідомлення краще використовувати _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)} );

Чи можете ви побачити тут stackoverflow.com/questions/25988574/… ?
Gangadhar Nimballi

5

Вам потрібно буде знайти URI повідомлення. Але як тільки ви це думаю, ви повинні мати можливість android.content.ContentResolver.delete (...) це.

Ось додаткова інформація .


2

Я думаю, що це поки не може бути ідеально зроблено. Є дві основні проблеми:

  1. Як ви можете переконатися, що sms вже знаходиться у вхідних, коли ви намагаєтесь його видалити?
    Зауважте, що SMS_RECEIVED не є упорядкованою трансляцією.
    Тож рішення дмюнґа - це повністю випробування удачі; навіть затримка відповіді Дуга не є гарантією.

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


2

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


Ну, це не так про перехоплення повідомлень , перш ніж поштову скриньку: ви можете отримати широкомовний android.provider.Telephony.SMS_RECEIVED, вам потрібно всього лише permssion android.permission.RECEIVE_SMS. Ви навіть можете легко зупинити повідомлення від доступу до вхідних, зателефонувавши на abortBroadcast (), оскільки це замовлена ​​трансляція. PS Має бути смішним, щоб виправитись через 2 роки :)
lapis

2

Використовуйте цю функцію, щоб видалити певний потік повідомлення або змінити відповідно до ваших потреб:

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

1

Просто вимкніть сповіщення програми SMS за замовчуванням. Обробляйте власні сповіщення про всі текстові повідомлення!


1

Просто подивіться на це посилання, воно дасть вам коротке уявлення про логіку:

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

http://htmlcoderhelper.com/how-to-delete-sms-from- Inbox-in-android-programmatic /

Дякую ..........


1

Ви просто спробуйте наступний код. Він видалить усі 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);
}

1

Також оновіть файл маніфесту, щоб видалити sms, потрібні дозволи на запис.

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

1

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


0

Зразок для видалення одного SMS, а не розмови:

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

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

0

Спробуйте це, я на 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) {

}

0

Використовуйте один із цього методу для вибору останнього отриманого SMS-повідомлення та видалення його, ось у цьому випадку я отримую найбільшу кількість sms і збираюся видалити, використовуючи значення потоку та ідентифікатора 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();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.