Come eliminare un SMS dalla posta in arrivo in Android a livello di programmazione?


98

Sui telefoni Android, anche i messaggi SMS registrati nelle applicazioni vengono inviati alla posta in arrivo del dispositivo. Tuttavia, per evitare confusione, sarebbe bello poter rimuovere messaggi SMS specifici dell'applicazione dalla posta in arrivo per ridurre il potenziale overflow di quei messaggi.

Le domande su altri gruppi Google su come ottenere una risposta definitiva su un modo programmatico per eliminare i messaggi SMS dalla posta in arrivo di Android non sembrano premere.

Quindi lo scenario:

  • Avvio dell'app Android.
  • registrare i tipi di messaggi SMS X, Y e Z
  • i messaggi P, Q, X, Y, Z vengono trasmessi nel corso del tempo, tutti depositati nella posta in arrivo
  • L'applicazione Android rileva la ricezione di X, Y, Z (presumibilmente come parte dell'evento di interruzione del programma)
  • processo X, Y, Z
  • Desiderio !!! X, Y, Z vengono eliminati dalla posta in arrivo di Android

È stato fatto? Può essere fatto?


4
Ho trovato che fare qualsiasi cosa utile con le funzionalità del telefono di Android sia un'esperienza molto spiacevole.
BobbyShaftoe

1
buona domanda amico. stavo cercando qualcosa di simile: D cheers
Harsha MV

3
La cosa migliore sarebbe impedire che l'SMS raggiunga la posta in arrivo in primo luogo: stackoverflow.com/questions/1741628/…
Christopher Orr

Risposte:


87

"A partire da Android 1.6, le trasmissioni di messaggi SMS in arrivo ( android.provider.Telephony.SMS_RECEIVED) vengono consegnate come una" trasmissione ordinata ", il che significa che puoi dire al sistema quali componenti dovrebbero ricevere la trasmissione per primi."

Ciò significa che è possibile intercettare il messaggio in arrivo e interromperne la trasmissione più avanti.

Nel tuo AndroidManifest.xmlfile, assicurati di avere la priorità impostata sulla massima:

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

Nella tua BroadcastReceiver, nel onReceive()metodo, prima di eseguire qualsiasi cosa con il vostro messaggio, è sufficiente chiamareabortBroadcast();

EDIT: A partire da KitKat, questo non funziona più apparentemente.

EDIT2: Maggiori informazioni su come farlo su KitKat qui:

Elimina SMS da Android su 4.4.4 (Righe interessate = 0 (Zero), dopo l'eliminazione)




La migliore risposta per questo = D
Mike Brian Olivera

27

Usando i suggerimenti di altri, penso di averlo fatto funzionare:

(utilizzando SDK v1 R2)

Non è perfetto, poiché ho bisogno di eliminare l'intera conversazione, ma per i nostri scopi è un compromesso sufficiente poiché almeno sapremo che tutti i messaggi verranno esaminati e verificati. Il nostro flusso probabilmente dovrà quindi ascoltare il messaggio, acquisire il messaggio che vogliamo, eseguire una query per ottenere il thread_id del messaggio in entrata di recente ed eseguire la chiamata delete ().

Nella nostra attività:

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

Nota: non sono riuscito a eliminare content: // sms / inbox / o content: // sms / all /

Sembra che il thread abbia la precedenza, il che ha senso, ma il messaggio di errore mi ha solo incoraggiato ad essere più arrabbiato. Quando provi l'eliminazione su sms / inbox / o sms / all /, probabilmente otterrai:

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)

Anche per ulteriore riferimento, assicurati di inserire questo nel tuo manifest per il tuo destinatario intento:

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

Nota che il tag del ricevitore non ha questo aspetto:

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

Quando avevo queste impostazioni, Android mi ha dato alcune eccezioni di permessi pazzi che non permettevano ad android.phone di trasferire l'SMS ricevuto secondo le mie intenzioni. Quindi, NON inserire l'attributo di autorizzazione RECEIVE_SMS nel tuo intento! Spero che qualcuno più saggio di me possa dirmi perché è stato così.



24

