2013-11-21 79 views

回答

57

首先,這需要兩個權限;一個發送短信,一個發送短信。以下內容需要在您的AndroidManifest.xml中,<manifest>標籤之間,但在<application>標籤之外。

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

這些都是非常危險的權限,所以你需要相應地處理他們,如果你的應用程序是在棉花糖(API等級23)或以上運行,並具有23+一targetSdkVersion。有關如何在運行時請求這些權限的信息可在this developer page上找到。


您將需要的Java類位於android.telephony包中;具體爲android.telephony.SmsManagerandroid.telephony.SmsMessage。確保你有兩個正確的導入類。

要發送的短信外發,你將使用的SmsManagersendTextMessage()方法,它具有以下特徵:

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

只有兩個論據都需要在這個方法的調用 - destinationAddresstext;第一個是電話號碼,第二個是消息內容。其餘的可以通過null。例如:

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

保持消息文本比較短是很重要的,因爲如果sendTextMessage()文本長度超過單條信息的字符數限制通常會靜默失敗。


接收和閱讀收到的消息,您將需要註冊與IntentFilter一個BroadcastReceiver"android.provider.Telephony.SMS_RECEIVED"行動。該Receiver可以靜態註冊在清單中,或者在運行時動態地註冊到Context

  • 靜態登記清單中的接收器類將讓您的應用程序接收傳入的消息,即使您的應用程序應該發生收貨前被殺害。然而,它可能需要一些額外的工作來獲得你想要的結果。所述<application>標籤之間:

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

    PackageManager#setComponentEnabledSetting()方法可用於啓用和根據需要禁用此<receiver>

  • 動態註冊上的Context一個接收器的實例可以是一個小更容易管理,代碼明智的,作爲接收器類可以作出關於哪個部件註冊它的內部類,所以具有該組件的部件的直接訪問。但是,這種方法可能不如靜態註冊那樣可靠,因爲一些不同的事情可能會阻止接收器獲得廣播;例如,您的應用程序的進程被終止,用戶遠離註冊Activity

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

    是否記得在適當的時候註銷Receiver。


在接收機的onReceive()方法,實際的消息來作爲附着到Intent作爲額外byte數組的數組。解碼細節因安卓版本而異,但這裏的結果是一個單一的SmsMessage對象,它會包含您之後的電話號碼和消息。

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

在這一點上,你只需在這裏比較number到一個傳遞給sendTextMessage()通話。爲此,建議使用PhoneNumberUtils.compare(),因爲在Receiver中檢索到的數字可能與所處理的格式不同。


注:

  • 示例這裏展示使用一個單一的部分消息,從而爲什麼消息文本應只限於相對短的長度。如果您確實想發送更長的消息,出於某種原因,可以使用sendMultipartTextMessage()方法代替。您需要首先分割文本,使用SmsManager#divideMessage(),並將生成的ArrayList傳遞給該方法,以代替消息String。要在Receiver中重新組合完整的消息,您必須將每個byte[]解碼爲SmsMessage,然後連接消息體。

  • 由於KitKat(API級別19),如果您的應用程序不是默認的消息應用程序,此處使用的消息將由系統和默認應用程序保存到SMS提供程序,因此可用於任何其他使用提供者的應用程序。關於這一點你可以做的事情不多,但如果你真的想避免它,這種技術可以用於數據短信,它不會觸發默認的應用程序,也不會保存到提供商。

    爲此,sendDataMessage()方法被使用,這將需要一個額外的參數short爲(任意的)的端口號,並且該消息被作爲一個byte[]通過,而不是一個String。要過濾的操作是"android.intent.action.DATA_SMS_RECEIVED",過濾器需要數據方案和權限(主機和端口)集。在清單中,它看起來像:

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

    ,並有在IntentFilter類對應的方法來設置這些動態。

    解碼SmsMessage是相同的,但消息byte[]檢索與getUserData(),而不是getMessageBody()

  • 在使用KitKat之前,應用程序負責編寫自己的傳出消息,因此如果您不需要任何記錄,那麼您可以在這些版本上不這樣做。

    傳入的消息可能被攔截,並且它們的廣播在主消息傳遞應用程序可以接收和寫入它們之前中止。爲了實現這一點,過濾器的優先級設置爲最大值,並在接收器中調用abortBroadcast()。在靜態選項中,android:priority="999"屬性被添加到開頭的<intent-filter>標記中。動態地,IntentFilter#setPriority()方法可以做同樣的事情。

    這並非完全可靠,因爲其他應用程序始終有可能比您擁有更高的優先級。

  • 在這些例子中,我省略了Receiver的廣播者許可,部分原因是爲了簡單明瞭,部分原因是因爲事物的性質不會讓你接觸到任何可能造成傷害的欺騙。但是,如果您想要包含此選項,則只需將android:permission="android.permission.BROADCAST_SMS"屬性添加到靜態選項的開頭<receiver>標記中即可。對於動態,請使用registerReceiver()方法的四參數超載,將權限String作爲第三個參數,將null作爲第四個參數。

+7

非常感謝您的詳細,完整的響應。 –

3

Sinch SDK允許您使用Flash呼叫技術驗證用戶的電話號碼。它依靠普通電話網絡,所以如果用戶電話號碼有效,您會收到未接電話。

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

欲瞭解更多信息,你可以看看這個教程:

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

+0

不要只是重新發布什麼版主刪除沒有解決評論。你可以在你的文章中加入[affiliation disclosure](https://stackoverflow.com/help/promotion)嗎?否則,這篇文章也將被刪除爲垃圾郵件。 –