Я хочу получить SMS-сообщения с устройства и отобразить их?
Я хочу получить SMS-сообщения с устройства и отобразить их?
Ответы:
Используйте 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 .
Я надеюсь, что это помогает :)
moveToFirst
как я.
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;
}
Класс смс ниже:
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" />
String receiveDayTime = Functions.dateFromMilisec(Long.valueOf(c.getColumnIndexOrThrow("date")), "hh:mm a MMM dd, yyyy");
new SimpleDateFormat("hh:mm", Locale.US).format(new Date(Long.parseLong(_time)));
Это даст вам 24 часа времени.
mActivity
не определен. Что это?
Это тривиальный процесс. Хороший пример вы можете увидеть в исходном коде 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;
}
Начиная с 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();
}
}
Этот пост немного устарел, но вот еще одно простое решение для получения данных, связанных с SMS
поставщиком контента в Android:
Используйте эту библиотеку: https://github.com/EverythingMe/easy-content-providers
Получить все SMS
:
TelephonyProvider telephonyProvider = new TelephonyProvider(context);
List<Sms> smses = telephonyProvider.getSms(Filter.ALL).getList();
В каждом SMS-сообщении есть все поля, поэтому вы можете получить любую нужную вам информацию:
адрес, тело, receiveDate, тип (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: сначала мы должны добавить разрешения в файл манифеста, как
<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)); }
else {}} }
catch(Exception e){} } }
public static void bindListener(SmsListener listener) {
mListener = listener; }}
Есть много уже доступных ответов, но я думаю, что все они упускают важную часть этого вопроса. Прежде чем читать данные из внутренней базы данных или ее таблицы, мы должны понять, как в ней хранятся данные, а затем найти решение вышеуказанного вопроса:
Как программно читать СМС-сообщения с устройства в Android?
Итак, в андроид смс таблица выглядит так
Знайте, мы можем выбрать все, что мы хотим из базы данных. В нашем случае нам нужно только
идентификатор, адрес и тело
В случае чтения СМС:
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);
Я надеюсь, что это будет полезно. Спасибо.
Сервисы Google Play имеют два API, которые вы можете использовать для упрощения процесса проверки на основе SMS
Предоставляет полностью автоматизированный пользовательский интерфейс, не требуя от пользователя ручного ввода кодов проверки и не требуя каких-либо дополнительных разрешений приложения, и должен использоваться по возможности. Однако он требует, чтобы вы поместили пользовательский хеш-код в тело сообщения, поэтому вы должны также контролировать серверную часть .
Запросить SMS-подтверждение в приложении для Android
Выполните проверку SMS на сервере
Не требует настраиваемого хеш-кода, однако требует, чтобы пользователь одобрил запрос вашего приложения на доступ к сообщению, содержащему проверочный код. Чтобы свести к минимуму вероятность появления неправильного сообщения для пользователя, SMS User Consent
будет отфильтровываться сообщения от отправителей в списке контактов пользователя.
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-сообщение и передаете одноразовый код своему бэкэнду!
4-10 digit alphanumeric code containing at least one number
Можете ли вы объяснить, что это значит? Означает ли это, что длина всего сообщения должна составлять 4-10 символов только из SMS-кода?
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;
изменено:
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";
Код Котлина для чтения смс:
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- Добавьте этот код запроса в Activity или фрагмент:
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 ")
}
}
}
}
Самая простая функция
Чтобы прочитать смс, я написал функцию, которая возвращает объект беседы:
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}")
}
}