Android'de gelen kutusundan programlı olarak bir SMS nasıl silinir?


98

Android telefonlarda, uygulamalara kaydedilen SMS mesajları da cihazın gelen kutusuna gönderilir. Ancak dağınıklığı önlemek için, bu mesajların olası taşmasını azaltmak için uygulamaya özel SMS mesajlarını gelen kutusundan kaldırabilmek güzel olurdu.

Diğer Google gruplarında, Android gelen kutusundan SMS mesajlarını programlı bir şekilde silmeye yönelik kesin bir yanıt almaya ilişkin sorular çok acil görünmüyor.

Öyleyse senaryo:

  • Android Uygulaması başlangıcı.
  • SMS mesaj türlerini kaydetme X, Y ve Z
  • mesajlar P, Q, X, Y, Z akışı zaman içinde gelir, tümü gelen kutusuna depolanır
  • Android uygulaması X, Y, Z'nin alındığını algılar (muhtemelen program kesinti olayının bir parçası olarak)
  • X, Y, Z süreci
  • Arzu !!! X, Y, Z Android gelen kutusundan silinir

Yapıldı mı? Yapılabilir mi?


4
Android'in telefon özellikleriyle yararlı bir şey yapmayı çok tatsız bir deneyim olarak buldum.
BobbyShaftoe

1
iyi soru dostum. benzer bir şey arıyordum: D alkışlar
Harsha MV

3
En iyisi, SMS'in gelen kutusuna ulaşmasını ilk etapta engellemektir: stackoverflow.com/questions/1741628/…
Christopher Orr

Yanıtlar:


87

"Android 1.6'dan itibaren, gelen SMS mesajı yayınları ( android.provider.Telephony.SMS_RECEIVED)" sıralı yayın "olarak teslim edilmektedir - bu, sisteme yayını önce hangi bileşenlerin alması gerektiğini söyleyebileceğiniz anlamına gelir."

Bu, gelen mesajı yakalayabileceğiniz ve daha sonra yayınlamayı iptal edebileceğiniz anlamına gelir.

Senin içinde AndroidManifest.xmldosyaya, en yüksek öncelik kümesine sahip emin olun:

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

Gözlerinde farklı BroadcastReceiver, içinde onReceive()yöntemle, mesajınızla şey yapmadan önce, basitçe çağrıabortBroadcast();

DÜZENLEME: KitKat itibariyle, bu artık görünüşe göre çalışmıyor.

DÜZENLEME2: KitKat'ta nasıl yapılacağı hakkında daha fazla bilgiyi burada bulabilirsiniz:

4.4.4'te Android'den SMS sil (Etkilenen satırlar = 0 (Sıfır), silindikten sonra)




Bunun için en iyi cevap = D
Mike Brian Olivera

27

Başkalarının önerilerini kullanarak, işe yaradığını düşünüyorum:

(SDK v1 R2 kullanarak)

Mükemmel değil, çünkü tüm konuşmayı silmem gerekiyor, ancak amaçlarımız için, en azından tüm mesajlara bakılacağını ve doğrulanacağını bileceğimiz için bu yeterli bir uzlaşmadır. Akışımızın muhtemelen mesajı dinlemesi, istediğimiz mesajı yakalaması, yakın zamanda gelen mesajın thread_id'sini almak için bir sorgu yapması ve delete () çağrısını yapması gerekecektir.

Faaliyetimizde:

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

Not: content: // sms / inbox / veya content: // sms / all / üzerinde silme işlemi yapamadım

Görünüşe göre iş parçacığı öncelikli, bu mantıklı, ancak hata mesajı beni daha öfkeli olmaya cesaretlendirdi. Sms / inbox / veya sms / all / üzerinde silmeyi denediğinizde, muhtemelen şunu alacaksınız:

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)

Daha fazla referans için, bunu niyet alıcınız için bildiriminize koyduğunuzdan emin olun:

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

Alıcı etiketinin şöyle görünmediğini unutmayın:

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

