Bagaimana cara menghapus SMS dari kotak masuk di Android secara terprogram?

98

Di ponsel Android, pesan SMS yang terdaftar ke aplikasi juga dikirim ke kotak masuk perangkat. Namun untuk mencegah kekacauan, alangkah baiknya jika dapat menghapus pesan SMS khusus aplikasi dari kotak masuk untuk mengurangi potensi meluapnya pesan tersebut.

Pertanyaan di grup Google lainnya tentang mendapatkan jawaban pasti tentang cara terprogram untuk menghapus pesan SMS dari kotak masuk Android tampaknya tidak mendesak.

Jadi skenarionya:

  • Memulai Aplikasi Android.
  • mendaftarkan pesan SMS jenis X, Y dan Z
  • Pesan P, Q, X, Y, Z mengalir seiring waktu, semua disimpan di kotak masuk
  • Aplikasi Android mendeteksi penerimaan X, Y, Z (mungkin sebagai bagian dari acara interupsi program)
  • proses X, Y, Z
  • Keinginan !!! X, Y, Z dihapus dari kotak masuk Android

Apakah sudah dilakukan? Bisakah itu dilakukan?

dmyung.dll
sumber
4
Saya telah menemukan melakukan sesuatu yang berguna dengan kemampuan ponsel Android menjadi pengalaman yang sangat tidak menyenangkan.
BobbyShaftoe
1
teman pertanyaan yang bagus. saya sedang mencari sesuatu yang serupa: D cheers
Harsha MV
3
Yang terbaik adalah mencegah SMS mencapai kotak masuk di tempat pertama: stackoverflow.com/questions/1741628/…
Christopher Orr

Jawaban:

87

"Pada Android 1.6, siaran pesan SMS masuk ( android.provider.Telephony.SMS_RECEIVED) dikirim sebagai" siaran yang dipesan "- artinya Anda dapat memberi tahu sistem komponen mana yang harus menerima siaran terlebih dahulu."

Ini berarti Anda dapat mencegat pesan masuk dan membatalkan penyiarannya lebih lanjut.

Di AndroidManifest.xmlfile Anda , pastikan untuk menetapkan prioritas ke tertinggi:

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

Dalam Anda BroadcastReceiver, di onReceive()metode, sebelum melakukan apa-apa dengan pesan Anda, cukup hubungiabortBroadcast();

EDIT: Pada KitKat, tampaknya ini tidak berfungsi lagi.

EDIT2: Info lebih lanjut tentang cara melakukannya di KitKat di sini:

Hapus SMS dari android di 4.4.4 (Baris yang terpengaruh = 0 (Nol), setelah dihapus)

Viktor Fonic
sumber
3
Dan pastikan untuk melihat stackoverflow.com/questions/1741628/…
Michael Levy
Bisakah Anda melihat di sini stackoverflow.com/questions/25988574/… ?
Gangadhar Nimballi
Jawaban terbaik untuk ini = D
Mike Brian Olivera
27

Dengan menggunakan saran dari orang lain, saya rasa saya berhasil:

(menggunakan SDK v1 R2)

Itu tidak sempurna, karena saya perlu menghapus seluruh percakapan, tetapi untuk tujuan kami, ini adalah kompromi yang cukup karena setidaknya kami akan tahu semua pesan akan dilihat dan diverifikasi. Alur kita mungkin perlu mendengarkan pesan, menangkap pesan yang kita inginkan, melakukan kueri untuk mendapatkan thread_id dari pesan yang baru-baru ini masuk dan melakukan panggilan delete ().

Dalam Aktivitas kami:

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

Catatan: Saya tidak dapat menghapus konten: // sms / inbox / atau konten: // sms / all /

Sepertinya utas diutamakan, dan itu masuk akal, tetapi pesan kesalahan hanya membuat saya semakin berani. Saat mencoba menghapus pada sms / inbox / atau sms / all /, Anda mungkin akan mendapatkan:

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)

Untuk referensi tambahan juga, pastikan untuk memasukkan ini ke dalam manifes untuk penerima maksud Anda:

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

Perhatikan bahwa tag penerima tidak terlihat seperti ini:

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

Ketika saya memiliki pengaturan itu, android memberi saya beberapa pengecualian izin gila yang tidak memungkinkan android.phone menyerahkan SMS yang diterima ke maksud saya. Jadi, JANGAN letakkan atribut izin RECEIVE_SMS itu dalam maksud Anda! Mudah-mudahan seseorang yang lebih bijaksana dari saya dapat memberi tahu saya mengapa hal itu terjadi.

