Wie lösche ich eine SMS programmgesteuert aus dem Posteingang in Android?


98

Auf Android-Telefonen werden in Anwendungen registrierte SMS-Nachrichten auch an den Posteingang des Geräts gesendet. Um jedoch Unordnung zu vermeiden, wäre es schön, anwendungsspezifische SMS-Nachrichten aus dem Posteingang entfernen zu können, um den möglichen Überlauf dieser Nachrichten zu verringern.

Fragen zu anderen Google-Gruppen, wie Sie programmgesteuert eine endgültige Antwort zum Löschen von SMS-Nachrichten aus dem Android-Posteingang erhalten, scheinen nicht dringlich zu sein.

Also das Szenario:

  • Start der Android App.
  • Registrieren Sie die SMS-Nachrichtentypen X, Y und Z.
  • Die Nachrichten P, Q, X, Y, Z werden im Laufe der Zeit eingespeist und im Posteingang abgelegt
  • Die Android-Anwendung erkennt den Empfang von X, Y, Z (vermutlich als Teil des Programmunterbrechungsereignisses).
  • Prozess X, Y, Z.
  • Ruhestand !!! X, Y, Z werden aus dem Android-Posteingang gelöscht

Wurde es getan? Kann es gemacht werden?


4
Ich habe festgestellt, dass es sehr unangenehm ist, mit den Telefonfunktionen von Android etwas Nützliches zu tun.
BobbyShaftoe

1
gute Frage Kumpel. Ich suchte nach etwas ähnlichem: D Prost
Harsha MV

3
Am besten verhindern Sie, dass die SMS den Posteingang erreicht: stackoverflow.com/questions/1741628/…
Christopher Orr

Antworten:


87

"Ab Android 1.6 werden eingehende SMS-Sendungen ( android.provider.Telephony.SMS_RECEIVED) als" geordnete Sendung "zugestellt. Dies bedeutet, dass Sie dem System mitteilen können, welche Komponenten die Sendung zuerst empfangen sollen."

Dies bedeutet, dass Sie eingehende Nachrichten abfangen und die Übertragung später abbrechen können.

Stellen Sie in Ihrer AndroidManifest.xmlDatei sicher, dass die Priorität auf die höchste gesetzt ist:

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

Rufen Sie BroadcastReceiverin Ihrer onReceive()Methode einfach auf, bevor Sie etwas mit Ihrer Nachricht ausführenabortBroadcast();

EDIT: Ab KitKat funktioniert dies anscheinend nicht mehr.

EDIT2: Weitere Informationen dazu auf KitKat finden Sie hier:

Löschen Sie SMS von Android am 4.4.4 (Betroffene Zeilen = 0 (Null), nach dem Löschen)


3
Und stellen Sie sicher, dass Sie stackoverflow.com/questions/1741628/…
Michael Levy


Die beste Antwort dafür = D
Mike Brian Olivera

27

Ich denke, ich habe es mit Vorschlägen anderer zum Laufen gebracht:

(mit SDK v1 R2)

Es ist nicht perfekt, da ich die gesamte Konversation löschen muss, aber für unsere Zwecke ist es ein ausreichender Kompromiss, da wir zumindest wissen, dass alle Nachrichten geprüft und verifiziert werden. Unser Datenfluss muss dann wahrscheinlich auf die Nachricht warten, die gewünschte Nachricht erfassen, eine Abfrage durchführen, um die thread_id der kürzlich eingehenden Nachricht abzurufen, und den Aufruf delete () ausführen.

In unserer Aktivität:

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

Hinweis: Ich konnte den Inhalt nicht löschen: // sms / inbox / oder den Inhalt: // sms / all /

Es sieht so aus, als hätte der Thread Vorrang, was Sinn macht, aber die Fehlermeldung hat mich nur ermutigt, wütender zu sein. Wenn Sie versuchen, auf sms / inbox / oder sms / all / zu löschen, erhalten Sie wahrscheinlich:

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)

Stellen Sie auch als zusätzliche Referenz sicher, dass Sie dies für Ihren Intent-Empfänger in Ihr Manifest aufnehmen:

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

Beachten Sie, dass das Empfänger-Tag nicht so aussieht:

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

Als ich diese Einstellungen hatte, gab mir Android einige verrückte Berechtigungsausnahmen, die es android.phone nicht erlaubten, die empfangene SMS an meine Absicht weiterzugeben. Setzen Sie dieses Berechtigungsattribut RECEIVE_SMS also NICHT in Ihre Absicht ein! Hoffentlich kann mir jemand, der klüger als ich ist, sagen, warum das so war.



