web-dev-qa-db-fra.com

Comment puis-je lire SMS messages de l'appareil par programmation dans Android?

Je veux récupérer les messages SMS de l'appareil et les afficher?

216
Hamaney

Utilisez le résolveur de contenu ( "content: // sms/inbox" ) pour lire SMS qui se trouvent dans la boîte de réception.

// public static final String INBOX = "content://sms/inbox";
// public static final String SENT = "content://sms/sent";
// public static final String DRAFT = "content://sms/draft";
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);

if (cursor.moveToFirst()) { // must check the result to prevent exception
    do {
       String msgData = "";
       for(int idx=0;idx<cursor.getColumnCount();idx++)
       {
           msgData += " " + cursor.getColumnName(idx) + ":" + cursor.getString(idx);
       }
       // use msgData
    } while (cursor.moveToNext());
} else {
   // empty box, no SMS
}

Veuillez ajouter READ_SMS permission.

J'espère que ça aide :)

142
Suryavel TR
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat) {
        final String myPackageName = getPackageName();
        if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {

            Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
            intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, myPackageName);
            startActivityForResult(intent, 1);
        }else {
            List<Sms> lst = getAllSms();
        }
    }else {
        List<Sms> lst = getAllSms();
    }

Définir l'application comme application par défaut SMS

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
    if (resultCode == RESULT_OK) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat) {
            final String myPackageName = getPackageName();
            if (Telephony.Sms.getDefaultSmsPackage(mActivity).equals(myPackageName)) {

                List<Sms> lst = getAllSms();
            }
        }
    }
}
}

Fonction pour recevoir des SMS

public List<Sms> getAllSms() {
    List<Sms> lstSms = new ArrayList<Sms>();
    Sms objSms = new Sms();
    Uri message = Uri.parse("content://sms/");
    ContentResolver cr = mActivity.getContentResolver();

    Cursor c = cr.query(message, null, null, null, null);
    mActivity.startManagingCursor(c);
    int totalSMS = c.getCount();

    if (c.moveToFirst()) {
        for (int i = 0; i < totalSMS; i++) {

            objSms = new Sms();
            objSms.setId(c.getString(c.getColumnIndexOrThrow("_id")));
            objSms.setAddress(c.getString(c
                    .getColumnIndexOrThrow("address")));
            objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));
            objSms.setReadState(c.getString(c.getColumnIndex("read")));
            objSms.setTime(c.getString(c.getColumnIndexOrThrow("date")));
            if (c.getString(c.getColumnIndexOrThrow("type")).contains("1")) {
                objSms.setFolderName("inbox");
            } else {
                objSms.setFolderName("sent");
            }

            lstSms.add(objSms);
            c.moveToNext();
        }
    }
    // else {
    // throw new RuntimeException("You have no SMS");
    // }
    c.close();

    return lstSms;
}

La classe Sms est en dessous:

public class Sms{
private String _id;
private String _address;
private String _msg;
private String _readState; //"0" for have not read sms and "1" for have read sms
private String _time;
private String _folderName;

public String getId(){
return _id;
}
public String getAddress(){
return _address;
}
public String getMsg(){
return _msg;
}
public String getReadState(){
return _readState;
}
public String getTime(){
return _time;
}
public String getFolderName(){
return _folderName;
}


public void setId(String id){
_id = id;
}
public void setAddress(String address){
_address = address;
}
public void setMsg(String msg){
_msg = msg;
}
public void setReadState(String readState){
_readState = readState;
}
public void setTime(String time){
_time = time;
}
public void setFolderName(String folderName){
_folderName = folderName;
}

}

N'oubliez pas de définir l'autorisation dans votre AndroidManifest.xml

<uses-permission Android:name="Android.permission.READ_SMS" />
64
Atif Mahmood

C'est un processus trivial. Vous pouvez voir un bon exemple dans le code source SMSPopup

Examinez les méthodes suivantes:

