Как программно читать SMS-сообщения с устройства в Android?

Я хочу получать SMS-сообщения с устройства и отображать их?


person Community    schedule 11.05.2009    source источник
comment
@David Freitas Доверенная ссылка +1   -  person Shahzad Imam    schedule 27.11.2012
comment
@DavidFreitas, эта ссылка не работает, не могли бы вы поделиться последней ссылкой?   -  person Khobaib    schedule 13.11.2013
comment
@Khobaib, как всегда, в интернете все мимолетно. Я нашел копию на сайте archive.org stackoverflow.com/a/19966227/40961, слава Богу (я пожертвовал в последнее время, чтобы они работали). Но мы должны рассмотреть возможность преобразования содержимого страницы из https://web.archive.org/web/20121022021217/http://mobdev.olin.edu/mobdevwiki/FrontPage/Tutorials/SMS%20Messaging для синтаксиса уценки в ответе на этот вопрос. Наверное, час работы.   -  person David d C e Freitas    schedule 14.11.2013


Ответы (12)


Используйте Content Resolver ("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.

Я надеюсь, что это помогает :)

person Suryavel TR    schedule 29.02.2012
comment
Спасибо! Вы неправильно написали getColumnName, в остальном это работает как шарм. Да, и если кто-то будет этим пользоваться, не забудьте добавить разрешение android.permission.READ_SMS. - person qwerty; 28.03.2012
comment
Использует ли это также недокументированный api, который @CommonsWare указал в своем комментарии к принятому ответу? - person Krishnabhadra; 20.08.2012
comment
Внимание! Не пропустите moveToFirst, как это сделал я. - person Alexandr Priymak; 23.04.2013
comment
@ Кришнабхадра Да. Он использует недокументированный контент-провайдер content: // sms / inbox. - person pm_labs; 02.05.2013
comment
Вопрос: предоставляет ли это доступ разработчику для чтения каждого сообщения в почтовом ящике SMS? - person Aditya M P; 13.12.2015
comment
добавьте Cursor.close () после завершения процесса запроса - person Amir Hossein Ghasemi; 15.05.2018
comment
Кто-нибудь, пожалуйста, удалите этот ответ, он больше не действителен - person Manoj Perumarath; 16.06.2019
comment
вы можете проверить URL-адрес developers.google.com/identity/sms-retriever/overview для последних обновлений - person SIVAKUMAR.J; 28.01.2020

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

Функция получения СМС

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

Класс смс ниже:

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" />
person Atif Mahmood    schedule 15.12.2012
comment
Хороший фрагмент кода. Только одно: время измеряется в миллисекундах. Думаю, будет лучше сделать его удобочитаемым форматом, например String receiveDayTime = Functions.dateFromMilisec(Long.valueOf(c.getColumnIndexOrThrow("date")), "hh:mm a MMM dd, yyyy"); - person Bibaswann Bandyopadhyay; 13.09.2015
comment
какова цель создания всего с помощью геттера и сеттера, я действительно не понимаю, почему бы просто не использовать ассоциативный массив или класс, элементы которого доступны напрямую - person michnovka; 25.10.2015
comment
@TomasNavara: проверьте этот код, чтобы понять использование геттеров и сеттеров. pastebin.com/Nh8YXtyJ - person Bugs Happen; 24.08.2016
comment
@BibaswannBandyopadhyay Если вы не хотите использовать ничего, кроме библиотек Android и библиотек Java. new SimpleDateFormat("hh:mm", Locale.US).format(new Date(Long.parseLong(_time))); Это даст вам 24 часа времени. - person Chris - Jr; 11.02.2017
comment
mActivity не определен. Что это? - person dthree; 15.11.2017
comment
Вы можете использовать Context или ActivityName.this вместо mActivity - person Atif Mahmood; 15.11.2017
comment
Индекс столбца не меняется от сообщения к сообщению, поэтому вы можете переместить все эти вызовы getColumnIndexOrThrow за пределы цикла. - person Rudiger W.; 06.05.2019

Это тривиальный процесс. Вы можете увидеть хороший пример в исходном коде 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;
}
person Ömer    schedule 12.05.2009
comment
Это не часть Android SDK. Этот код делает неверное предположение, что все устройства поддерживают этого недокументированного и неподдерживаемого поставщика содержимого. Google прямо указал, что полагаться на это - не лучшая идея: android-developers.blogspot.com/2010/05/ - person CommonsWare; 15.12.2010
comment
@Janusz: не существует документированных и поддерживаемых средств, которые работают со всеми SMS-клиентами на всех устройствах. - person CommonsWare; 27.12.2010
comment
@CommonsWare, что грустно слышать. Тогда, возможно, придется жить с этим API. - person Janusz; 28.12.2010
comment
@Omer Есть идеи, как бы вы подсчитали количество SMS-сообщений на контакт? - person ; 21.05.2012
comment
Код переехал. Поиск SmsPopupUtils.java дал мне новую ссылку на него в коде Google. На случай, если они переместят его снова или полностью прекратят использование, вот резервная ссылка - pastebin.com/iPt7MLyM - person KalEl; 03.06.2012

