@ DavidFreitas dieser Link funktioniert nicht, können Sie bitte den neuesten Link teilen?
Khobaib
3
@ Khobaib, wie immer sind die Dinge im Internet flüchtig. Ich habe eine Kopie auf archive.org stackoverflow.com/a/19966227/40961 gefunden , Gott sei Dank für sie (ich habe kürzlich gespendet, um sie am Laufen zu halten). Wir sollten jedoch in Betracht ziehen, den Inhalt der Seite von web.archive.org/web/20121022021217/http://mobdev.olin.edu/… in eine Markdown-Syntax in einer Antwort auf diese Frage zu konvertieren . Wahrscheinlich eine Stunde Arbeit.
David d C e Freitas
Antworten:
157
Verwenden Sie Content Resolver ( "content: // sms / inbox" ), um SMS zu lesen, die sich im Posteingang befinden.
// 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 exceptiondo{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}
Danke dir! Sie haben "getColumnName" falsch geschrieben, ansonsten funktioniert es wie ein Zauber. Oh, und wenn jemand dies verwenden wird, vergessen Sie nicht, die Berechtigung android.permission.READ_SMS hinzuzufügen.
QWERTY
1
Vielen Dank. Ich habe es geändert :)
Suryavel TR
5
Verwendet dies auch die undokumentierte API, die @CommonsWare in seinem Kommentar zur akzeptierten Antwort angegeben hat?
Krishnabhadra
1
Beachtung! Verpassen Sie nicht moveToFirstwie ich.
Alexandr Priymak
4
@Krishnabhadra Ja. Es wird der undokumentierte Inhaltsanbieter "content: // sms / inbox" verwendet.
Das ist ein schönes Stück Code. Nur eines: Die Zeit wird in Millisekunden angegeben. Ich denke, es wird besser sein, es zu einem für Menschen lesbaren Format wieString receiveDayTime = Functions.dateFromMilisec(Long.valueOf(c.getColumnIndexOrThrow("date")), "hh:mm a MMM dd, yyyy");
Bibaswann Bandyopadhyay
1
Was ist der Zweck, alles mit Getter und Setter zu machen? Ich verstehe wirklich nicht, warum ich nicht einfach ein Assoc-Array oder eine Assoc-Klasse verwende, auf deren Elemente direkt zugegriffen wird
michnovka
1
@TomasNavara: Überprüfen Sie diesen Code, um die Verwendung von Getter und Setter zu verstehen. pastebin.com/Nh8YXtyJ
Bugs Happen
@BibaswannBandyopadhyay Wenn Sie nichts anderes als Android-Bibliotheken und Java-Bibliotheken verwenden möchten. new SimpleDateFormat("hh:mm", Locale.US).format(new Date(Long.parseLong(_time)));Dies gibt Ihnen 24 Stunden Zeit.
Chris - Jr
mActivityist nicht definiert. Was ist das?
Drei
61
Es ist ein trivialer Prozess. Sie können ein gutes Beispiel im Quellcode SMSPopup sehen
Dies ist nicht Teil des Android SDK. Dieser Code geht fälschlicherweise davon aus, dass alle Geräte diesen undokumentierten und nicht unterstützten Inhaltsanbieter unterstützen. Google hat ausdrücklich darauf hingewiesen, dass es keine gute Idee ist, sich darauf zu verlassen: android-developers.blogspot.com/2010/05/…
CommonsWare
1
@Janusz: Es gibt keine dokumentierten und unterstützten Mittel, die auf allen SMS-Clients auf allen Geräten funktionieren.
CommonsWare
9
@ CommonsWare das ist traurig zu hören. Möglicherweise muss dann mit dieser API leben.
Janusz
@Omer Hast du eine Idee, wie du die Anzahl der SMS-Nachrichten pro Kontakt zählen würdest?
SpicyWeenie
4
Der Code wurde verschoben. Durch die Suche in SmsPopupUtils.java habe ich einen neuen Link in Google Code erhalten. Im Fall , dass sie es wieder verschieben oder ganz einzustellen, hier ist eine Backup - Verbindung - pastebin.com/iPt7MLyM
Kalel
25
Ab API 19 können Sie dafür die Telefonieklasse verwenden; Da hartgesottene Werte nicht auf allen Geräten Nachrichten abrufen, ändert sich der Inhaltsanbieter Uri von Geräten und Herstellern.
publicvoid 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=newDate(Long.valueOf(smsDate));String type;switch(Integer.parseInt(c.getString(c.getColumnIndexOrThrow(Telephony.Sms.TYPE)))){caseTelephony.Sms.MESSAGE_TYPE_INBOX:
type ="inbox";break;caseTelephony.Sms.MESSAGE_TYPE_SENT:
type ="sent";break;caseTelephony.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();}}
Scheint die einzige Antwort zu sein, die keine undokumentierte API verwendet und sich nicht auf Bibliotheken von Drittanbietern bezieht.
Ishamael
Ich habe versucht, diesen Code zu verwenden, um SMS-Nachrichten von Hangouts abzurufen (dies ist meine Standard-SMS-App). Stattdessen wurde die letzte ausgehende Nachricht abgerufen, die ich über Messenger gesendet habe ... Wissen Sie, was dies verursacht?
Miki P
@MikiP Mit meinen Vermutungsfähigkeiten werde ich sagen, dass die Messenger-App Sie gefragt hat, ob Sie die SMS-Verwaltung durch Messenger ersetzen möchten. Es passiert mit einer anderen Messaging-App. Ich habe keine andere Erklärung.
m3nda
2
Vergessen Sie nicht, c.close () aufzurufen.
Cícero Moura
1
@SardarAgabejli Wenn wir hartgesottene Werte wie "contenturi: sms" verwenden, ist dies nicht für jedes Gerät gleich. Wenn wir jedoch die Telefonieklasse verwenden, erhalten wir direkten Zugriff auf diese Inhalts-Uri oder den Pfad der SMS-Datenbank dieses Geräts eine
Helferklasse
23
Dieser Beitrag ist etwas alt, aber hier ist eine weitere einfache Lösung, um Daten zum SMSInhaltsanbieter in Android abzurufen:
Jede SMS hat alle Felder, so dass Sie alle Informationen erhalten können, die Sie benötigen: Adresse, Text, Empfangsdatum, Typ (INBOX, SENT, DRAFT, ..), threadId, ...
Nun ... ist das ("com.aquadeals.seller.services.SmsReceiver") der gebräuchliche Dienstname?
m3nda
Ya das ist kein Dienstname, das ist SmsReceiver Klassenpfad in meiner App
Venkatesh
Warum benötigen Sie eine Genehmigung für LOCATION?
Zam Sunk
1
Ich versuche, eine App zu erstellen, die den SMS-Inhalt für den Benutzer anzeigt, auch wenn die App getötet wurde
Anjani Mittal
11
Es gibt bereits viele Antworten, aber ich denke, allen fehlt ein wichtiger Teil dieser Frage. Bevor wir Daten aus einer internen Datenbank oder ihrer Tabelle lesen, müssen wir verstehen, wie Daten darin gespeichert sind, und dann können wir die Lösung der obigen Frage finden:
Wie kann ich in Android programmgesteuert SMS-Nachrichten vom Gerät lesen?
Also, in Android SMS Tabelle sieht so aus
Wissen Sie, wir können aus der Datenbank auswählen, was wir wollen. In unserem Fall haben wir nur benötigt
ID, Adresse und Körper
Beim Lesen von SMS:
1. Fragen Sie nach Berechtigungen
int REQUEST_PHONE_CALL =1;if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.READ_SMS)!=PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this,newString[]{Manifest.permission.READ_SMS}, REQUEST_PHONE_CALL);}
Bietet eine vollautomatische Benutzererfahrung, ohne dass der Benutzer manuell Bestätigungscodes eingeben muss und ohne zusätzliche App-Berechtigungen, und sollte nach Möglichkeit verwendet werden. Es ist jedoch erforderlich, dass Sie einen benutzerdefinierten Hash-Code in den Nachrichtentext einfügen, sodass Sie auch die Kontrolle über die Serverseite haben müssen .
Nachrichtenanforderungen - 11-stelliger Hash-Code, der Ihre App eindeutig identifiziert
Erfordert keinen benutzerdefinierten Hash-Code. Der Benutzer muss jedoch die Anforderung Ihrer App genehmigen, auf die Nachricht mit dem Bestätigungscode zuzugreifen. Um die Wahrscheinlichkeit zu minimieren, dass dem Benutzer die falsche Nachricht angezeigt SMS User Consentwird, werden Nachrichten von Absendern in der Kontaktliste des Benutzers herausgefiltert.
Nachrichtenanforderungen - 4-10-stelliger alphanumerischer Code mit mindestens einer Nummer
Absenderanforderungen - Der Absender darf nicht in der Kontaktliste des Benutzers enthalten sein
Benutzerinteraktion - Ein Tipp zum Genehmigen
The SMS User Consent APIist Teil von Google Play Services. Um es zu verwenden, benötigen Sie mindestens eine Version 17.0.0dieser Bibliotheken:
Die Zustimmung des SMS-Benutzers wartet bis zu fünf Minuten lang auf eingehende SMS-Nachrichten, die einen Einmalcode enthalten. Es werden keine Nachrichten angezeigt, die vor dem Start gesendet wurden. Wenn Sie die Telefonnummer kennen, die den Einmalcode sendet, können Sie die angeben senderPhoneNumber, oder wenn Sie nullmit keiner Nummer übereinstimmen.
smsRetriever.startSmsUserConsent(senderPhoneNumber /* or null */)
Schritt 2: Fordern Sie die Zustimmung zum Lesen einer Nachricht an
Sobald Ihre App eine Nachricht mit einem Einmalcode erhält, wird diese per Broadcast benachrichtigt. Zu diesem Zeitpunkt haben Sie keine Einwilligung zum Lesen der Nachricht. Stattdessen erhalten Sie eine Einwilligung, mit der Sie Intentden Benutzer zur Einwilligung auffordern können. In Ihrem BroadcastReceiverzeigen Sie die Eingabeaufforderung mit der Intentin der extras. Wenn Sie diese Absicht starten, werden Sie aufgefordert, eine einzelne Nachricht zu lesen. Ihnen wird der gesamte Text angezeigt, den sie mit Ihrer App teilen.
val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)
Schritt 3: Analysieren Sie den Einmalcode und schließen Sie die SMS-Überprüfung ab
Wenn der Benutzer klickt, ist “Allow”es Zeit, die Nachricht tatsächlich zu lesen! Innerhalb von onActivityResultkönnen Sie den vollständigen Text der SMS-Nachricht aus den Daten erhalten:
val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
Sie analysieren dann die SMS-Nachricht und geben den Einmalcode an Ihr Backend weiter!
4-10 digit alphanumeric code containing at least one numberKönnen Sie erklären, was das bedeutet? Bedeutet dies, dass die Länge der gesamten Nachricht 4-10 Zeichen nur des SMS-Codes betragen sollte?
Zeeshan Shabbir
Vielen Dank auch
Levon Petrosyan
Dies funktioniert nur für die OTP-Überprüfung, oder? Was ist mit dem Lesen aller anderen Nachrichten im Telefon, aller SMS usw.? Gibt es dafür eine neue API? Bitte lassen Sie es mich wissen. Viel Spaß beim Codieren! :)
Manoj Perumarath
Wir haben immer den Timeout-Fehler. Bitte helfen Sie mir
package utils.broadcastreceivers
import android.content.BroadcastReceiverimport android.content.Contextimport android.content.Intentimport android.telephony.SmsMessageimport android.util.LogclassMySMSBroadCastReceiver:BroadcastReceiver(){override fun onReceive(context:Context?, intent:Intent?){var body =""
val bundle = intent?.extras
val pdusArr = bundle!!.get("pdus")asArray<Any>var messages:Array<SmsMessage?>= arrayOfNulls(pdusArr.size)// if SMSis Long and contain more than 1 Message we'll read all of themfor(i in pdusArr.indices){
messages[i]=SmsMessage.createFromPdu(pdusArr[i]asByteArray)}varMobileNumber: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-Berechtigung ab Android 6 abrufen:
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- Fügen Sie diesen Anforderungscode zu Aktivität oder Fragment hinzu:
companion object{const val PERMISSIONS_REQUEST_READ_SMS =100}
override fun onRequestPermissionsResult(
requestCode:Int, permissions:Array<outString>,
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 ")}}}}
Um die SMS zu lesen, habe ich eine Funktion geschrieben, die ein Conversation-Objekt zurückgibt:
classConversation(val number:String, val message:List<Message>)classMessage(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 }asArrayList<Conversation>}
completion(results)}
Antworten:
Verwenden Sie Content Resolver ( "content: // sms / inbox" ), um SMS zu lesen, die sich im Posteingang befinden.
Bitte fügen Sie die READ_SMS- Berechtigung hinzu.
Ich hoffe, es hilft :)
quelle
moveToFirst
wie ich.Legen Sie die App als Standard-SMS-App fest
Funktion zum Abrufen von SMS
SMS-Klasse ist unten:
Vergessen Sie nicht, die Berechtigung in Ihrer AndroidManifest.xml zu definieren
quelle
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)));
Dies gibt Ihnen 24 Stunden Zeit.mActivity
ist nicht definiert. Was ist das?Es ist ein trivialer Prozess. Sie können ein gutes Beispiel im Quellcode SMSPopup sehen
Untersuchen Sie die folgenden Methoden:
Dies ist die Methode zum Lesen:
quelle
Ab API 19 können Sie dafür die Telefonieklasse verwenden; Da hartgesottene Werte nicht auf allen Geräten Nachrichten abrufen, ändert sich der Inhaltsanbieter Uri von Geräten und Herstellern.
quelle
Dieser Beitrag ist etwas alt, aber hier ist eine weitere einfache Lösung, um Daten zum
SMS
Inhaltsanbieter in Android abzurufen:Verwenden Sie diese Bibliothek: https://github.com/EverythingMe/easy-content-providers
Holen Sie sich alles
SMS
:Jede SMS hat alle Felder, so dass Sie alle Informationen erhalten können, die Sie benötigen:
Adresse, Text, Empfangsdatum, Typ (INBOX, SENT, DRAFT, ..), threadId, ...
Gel alle
MMS
:Gel alle
Thread
:Gel alle
Conversation
:Es funktioniert mit
List
oderCursor
und es gibt eine Beispiel-App, um zu sehen, wie es aussieht und funktioniert.In der Tat gibt es eine Unterstützung für alle Android-Inhaltsanbieter wie: Kontakte, Anrufprotokolle, Kalender, ... Vollständiges Dokument mit allen Optionen: https://github.com/EverythingMe/easy-content-providers/wiki/Android- Anbieter
Hoffe es hat auch geholfen :)
quelle
Schritt 1: Zuerst müssen wir Berechtigungen in Manifest-Dateien wie hinzufügen
Schritt 2: Fügen Sie dann die Service-SMS-Empfängerklasse zum Empfangen von SMS hinzu
Schritt 3: Laufzeitberechtigung hinzufügen
Schritt 4: Fügen Sie diese Klassen in Ihre App ein und testen Sie die Interface-Klasse
SmsReceiver.java
quelle
Es gibt bereits viele Antworten, aber ich denke, allen fehlt ein wichtiger Teil dieser Frage. Bevor wir Daten aus einer internen Datenbank oder ihrer Tabelle lesen, müssen wir verstehen, wie Daten darin gespeichert sind, und dann können wir die Lösung der obigen Frage finden:
Wie kann ich in Android programmgesteuert SMS-Nachrichten vom Gerät lesen?
Also, in Android SMS Tabelle sieht so aus
Wissen Sie, wir können aus der Datenbank auswählen, was wir wollen. In unserem Fall haben wir nur benötigt
Beim Lesen von SMS:
1. Fragen Sie nach Berechtigungen
oder
2. Jetzt geht Ihr Code so
Ich hoffe, dass dieser hilfreich sein wird. Vielen Dank.
quelle
Die Google Play-Dienste verfügen über zwei APIs, mit denen Sie den SMS-basierten Überprüfungsprozess optimieren können
SMS Retriever API
Bietet eine vollautomatische Benutzererfahrung, ohne dass der Benutzer manuell Bestätigungscodes eingeben muss und ohne zusätzliche App-Berechtigungen, und sollte nach Möglichkeit verwendet werden. Es ist jedoch erforderlich, dass Sie einen benutzerdefinierten Hash-Code in den Nachrichtentext einfügen, sodass Sie auch die Kontrolle über die Serverseite haben müssen .
Fordern Sie eine SMS-Bestätigung in einer Android-App an
Führen Sie eine SMS-Überprüfung auf einem Server durch
SMS User Consent API
Erfordert keinen benutzerdefinierten Hash-Code. Der Benutzer muss jedoch die Anforderung Ihrer App genehmigen, auf die Nachricht mit dem Bestätigungscode zuzugreifen. Um die Wahrscheinlichkeit zu minimieren, dass dem Benutzer die falsche Nachricht angezeigt
SMS User Consent
wird, werden Nachrichten von Absendern in der Kontaktliste des Benutzers herausgefiltert.The SMS User Consent API
ist Teil von Google Play Services. Um es zu verwenden, benötigen Sie mindestens eine Version17.0.0
dieser Bibliotheken:Schritt 1: Hören Sie auf SMS-Nachrichten
Die Zustimmung des SMS-Benutzers wartet bis zu fünf Minuten lang auf eingehende SMS-Nachrichten, die einen Einmalcode enthalten. Es werden keine Nachrichten angezeigt, die vor dem Start gesendet wurden. Wenn Sie die Telefonnummer kennen, die den Einmalcode sendet, können Sie die angeben
senderPhoneNumber
, oder wenn Sienull
mit keiner Nummer übereinstimmen.Schritt 2: Fordern Sie die Zustimmung zum Lesen einer Nachricht an
Sobald Ihre App eine Nachricht mit einem Einmalcode erhält, wird diese per Broadcast benachrichtigt. Zu diesem Zeitpunkt haben Sie keine Einwilligung zum Lesen der Nachricht. Stattdessen erhalten Sie eine Einwilligung, mit der Sie
Intent
den Benutzer zur Einwilligung auffordern können. In IhremBroadcastReceiver
zeigen Sie die Eingabeaufforderung mit derIntent
in derextras
. Wenn Sie diese Absicht starten, werden Sie aufgefordert, eine einzelne Nachricht zu lesen. Ihnen wird der gesamte Text angezeigt, den sie mit Ihrer App teilen.Schritt 3: Analysieren Sie den Einmalcode und schließen Sie die SMS-Überprüfung ab
Wenn der Benutzer klickt, ist
“Allow”
es Zeit, die Nachricht tatsächlich zu lesen! Innerhalb vononActivityResult
können Sie den vollständigen Text der SMS-Nachricht aus den Daten erhalten:Sie analysieren dann die SMS-Nachricht und geben den Einmalcode an Ihr Backend weiter!
quelle
4-10 digit alphanumeric code containing at least one number
Können Sie erklären, was das bedeutet? Bedeutet dies, dass die Länge der gesamten Nachricht 4-10 Zeichen nur des SMS-Codes betragen sollte?verändert von:
quelle
Kotlin Code zum Lesen von SMS:
1- Fügen Sie diese Berechtigung zu AndroidManifest.xml hinzu:
2-Erstellen Sie eine BroadCastreceiver-Klasse:
3-SMS-Berechtigung ab Android 6 abrufen:
4- Fügen Sie diesen Anforderungscode zu Aktivität oder Fragment hinzu:
5- Override Check permisstion Ergebnis anfordern Spaß:
quelle
Die einfachste Funktion
Um die SMS zu lesen, habe ich eine Funktion geschrieben, die ein Conversation-Objekt zurückgibt:
Verwenden von:
Oder erhalten Sie nur ein Gespräch mit einer bestimmten Nummer:
quelle