SmsMmsMessage getSmsDetails(Context context, long ignoreThreadId, boolean unreadOnly)
long findMessageId(Context context, long threadId, long _timestamp, int messageType
void setMessageRead(Context context, long messageId, int messageType)
void deleteMessage(Context context, long messageId, long threadId, int messageType)

c'est la méthode pour lire:

SmsMmsMessage getSmsDetails(Context context,
                            long ignoreThreadId, boolean unreadOnly)
{
   String SMS_READ_COLUMN = "read";
   String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;
   String SORT_ORDER = "date DESC";
   int count = 0;
   // Log.v(WHERE_CONDITION);
   if (ignoreThreadId > 0) {
      // Log.v("Ignoring sms threadId = " + ignoreThreadId);
      WHERE_CONDITION += " AND thread_id != " + ignoreThreadId;
   }
   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();
            // String[] columns = cursor.getColumnNames();
            // for (int i=0; i<columns.length; i++) {
            // Log.v("columns " + i + ": " + columns[i] + ": " + cursor.getString(i));
            // }                                         
            long messageId = cursor.getLong(0);
            long threadId = cursor.getLong(1);
            String address = cursor.getString(2);
            long contactId = cursor.getLong(3);
            String contactId_string = String.valueOf(contactId);
            long timestamp = cursor.getLong(4);

            String body = cursor.getString(5);                             
            if (!unreadOnly) {
                count = 0;
            }

            SmsMmsMessage smsMessage = new SmsMmsMessage(context, address,
                          contactId_string, body, timestamp,
                          threadId, count, messageId, SmsMmsMessage.MESSAGE_TYPE_SMS);
            return smsMessage;
         }
      } finally {
         cursor.close();
      }
   }               
   return null;
}
59
Ömer

Cet article est un peu ancien, mais voici une autre solution facile pour obtenir des données relatives au fournisseur de contenu SMS dans Android:

Utilisez cette lib: https://github.com/EverythingMe/easy-content-providers

  • Obtenez tous SMS:

    TelephonyProvider telephonyProvider = new TelephonyProvider(context);
    List<Sms> smses = telephonyProvider.getSms(Filter.ALL).getList();
    

    Chaque Sms a tous les champs, vous pouvez donc obtenir toutes les informations dont vous avez besoin:
    adresse, corps, reçu Date, type (INBOX, SENT, DRAFT, ..), threadId, ...

  • Gel tous MMS:

    List<Mms> mmses = telephonyProvider.getMms(Filter.ALL).getList();
    
  • Gel tous Thread:

    List<Thread> threads = telephonyProvider.getThreads().getList();
    
  • Gel tous Conversation:

    List<Conversation> conversations = telephonyProvider.getConversations().getList();
    

Cela fonctionne avec List ou Cursor et il existe un exemple d'application pour voir à quoi cela ressemble et fonctionne. 

En fait, il existe un support pour tous les fournisseurs de contenu Android tels que: Contacts, journaux des appels, Calendrier, ... Doc complète avec toutes les options: https://github.com/EverythingMe/easy-content-providers/wiki/Android-providers

J'espère que ça a aussi aidé :)

21
sromku

À partir de l'API 19, vous pouvez utiliser la classe de téléphonie pour cela; Étant donné que les valeurs en dur ne récupèrent pas les messages sur tous les appareils, car l’URI du fournisseur de contenu change selon les appareils et les fabricants.

