現在的SIM卡通常具備基站定位、語音通話、短信消息、網絡流量這四大功能,而在移動端是無法對SIM卡使用基站定位功能的,所以這里只介紹移動端如何使用SIM卡實現語音通話、短信消息、數據流量三個功能。
語音通話
Android系統中提供了通話服務,同時自帶系統級應用可以通過該通話服務使用SIM卡的通話功能。因此在第三方應用中使用語音通話功能,有兩種思路。其一是通過應用間喚起,由第三方應用傳入指定的Intent
意圖對象調起系統電話應用,之后在系統電話應用操作完成后返回第三方應用;其二是在第三方應用中直接調用通話服務相關接口,通話服務可實現自定義通話界面、語音通話和保存歷史通話信息等功能。
應用間喚起方式
喚起系統的電話應用,有兩種等價方式,其一是將指定的意圖對象傳入startActivtiy(Intent intent)
中,其二是通過android.telecom.TelecomManager電話管理類的相關方法調用,獲取TelecomManager
對象的方式是通常調用Context
對象的getSystemService(String name)
方法,傳入參數 name 值為Context.TELECOM_SERVICE="telecom"
得到的返回值。方式一是對方式二的代碼封裝。
權限聲明
需要在清單文件中聲明撥打電話權限,其值為Manifest.permission.CALL_PHONE="android.permission.CALL_PHONE"
。該權限為 dangerous 級權限,因此在Android6.0即API 23及之后的版本中,還需要在喚起系統電話應用之前動態申請該權限。
喚起流程
在調用startActivity(Intent intent)
方法時,傳入的參數 intent 必須設置其 action 行為值為Intent.ACTION_CALL。如果需要輸入電話號碼,可以設置其 data 數據值為Uri.parse(String str)
的生成結果,其中參數 str 便是以"tel:"
起始加電話號的字符串結構。另外還可以對 intent 設置額外數據,其鍵值在TelecomManager
中均以常量形式定義。
如果使用TelecomManager
通話管理類對象,則是調用該對象的placeCall(Uri address, Bundle extras)
,該方法中的參數 address 即使用第三方應用喚醒系統通話時傳入意圖中的數據參數 data 值;而參數 extras 同樣是第三方應用喚醒系統通話時傳入意圖中的額外數據。
自定義界面實現通話服務
主要是自定義Service
服務實現android.telecom.ConnectionService語音通話連接服務類。
使用通話服務,首先要在清單文件中聲明通話的四大權限,包括管理通話權限Manifest.permission.MANAGE_OWN_CALLS="android.permission.MANAGE_OWN_CALLS"
,讀取通話記錄權限Manifest.permission.READ_CALL_LOG="android.permission.READ_CALL_LOG"
,讀取通話狀態權限Manifest.permission.READ_PHONE_STATE="android.permission.READ_PHONE_STATE"
,讀取電話號碼權限Manifest.permissions.READ_PHONE_NUMBERS="android.permissions.READ_PHONE_NUMBERS"
。
還要在清單文件中注冊自定義的Service
服務,在<service></service>
標簽中聲明該服務所使用的權限為Manifest.permission.BIND_TELECOM_CONNECTION_SERVICE="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
綁定通話連接服務權限,同時設置其意圖過濾標簽<intent-filter></intent-filter>
中的行為標簽<action>
值必須為"android.telecom.ConnectionService"
,該意圖行為與系統通話服務一致,因此在該應用中收到該意圖后,系統將會調用該應用中的自定義通話連接服務。
之后就是自定義的ConnectionService
通話連接服務中的代碼了,在該類中主要重寫兩個方法,包括去電時的回調方法onCreateOutgoingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)
,盒來電時的回調方法onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request)
。這兩個方法都會在最后返回android.telecom.Connection通話連接類的對象。
在自定義的Connection
通話連接類中,可以重寫在通話過程中的不同狀態發生變化時的相關回調方法,包括接聽來電方法onAnswer()
,拒接來電方法onReject()
,保持通話方法onHold()
,恢復通話方法onUnhold()
,掛斷通話方法onDisconnect()
等。
短信消息
Android系統中同樣提供了短信服務,也帶有一款系統級應用可以使用SIM卡的短信消息功能。因此在第三方應用中使用短信功能,同樣有兩種思路。與上文的語音通話功能實現類似,其一是通過應用間喚起的方式,調起系統短信應用.其二是在第三方應用中直接調用短信廣播接收器,短信廣播接收器可實現及時接收短信內容相關功能。
應用間喚起方式
喚起系統的短信應用,有兩種等價方式,其一是將指定的意圖對象傳入startActivtiy(Intent intent)
中,其二是通過android.telephony.SmsManager短信管理類,直接調用相關短信接口。獲取SmsManager
對象的方式,在Android12即API 31級別以前是通過調用單例模式的靜態方法SmsManager.getDefault()
直接獲取,而從Android12開始改用Context
對象的getSystemService(Class<T> serviceClass)
傳入參數 serviceClass 值為SmsManager.class
返回得到的對象。這里的方式一同樣也是對方式二的代碼封裝。
權限聲明
需要在清單文件中聲明發送短信權限,其值為Manifest.permission.SEND_SMS="android.permission.SEND_SMS"
。該權限為 dangerous 級權限,因此在Android6.0即API 23及之后的版本中,還需要在喚起系統短信應用之前動態申請該權限。
喚起流程
在調用startActivity(Intent intent)
方法時,傳入的參數 intent 必須設置其 action 行為值為Intent.ACTION_SENDTO。如果需要輸入接收方的電話號碼,可以設置其 data 數據值為Uri.parse(String str)
的生成結果,其中參數 str 便是以"smsto:"
起始加電話號的字符串結構。另外還可以對 intent 設置額外數據,其鍵值在SmsManager
中均以常量形式定義。
如果使用SmsManager
短信管理類對象,則是調用該對象的sendTextMessage(String destinationAddress, String scAddress, String text, PendingIntent sentIntent, PendingIntent deliveryIntent)
及其他相關方法發送消息,在該方法中,參數 destinationAddress 即接收方的地址,參數 scAddress 是使用的服務器中心地址,通常為值為null
表示使用默認的電信中心服務器,參數 text 為發送的消息體內容,通常一條短信長度為70字節,參數 sentIntent 非空時,將會在短信發送之后回調注冊該意圖的組件,參數 deliveryIntent 非空時,將會在短信發送給接收方之后回調注冊該意圖的組件。
自定義界面實現短信服務
主要是自定義BroadcastReceiver
廣播接收器,實現短信接收實時監聽功能。
首先要在清單文件中聲明短信接收權限Manifest.permission.RECEIVE_SMS="android.permission.RECEIVE_SMS"
還要在清單文件中注冊自定義的BroadcastReceiver
廣播接收器,在<receiver></receiver>
標簽內部,設置其意圖過濾標簽<intent-filter></intent-filter>
中的行為標簽<action>
值必須為"android.provider.Telephony.SMS_RECEIVED"
,該意圖行為與系統短信一致,因此在該應用中收到該意圖后,系統發送的廣播將會由該應用中的廣播接收器接收到。
最后在自定義的BroadcastReceiver
中,實現onReceiver(Context context, Intent intent)
方法,在該方法中處理接收到廣播之后的操作。接收到的短信數據以Protocol Description Unit數據額外數據形式保存在參數 intent 中,可以調用android.provider.Telephony.Sms.Intents.getMessagesFromIntent(Intent intent)靜態方法,得到android.telephony.SmsMessage短消息類型。在SmsMessage
中便可查看收到的消息內容等信息。
數據流量
數據流量作為聯網方式之一,與WLAN聯網一起,都可以在android.net.ConnectivityManager連接管理類中操作管理。而由於ConnectivityManager
只能管理監聽系統的網絡狀態信息,因此只在連接管理類中判斷聯網方式時有所涉及,故數據流量的相關功能操作不再單獨過多介紹。