Начиная с 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();
    }
}
person Manoj Perumarath    schedule 04.01.2017
comment
Кажется, это единственный ответ, который не использует недокументированный API и не относится к сторонним библиотекам. - person Ishamael; 19.01.2017
comment
Я пытался использовать этот код, чтобы получать SMS-сообщения из Hangouts (это мое приложение для SMS по умолчанию). Вместо этого он получил последнее исходящее сообщение, которое я отправил через Messenger ... Вы знаете, чем это вызвано? - person Miki P; 20.01.2017
comment
@MikiP, используя мои догадки, скажу, что приложение Messenger просило вас заменить управление SMS на Messenger. Это происходит с другим приложением для обмена сообщениями. Другого объяснения у меня нет. - person m3nda; 18.08.2017
comment
Не забудьте вызвать c.close (); - person Cícero Moura; 20.04.2018
comment
Здравствуйте, можем ли мы предположить, что этот код работает не на всех устройствах, начиная с API19? - person Sardar Agabejli; 05.11.2019
comment
@SardarAgabejli Если мы используем жестко заданные значения, такие как contenturi: sms, они не будут одинаковыми для каждого устройства, но если мы используем класс Telephony, мы получим прямой доступ к этому conetnt uri или пути sms db этого устройства, это помощник класс, чтобы указать на БД смс - person Manoj Perumarath; 06.11.2019
comment
Можно ли так вести разговоры? Или для каждой смс есть специальный атрибут, например идентификатор беседы? - person Sardar Agabejli; 06.11.2019
comment
Используйте этот класс беседы, чтобы прочитать, что developer.android.com/reference/android / provider /, или, если вы не можете найти, вы можете опубликовать это как вопрос, счастливого кодирования, братан :) - person Manoj Perumarath; 06.11.2019

Этот пост немного устарел, но вот еще одно простое решение для получения данных, связанных с SMS контент-провайдером в Android:

Используйте эту библиотеку: https://github.com/EverythingMe/easy-content-providers

  • Получить все SMS:

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

    В каждом SMS есть все поля, поэтому вы можете получить любую необходимую информацию:
    адрес, тело, полученная дата, тип (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, таких как: Контакты, Журналы вызовов, Календарь, ... Полный документ со всеми параметрами:

Надеюсь, это тоже помогло :)

person sromku    schedule 22.08.2015
comment
Исходный код и примеры на github весьма полезны. Это хорошая оболочка / фасад для большинства распространенных провайдеров. Спасибо. - person m3nda; 18.08.2017

Шаг 1: сначала нам нужно добавить разрешения в файл манифеста, например

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

Шаг 2: затем добавьте класс приемника служебных смс для приема смс.

<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));
                    }
                }
            }
            catch(Exception e){}
        }
    }
    public static void bindListener(SmsListener listener) {
        mListener = listener; 
    }
}
person Venkatesh    schedule 06.10.2016
comment
Что делает узор? - person Mark Buikema; 19.10.2016
comment
Хорошо ... это (com.aquadeals.seller.services.SmsReceiver) общее имя службы? - person m3nda; 18.08.2017
comment
Я., это не имя службы, это путь к классу SmsReceiver в моем приложении - person Venkatesh; 18.08.2017
comment
Зачем нужно разрешение на МЕСТО? - person Zam Sunk; 05.04.2018
comment
В моем приложении требуется разрешение на местоположение, поэтому я включил. Если вы не хотите пропускать это разрешение, не проблема @ZamSunk - person Venkatesh; 09.04.2018
comment
привет, получаю ошибку, исключение нулевого указателя на mlistner, можете ли вы помочь - person Anjani Mittal; 17.07.2018
comment
@AnjaniMittal, что происходит, чувак, ты можешь мне правильно сказать - person Venkatesh; 17.07.2018
comment
@AnjaniMittal, правильно ли вы выполнили эти шаги? добавление интерфейса и файла манифеста - person Venkatesh; 17.07.2018
comment
@VenkateshNani Я выполнил все вышеперечисленные шаги, когда я получаю sms, приложение показывает NullPointerException на mListner - person Anjani Mittal; 17.07.2018
comment
Я пытаюсь создать приложение, которое выводит на экран смс-контент, даже если приложение было убито - person Anjani Mittal; 17.07.2018
comment
@AnjaniMittal, ладно, сначала распечатайте свое сообщение, а затем вы измените код, что вам нужно получить из этого контента. Фактически это для считывания всего 6-значного кода. Вы проверяли, что когда-то код приемника - person Venkatesh; 17.07.2018

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