public void getAllSms(Context context) {

    ContentResolver cr = context.getContentResolver();
    Cursor c = cr.query(Telephony.Sms.CONTENT_URI, null, null, null, null);
    int totalSMS = 0;
    if (c != null) {
        totalSMS = c.getCount();
        if (c.moveToFirst()) {
            for (int j = 0; j < totalSMS; j++) {
                String smsDate = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.DATE));
                String number = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.ADDRESS));
                String body = c.getString(c.getColumnIndexOrThrow(Telephony.Sms.BODY));
                Date dateFormat= new Date(Long.valueOf(smsDate));
                String type;
                switch (Integer.parseInt(c.getString(c.getColumnIndexOrThrow(Telephony.Sms.TYPE)))) {
                    case Telephony.Sms.MESSAGE_TYPE_INBOX:
                        type = "inbox";
                        break;
                    case Telephony.Sms.MESSAGE_TYPE_SENT:
                        type = "sent";
                        break;
                    case Telephony.Sms.MESSAGE_TYPE_OUTBOX:
                        type = "outbox";
                        break;
                    default:
                        break;
                }


                c.moveToNext();
            }
        }

        c.close();

    } else {
        Toast.makeText(this, "No message to show!", Toast.LENGTH_SHORT).show();
    }
}
16
Manoj Perumarath

Étape 1: nous devons d'abord ajouter des autorisations dans le fichier manifestelike

<uses-permission Android:name="Android.permission.RECEIVE_SMS" Android:protectionLevel="signature" />
<uses-permission Android:name="Android.permission.READ_SMS" />

Étape 2: puis ajoutez la classe de service sms receiver pour recevoir des sms

<receiver Android:name="com.aquadeals.seller.services.SmsReceiver">
    <intent-filter>
        <action Android:name="Android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
</receiver>

Étape 3: Ajouter une autorisation d'exécution 

private boolean checkAndRequestPermissions()
{
    int sms = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS);

    if (sms != PackageManager.PERMISSION_GRANTED)
    {
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS}, REQUEST_ID_MULTIPLE_PERMISSIONS);
        return false;
    }
    return true;
}

Étape 4: Ajoutez ces classes dans votre application et testez Classe d'interface  

public interface SmsListener {
   public void messageReceived(String messageText);
}

SmsReceiver.Java

public class SmsReceiver extends BroadcastReceiver {
private static SmsListener mListener;
public Pattern p = Pattern.compile("(|^)\\d{6}");
@Override
public void onReceive(Context context, Intent intent) {
    Bundle data  = intent.getExtras();
    Object[] pdus = (Object[]) data.get("pdus");
    for(int i=0;i<pdus.length;i++)
    {
        SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
        String sender = smsMessage.getDisplayOriginatingAddress();
        String phoneNumber = smsMessage.getDisplayOriginatingAddress();
        String senderNum = phoneNumber ;
        String messageBody = smsMessage.getMessageBody();
        try
        {
  if(messageBody!=null){
   Matcher m = p.matcher(messageBody);
    if(m.find()) {
      mListener.messageReceived(m.group(0));  }
 else {}}  }
        catch(Exception e){} } }
public static void bindListener(SmsListener listener) {
    mListener = listener; }}
11
Venkatesh

Il existe déjà de nombreuses réponses mais je pense qu’il manque à chacune d’entre elles une partie importante de cette question . Avant de lire les données d’une base de données interne ou de sa table, nous devons comprendre comment les données sont stockées et nous trouvez la solution de la question ci-dessus qui est:

Comment puis-je lire SMS les messages de l'appareil par programmation dans Android?

Donc, dans Android SMS, la table ressemble à ceci

 enter image description here

Sachez que nous pouvons sélectionner ce que nous voulons dans la base de données. Dans notre cas, nous n’avons 

identifiant, adresse et corps

En cas de lecture de SMS:

1. Demander les autorisations

int REQUEST_PHONE_CALL = 1;

   if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_SMS}, REQUEST_PHONE_CALL);
        }

ou

 <uses-permission Android:name="Android.permission.READ_SMS" />

2.Maintenant votre code va comme ceci

// Create Inbox box URI
Uri inboxURI = Uri.parse("content://sms/inbox");

// List required columns
String[] reqCols = new String[]{"_id", "address", "body"};

// Get Content Resolver object, which will deal with Content Provider
ContentResolver cr = getContentResolver();

// Fetch Inbox SMS Message from Built-in Content Provider
Cursor c = cr.query(inboxURI, reqCols, null, null, null);

