Intereting Posts
Ошибка эмулятора Android: PANIC: Не удалось открыть: C: \ Users \ hallo \ .android / avd / myemu.ini Панель действий не показана с помощью AppCompat Chromecast добавляет субтитры во время воспроизведения видео Использование андроидных векторных чертежей Есть ли способ получить строку пользовательского агента по умолчанию, кроме WebView.getSettings (). GetUserAgentString ()? AsyncTaskLoader против AsyncTask Ошибка: выполнение выполнено для задачи ': android: transformClassesAndResourcesWithProguardForRelease' Как использовать графические элементы по умолчанию для Android Не удалось удалить старое действие javaCompile, возможно, имя класса изменилось Android: Как вы можете выровнять кнопку внизу и listview выше? Как получить адрес электронной почты с адресом первичной покупки Повторное использование сеансов SSL в Android с HttpClient Как добавить банку в внешние библиотеки в студии android Добавление проекта андроидной библиотеки в проект андроида предотвращает создание Ant Run-as говорит, что «пакет неизвестен» после обновления Android до 4.3

Использование SMS для проверки номера телефона устройства

Я пытаюсь проверить номер телефона Android-устройства, отправив SMS-сообщение самому себе и автоматически проверяя, получено ли SMS-сообщение. Как я могу это сделать?

Solutions Collecting From Web of "Использование SMS для проверки номера телефона устройства"

Для начала потребуется два разрешения; Один для отправки SMS-сообщений и один для их получения. В вашем AndroidManifest.xml должно быть указано следующее: теги <manifest> , но вне тегов <application> .

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

Это и опасные разрешения, поэтому вам нужно будет обрабатывать их соответственно, если ваше приложение должно работать на Marshmallow (API-уровень 23) или выше и имеет targetSdkVersion 23+. Информацию о том, как запрашивать эти разрешения во время выполнения, можно найти на этой странице разработчика .


Классы Java, которые вам понадобятся, находятся в пакете android.telephony ; В частности, android.telephony.SmsManager и android.telephony.SmsMessage . Убедитесь, что у вас есть правильные классы, импортированные для обоих.

Чтобы отправить исходящие SMS, вы будете использовать SmsManager sendTextMessage() , который имеет следующую подпись:

 sendTextMessage(String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) 

В этом вызове метода требуются только два аргумента – destinationAddress и text ; Первый из которых является номером телефона, второй – содержимым сообщения. null может быть передано для остальных. Например:

 String number = "1234567890"; String message = "Verification message."; SmsManager sm = SmsManager.getDefault(); sm.sendTextMessage(number, null, message, null, null); 

Важно, чтобы текст сообщения был относительно коротким, так как sendTextMessage() обычно терпит неудачу, если длина текста превышает лимит символов для одного сообщения.


Чтобы получать и читать входящее сообщение, вам необходимо зарегистрировать BroadcastReceiver с IntentFilter для действия "android.provider.Telephony.SMS_RECEIVED" . Этот приемник может быть зарегистрирован либо статически в манифесте, либо динамически в Context во время выполнения.

  • Статическая регистрация класса Receiver в манифесте позволит вашему приложению получать входящее сообщение, даже если ваше приложение должно быть убито до получения. Однако, возможно, потребуется немного дополнительной работы, чтобы получить результаты там, где вы хотите. Между тегами <application> :

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

    Метод PackageManager#setComponentEnabledSetting() может использоваться для включения и отключения этого <receiver> мере необходимости.

  • Динамически регистрировать экземпляр приемника в Context может быть немного проще управлять, по коду, поскольку класс Receiver может быть сделан внутренним классом в зависимости от того, какой компонент регистрирует его и, следовательно, имеет прямой доступ к членам этого компонента. Однако этот подход может быть не таким надежным, как статическая регистрация, поскольку несколько разных вещей могут помешать Получателю получить трансляцию; Например, процесс вашего приложения уничтожается, пользователь переходит от регистрирующего Activity и т. Д.

     SmsReceiver receiver = new SmsReceiver(); IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); registerReceiver(receiver, filter); 

    Не забывайте регистрировать приемник, когда это необходимо.


