Як я можу програмно читати SMS-повідомлення з пристрою в Android?


249

Хочу отримати SMS-повідомлення з пристрою та відобразити їх?


@David Freitas Довірене посилання +1
Шахзад Імам

3
@DavidFreitas це посилання не працює, ви можете поділитися найменшим посиланням?
Хобайб

3
@Khobaib, як завжди, речі в Інтернеті швидкоплинні. Я знайшов копію на archive.org stackoverflow.com/a/19966227/40961 , дякую їм за добро (я нещодавно пожертвував, щоб продовжувати працювати). Але ми повинні розглянути можливість перетворення вмісту сторінки з web.archive.org/web/20121022021217/http://mobdev.olin.edu/… у синтаксис розмітки у відповіді на це запитання. Напевно, година роботи.
David d C e Freitas

Відповіді:


157

Використовуйте Resolver Content ( "content: // sms / inbox" ), щоб читати SMS, які перебувають у папці "Вхідні".

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

Додайте дозвіл READ_SMS .

Сподіваюся, це допомагає :)


7
Дякую! Ви неправильно написали "getColumnName", крім того, що це працює як принадність. О, і якщо хтось цим скористається, не забудьте додати дозвіл android.permission.READ_SMS.
qwerty

1
Дякую. Я це змінив :)
Suryavel TR

5
Чи використовує це також незадокументоване api, яке @CommonsWare вказав у своєму коментарі до прийнятої відповіді?
Крішнабхадра

1
Увага! Не пропустіть, moveToFirstяк я.
Олександр Приймак

4
@Krishnabhadra Так. Він використовує незадокументований постачальник вмісту "content: // sms / inbox".
pm_labs

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

Встановіть програму як додаток 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();
            }
        }
    }
}
}

Функція для отримання 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;
}

Клас Sms нижче:

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

}

Не забудьте визначити дозвіл у своєму AndroidManifest.xml

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

2
Це приємний фрагмент коду. Тільки одне, час виходить у мілісекундах. Я думаю, що буде краще зробити його в String receiveDayTime = Functions.dateFromMilisec(Long.valueOf(c.getColumnIndexOrThrow("date")), "hh:mm a MMM dd, yyyy");
читаному

1
яка мета створити все з геттером та сеттером, я насправді не розумію, чому просто не використовувати масив
Assoc

1
@TomasNavara: Перевірте цей код, щоб зрозуміти використання геттера та сеттера. pastebin.com/Nh8YXtyJ
Помилки трапляються

@BibaswannBandyopadhyay Якщо ви не хочете використовувати нічого, крім андроїд-бібліотек та java-бібліотек. new SimpleDateFormat("hh:mm", Locale.US).format(new Date(Long.parseLong(_time)));Це дасть вам 24 години часу.
Кріс - молодший

mActivityне визначено. Що це?
dthree

61

Це тривіальний процес. Ви можете побачити хороший приклад у вихідному коді SMSPopup

Вивчіть наступні методи:

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)

це метод для читання:

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

47
Це не є частиною Android SDK. Цей код робить неправильним припущення, що всі пристрої підтримують цього недокументованого та непідтримуваного постачальника вмісту. Google прямо вказав, що покладатися на це не є хорошою ідеєю: android-developers.blogspot.com/2010/05/…
CommonsWare

1
@Janusz: Немає документально підтверджених та підтримуваних засобів, які працюють на всіх клієнтах SMS на всіх пристроях.
CommonsWare

9
@CommonsОбережно, що це чутно. Можливо, тоді доведеться жити з цим API.
Януш

@Omer Будь-яке уявлення про те, як би ви порахували кількість SMS-повідомлень за контакт?
SpicyWeenie

4
Код переміщено. Пошук SmsPopupUtils.java отримав мені нове посилання на нього в коді google. Якщо вони
перенесуть

25

Від API 19 ви можете використовувати Клас телефонії для цього; Оскільки значення з твердим кольором не можуть отримувати повідомлення на всіх пристроях, оскільки постачальник вмісту Uri змінюється від пристроїв та виробників.

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