// Attached Cursor with adapter and display in listview
adapter = new SimpleCursorAdapter(this, R.layout.a1_row, c,
        new String[]{"body", "address"}, new int[]{
        R.id.A1_txt_Msg, R.id.A1_txt_Number});
lst.setAdapter(adapter);

J'espère que celui-ci vous sera utile ... Merci.

4
Nitin Khanna
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;

changé par:

String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";
2
Van Hau Hoang

Code Kotlin à lire SMS:

1- Ajoutez cette permission à AndroidManifest.xml: 

    <uses-permission Android:name="Android.permission.RECEIVE_SMS"/>

2-Créer une classe BroadCastreceiver:

package utils.broadcastreceivers

import Android.content.BroadcastReceiver
import Android.content.Context
import Android.content.Intent
import Android.telephony.SmsMessage
import Android.util.Log

class MySMSBroadCastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
    var body = ""
    val bundle = intent?.extras
    val pdusArr = bundle!!.get("pdus") as Array<Any>
    var messages: Array<SmsMessage?>  = arrayOfNulls(pdusArr.size)

 // if SMSis Long and contain more than 1 Message we'll read all of them
    for (i in pdusArr.indices) {
        messages[i] = SmsMessage.createFromPdu(pdusArr[i] as ByteArray)
    }
      var MobileNumber: String? = messages[0]?.originatingAddress
       Log.i(TAG, "MobileNumber =$MobileNumber")         
       val bodyText = StringBuilder()
        for (i in messages.indices) {
            bodyText.append(messages[i]?.messageBody)
        }
        body = bodyText.toString()
        if (body.isNotEmpty()){
       // Do something, save SMS in DB or variable , static object or .... 
                       Log.i("Inside Receiver :" , "body =$body")
        }
    }
 }

3-Obtenir la permission SMS si Android 6 et supérieur:

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && 
    ActivityCompat.checkSelfPermission(context!!,
            Manifest.permission.RECEIVE_SMS
        ) != PackageManager.PERMISSION_GRANTED
    ) { // Needs permission

            requestPermissions(arrayOf(Manifest.permission.RECEIVE_SMS),
            PERMISSIONS_REQUEST_READ_SMS
        )

    } else { // Permission has already been granted

    }

4- Ajoutez ce code de demande à Activité ou fragment:

 companion object {
    const val PERMISSIONS_REQUEST_READ_SMS = 100
   }

5- Permission Contrôle d'autorisation Demande de résultat amusant:

 override fun onRequestPermissionsResult(
    requestCode: Int, permissions: Array<out String>,
    grantResults: IntArray
) {
    when (requestCode) {

        PERMISSIONS_REQUEST_READ_SMS -> {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Log.i("BroadCastReceiver", "PERMISSIONS_REQUEST_READ_SMS Granted")
            } else {
                //  toast("Permission must be granted  ")
            }
        }
    }
}
1
Hamed Jaliliani

Les services Google Play disposent de deux API que vous pouvez utiliser pour rationaliser le processus de vérification par SMS.

API SMS Retriever

Fournit une expérience utilisateur entièrement automatisée, sans demander à l'utilisateur de saisir manuellement les codes de vérification et sans nécessiter d'autorisations d'applications supplémentaires. Elle doit être utilisée dans la mesure du possible. Toutefois, il vous oblige à insérer un code de hachage personnalisé dans le corps du message. Par conséquent, vous devez également contrôler le côté serveur .

  • Exigences du message - Code de hachage à 11 chiffres identifiant de manière unique votre application
  • Conditions d'expéditeur - Aucune
  • Interaction utilisateur - Aucune

Demande SMS Vérification dans une Android App

Effectuez SMS Vérification sur un serveur

API de consentement de l'utilisateur SMS