24

Also hatte ich ein Spiel und es ist möglich, eine empfangene SMS zu löschen. Leider ist nicht alles einfach zu segeln :(

Ich habe einen Empfänger, der eingehende SMS-Nachrichten entgegennimmt. Das eingehende Routing für Android-SMS funktioniert nun so, dass der Code, der für die Dekodierung der Nachrichten verantwortlich ist, eine Sendung sendet (er verwendet die sendBroadcast()Methode - die leider NICHT die Version ist, mit der Sie einfach anrufen könnenabortBroadcast() jedem Eintreffen einer Nachricht ).

Mein Empfänger kann vor dem System-SMS-Empfänger angerufen werden oder nicht, und in jedem Fall hat die empfangene Sendung keine Eigenschaft, die die _idSpalte in der SMS-Tabelle widerspiegeln könnte .

Da ich jedoch nicht so einfach gestoppt werden kann, poste ich mir (über einen Handler) eine verzögerte Nachricht mit der SmsMessage als angehängtem Objekt. (Ich nehme an, du könntest dir auch einen Runnable posten ...)

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

Die Verzögerung soll sicherstellen, dass bis zum Eintreffen der Nachricht alle Rundfunkempfänger ihre Arbeit beendet haben und die Nachricht sicher in der SMS-Tabelle gespeichert ist.

Wenn die Nachricht (oder Runnable) hier empfangen wird, mache ich Folgendes:

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

Ich verwende das Feld für die ursprüngliche Adresse und den Zeitstempel, um eine sehr hohe Wahrscheinlichkeit zu gewährleisten, dass NUR die Nachricht gelöscht wird, an der ich interessiert bin. Wenn ich noch paranoider sein möchte, könnte ich die einschließen msg.getMessageBody() Inhalt als Teil der Abfrage aufnehmen.

Ja, die Nachricht wird gelöscht (Hurra!). Leider wird die Benachrichtigungsleiste nicht aktualisiert :(

Wenn Sie den Benachrichtigungsbereich öffnen, wird die Nachricht dort für Sie angezeigt ... aber wenn Sie darauf tippen, um sie zu öffnen, ist sie weg!

Für mich ist dies nicht gut genug - ich möchte, dass alle Spuren der Nachricht verschwinden - ich möchte nicht, dass der Benutzer denkt, dass es eine TXT gibt, wenn dies nicht der Fall ist (dies würde nur Fehlerberichte verursachen).

Intern im Betriebssystem ruft das Telefon an MessagingNotification.updateNewMessageIndicator(Context), aber ich, diese Klasse, wurde vor der API ausgeblendet, und ich wollte nicht den gesamten Code replizieren, nur um den Indikator korrekt zu machen.


Doug, das ist großartig. Wissen Sie als Frage, ob es notwendig ist, die Post an den Handler zu senden? Ich frage mich, ob die SMS in die System-SMS-Datenbank eingefügt wurde, bevor und von den Rundfunkempfängern aufgerufen wird. Ich werde wahrscheinlich in das Betriebssystem schauen müssen, um zu sehen, wo das Einfügen erfolgt, aber ich würde annehmen, dass das Einfügen der SMS in eine Datenbank erfolgt, bevor die Rundfunkempfänger informiert werden. Haben Sie einen Einblick in diese oder haben Sie bereits danach gesucht?
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;
}

Verwenden Sie diese Berechtigung in AndroidManifiest

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

1
Wie bekommen wir eine SMS-ID?
Dev01


@ Dev01Wenn Sie eine bestimmte SMS löschen möchten, müssen Sie deren ID richtig haben? und wenn nicht, müssen Sie die ID entweder mit Adresse oder SMS abfragen
Dr. aNdRO

6

Es ist besser, die _id und die thread_id zu verwenden, um eine Nachricht zu löschen.

Thread_id wird den Nachrichten zugewiesen, die von demselben Benutzer stammen. Wenn Sie also nur thread_id verwenden, werden alle Nachrichten vom Absender gelöscht.

Wenn Sie die Kombination von _id, thread_id verwenden, wird die genaue Nachricht gelöscht, die Sie löschen möchten.

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

Sie müssen den URI der Nachricht finden. Aber sobald Sie dies tun, denke ich, sollten Sie in der Lage sein, android.content.ContentResolver.delete (...) es.

Hier noch ein paar Infos .


2

Ich denke, das kann vorerst nicht perfekt gemacht werden. Es gibt 2 grundlegende Probleme:

  1. Wie können Sie sicherstellen, dass sich die SMS bereits im Posteingang befindet, wenn Sie versuchen, sie zu löschen?
    Beachten Sie, dass SMS_RECEIVED keine bestellte Sendung ist.
    Die Lösung von dmyung besteht also darin, sein Glück zu versuchen. Selbst die Verzögerung in Dougs Antwort ist keine Garantie.

  2. Der SmsProvider ist nicht threadsicher (siehe http://code.google.com/p/android/issues/detail?id=2916#c0 ).
    Die Tatsache, dass mehr als ein Client das Löschen und Einfügen anfordert Gleichzeitig führt dies zu einer Beschädigung der Daten oder sogar zu einer sofortigen Laufzeitausnahme.


2

Ich konnte es mit der Lösung von dmyung nicht zum Laufen bringen. Es gab mir eine Ausnahme, wenn ich entweder die Nachrichten-ID oder die Thread-ID erhielt.

Am Ende habe ich die folgende Methode verwendet, um die Thread-ID zu erhalten:

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

Dann könnte ich es löschen. Wie Doug sagte, ist die Benachrichtigung jedoch immer noch vorhanden, sogar die Nachricht wird beim Öffnen des Benachrichtigungsfelds angezeigt. Nur wenn ich auf die Nachricht tippe, kann ich tatsächlich sehen, dass sie leer ist.

Ich denke, der einzige Weg, wie dies funktionieren würde, wäre, die SMS tatsächlich irgendwie abzufangen, bevor sie an das System gesendet wird, bevor sie überhaupt den Posteingang erreicht. Ich bezweifle jedoch sehr, dass dies machbar ist. Bitte korrigieren Sie mich, wenn ich falsch liege.


Nun, Sie sind falsch über Nachrichten vor dem Posteingang Abfangen: Sie eine Sendung android.provider.Telephony.SMS_RECEIVED empfangen können, müssen Sie nur ein permssion android.permission.RECEIVE_SMS. Sie können sogar ganz einfach verhindern, dass die Nachricht den Posteingang erreicht, indem Sie abortBroadcast () aufrufen, da es sich um eine geordnete Sendung handelt. PS Muss lustig sein, um 2 Jahre später korrigiert zu werden :)
Lapis

2

Verwenden Sie diese Funktion, um einen bestimmten Nachrichtenthread zu löschen oder entsprechend Ihren Anforderungen zu ändern:

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

  }
}

