2013-11-21 19 views

Antwort

57

Zu Beginn benötigt dies zwei Berechtigungen; eine zum Senden von SMS-Nachrichten und eine zum Empfangen von SMS-Nachrichten. Folgendes muss in Ihrer AndroidManifest.xml zwischen den <manifest> Tags, aber außerhalb der <application> Tags sein.

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

Diese sind beide gefährlich Berechtigungen, damit Sie sie entsprechend müssen behandeln, wenn Ihre Anwendung auf Eibisch (API-Ebene 23) oder darüber und eine targetSdkVersion von 23+ hat laufen soll. Informationen dazu, wie Sie diese Berechtigungen zur Laufzeit anfordern, finden Sie unter this developer page.


Die Java-Klassen, die Sie sind in der android.telephony Paket müssen; speziell android.telephony.SmsManager und android.telephony.SmsMessage. Stellen Sie sicher, dass Sie die richtigen Klassen für beide importiert haben.

die abgehende SMS zu senden, werden Sie SmsManager ‚s sendTextMessage() Methode, die hat die folgende Signatur verwenden:

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

nur zwei Argumente erforderlich sind, in diesem Methodenaufruf - destinationAddress und text; Die erste ist die Telefonnummer, die zweite ist der Inhalt der Nachricht. null kann für den Rest übergeben werden. Zum Beispiel:

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

Es ist wichtig, den Nachrichtentext relativ kurz zu halten, wie sendTextMessage() wird in der Regel unbemerkt fehlschlagen, wenn die Textlänge die maximale Zeichenanzahl für eine einzelne Nachricht überschreitet.


zu erhalten und die eingehende Nachricht zu lesen, werden Sie eine BroadcastReceiver mit einem IntentFilter für die "android.provider.Telephony.SMS_RECEIVED" Aktion registrieren müssen. Dieser Empfänger kann entweder statisch im Manifest oder dynamisch auf einem Context zur Laufzeit registriert werden.

  • Statisch Registrierung der Empfängerklasse im Manifest können Sie Ihre App die eingehende Nachricht, auch wenn Ihre App erhalten sollte vor Eingang getötet werden passieren. Es kann jedoch ein wenig mehr Arbeit erfordern, um die Ergebnisse dort zu erhalten, wo Sie sie haben wollen. Zwischen den <application> tags:

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

    Die PackageManager#setComponentEnabledSetting() Methode kann diese <receiver> nach Bedarf zu aktivieren und deaktivieren verwendet werden.

  • Die dynamische Registrierung einer Empfängerinstanz auf einer Context kann etwas einfacher zu verwalten sein, da die Receiver-Klasse zu einer inneren Klasse für die jeweils registrierte Komponente gemacht werden kann und direkten Zugriff auf die Mitglieder dieser Komponente hat . Dieser Ansatz ist jedoch möglicherweise nicht so zuverlässig wie die statische Registrierung, da einige wenige Dinge verhindern könnten, dass der Empfänger die Übertragung erhält. Beispiel: Der Prozess Ihrer App wird beendet, der Benutzer navigiert von der Registrierung Activity usw.

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

    Denken Sie daran, den Empfänger bei Bedarf abzumelden.


In dem onReceive() Methode des Empfängers kommt die eigentliche Nachricht als ein Array von Arrays byte zum Intent als extra befestigt. Die Decodierungsdetails variieren je nach Android-Version, aber das Ergebnis ist ein einzelnes SmsMessage Objekt, das die Telefonnummer und die Nachricht haben wird, nach der Sie suchen.

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(); 
     ... 
    } 
} 

An diesem Punkt vergleichen Sie einfach die number hier auf die an den sendTextMessage() Aufruf übergeben ein. Es empfiehlt sich, hierfür PhoneNumberUtils.compare() zu verwenden, da die im Empfänger abgerufene Nummer möglicherweise ein anderes als das adressierte Format aufweist.