Quindi, ho giocato ed è possibile cancellare un SMS ricevuto. Purtroppo non è tutto normale :(

Ho un ricevitore che risponde ai messaggi SMS in arrivo. Ora il modo in cui funziona il routing in entrata degli SMS di Android è che il pezzo di codice responsabile della decodifica dei messaggi invia una trasmissione (utilizza il sendBroadcast()metodo - che purtroppo NON è la versione che ti consente semplicemente di chiamare abortBroadcast()) ogni volta che arriva un messaggio.

Il mio destinatario può o meno essere chiamato prima del ricevitore SMS di Sistema, e in ogni caso la trasmissione ricevuta non ha proprietà che potrebbero riflettere la _idcolonna nella tabella SMS.

Tuttavia, non essendo uno da fermare così facilmente, invio a me stesso (tramite un gestore) un messaggio ritardato con SmsMessage come oggetto allegato. (Suppongo che potresti pubblicare anche tu un Runnable ...)

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

Il ritardo è lì per garantire che, nel momento in cui arriva il messaggio, tutti i destinatari di Broadcast avranno finito il loro lavoro e il messaggio sarà inserito in modo sicuro nella tabella degli SMS.

Quando il messaggio (o Runnable) viene ricevuto ecco cosa faccio:

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

Uso l'indirizzo di origine e il campo timestamp per garantire un'elevata probabilità di eliminare SOLO il messaggio che mi interessa. Se volessi essere ancora più paranoico, potrei includere il msg.getMessageBody()contenuto come parte della query.

Sì, il messaggio È cancellato (evviva!). Purtroppo la barra delle notifiche non viene aggiornata :(

Quando apri l'area di notifica vedrai il messaggio seduto lì per te ... ma quando lo tocchi per aprirlo, non c'è più!

Per me, questo non è abbastanza buono - voglio che tutte le tracce del messaggio scompaiano - non voglio che l'utente pensi che ci sia un TXT quando non c'è (ciò causerebbe solo segnalazioni di bug).

Internamente nel sistema operativo le telefonate MessagingNotification.updateNewMessageIndicator(Context), ma io quella classe è stata nascosta dall'API e non volevo replicare tutto quel codice solo per rendere l'indicatore accurato.


Doug, è fantastico. Come domanda, sai se è necessario fare il post all'Handler? Chissà se l'SMS viene inserito nel database SMS di sistema prima e vengono chiamati i ricevitori broadcast? Probabilmente dovrò esaminare il sistema operativo per vedere dove avviene l'inserimento, ma presumo che l'inserimento dell'SMS in qualche database avvenga prima che i destinatari della trasmissione vengano informati. Hai qualche idea in merito o l'hai già verificata?
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;
}

usa questa autorizzazione in AndroidManifiest

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

1
Come otteniamo l'ID sms?
Dev01


@ Dev01se vuoi cancellare un particolare sms devi avere il suo id giusto? e in caso contrario è necessario interrogare l'id con indirizzo o smsbody
Dr. aNdRO

6

È meglio usare _id e thread_id per eliminare un messaggio.

Thread_id è qualcosa assegnato ai messaggi provenienti dallo stesso utente. Quindi, se usi solo thread_id, tutti i messaggi del mittente verranno eliminati.

Se usi la combinazione di _id, thread_id, eliminerà il messaggio esatto che stai cercando di eliminare.

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

Dovrai trovare l' URI del messaggio. Ma una volta che lo fai, penso che dovresti essere in grado di android.content.ContentResolver.delete (...).

Ecco qualche informazione in più .


2

Penso che questo non possa essere fatto perfettamente per il momento. Ci sono 2 problemi di base:

  1. Come puoi assicurarti che l'SMS sia già nella posta in arrivo quando provi a eliminarlo?
    Notare che SMS_RECEIVED non è una trasmissione ordinata.
    Quindi la soluzione di dmyung è tentare completamente la fortuna; anche il ritardo nella risposta di Doug non è una garanzia.

  2. SmsProvider non è thread-safe. (Fare riferimento a http://code.google.com/p/android/issues/detail?id=2916#c0 )
    Il fatto che più di un client richieda l'eliminazione e l'inserimento al suo interno in stesso tempo provocherà il danneggiamento dei dati o anche un'eccezione immediata di runtime.


2

Non sono riuscito a farlo funzionare utilizzando la soluzione di dmyung, mi ha dato un'eccezione quando ottenevo l'ID del messaggio o l'ID del thread.

Alla fine, ho usato il seguente metodo per ottenere l'ID thread:

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

Quindi potrei cancellarlo. Tuttavia, come ha detto Doug, la notifica è ancora lì, anche il messaggio viene visualizzato all'apertura del pannello delle notifiche. Solo toccando il messaggio ho potuto effettivamente vedere che è vuoto.

Quindi immagino che l'unico modo in cui funzionerebbe sarebbe effettivamente intercettare in qualche modo l'SMS prima che venga consegnato al sistema, prima ancora che raggiunga la posta in arrivo. Tuttavia, dubito fortemente che ciò sia fattibile. Per favore correggimi se sbaglio.


Beh, sei sbagliato su intercettare i messaggi prima che la casella di posta elettronica: è possibile ricevere una trasmissione android.provider.Telephony.SMS_RECEIVED, è necessario solo un PERMSSION android.permission.RECEIVE_SMS. Puoi anche impedire facilmente al messaggio di raggiungere la posta in arrivo chiamando abortBroadcast () poiché è una trasmissione ordinata. PS Deve essere divertente da correggere 2 anni dopo :)
lapislazzuli

2

Utilizzare questa funzione per eliminare thread di messaggi specifici o modificare in base alle proprie esigenze:

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

  }
}

Chiama questa funzione semplicemente di seguito:

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

Non dimenticare di aggiungere l'autorizzazione mainfest di Android di seguito:

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

1

Basta disattivare le notifiche per l'app SMS predefinita. Elabora le tue notifiche per tutti i messaggi di testo!



1

Basta provare il seguente codice, cancellerà tutti gli sms che sono tutti nel telefono (ricevuti o inviati)

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

Aggiorna anche il file manifest in quanto per eliminare un sms hai bisogno dei permessi di scrittura.

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

1

Ora il abortBroadcast();metodo può essere utilizzato per limitare il messaggio in arrivo alla posta in arrivo.


0

Esempio per l'eliminazione di un SMS, non di una conversazione:

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

Prova questo, sono sicuro al 100% che funzionerà bene: - // metti qui l'indirizzo di conversione per eliminare l'intera conversione per indirizzo (non dimenticare di aggiungere il permesso di lettura e scrittura nel mainfest) Ecco il codice:

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

Usa uno di questo metodo per selezionare l'ultimo SMS ricevuto ed eliminarlo, qui in questo caso sto ottenendo il maggior numero di sms e sto per eliminare usando il thread e il valore dell'ID di 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();
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.