В onReceive() получателя фактическое сообщение приходит как массив массивов byte прикрепленных к Intent как дополнительный. Детали декодирования варьируются в зависимости от версии Android, но результатом здесь является единственный объект SmsMessage котором будут SmsMessage номер телефона и сообщение.

 class SmsReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { SmsMessage msg; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent); msg = msgs[0]; } else { Object pdus[] = (Object[]) intent.getExtras().get("pdus"); msg = SmsMessage.createFromPdu((byte[]) pdus[0]); } String number = msg.getOriginatingAddress(); String message = msg.getMessageBody(); ... } } 

На этом этапе вы просто сравниваете number здесь с тем, который был передан sendTextMessage() . Целесообразно использовать PhoneNumberUtils.compare() для этого, поскольку номер, полученный в приемнике, может быть в другом формате, чем тот, который адресован.


Заметки:

  • Пример, продемонстрированный здесь, заключается в использовании одного сообщения с одной частью, поэтому текст сообщения должен быть ограничен относительно короткой длиной. Если вы хотите отправить более длинное сообщение, по какой-либо причине вместо этого можно использовать метод sendMultipartTextMessage() . Сначала вам нужно разбить текст, используя SmsManager#divideMessage() и передать полученный ArrayList этому методу вместо сообщения String . Чтобы собрать полное сообщение в приемнике, вам нужно будет декодировать каждый byte[] в SmsMessage и SmsMessage тела сообщений.

  • Начиная с KitKat (API уровня 19), если ваше приложение не является приложением по умолчанию для обмена сообщениями, используемые здесь сообщения будут сохраняться в поставщике SMS с помощью системы и приложения по умолчанию и поэтому будут доступны для любого другого приложения, которое использует Provider. Вы не можете этого сделать, но если вы действительно этого хотите избежать, эту же технику можно использовать с данными SMS, которые не запускают приложение по умолчанию, и не будут сохранены в Провайдере.

    Для этого используется метод sendDataMessage() , которому потребуется дополнительный short аргумент для номера (произвольного) порта, и сообщение передается как byte[] , а не String . Действие для фильтрации – это "android.intent.action.DATA_SMS_RECEIVED" , и для фильтра потребуется установка схемы данных и полномочий (хост и порт). В манифесте это будет выглядеть так:

     <intent-filter> <action android:name="android.intent.action.DATA_SMS_RECEIVED" /> <data android:scheme="sms" android:host="localhost" android:port="1234" /> </intent-filter> 

    И в классе IntentFilter есть соответствующие методы, чтобы динамически их устанавливать.

    Декодирование SmsMessage одинаковое, но byte[] сообщения byte[] извлекается с помощью getUserData() , а не getMessageBody() .

  • До появления KitKat приложения отвечали за составление собственных исходящих сообщений, поэтому вы можете просто не делать этого в этих версиях, если вы не хотите его записывать.

    Входящие сообщения могут быть перехвачены, а их трансляции прерваны до того, как основное приложение обмена сообщениями сможет их получить и записать. Для этого приоритет фильтра устанавливается на максимум, а abortBroadcast() вызывается в приемнике. В статической опции атрибут android:priority="999" добавляется к открывающему тегу <intent-filter> . Динамически метод IntentFilter#setPriority() может делать то же самое.

    Это не совсем безопасно, так как для другого приложения всегда возможно иметь более высокий приоритет, чем ваш.

  • Я пропустил прием Получателя с разрешением вещателя в этих примерах, отчасти для простоты и ясности, а отчасти потому, что природа вещи не оставила бы вас открытой для любого рода подмены, которые могли бы нанести вред. Однако, если вы хотите включить это, вам просто нужно добавить атрибут android:permission="android.permission.BROADCAST_SMS" в открывающий <receiver> для статического параметра. Для динамического использования используйте четырехпараметрическую перегрузку метода registerReceiver() , передав это разрешение String в качестве третьего аргумента, а null как четвертое.

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

 private void startVerification(String phoneNumber) { Config config = SinchVerification.config().applicationKey("your_app_key").context(getApplicationContext()).build(); VerificationListener listener = new MyVerificationListener(); verification = SinchVerification.createFlashCallVerification(config, phoneNumber, listener); verification.initiate(); } 

Для получения дополнительной информации вы можете посмотреть этот учебник:

https://www.sinch.com/tutorials/android-flash-call-verification/