9
Єдина відповідь, яка не використовує недокументований API і не посилається на сторонні бібліотеки.
Ізмаїл

Я намагався використовувати цей код, щоб отримувати SMS-повідомлення з Hangouts (це мій додаток SMS за замовчуванням). Натомість він отримав останнє вихідне повідомлення, яке я надіслав через Messenger ... Чи знаєте ви, що це спричиняє?
Мікі П

@MikiP, використовуючи мої здогадки, я скажу, що програма Messenger попросила вас про заміну управління SMS-повідомленнями Messenger. Це відбувається з деяким іншим додатком для обміну повідомленнями. Іншого пояснення у мене немає.
m3nda

2
Не забудьте зателефонувати c.close ();
Cícero Moura

1
@SardarAgabejli Якщо ми використовуємо значення з твердим кольором, як-от "contenturi: sms", це не буде однаковим для кожного пристрою, але якщо ми використовуємо клас Telephony, ми отримуємо прямий доступ до цього ури конента або шляху sms db цього пристрою, це клас помічників, щоб вказати на
смерть

23

Ця публікація трохи постаріла, але ось ще одне просте рішення для отримання даних, пов’язаних з SMSпровайдером вмісту в Android:

Скористайтеся цією lib: https://github.com/EverythingMe/easy-content-providers

  • Отримати все SMS:

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

    У кожному смс є всі поля, тому ви можете отримати будь-яку необхідну інформацію:
    адресу, тіло, отриманий дату, тип (INBOX, SENT, DRAFT, ..), threadId, ...

  • Гель все MMS:

    List<Mms> mmses = telephonyProvider.getMms(Filter.ALL).getList();
  • Гель все Thread:

    List<Thread> threads = telephonyProvider.getThreads().getList();
  • Гель все Conversation:

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

Він працює з Listабо Cursorє прикладний додаток, щоб побачити, як це виглядає і працює.

Насправді існує підтримка всіх постачальників вмісту Android, таких як: Контакти, журнали викликів, календар, ... Повний документ із усіма параметрами: https://github.com/EverythingMe/easy-content-providers/wiki/Android- провайдерів

Сподіваюся, це теж допомогло :)


1
Вихідний код та приклади на github досить корисні. Це гарна обгортка / фасад для більшості розповсюджених постачальників. Дякую.
m3nda

14

Крок 1: спочатку ми повинні додати дозволи в файл маніфесту, як

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

Крок 2: потім додайте службовий sms-приймач класу для отримання sms

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

Крок 3. Додайте дозвіл на час запуску

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

Крок 4: Додайте ці класи у свою програму та випробуйте клас інтерфейсу

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

Що робить візерунок?
Марк Буйкема

Ну ... це що ("com.aquadeals.seller.services.SmsReceiver") загальна назва служби?
m3nda

Так, це не назва служби, тобто шлях класу SmsReceiver в моєму додатку
Venkatesh

Навіщо потрібен дозвіл на LOCATION?
Zam Sunk

1
я намагаюся зробити додаток, який вискакує вміст sms для користувача, навіть якщо додаток було вбито
Anjani Mittal

11

Є багато відповідей, але я думаю, що всі вони пропускають важливу частину цього питання. Перш ніж читати дані з внутрішньої бази даних або її таблиці, ми повинні зрозуміти, як зберігаються дані в ній, і тоді ми можемо знайти рішення вищезазначеного питання, яке:

Як я можу програмно читати SMS-повідомлення з пристрою в Android?

Отже, в андроїд SMS таблиця виглядає приблизно так

введіть тут опис зображення

Знайте, ми можемо вибрати все, що хочемо, із бази даних. У нашому випадку ми лише вимагаємо

ідентифікатор, адреса та тіло

У разі читання SMS:

1.Будьте дозволів

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

або

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

2.Зараз ваш код іде так

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

Я сподіваюся, що це буде корисним. Дякую.


7

У службах Google Play є два API, які ви можете використовувати для впорядкування процесу підтвердження на основі SMS

API ретривера SMS

