Comment supprimer un SMS de la boîte de réception sous Android par programmation?

98

Sur les téléphones Android, les messages SMS enregistrés dans les applications sont également envoyés dans la boîte de réception de l'appareil. Cependant, pour éviter l'encombrement, il serait bien de pouvoir supprimer les messages SMS spécifiques à une application de la boîte de réception pour réduire le débordement potentiel de ces messages.

Les questions sur d'autres groupes Google sur l'obtention d'une réponse définitive sur un moyen programmatique de supprimer les messages SMS de la boîte de réception Android ne semblent pas pressantes.

Donc le scénario:

  • Démarrage de l'application Android.
  • enregistrer les types de messages SMS X, Y et Z
  • les messages P, Q, X, Y, Z circulent au fil du temps, tous déposés dans la boîte de réception
  • L'application Android détecte la réception de X, Y, Z (probablement dans le cadre de l'événement d'interruption de programme)
  • processus X, Y, Z
  • Désir !!! X, Y, Z sont supprimés de la boîte de réception Android

Cela a-t-il été fait? Cela peut-il être fait?

dmyung
la source
4
J'ai trouvé que faire quelque chose d'utile avec les capacités du téléphone d'Android était une expérience très désagréable.
BobbyShaftoe
1
bon compagnon de question. Je cherchais quelque chose de similaire: D cheers
Harsha MV
3
Le mieux serait d'empêcher le SMS d'atteindre la boîte de réception en premier lieu: stackoverflow.com/questions/1741628/...
Christopher Orr

Réponses:

87

«À partir d'Android 1.6, les diffusions de messages SMS entrants ( android.provider.Telephony.SMS_RECEIVED) sont livrées sous la forme d'une« diffusion ordonnée », ce qui signifie que vous pouvez indiquer au système quels composants doivent recevoir la diffusion en premier.»

Cela signifie que vous pouvez intercepter le message entrant et interrompre sa diffusion ultérieurement.

Dans votre AndroidManifest.xmlfichier, assurez-vous d'avoir la priorité la plus élevée:

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

Dans votre BroadcastReceiver, en onReceive()méthode, avant d' effectuer quoi que ce soit avec votre message, il suffit d' appelerabortBroadcast();

EDIT: à partir de KitKat, cela ne fonctionne plus apparemment.

EDIT2: Plus d'informations sur la façon de le faire sur KitKat ici:

Supprimer les SMS d'Android sur 4.4.4 (lignes affectées = 0 (zéro), après suppression)

Viktor Fonic
la source
3
Et assurez-vous de voir stackoverflow.com/questions/1741628/…
Michael Levy
Pouvez-vous voir ici stackoverflow.com/questions/25988574/… ?
Gangadhar Nimballi
La meilleure réponse pour ça = D
Mike Brian Olivera
27

En utilisant les suggestions des autres, je pense que je l'ai fait fonctionner:

(à l'aide du SDK v1 R2)

Ce n'est pas parfait, car je dois supprimer toute la conversation, mais pour nos besoins, c'est un compromis suffisant car nous saurons au moins que tous les messages seront examinés et vérifiés. Notre flux devra probablement ensuite écouter le message, capturer le message que nous voulons, faire une requête pour obtenir le thread_id du message récemment encerclé et faire l'appel à delete ().

Dans notre activité:

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

Remarque: je n'ai pas pu effectuer de suppression sur content: // sms / inbox / ou content: // sms / all /

On dirait que le fil a la priorité, ce qui a du sens, mais le message d'erreur m'a seulement encouragé à être plus en colère. En essayant la suppression sur sms / boîte de réception / ou sms / all /, vous obtiendrez probablement:

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)

Pour plus d'informations, assurez-vous de mettre ceci dans votre manifeste pour votre récepteur d'intention:

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

Notez que l'étiquette du récepteur ne ressemble pas à ceci:

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

Lorsque j'avais ces paramètres, Android m'a donné des exceptions d'autorisations folles qui ne permettaient pas à android.phone de transmettre les SMS reçus à mon intention. Donc, NE mettez PAS cet attribut d'autorisation RECEIVE_SMS dans votre intention! J'espère que quelqu'un de plus sage que moi pourra me dire pourquoi c'était le cas.

