SmsManager(簡訊管理器)


本節引言:

本節帶來的是Android中的SmsManager(短利管理器),見名知意,就是用來管理手機簡訊的, 而該類別的應用程式場景不多,通常是我們傳簡訊的時候才會用到這個API,當然這種簡訊是 文字短信,對於彩信過於複雜,而且在QQ微信各種社交APP橫行的年代,你會去發1塊錢一條的 彩信嗎?所以本節我們只討論發送普通文字簡訊! 官方文件:SmsManager


1.呼叫系統發送簡訊功能:

就是把寫好的收信人和內容傳送到系統的發送簡訊的介面,使用者驗證收件者內容是否真正確再點擊發送! 說穿了就是呼叫系統發短信的視窗,這樣做有一定的好處:

這樣發短信,app安裝的時候就可以少寫一條發短信的權限,那麼諸如360這類安全軟體在安裝的時候 就不會提醒用戶:"這個APP有短信權限,可能會偷偷滴發短信喔",而用戶對於偷偷發短信的行為是十分 厭惡的,當然有些人不看直接安裝,而有些人可能會覺得會偷偷發短信喔,好噁心的應用,我才不裝咧, 又或者直接禁止我們的APP發送短信,那麼當我們APP在發送短信的時候就可能會出現一些異常,或者 應用直接崩潰等!所以如果你的應用需要發送簡訊進行驗證或付費這些東西的話,建議使用這種方式!

核心代碼

public void SendSMSTo(String phoneNumber,String message){    
    //判断输入的phoneNumber是否为合法电话号码  
    if(PhoneNumberUtils.isGlobalPhoneNumber(phoneNumber)){  
        //Uri.parse("smsto") 这里是转换为指定Uri,固定写法  
        Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.parse("smsto:"+phoneNumber));        
        intent.putExtra("sms_body", message);              
        startActivity(intent);    
    }    
}

2.呼叫系統提供的簡訊介面發送簡訊

這個就需要發簡訊的權限啦

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

我們直接呼叫SmsManager為我們提供的簡訊介面傳送簡訊:

sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliverIntent);

參數依序是:

  • destinationAddress:收信人的電話號碼
  • scAddress:簡訊中心的號碼,null的話使用目前預設的簡訊服務中心
  • text:簡訊內容
  • sentIntent:簡訊傳送狀態的訊息:(傳送狀態的Intent) 如果不為null,當訊息成功發送或失敗這個PendingIntent就廣播。結果代碼是Activity.RESULT_OK 表示成功,或RESULT_ERROR_GENERIC_FAILURE、RESULT_ERROR_RADIO_OFF、RESULT_ERROR_NULL_PDU 之一表示錯誤。對應RESULT_ERROR_GENERIC_FAILURE,sentIntent可能包括額外的"錯誤代碼"包含一 個無線電廣播技術特定的值,通常只在修復故障時有用。每一個基於SMS的應用程式控制檢測sentIntent。 如果sentIntent是空,呼叫者將檢測所有未知的應用程序,這將導致在檢測的時候發送較小數量的SMS。
  • deliverIntent:簡訊是否被對方收到的狀態訊息:(接收狀態的Intent) 如果不為null,當這個簡訊發送到接收者那裡,這個PendtingIntent會被廣播, 狀態報告產生的pdu(指對等層次之間傳遞的資料單位)會拓展到資料("pdu")

1.jpg...那麼複雜,pdu是什麼卵?好吧,別糾結,簡單知道這些參數是:

電話號碼,訊息中心,簡訊內容,是否發送成功的監聽,以及收信人是否接受的監聽就好了!

核心代碼

public void sendSMS(String phoneNumber,String message){  
    //获取短信管理器   
    android.telephony.SmsManager smsManager = android.telephony.SmsManager.getDefault();  
    //拆分短信内容(手机短信长度限制),貌似长度限制为140个字符,就是
    //只能发送70个汉字,多了要拆分成多条短信发送
    //第四五个参数,如果没有需要监听发送状态与接收状态的话可以写null    
    List divideContents = smsManager.divideMessage(message);   
    for (String text : divideContents) {    
        smsManager.sendTextMessage(phoneNumber, null, text, sentPI, deliverPI);    
    }  
}

可能你還需要監聽簡訊是否發送成功,或是收信者是否接收到訊息,就把下面的加上吧:

1)處理傳回傳送狀態的sentIntent

//处理返回的发送状态   
String SENT_SMS_ACTION = "SENT_SMS_ACTION";  
Intent sentIntent = new Intent(SENT_SMS_ACTION);  
PendingIntent sentPI = PendingIntent.getBroadcast(context, 0, sentIntent,  0);  
//注册发送信息的广播接收者
context.registerReceiver(new BroadcastReceiver() {  
    @Override  
    public void onReceive(Context _context, Intent _intent) {  
        switch (getResultCode()) {  
        case Activity.RESULT_OK:
            Toast.makeText(context, "短信发送成功", Toast.LENGTH_SHORT).show();  
            break;  
        case SmsManager.RESULT_ERROR_GENERIC_FAILURE:    //普通错误
            break;
        case SmsManager.RESULT_ERROR_RADIO_OFF:         //无线广播被明确地关闭
            break;          
        case SmsManager.RESULT_ERROR_NULL_PDU:          //没有提供pdu
            break;      
        case SmsManager.RESULT_ERROR_NO_SERVICE:         //服务当前不可用
            break;              
        }  
    }  
}, new IntentFilter(SENT_SMS_ACTION));

2)處理傳回接收狀態的deliverIntent

//处理返回的接收状态   
String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";  
//创建接收返回的接收状态的Intent  
Intent deliverIntent = new Intent(DELIVERED_SMS_ACTION);  
PendingIntent deliverPI = PendingIntent.getBroadcast(context, 0,deliverIntent, 0);  
context.registerReceiver(new BroadcastReceiver() {  
   @Override  
   public void onReceive(Context _context, Intent _intent) {  
       Toast.makeText(context,"收信人已经成功接收", Toast.LENGTH_SHORT).show();  
   }  
}, new IntentFilter(DELIVERED_SMS_ACTION));

另外這裡涉及到了廣播的知識,如果你對廣播不怎麼了解的話,可以看下:

Android基礎入門教程——BroadcastReceiver牛刀小試

Android基礎入門教學-4.3.2 BroadcastReceiver廬丁解牛


#本節小結:

2.gif好的,本節介紹了SmsManager發送文字簡訊的兩種方式~非常簡單~建議還是使用 第一種方案吧,起碼用戶體驗好一點...