Как я могу программно читать SMS-сообщения с устройства в Android?

В android таблица SMS выглядит так

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

Теперь вы можете выбрать из базы данных все, что хотите. В нашем случае нам нужно только

id, адрес и тело

В случае чтения 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);
        }

or

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

Надеюсь, это будет полезно. Спасибо.

person nitin    schedule 06.03.2018

В сервисах Google Play есть два API, которые можно использовать для оптимизации процесса проверки по SMS.

SMS Retriever API

Обеспечивает полностью автоматизированный пользовательский интерфейс, не требуя от пользователя вручную вводить коды подтверждения и не требуя каких-либо дополнительных разрешений приложения и должен использоваться, когда это возможно. Однако он требует, чтобы вы поместили собственный хэш-код в тело сообщения, поэтому вы также должны иметь контроль над серверной частью.

  • Требования к сообщению - 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 User Consent будет прослушивать входящие 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-сообщение и передаете одноразовый код своему бэкэнду!

person Levon Petrosyan    schedule 07.08.2019
comment
4-10 digit alphanumeric code containing at least one number Вы можете объяснить, что это значит? Означает ли это, что длина всего сообщения должна составлять 4-10 символов только кода смс? - person Zeeshan Shabbir; 14.10.2019
comment
И тебе спасибо - person Levon Petrosyan; 14.10.2019
comment
Это работает только для проверки OTP, верно? Как насчет чтения всех других сообщений в телефоне, всех SMS и т. Д.? Есть ли для этого какой-нибудь новый API? Пожалуйста, дайте мне знать. Удачного кодирования! :) - person Manoj Perumarath; 28.10.2019
comment
У нас всегда была ошибка тайм-аута. Помогите, пожалуйста - person Manikandan K; 18.06.2020

Самая простая функция

Для чтения смс я написал функцию, которая возвращает объект 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)
    }

С использованием:

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}")
    }
}
person Mickael Belhassen    schedule 26.01.2019

Код Kotlin для чтения 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 Check Permisstion Request результат весело:

 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  ")
            }
        }
    }
}
person Hamed Jaliliani    schedule 07.01.2019

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

изменено:

String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";
person Van Hau Hoang    schedule 28.09.2013

Вот отличный видеоурок !!!! Работает потрясающе !!!

Это комбинация из Google Sheet List с числами и приложения для Android. (Очень легко следовать руководству, даже для не кодировщиков !!!

Перейдите по ссылке для учебника:

https://www.youtube.com/watch?v=PReU4ITp37I&list=PLuB9drjjGa0QvFzWq_bwO8bOTRaWpdP_d&index=2

Вот код для скрипта приложения Google:

const SHEET_URL = "https://docs.google.com/spreadsheets/d/16_fp7lQsnaMLaDYMVsE5YxsohQBANllEVcZeMP5ZpiU/edit#gid=0";
const SHEET_NAME = "SMS";

const doGet = () => {
  const sheet = SpreadsheetApp.openByUrl(SHEET_URL).getSheetByName(SHEET_NAME);
  const [header, ...data] = sheet.getDataRange().getDisplayValues();
  

  const PHONE = header.indexOf("Phone");
  const TEXT = header.indexOf("Text");
  const STATUS = header.indexOf("Status");

  const output = [];

 data.forEach((row, index) => {
  if (row[STATUS] === "") {
    output.push([index+1, row[PHONE], row[TEXT]]);
  }
});

const json = JSON.stringify(output);

return ContentService.createTextOutput(json).setMimeType(ContentService.MimeType.TEXT);
}

const doPost = (e) => {
  const sheet = SpreadsheetApp.openByUrl(SHEET_URL).getSheetByName(SHEET_NAME);
  const [header] = sheet.getRange("A1:1").getValues();
  const STATUS = header.indexOf("Status");
  var rowId = Number(e.parameter.row);
  sheet.getRange(rowId + 1, STATUS +1).setValue("SMS Sent");
  return ContentService.createTextOutput("").setMimeType(ContentService.MimeType.TEXT);
}

И тогда вам нужно только просмотреть вторую часть видео, где он создает приложение для Android в MIT App Inventer. Я сделал снимок экрана, чтобы увидеть проект

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

person Proboto    schedule 31.03.2021