Hinweise:

  • Das Beispiel demonstriert ein Einzelteil-Nachricht mit, so warum der Nachrichtentext auf eine relativ kurze Länge beschränkt werden sollte. Wenn Sie aus irgendeinem Grund eine längere Nachricht senden möchten, kann stattdessen die Methode sendMultipartTextMessage() verwendet werden. Sie müssten den Text zuerst unter Verwendung von SmsManager#divideMessage() aufteilen und das Ergebnis ArrayList anstelle der Meldung String an diese Methode übergeben. Um die gesamte Nachricht im Empfänger wieder zusammenzusetzen, müssten Sie alle byte[] in eine SmsMessage decodieren und die Nachrichtentexte verketten.

  • Da KitKat (API-Stufe 19), wenn Ihre App nicht die Standard-Messaging-App ist, werden die hier verwendeten Nachrichten vom System und der Standard-App im SMS-Anbieter gespeichert und sind daher für alle verfügbar andere App, die den Provider verwendet. Es gibt nicht viel, was Sie dagegen tun können, aber wenn Sie es wirklich vermeiden möchten, kann die gleiche Technik mit Daten-SMS verwendet werden, die die Standard-App nicht auslösen und nicht auf dem Provider gespeichert werden.

    Hierzu wird die sendDataMessage() Methode verwendet, die für die (beliebige) Port-Nummer ein zusätzliches short Argument benötigt, und die Nachricht als byte[] geben wird, sondern als ein String. Die zu filternde Aktion ist "android.intent.action.DATA_SMS_RECEIVED", und der Filter benötigt ein Datenschema und eine Berechtigung (Host und Port). In dem Manifest, würde es wie folgt aussehen:

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

    und es gibt entsprechende Methoden in der Klasse IntentFilter diejenigen dynamisch einzustellen.

    die SmsMessage Decodierung ist die gleiche, aber die Nachricht byte[] mit getUserData() abgerufen, anstatt getMessageBody().

  • Vor KitKat waren Apps dafür verantwortlich, dass sie ihre eigenen ausgehenden Nachrichten verfassten. Das kann man auf diesen Versionen einfach nicht tun, wenn man keine Aufzeichnungen davon haben möchte.

    Eingehende Nachrichten konnten abgefangen und ihre Übertragungen abgebrochen werden, bevor die Hauptnachrichten-App sie empfangen und schreiben konnte. Um dies zu erreichen, wird die Priorität des Filters auf den Höchstwert gesetzt, und abortBroadcast() wird im Empfänger aufgerufen.In der statischen Option wird das Attribut android:priority="999" zum öffnenden Tag <intent-filter> hinzugefügt. Dynamisch kann die IntentFilter#setPriority() Methode dasselbe tun.

    Dies ist überhaupt nicht zuverlässig, da es immer möglich ist, dass eine andere App eine höhere Priorität hat als Ihre.

  • Ich habe es versäumt, den Receiver in diesen Beispielen mit der Erlaubnis des Senders zu sichern, teils aus Gründen der Einfachheit und Klarheit, teils weil die Natur der Sache nicht wirklich für Spoofing offen ist, das Schaden anrichten könnte . Wenn Sie dies jedoch hinzufügen möchten, müssen Sie lediglich das Attribut android:permission="android.permission.BROADCAST_SMS" zum öffnenden Tag <receiver> für die statische Option hinzufügen. Verwenden Sie für die Dynamik die Vier-Parameter-Überladung der registerReceiver()-Methode, übergeben Sie diese Berechtigung String als drittes Argument und null als die vierte.

+7

Vielen Dank für die ausführliche und vollständige Antwort. –

3

Mit dem SDK von Sinch können Sie die Telefonnummer des Benutzers mithilfe der Flash-Anruf-Technologie überprüfen. Es beruht auf dem normalen Telefonnetz. Wenn die Telefonnummer des Benutzers gültig ist, erhalten Sie einen verpassten Anruf.

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(); 
} 

Für weitere Informationen können Sie in diesem Tutorial sehen:

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

+0

Repotieren Sie nicht einfach, was ein Moderator gelöscht hat, ohne den Kommentar zu adressieren. Können Sie bitte eine [Affiliation-Offenlegung] (https://stackoverflow.com/help/promotion) in Ihren Beitrag aufnehmen? Ansonsten wird auch dieser Beitrag als Spam gelöscht. –

Verwandte Themen