dmyung.dll
sumber
Bisakah Anda melihat di sini stackoverflow.com/questions/25988574/… ?
Gangadhar Nimballi
24

Jadi, saya harus bermain, dan itu adalah mungkin untuk menghapus SMS yang diterima. Sayangnya tidak semuanya lancar :(

Saya memiliki penerima yang menangkap pesan SMS yang masuk. Sekarang cara kerja perutean masuk SMS Android adalah bahwa bagian kode yang bertanggung jawab untuk mendekode pesan mengirim Siaran (ini menggunakan sendBroadcast()metode - yang sayangnya BUKAN versi yang memungkinkan Anda menelepon abortBroadcast()) setiap kali pesan masuk.

Penerima saya mungkin atau mungkin tidak dipanggil sebelum penerima SMS Sistem, dan bagaimanapun juga siaran yang diterima tidak memiliki properti yang dapat mencerminkan _idkolom di tabel SMS.

Namun, tidak menjadi orang yang harus dihentikan semudah itu saya memposting sendiri (melalui Handler) pesan tertunda dengan SmsMessage sebagai objek terlampir. (Saya kira Anda bisa memposting sendiri Runnable juga ...)

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

Penundaan ada untuk memastikan bahwa pada saat pesan tiba, semua penerima siaran telah menyelesaikan barang mereka dan pesan akan disimpan dengan aman di tabel SMS.

Saat pesan (atau Runnable) diterima, inilah yang saya lakukan:

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

Saya menggunakan alamat asal dan bidang cap waktu untuk memastikan kemungkinan yang sangat tinggi untuk menghapus HANYA pesan yang saya minati. Jika saya ingin lebih paranoid, saya dapat menyertakan msg.getMessageBody()konten sebagai bagian dari kueri.

Ya, pesan IS dihapus (hore!). Sayangnya bilah notifikasi tidak diperbarui :(

Saat Anda membuka area notifikasi, Anda akan melihat pesan yang ada di sana untuk Anda ... tetapi ketika Anda mengetuknya untuk membukanya - pesan itu hilang!

Bagi saya, ini tidak cukup baik - Saya ingin semua jejak pesan menghilang - Saya tidak ingin pengguna berpikir ada TXT ketika tidak ada (itu hanya akan menyebabkan laporan bug).

Secara internal di OS panggilan telepon MessagingNotification.updateNewMessageIndicator(Context), tetapi saya kelas itu telah disembunyikan dari API, dan saya tidak ingin mereplikasi semua kode itu hanya demi membuat indikator akurat.

Doug
sumber
Doug, ini bagus. Sebagai pertanyaan, apakah anda tahu jika perlu melakukan posting ke Handler? Saya bertanya-tanya apakah SMS dimasukkan ke dalam database sistem SMS sebelumnya dan penerima siaran dipanggil? Saya mungkin harus melihat ke OS untuk melihat di mana penyisipan terjadi, tetapi saya akan menganggap bahwa penyisipan SMS ke dalam beberapa database terjadi sebelum penerima siaran diberitahu. Punya wawasan tentang ini atau apakah Anda sudah memeriksanya?
Hamy
Bisakah Anda melihat di sini 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;
}

gunakan izin ini di AndroidManifiest

<uses-permission android:name="android.permission.WRITE_SMS"/>
Atif Mahmood
sumber
1
Bagaimana cara mendapatkan id sms?
Dev01
@ Dev01jika anda ingin menghapus sms tertentu anda harus mempunyai id nya kan? dan jika tidak, Anda harus menanyakan id dengan salah satu alamat atau smsbody
Dr. aNdRO
6

Lebih baik menggunakan _id dan thread_id untuk menghapus pesan.

Thread_id adalah sesuatu yang ditugaskan ke pesan yang datang dari pengguna yang sama. Jadi, jika Anda hanya menggunakan thread_id, semua pesan dari pengirim akan dihapus.

Jika Anda menggunakan kombinasi _id, thread_id, maka itu akan menghapus pesan yang ingin Anda hapus.

Uri thread = Uri.parse( "content://sms");
int deleted = contentResolver.delete( thread, "thread_id=? and _id=?", new String[]{String.valueOf(thread_id), String.valueOf(id)} );
Naresh Kavali
sumber
Bisakah Anda melihat di sini stackoverflow.com/questions/25988574/… ?
Gangadhar Nimballi
5

Anda harus menemukan URI pesan tersebut. Tapi begitu Anda melakukannya, saya pikir Anda harus bisa ke android.content.ContentResolver.delete (...) itu.

Berikut info selengkapnya .

Neil
sumber
2

Saya pikir ini tidak dapat dilakukan dengan sempurna untuk saat ini. Ada 2 masalah dasar:

  1. Bagaimana cara memastikan sms sudah ada di kotak masuk saat Anda mencoba menghapusnya?
    Perhatikan bahwa SMS_RECEIVED bukanlah siaran yang dipesan.
    Jadi solusi dmyung benar-benar mencoba keberuntungan; bahkan keterlambatan jawaban Doug bukanlah jaminan.

  2. SmsProvider tidak thread safe. (Lihat http://code.google.com/p/android/issues/detail?id=2916#c0 )
    Fakta bahwa lebih dari satu klien meminta penghapusan dan sisipkan di dalamnya di waktu yang sama akan menyebabkan kerusakan data atau bahkan Pengecualian Runtime langsung.

an0
sumber
2

Saya tidak bisa membuatnya berfungsi menggunakan solusi dmyung, itu memberi saya pengecualian saat mendapatkan id pesan atau id utas.

Pada akhirnya, saya telah menggunakan metode berikut untuk mendapatkan id utas:

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

Lalu saya bisa menghapusnya. Namun, seperti yang dikatakan Doug, notifikasi tersebut tetap ada, bahkan pesan tersebut ditampilkan saat membuka panel notifikasi. Hanya ketika mengetuk pesan saya benar-benar dapat melihat bahwa itu kosong.

Jadi saya kira satu-satunya cara ini akan bekerja adalah dengan benar-benar mencegat SMS sebelum dikirim ke sistem, bahkan sebelum mencapai kotak masuk. Namun, saya sangat meragukan ini bisa dilakukan. Harap perbaiki saya jika saya salah.

Stelian Iancu
sumber
Nah, Anda yang salah tentang mencegat pesan sebelum kotak masuk: Anda dapat menerima siaran android.provider.Telephony.SMS_RECEIVED, Anda hanya perlu permssion android.permission.RECEIVE_SMS. Anda bahkan dapat dengan mudah menghentikan pesan agar tidak masuk ke kotak masuk dengan memanggil abortBroadcast () karena ini adalah siaran yang dipesan. PS Harus lucu dikoreksi 2 tahun kemudian :)
lapis
2

Gunakan fungsi ini untuk menghapus utas pesan tertentu atau memodifikasi sesuai kebutuhan Anda:

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) {

  }
}

