Quero recuperar as mensagens SMS do dispositivo e exibi-las?
Quero recuperar as mensagens SMS do dispositivo e exibi-las?
Respostas:
Use o resolvedor de conteúdo ( "content: // sms / inbox" ) para ler o SMS que está na caixa de entrada.
// 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
}
Por favor, adicione a permissão READ_SMS .
Espero que ajude :)
moveToFirst
como eu.
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();
}
Definir aplicativo como aplicativo SMS padrão
@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();
}
}
}
}
}
Função para receber 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;
}
A classe Sms está abaixo:
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ão se esqueça de definir a permissão no seu 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)));
Isso lhe dará tempo de 24 horas.
mActivity
não está definido. O que é isso?
É um processo trivial. Você pode ver um bom exemplo no código-fonte SMSPopup
Examine os seguintes métodos:
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)
este é o método para leitura:
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;
}
A partir da API 19, você pode fazer uso da classe de telefonia para isso; Como os valores marcados não recuperam mensagens em todos os dispositivos, porque o provedor de conteúdo Uri muda de dispositivos e fabricantes.
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();
}
}
Esta postagem é um pouco antiga, mas aqui está outra solução fácil para obter dados relacionados ao SMS
provedor de conteúdo no Android:
Use esta lib: https://github.com/EverythingMe/easy-content-providers
Obter tudo SMS
:
TelephonyProvider telephonyProvider = new TelephonyProvider(context);
List<Sms> smses = telephonyProvider.getSms(Filter.ALL).getList();
Cada SMS tem todos os campos, para que você possa obter qualquer informação que você precise:
endereço, corpo, dataData, tipo (INBOX, SENT, DRAFT, ..), threadId, ...
Gel tudo MMS
:
List<Mms> mmses = telephonyProvider.getMms(Filter.ALL).getList();
Gel tudo Thread
:
List<Thread> threads = telephonyProvider.getThreads().getList();
Gel tudo Conversation
:
List<Conversation> conversations = telephonyProvider.getConversations().getList();
Ele funciona com List
ou Cursor
e existe um aplicativo de exemplo para ver como ele funciona e como funciona.
De fato, há suporte para todos os provedores de conteúdo do Android, como: Contatos, Logs de chamadas, Calendário ... Documento completo com todas as opções: https://github.com/EverythingMe/easy-content-providers/wiki/Android- fornecedores
Espero que também tenha ajudado :)
Etapa 1: primeiro temos que adicionar permissões no arquivo de manifesto, como
<uses-permission android:name="android.permission.RECEIVE_SMS" android:protectionLevel="signature" />
<uses-permission android:name="android.permission.READ_SMS" />
Etapa 2: em seguida, adicione a classe de receptor de serviço sms para receber sms
<receiver android:name="com.aquadeals.seller.services.SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
Etapa 3: adicionar permissão de tempo de execução
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;
}
Etapa 4: adicione essas classes ao seu aplicativo e teste a classe 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; }}
Já existem muitas respostas disponíveis, mas acho que todas elas estão faltando uma parte importante desta pergunta. Antes de ler os dados de um banco de dados interno ou de sua tabela, precisamos entender como os dados são armazenados nele e, em seguida, podemos encontrar a solução da pergunta acima:
Como posso ler mensagens SMS do dispositivo programaticamente no Android?
Então, na tabela SMS do Android, é assim:
Saiba, podemos selecionar o que quisermos do banco de dados. No nosso caso, apenas solicitamos
id, endereço e corpo
Em caso de leitura de SMS:
1. Peça permissões
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.Agora, seu código fica assim
// 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);
Espero que este seja útil. Obrigado.
Os serviços do Google Play têm duas APIs que você pode usar para otimizar o processo de verificação por SMS
Fornece uma experiência de usuário totalmente automatizada, sem exigir que o usuário digite manualmente códigos de verificação e sem exigir permissões extras de aplicativos e deve ser usado quando possível. No entanto, exige que você coloque um código de hash personalizado no corpo da mensagem, portanto, você também deve ter controle sobre o lado do servidor .
Solicitar verificação de SMS em um aplicativo Android
Executar verificação de SMS em um servidor
API de consentimento do usuário do SMS
Não requer o código hash personalizado, mas exige que o usuário aprove a solicitação do seu aplicativo para acessar a mensagem que contém o código de verificação. Para minimizar as chances de aparecer a mensagem errada para o usuário, SMS User Consent
filtrará as mensagens dos remetentes na lista de contatos do usuário.
The SMS User Consent API
faz parte do Google Play Services. Para usá-lo, você precisará de pelo menos a versão 17.0.0
dessas bibliotecas:
implementation "com.google.android.gms:play-services-auth:17.0.0"
implementation "com.google.android.gms:play-services-auth-api-phone:17.1.0"
Etapa 1: comece a ouvir as mensagens SMS
O consentimento do usuário do SMS escutará as mensagens SMS recebidas que contenham um código único por até cinco minutos. Ele não examinará nenhuma mensagem enviada antes de ser iniciada. Se você souber o número de telefone que enviará o código único, poderá especificar o senderPhoneNumber
, ou se não null
corresponderá a nenhum número.
smsRetriever.startSmsUserConsent(senderPhoneNumber /* or null */)
Etapa 2: solicitar consentimento para ler uma mensagem
Depois que seu aplicativo receber uma mensagem contendo um código único, ele será notificado por uma transmissão. Neste ponto, você não tem consentimento para ler a mensagem. Em vez disso, você recebe um Intent
aviso de que pode começar a solicitar o consentimento do usuário. Dentro do seu BroadcastReceiver
, você mostra o prompt usando o Intent
no extras
. Quando você inicia essa intenção, ele solicita ao usuário permissão para ler uma única mensagem. Eles mostrarão o texto inteiro que compartilharão com seu aplicativo.
val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)
Etapa 3: analisar o código único e concluir a verificação por SMS
Quando o usuário clica “Allow”
- é hora de realmente ler a mensagem! Dentro de onActivityResult
você, você pode obter o texto completo da mensagem SMS a partir dos dados:
val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
Você analisa a mensagem SMS e passa o código único para o seu back-end!
4-10 digit alphanumeric code containing at least one number
Você pode explicar o que isso significa? Isso significa que o comprimento da mensagem inteira deve ser de 4 a 10 caracteres apenas do código sms?
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;
Alterado por:
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";
Código Kotlin para ler SMS:
1- Adicione esta permissão ao AndroidManifest.xml:
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
2-Crie uma 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-Obtenha permissão de SMS se o Android 6 e superior:
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- Adicione este código de solicitação à Atividade ou fragmento:
companion object {
const val PERMISSIONS_REQUEST_READ_SMS = 100
}
5- Substituição da permissão de verificação Solicitar resultado divertido:
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 ")
}
}
}
}
A função mais fácil
Para ler o sms, escrevi uma função que retorna um objeto de conversa:
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)
}
Usando:
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 obtenha apenas uma conversa de número específico:
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}")
}
}