web-dev-qa-db-fra.com

Écoutez sortant SMS ou boîte envoyée dans Android

Je développe une application qui stockera tous les sms entrants et sortants dans un fichier texte sur la carte SD.

Je peux écouter les messages entrants en utilisant le récepteur de diffusion. J'ai du mal à écouter les SMS sortants.

Je sais dans une certaine mesure qu'un observateur de contenu sur la boîte ou la boîte d'envoi envoyée doit être défini, mais je ne sais pas comment le faire.

Comment cela peut-il être fait?

32
Vivek

Fondamentalement, vous devez enregistrer un observateur de contenu ... quelque chose comme ceci:

ContentResolver contentResolver = context.getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms/out"),true, yourObserver);

yourObserver est un objet (new YourObserver(new Handler())) qui pourrait ressembler à ceci:

class YourObserver extends ContentObserver {

    public YourObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        // save the message to the SD card here
    }
}

Alors, comment obtenez-vous exactement le contenu du SMS? Vous devez utiliser un Cursor:

// save the message to the SD card here
Uri uriSMSURI = Uri.parse("content://sms/out");
Cursor cur = this.getContentResolver().query(uriSMSURI, null, null, null, null);
 // this will make it point to the first record, which is the last SMS sent
cur.moveToNext();
String content = cur.getString(cur.getColumnIndex("body"));
// use cur.getColumnNames() to get a list of all available columns...
// each field that compounds a SMS is represented by a column (phone number, status, etc.)
// then just save all data you want to the SDcard :)
47
Cristian

Celui-ci est mon approche pour résoudre ce

  1. Créer un service qui a appelé depuis une autre activité
  2. Créez un observateur de contenu à l'intérieur

     @Override
     public int onStartCommand(Intent intent, int flag, int startId) {
     MyObserver myObserver = new MyObserver(new Handler());
     ContentResolver contentResolver = this.getApplicationContext().getContentResolver();
     contentResolver.registerContentObserver(Uri.parse("content://sms/sent"), true, myObserver);
     return START_STICKY;
     }
    
  3. Créer la classe d'observateur

    class MyObserver extends ContentObserver {
    
    public MyObserver(Handler handler) {
        super(handler);
    }
    
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        Uri uriSMSURI = Uri.parse("content://sms/sent");
        Cursor cur = getContentResolver().query(uriSMSURI, null, null, null, null);
        cur.moveToNext();
        String content = cur.getString(cur.getColumnIndex("body"));
        String smsNumber = cur.getString(cur.getColumnIndex("address"));
        if (smsNumber == null || smsNumber.length() <= 0) {
            smsNumber = "Unknown";
        }
        cur.close();
    
        if(smsChecker( "OutgoingSMS to " + smsNumber + ": " + content)) {
            //save data into database/sd card here
        }
    }
    }
    
  4. J'ai ajouté une méthode smsChecker () pour vérifier si le nouveau message est exactement le même que le dernier message

    public boolean smsChecker(String sms) {
    boolean flagSMS = true;
    
    if (sms.equals(lastSMS)) {
        flagSMS = false;
    }
    else {
        lastSMS = sms;
    }
    //if flagSMS = true, those 2 messages are different
    return flagSMS;
    }
    

si je ne me trompe pas, nous utilisons "content: // sms/sent" si nous voulons UNIQUEMENT vérifier tous les messages envoyés, "content: // sms/out" si nous voulons UNIQUEMENT vérifier tous les messages à l'intérieur de la boîte d'envoi, et "contenu : // sms "si nous voulons vérifier TOUS les messages.

5
baskara

Ceci est ma version, qui a été vérifiée en Android 6.0+

class smsObserver extends ContentObserver {

    private String lastSmsId;

    public smsObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        Uri uriSMSURI = Uri.parse("content://sms/sent");
        Cursor cur = getContentResolver().query(uriSMSURI, null, null, null, null);
        cur.moveToNext();
        String id = cur.getString(cur.getColumnIndex("_id"));
        if (smsChecker(id)) {
            String address = cur.getString(cur.getColumnIndex("address"));
            // Optional: Check for a specific sender
            if (address.equals(phoneNumber)) {
                String message = cur.getString(cur.getColumnIndex("body"));
                // Use message content for desired functionality
            }
        }
    }

    // Prevent duplicate results without overlooking legitimate duplicates
    public boolean smsChecker(String smsId) {
        boolean flagSMS = true;

        if (smsId.equals(lastSmsId)) {
            flagSMS = false;
        }
        else {
            lastSmsId = smsId;
        }

        return flagSMS;
    }
}

Placez ce code là où l'observateur doit être activé

ContentResolver contentResolver = getContentResolver();
contentResolver.registerContentObserver(Uri.parse("content://sms"), true, new smsObserver(new Handler()));

Cela suppose que vous utilisez une activité. N'oubliez pas que vous aurez besoin d'une référence de contexte pour appeler getContentResolver() à partir d'un service ou d'un récepteur.

2
Abandoned Cart

J'ai vu ce qui ne va pas. c'est sur la ligne:

 contentResolver.registerContentObserver(Uri.parse("content://sms/sent"), true, _myObserver);

vous devez supprimer '/ sent' et écrire simplement 'content: // sms' son est déjà spécifié dans le ContentObserver pour rechercher les sms envoyés.

0
el_tamanois