Chcę pobrać wiadomości SMS z urządzenia i wyświetlić je?
Chcę pobrać wiadomości SMS z urządzenia i wyświetlić je?
Odpowiedzi:
Użyj Content Resolver ( „content: // sms / inbox” ), aby odczytać SMS-y znajdujące się w skrzynce odbiorczej.
// 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
}
Dodaj uprawnienie READ_SMS .
Mam nadzieję, że to pomoże :)
moveToFirst
tak jak ja.
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();
}
Ustaw aplikację jako domyślną aplikację do SMS-ów
@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();
}
}
}
}
}
Funkcja otrzymywania wiadomości 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;
}
Klasa SMS jest poniżej:
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;
}
}
Nie zapomnij zdefiniować uprawnień w pliku 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)));
To da ci 24 godziny.
mActivity
nie jest zdefiniowany. Co to jest?
To jest trywialny proces. Dobry przykład możesz zobaczyć w kodzie źródłowym SMSPopup
Sprawdź następujące metody:
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)
to jest metoda czytania:
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;
}
Począwszy od API 19, możesz do tego wykorzystywać klasę telefonii; Ponieważ wartości zapisane na stałe nie będą pobierać wiadomości z każdego urządzenia, ponieważ dostawca treści Uri zmienia się od urządzeń i producentów.
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();
}
}
Ten post jest trochę stary, ale oto inne łatwe rozwiązanie do pobierania danych związanych z SMS
dostawcą treści w systemie Android:
Użyj tej biblioteki: https://github.com/EverythingMe/easy-content-providers
Zbierz wszystkie SMS
:
TelephonyProvider telephonyProvider = new TelephonyProvider(context);
List<Sms> smses = telephonyProvider.getSms(Filter.ALL).getList();
Każdy SMS ma wszystkie pola, dzięki czemu możesz uzyskać wszelkie potrzebne informacje:
adres, treść, otrzymano Data, typ (SKRZYNKA, WYSŁANE, PROJEKT, ...), wątek, ...
Żel wszystko MMS
:
List<Mms> mmses = telephonyProvider.getMms(Filter.ALL).getList();
Żel wszystko Thread
:
List<Thread> threads = telephonyProvider.getThreads().getList();
Żel wszystko Conversation
:
List<Conversation> conversations = telephonyProvider.getConversations().getList();
Działa z List
lub Cursor
i jest przykładowa aplikacja, aby zobaczyć, jak to wygląda i działa.
W rzeczywistości istnieje wsparcie dla wszystkich dostawców treści dla Androida, takich jak: Kontakty, dzienniki połączeń, kalendarz, ... Pełny dokument ze wszystkimi opcjami: https://github.com/EverythingMe/easy-content-providers/wiki/Android- dostawcy
Mam nadzieję, że to również pomogło :)
Krok 1: najpierw musimy dodać uprawnienia w pliku manifestu, takim jak
<uses-permission android:name="android.permission.RECEIVE_SMS" android:protectionLevel="signature" />
<uses-permission android:name="android.permission.READ_SMS" />
Krok 2: następnie dodaj klasę usługowego odbiornika SMS do odbierania wiadomości SMS
<receiver android:name="com.aquadeals.seller.services.SmsReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
Krok 3: Dodaj uprawnienie w czasie wykonywania
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;
}
Krok 4: Dodaj te klasy do swojej aplikacji i przetestuj klasę interfejsu
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; }}
Istnieje wiele odpowiedzi, które są już dostępne, ale myślę, że we wszystkich brakuje ważnej części tego pytania. Przed odczytem danych z wewnętrznej bazy danych lub jej tabeli musimy zrozumieć, w jaki sposób dane są w niej przechowywane, a następnie możemy znaleźć rozwiązanie powyższego pytania, które brzmi:
Jak mogę programowo odczytać wiadomości SMS z urządzenia na Androidzie?
Tak więc w Androidzie Tabela SMS wygląda tak
Wiemy, że możemy wybrać z bazy danych wszystko, co chcemy, w naszym przypadku mamy tylko wymagane
identyfikator, adres i treść
W przypadku czytania SMS:
1. Zapytaj o uprawnienia
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);
}
lub
<uses-permission android:name="android.permission.READ_SMS" />
2. Teraz twój kod wygląda tak
// 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);
Mam nadzieję, że ten będzie pomocny. Dzięki.
Usługi Google Play mają dwa interfejsy API, za pomocą których można usprawnić proces weryfikacji za pomocą wiadomości SMS
Zapewnia w pełni zautomatyzowane środowisko użytkownika, bez konieczności ręcznego wpisywania kodów weryfikacyjnych i bez dodatkowych uprawnień aplikacji i należy z niego korzystać, gdy to możliwe. Wymaga to jednak umieszczenia niestandardowego kodu skrótu w treści wiadomości, więc musisz mieć kontrolę również po stronie serwera .
Poproś o weryfikację SMS w aplikacji na Androida
Wykonaj weryfikację SMS na serwerze
Interfejs API zgody użytkownika SMS
Nie wymaga niestandardowego kodu skrótu, wymaga jednak od użytkownika zatwierdzenia prośby aplikacji o dostęp do wiadomości zawierającej kod weryfikacyjny. Aby zminimalizować ryzyko wyświetlenia niewłaściwej wiadomości użytkownikowi, SMS User Consent
odfiltruje wiadomości od nadawców z listy kontaktów użytkownika.
The SMS User Consent API
jest częścią usług Google Play. Aby z niego skorzystać, potrzebujesz co najmniej wersji 17.0.0
tych bibliotek:
implementation "com.google.android.gms:play-services-auth:17.0.0"
implementation "com.google.android.gms:play-services-auth-api-phone:17.1.0"
Krok 1: Rozpocznij nasłuchiwanie wiadomości SMS
Zgoda użytkownika SMS będzie nasłuchiwać przychodzących wiadomości SMS zawierających jednorazowy kod przez maksymalnie pięć minut. Nie będzie patrzeć na żadne wiadomości wysłane przed jego uruchomieniem. Jeśli znasz numer telefonu, który wyśle jednorazowy kod, możesz podać senderPhoneNumber
lub, jeśli nie null
, dopasować dowolny numer.
smsRetriever.startSmsUserConsent(senderPhoneNumber /* or null */)
Krok 2: Poproś o zgodę na przeczytanie wiadomości
Gdy aplikacja otrzyma wiadomość zawierającą kod jednorazowy, zostanie o tym powiadomiona przez transmisję. W tym momencie nie masz zgody na przeczytanie wiadomości - zamiast tego otrzymujesz informację Intent
, że możesz zacząć pytać użytkownika o zgodę. Wewnątrz BroadcastReceiver
wyświetlasz monit za pomocą Intent
w extras
. Po uruchomieniu tego zamiaru użytkownik poprosi o zgodę na przeczytanie pojedynczej wiadomości. Wyświetlą się cały tekst, który udostępnią Twojej aplikacji.
val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)
Krok 3: Analizuj kod jednorazowy i zakończ weryfikację SMS
Gdy użytkownik kliknie “Allow”
- nadszedł czas, aby przeczytać wiadomość! Wewnątrz onActivityResult
możesz uzyskać pełny tekst wiadomości SMS z danych:
val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
Następnie parsujesz wiadomość SMS i przekazujesz jednorazowy kod do backendu!
4-10 digit alphanumeric code containing at least one number
Czy możesz wyjaśnić, co to znaczy? Czy to oznacza, że długość całej wiadomości powinna wynosić 4–10 znaków samego kodu sms?
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;
zmienione przez:
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0 " : SMS_READ_COLUMN + " = 1 ";
Kod Kotlin do czytania SMS:
1- Dodaj to uprawnienie do AndroidManifest.xml:
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
2-Utwórz klasę 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-Uzyskaj uprawnienie SMS, jeśli Android 6 i nowszy:
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- Dodaj ten kod żądania do działania lub fragmentu:
companion object {
const val PERMISSIONS_REQUEST_READ_SMS = 100
}
5- Przesłoń Sprawdź uprawnienia Prośba o wynik zabawy:
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 ")
}
}
}
}
Najłatwiejsza funkcja
Aby odczytać sms, napisałem funkcję, która zwraca obiekt konwersacji:
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)
}
Za pomocą:
getSmsConversation(this){ conversations ->
conversations.forEach { conversation ->
println("Number: ${conversation.number}")
println("Message One: ${conversation.message[0].body}")
println("Message Two: ${conversation.message[1].body}")
}
}
Lub uzyskaj tylko rozmowę o określonym numerze:
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}")
}
}