Rufen Sie diese Funktion einfach unten auf:

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

Vergiss nicht, unten die Erlaubnis für das Android-Mainfest hinzuzufügen:

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

1

Deaktivieren Sie einfach Benachrichtigungen für die Standard-SMS-App. Verarbeiten Sie Ihre eigenen Benachrichtigungen für alle Textnachrichten!


1

Schauen Sie sich diesen Link an, er gibt Ihnen einen kurzen Überblick über die Logik:

https://gist.github.com/5178e798d9a00cac4ddb
Rufen Sie einfach die Funktion deleteSMS () mit einer gewissen Verzögerung auf, da es einen kleinen Zeitunterschied gibt der Benachrichtigung und wenn es tatsächlich gespeichert wird ...., für Details schauen Sie sich auch diesen Link an ..........

http://htmlcoderhelper.com/how-to-delete-sms-from- Posteingang-in-android-programmatisch /

Danke ..........


1

Versuchen Sie einfach den folgenden Code. Er löscht alle SMS, die sich alle im Telefon befinden (empfangen oder gesendet).

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

Aktualisieren Sie auch die Manifestdatei, um eine SMS zu löschen, für die Sie Schreibberechtigungen benötigen.

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

1

Jetzt abortBroadcast();kann die Methode verwendet werden, um die eingehende Nachricht auf den Posteingang zu beschränken.


0

Beispiel für das Löschen einer SMS, keine Konversation:

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

Versuchen Sie dies. Ich bin zu 100% sicher, dass dies gut funktioniert: - // Geben Sie hier einfach die Konvertierungsadresse ein, um die gesamte Konvertierung nach Adresse zu löschen (vergessen Sie nicht, die Lese- und Schreibberechtigung für das Hauptfest hinzuzufügen). Hier ist Code:

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

Verwenden Sie eine dieser Methoden, um die zuletzt empfangene SMS auszuwählen und zu löschen. In diesem Fall erhalte ich die meisten SMS und lösche sie mithilfe des Threads und des ID-Werts der 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();
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.