Ne nécessite pas le code de hachage personnalisé, mais oblige l'utilisateur à approuver la demande de votre application pour accéder au message contenant le code de vérification. Afin de minimiser les risques de faire passer le mauvais message à l'utilisateur, SMS User Consent filtrera les messages des expéditeurs figurant dans la liste de contacts de l'utilisateur.

  • Spécifications du message - Code alphanumérique de 4 à 10 chiffres contenant au moins un numéro
  • Conditions requises pour l'expéditeur - L'expéditeur ne peut pas figurer dans la liste de contacts de l'utilisateur
  • Interaction utilisateur - Un robinet pour approuver

The SMS User Consent API fait partie des services Google Play. Pour l'utiliser, vous aurez besoin d'au moins la version 17.0.0 de ces bibliothèques:

implementation "com.google.Android.gms:play-services-auth:17.0.0"
implementation "com.google.Android.gms:play-services-auth-api-phone:17.1.0"

Étape 1: commencez à écouter les SMS messages

Le consentement de l'utilisateur SMS sera à l'écoute des SMS messages entrants contenant un code à usage unique pouvant aller jusqu'à cinq minutes. Il ne verra aucun message envoyé avant son lancement. Si vous connaissez le numéro de téléphone qui enverra le code à usage unique, vous pouvez spécifier la valeur senderPhoneNumber ou, si vous ne le faites pas null, il ne correspond à aucun numéro.

 smsRetriever.startSmsUserConsent(senderPhoneNumber /* or null */)

Étape 2: Demander votre consentement pour lire un message

Une fois que votre application reçoit un message contenant un code unique, elle sera notifiée par une diffusion. À ce stade, vous n’avez pas consenti à lire le message. À la place, vous obtenez une Intent que vous pouvez commencer à demander à l’utilisateur de donner son consentement. Dans votre BroadcastReceiver, vous affichez l'invite à l'aide de Intent dans le extras. Lorsque vous démarrez cette intention, il demande à l'utilisateur l'autorisation de lire un seul message. Ils verront tout le texte qu'ils partageront avec votre application.

val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)

enter image description here

Étape 3: Analyse du code à usage unique et complète SMS Vérification

Lorsque l'utilisateur clique sur “Allow”, il est temps de lire le message! À l'intérieur de onActivityResult, vous pouvez obtenir le texte complet du SMS Message à partir des données:

val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)

Vous analysez ensuite le message SMS et transmettez le code à usage unique à votre serveur!

0
Levon Petrosyan

La fonction la plus simple

Pour lire le sms, j'ai écrit une fonction qui retourne un objet de conversation:

class Conversation(val number: String, val message: List<Message>)
class Message(val number: String, val body: String, val date: Date)

fun getSmsConversation(context: Context, number: String? = null, completion: (conversations: List<Conversation>?) -> Unit) {
        val cursor = context.contentResolver.query(Telephony.Sms.CONTENT_URI, null, null, null, null)

        val numbers = ArrayList<String>()
        val messages = ArrayList<Message>()
        var results = ArrayList<Conversation>()

        while (cursor != null && cursor.moveToNext()) {
            val smsDate = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.DATE))
            val number = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.ADDRESS))
            val body = cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Sms.BODY))

            numbers.add(number)
            messages.add(Message(number, body, Date(smsDate.toLong())))
        }

        cursor?.close()

        numbers.forEach { number ->
            if (results.find { it.number == number } == null) {
                val msg = messages.filter { it.number == number }
                results.add(Conversation(number = number, message = msg))
            }
        }

        if (number != null) {
            results = results.filter { it.number == number } as ArrayList<Conversation>
        }

        completion(results)
    }

En utilisant:

getSmsConversation(this){ conversations ->
    conversations.forEach { conversation ->
        println("Number: ${conversation.number}")
        println("Message One: ${conversation.message[0].body}")
        println("Message Two: ${conversation.message[1].body}")
    }
}

Ou n'obtenez que la conversation d'un numéro spécifique:

getSmsConversation(this, "+33666494128"){ conversations ->
    conversations.forEach { conversation ->
        println("Number: ${conversation.number}")
        println("Message One: ${conversation.message[0].body}")
        println("Message Two: ${conversation.message[1].body}")
    }
}
0
Mickael Belhassen