Забезпечує повністю автоматизовану роботу користувачів, не вимагаючи від користувача вручну перевіряти коди та не вимагаючи додаткових дозволів додатків, і їх слід використовувати, коли це можливо. Однак потрібно вимагати розміщення спеціального хеш-коду в тілі повідомлення, тому ви також повинні мати контроль над стороною сервера .

  • Вимоги до повідомлення - 11-значний хеш-код, який однозначно ідентифікує вашу програму
  • Вимоги до відправника - немає
  • Взаємодія користувача - немає

Попросіть підтвердження SMS у додатку для Android

Виконайте перевірку SMS на сервері

API згоди користувача з SMS

Не вимагає спеціального хеш-коду, однак вимагає від користувача схвалити запит вашого додатка на доступ до повідомлення, що містить код підтвердження. Щоб звести до мінімуму шанси набути помилкового повідомлення для користувача, SMS User Consentвідфільтруйте повідомлення від відправників у списку контактів користувача.

  • Вимоги до повідомлення - 4-10-цифровий буквено-цифровий код, що містить принаймні одне число
  • Вимоги до відправника - Відправник не може бути у списку контактів користувача
  • Взаємодія користувача - одним натисканням для схвалення

The SMS User Consent APIє частиною Служб Google Play. Для його використання вам знадобиться принаймні версія 17.0.0цих бібліотек:

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

Крок 1. Почніть слухати SMS-повідомлення

Згода користувача SMS прослухає вхідні SMS-повідомлення, які містять одноразовий код до п'яти хвилин. Він не буде розглядати жодні повідомлення, надіслані до його запуску. Якщо ви знаєте номер телефону, який надсилатиме одноразовий код, ви можете вказати senderPhoneNumberабо, якщо ви не nullвідповідатиме жодному номеру.

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

Крок 2: Попросіть згоду на читання повідомлення

Щойно ваша програма отримає повідомлення, що містить одноразовий код, про це буде повідомлено трансляцією. На даний момент у вас немає згоди на читання повідомлення - замість цього вам надається повідомлення про Intentте, що ви можете почати сповіщати користувача про згоду. Всередині вашого BroadcastReceiverвідображається підказка за Intentдопомогою extras. Після запуску цього наміру він запропонує користувачеві отримати дозвіл на читання одного повідомлення. Їм буде показано весь текст, яким вони поділяться з вашим додатком.

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

введіть тут опис зображення

Крок 3: Проаналізуйте одноразовий код і завершіть перевірку SMS

Коли користувач клацає “Allow”- саме час насправді прочитати повідомлення! Всередині onActivityResultви можете отримати повний текст SMS-повідомлення з даних:

val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)

Потім ви розбираєте SMS-повідомлення та передаєте одноразовий код своєму бекенду!


4-10 digit alphanumeric code containing at least one numberЧи можете ви пояснити, що це означає? Чи означає це, що довжина всього повідомлення повинна становити 4-10 символів лише sms-коду?
Zeeshan Shabbir

Дякую також вам
Левон Петросян

Це працює лише для перевірки OTP? Що з читанням усіх інших повідомлень всередині телефону, усіх SMS тощо? Чи є новий API для цього, будь ласка, дайте мені знати. Щасливого кодування! :)
Маной Перумарат

У нас завжди є помилка тайм-аута. Будь ласка, допоможіть мені
Манікандан К

2
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;

змінив:

String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";

2

Котлін Код, щоб прочитати SMS:

1- Додайте цей дозвіл на AndroidManifest.xml:

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

2 - Створіть клас 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-одержуйте дозвіл на отримання SMS-повідомлень, якщо Android 6 і вище:

   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- Додайте цей код запиту до Діяльності або фрагменту:

 companion object {
    const val PERMISSIONS_REQUEST_READ_SMS = 100
   }

5- Переозначення Перевірка дозволу Запит задоволення від результату:

 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

Найпростіша функція

Для читання sms я написав функцію, яка повертає об’єкт Бесіди:

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

Використання:

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

Або отримати лише розмову конкретної кількості:

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}")
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.