dmyung
la source
Pouvez-vous voir ici stackoverflow.com/questions/25988574/… ?
Gangadhar Nimballi
24

Donc, j'ai eu un jeu, et il est possible de supprimer un SMS reçu. Malheureusement, tout n'est pas simple :(

J'ai un récepteur qui détecte les SMS entrants. Maintenant, la façon dont fonctionne le routage entrant SMS Android est que le morceau de code responsable du décodage des messages envoie une diffusion (il utilise la sendBroadcast()méthode - qui n'est malheureusement PAS la version qui vous permet simplement d'appeler abortBroadcast()) chaque fois qu'un message arrive.

Mon récepteur peut ou non être appelé avant le récepteur SMS de Systems, et dans tous les cas l'émission reçue n'a aucune propriété qui pourrait refléter la _idcolonne dans la table SMS.

Cependant, n'étant pas du genre à être arrêté aussi facilement, je poste moi-même (via un gestionnaire) un message retardé avec le SmsMessage comme objet attaché. (Je suppose que vous pourriez aussi vous poster un Runnable ...)

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

Le délai est là pour s'assurer qu'au moment où le message arrive, tous les récepteurs de diffusion auront terminé leur travail et le message sera en toute sécurité installé dans la table SMS.

Lorsque le message (ou Runnable) est reçu, voici ce que je fais:

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

J'utilise l'adresse d'origine et le champ d'horodatage pour assurer une très forte probabilité de supprimer UNIQUEMENT le message qui m'intéresse. Si je voulais être encore plus paranoïaque, je pourrais inclure le msg.getMessageBody()contenu dans le cadre de la requête.

Oui, le message EST supprimé (hourra!). Malheureusement, la barre de notification n'est pas mise à jour :(

Lorsque vous ouvrez la zone de notification, vous verrez le message assis là pour vous ... mais lorsque vous appuyez dessus pour l'ouvrir - il est parti!

Pour moi, ce n'est pas assez bien - je veux que toute trace du message disparaisse - je ne veux pas que l'utilisateur pense qu'il y a un TXT alors qu'il n'y en a pas (cela ne ferait que provoquer des rapports de bogue).

En interne, dans le système d'exploitation, les appels téléphoniques MessagingNotification.updateNewMessageIndicator(Context), mais je cette classe a été cachée de l'API, et je ne voulais pas répliquer tout ce code juste pour rendre l'indicateur précis.

Doug
la source
Doug, c'est super. En guise de question, savez-vous s'il est nécessaire de publier le message auprès du gestionnaire? Je me demande si le SMS est inséré dans la base de données SMS du système avant et des récepteurs de diffusion sont appelés? Je devrai probablement regarder dans le système d'exploitation pour voir où l'insertion se produit, mais je suppose que l'insertion du SMS dans une base de données se produit avant que les récepteurs de diffusion ne soient informés. Avez-vous un aperçu de cela ou l'avez-vous déjà vérifié?
Hamy
Pouvez-vous voir ici 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;
}

utiliser cette autorisation dans AndroidManifiest

<uses-permission android:name="android.permission.WRITE_SMS"/>
Atif Mahmood
la source
1
Comment obtenir un identifiant SMS?
Dev01
@ Dev01si vous souhaitez supprimer un sms particulier, vous devez avoir son identifiant, non? et sinon vous devez interroger l'identifiant avec l'adresse ou le smsbody
Dr. aNdRO
6

Il est préférable d'utiliser _id et thread_id pour supprimer un message.

Thread_id est quelque chose attribué aux messages provenant du même utilisateur. Donc, si vous n'utilisez que thread_id, tous les messages de l'expéditeur seront supprimés.

Si vous utilisez la combinaison de _id, thread_id, alors il supprimera le message exact que vous cherchez à supprimer.

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
la source
Pouvez-vous voir ici stackoverflow.com/questions/25988574/… ?
Gangadhar Nimballi
5

Vous devrez trouver l' URI du message. Mais une fois que vous le faites, je pense que vous devriez pouvoir le supprimer (...) android.content.ContentResolver.delete (...).