Bu ayarlara sahip olduğumda, android bana android.phone'un alınan SMS'i amacıma göre teslim etmesine izin vermeyen bazı çılgın izinler verdi. Bu nedenle, RECEIVE_SMS izin özniteliğini amacınıza KOYMAYIN! Umarım benden daha bilge biri bunun neden böyle olduğunu bana söyleyebilir.



24

Yani, bir oyun vardı ve olan bir alınan SMS silmek mümkün. Maalesef tamamen düz yelken değil :(

Gelen SMS mesajlarını alan bir alıcım var. Artık Android SMS gelen yönlendirmesinin çalışma şekli, mesajların kodunu çözmekten sorumlu olan kod parçasının bir mesaj geldiğinde bir Yayın göndermesidir (bu sendBroadcast()yöntemi kullanır - maalesef basitçe aramanıza izin veren sürüm DEĞİLDİR abortBroadcast()).

Alıcım, Sistemlerin SMS alıcısından önce aranabilir veya aranmayabilir ve her durumda alınan yayının, _idSMS tablosundaki sütunu yansıtabilecek hiçbir özelliği yoktur .

Ancak, bu kadar kolay durdurulacak biri olmamakla birlikte kendime (bir İşleyici aracılığıyla) SmsMessage'ın ekli nesne olduğu gecikmiş bir mesaj gönderiyorum. (Sanırım kendine de Runnable koyabilirsin ...)

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

Gecikme, mesaj geldiğinde tüm Yayın alıcılarının işlerini bitirmesini ve mesajın SMS tablosuna güvenli bir şekilde yerleştirilmesini sağlamak içindir.

Mesaj (veya Runnable) alındığında burada yaptığım şey:

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

YALNIZCA ilgilendiğim mesajı silme olasılığının çok yüksek olmasını sağlamak için kaynak adresi ve zaman damgası alanını kullanıyorum. Daha da paranoyak olmak istersem, msg.getMessageBody()içeriği sorgunun bir parçası olarak ekleyebilirim .

Evet, mesaj silinmiştir (yaşasın!). Maalesef bildirim çubuğu güncellenmedi :(

Bildirim alanını açtığınızda, orada sizin için oturan mesajı göreceksiniz ... ama açmak için üzerine dokunduğunuzda - gitti!

Bana göre bu yeterince iyi değil - mesajın tüm izinin kaybolmasını istiyorum - yokken kullanıcının TXT olduğunu düşünmesini istemiyorum (bu sadece hata raporlarına neden olur).

İşletim sisteminde dahili olarak telefon arar MessagingNotification.updateNewMessageIndicator(Context), ancak ben bu sınıf API'den gizlendi ve sadece göstergeyi doğru yapmak adına bu kodun tamamını kopyalamak istemedim.


Doug, bu harika. Soru olarak, gönderiyi İşleyiciye göndermenin gerekli olup olmadığını biliyor musunuz? Acaba yayın alıcıları aranmadan önce SMS sistem SMS veri tabanına eklenmiş mi? Eklemenin nerede gerçekleştiğini görmek için büyük olasılıkla işletim sistemine bakmam gerekecek, ancak SMS'nin bazı veri tabanına eklenmesinin yayın alıcıları bilgilendirilmeden önce gerçekleştiğini varsayıyorum. Bununla ilgili herhangi bir fikriniz var mı yoksa zaten kontrol ettiniz mi?
Hamy


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

bu izni AndroidManifiest'te kullan

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

1
Sms id nasıl alınır?
Dev01


@ Dev01 Belirli bir sms'i silmek istiyorsanız, kimliğinin doğru olması gerekir? ve yoksa kimliği ya adres ya da smsbody ile sorgulamanız gerekir
Dr. aNdRO

6

Bir mesajı silmek için _id ve thread_id kullanmak daha iyidir.

Thread_id, aynı kullanıcıdan gelen mesajlara atanan bir şeydir. Dolayısıyla, yalnızca thread_id kullanırsanız, gönderenden gelen tüm mesajlar silinecektir.

_İd, thread_id kombinasyonunu kullanırsanız, silmek istediğiniz mesajı tam olarak silecektir.

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

Mesajın URI'sini bulmanız gerekecek . Ama bir kez yaptıktan sonra android.content.ContentResolver.delete (...) yapabilmeniz gerektiğini düşünüyorum.

İşte biraz daha bilgi .


2

Bunun şimdilik mükemmel bir şekilde yapılamayacağını düşünüyorum. 2 temel sorun var:

  1. Silmeye çalıştığınızda sms'nin zaten gelen kutusunda olduğundan nasıl emin olabilirsiniz?
    SMS_RECEIVED'in sıralı bir yayın olmadığına dikkat edin.
    Yani dmyung'un çözümü tamamen kişinin şansını denemektir; Doug'un cevabındaki gecikme bile bir garanti değil.

  2. SmsProvider iş parçacığı için güvenli değildir. ( Http://code.google.com/p/android/issues/detail?id=2916#c0 adresine bakın )
    Birden fazla istemcinin silme isteğinde bulunması ve aynı zamanda veri bozulmasına ve hatta anında Çalışma Zamanı İstisnasına neden olur.


2

Dmyung'un çözümünü kullanarak çalışmasını sağlayamadım, mesaj kimliği veya iş parçacığı kimliği alırken bana bir istisna verdi.

Sonunda, iş parçacığı kimliğini almak için aşağıdaki yöntemi kullandım:

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

Sonra onu silebilirim. Ancak, Doug'un dediği gibi, bildirim hala oradadır, hatta bildirim paneli açılırken mesaj görüntülenir. Sadece mesaja dokunduğumda aslında boş olduğunu görebiliyordum.

Bu yüzden, bunun işe yaramasının tek yolu, SMS'i sisteme teslim edilmeden, hatta gelen kutusuna ulaşmadan önce bir şekilde durdurmak olabilir. Ancak bunun yapılabileceğinden çok şüpheliyim. Yanılıyorsam lütfen beni düzeltin.


Eh, olan gelen kutusunda önce iletileri müdahale hakkında yanlış: Bir yayın android.provider.Telephony.SMS_RECEIVED alabilir, yalnızca permssion android.permission.RECEIVE_SMS gerekir. Sıralı bir yayın olduğu için abortBroadcast () 'i çağırarak mesajın gelen kutusuna ulaşmasını bile kolayca durdurabilirsiniz. Not: 2 yıl sonra düzeltilmek için komik olmalı :)
lapis

2

Bu işlevi, belirli bir mesaj dizisini silmek veya ihtiyaçlarınıza göre değiştirmek için kullanın:

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

  }
}

Bu işlevi basitçe aşağıda arayın:

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

Aşağıya android mainfest iznini eklemeyi unutmayın:

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

1

Varsayılan sms uygulaması için bildirimleri kapatmanız yeterlidir. Tüm kısa mesajlar için kendi bildirimlerinizi işleyin!



1

Sadece aşağıdaki kodu deneyin.Telefonda bulunan tüm sms'leri silecektir (Alınan veya Gönderilen)

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

Ayrıca manifest dosyasını, yazma izinlerine ihtiyacınız olan bir sms'i silmek için güncelleyin.

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

1

Artık abortBroadcast();yöntem, gelen mesajın gelen kutusuna gitmesini kısıtlamak için kullanılabilir.


0

Bir SMS'i silmek için örnek, görüşmeyi değil:

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

Bunu deneyin, bunun iyi çalışacağından% 100 eminim: - // sadece adrese göre tüm dönüşümü silmek için buraya dönüşüm adresini girin (ana festivalde okuma, yazma izni eklemeyi unutmayın) İşte Kod:

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

Son alınan SMS'i seçmek ve silmek için bu yöntemlerden birini kullanın, burada bu durumda en çok sms alıyorum ve sms'nin thread ve id değerini kullanarak sileceğim,

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();
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.