Panggil fungsi ini di bawah ini:

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

Jangan lupa tambahkan izin mainfest android di bawah ini:

<uses-permission android:name="android.permission.WRITE_SMS"/>
Ashish Sahu
sumber
1

Matikan saja notifikasi untuk aplikasi sms default. Proses notifikasi Anda sendiri untuk semua pesan teks!

Noah Seidman
sumber
1

Anda cukup mencoba kode berikut. Ini akan menghapus semua sms yang ada di telepon (Diterima atau Terkirim)

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);
}
Rajamohan Sugumaran
sumber
1

Juga perbarui file manifes untuk menghapus sms yang Anda butuhkan izin menulis.

<uses-permission android:name="android.permission.WRITE_SMS"/>
Wasif Kirmani
sumber
1

Sekarang abortBroadcast();metode dapat digunakan untuk membatasi pesan masuk untuk masuk ke kotak masuk.

Arun Badole
sumber
0

Contoh untuk menghapus satu SMS, bukan percakapan:

getContentResolver().delete(Uri.parse("content://sms/conversations/" + threadID), "_id = ?", new String[]{id});
embo
sumber
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;
}
sharma_kunal
sumber
0

Coba ini saya 100% yakin ini akan berfungsi dengan baik: - // cukup taruh alamat konversi di sini untuk menghapus seluruh konversi berdasarkan alamat (jangan lupa menambahkan izin baca, tulis di mainfest) Berikut adalah Kode:

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) {

}
Ashish Sahu
sumber
0

Gunakan salah satu metode ini untuk memilih SMS yang terakhir diterima dan menghapusnya, di sini dalam hal ini saya mendapatkan sms paling banyak dan akan menghapus menggunakan utas dan nilai id dari 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();
}
Pir Fahim Shah
sumber