Voici quelques informations supplémentaires .

Neil
la source
2

Je pense que cela ne peut pas être parfaitement fait pour le moment. Il y a 2 problèmes de base:

  1. Comment pouvez-vous vous assurer que le SMS est déjà dans la boîte de réception lorsque vous essayez de le supprimer?
    Notez que SMS_RECEIVED n'est pas une diffusion ordonnée.
    La solution de dmyung est donc de tenter sa chance; même le retard dans la réponse de Doug n'est pas une garantie.

  2. Le SmsProvider n'est pas thread-safe. (Reportez-vous à http://code.google.com/p/android/issues/detail?id=2916#c0 )
    Le fait que plusieurs clients demandent la suppression et l'insertion en même temps entraînera une corruption des données ou même une exception d'exécution immédiate.

an0
la source
2

Je ne pouvais pas le faire fonctionner en utilisant la solution de dmyung, cela m'a donné une exception lors de l'obtention de l'identifiant du message ou de l'identifiant du fil.

En fin de compte, j'ai utilisé la méthode suivante pour obtenir l'ID du 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;
}

Ensuite, je pourrais le supprimer. Cependant, comme Doug l'a dit, la notification est toujours là, même le message est affiché lors de l'ouverture du panneau de notification. Ce n'est qu'en appuyant sur le message que j'ai pu voir qu'il était vide.

Donc, je suppose que la seule façon dont cela fonctionnerait serait d'intercepter d'une manière ou d'une autre le SMS avant qu'il ne soit livré au système, avant même qu'il n'atteigne la boîte de réception. Cependant, je doute fort que cela soit faisable. Corrigez-moi si j'ai tort, s'il-vous plait.

Stelian Iancu
la source
Eh bien, vous êtes trompé sur l' interception des messages avant la boîte de réception: vous pouvez recevoir une émission android.provider.Telephony.SMS_RECEIVED, vous avez seulement besoin de android.permission.RECEIVE_SMS permssion. Vous pouvez même facilement empêcher le message d'atteindre la boîte de réception en appelant abortBroadcast () car il s'agit d'une diffusion ordonnée. PS Doit être drôle pour être corrigé 2 ans plus tard :)
lapis
2

Utilisez cette fonction pour supprimer un fil de messages spécifique ou modifier selon vos besoins:

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

  }
}

Appelez cette fonction simplement ci-dessous:

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

N'oubliez pas d'ajouter la permission Android Mainfest ci-dessous:

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

Désactivez simplement les notifications pour l'application SMS par défaut. Traitez vos propres notifications pour tous les messages texte!

Noah Seidman
la source
1

Jetez un œil à ce lien, il vous donnera une brève idée de la logique:

https://gist.github.com/5178e798d9a00cac4ddb
Il suffit d'appeler la fonction deleteSMS () avec un certain retard, car il y a une légère différence entre l'heure de la notification et quand il est enregistré réellement ...., pour plus de détails, consultez également ce lien ..........

http://htmlcoderhelper.com/how-to-delete-sms-from- boîte de réception dans android par programmation /

Merci ..........

viv
la source
1

Essayez simplement le code suivant, il supprimera tous les sms qui sont tous dans le téléphone (reçus ou envoyés)

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
la source
1

Mettez également à jour le fichier manifeste car pour supprimer un sms, vous avez besoin d'autorisations d'écriture.

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

Maintenant, la abortBroadcast();méthode peut être utilisée pour restreindre le message entrant à aller dans la boîte de réception.

Arun Badole
la source
0

Exemple pour supprimer un SMS, pas une conversation:

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

Essayez ceci, je suis sûr à 100% que cela fonctionnera bien: - // il suffit de mettre l'adresse de conversion ici pour supprimer toute la conversion par adresse (n'oubliez pas d'ajouter l'autorisation de lecture et d'écriture dans mainfest) Voici le 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) {

}
Ashish Sahu
la source
0

Utilisez l'une de cette méthode pour sélectionner le dernier SMS reçu et le supprimer, ici, dans ce cas, je reçois le plus de sms et je vais supprimer en utilisant le fil et la valeur d'identifiant de 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
la source