现在的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
只能管理监听系统的网络状态信息,因此只在连接管理类中判断联网方式时有所涉及,故数据流量的相关功能操作不再单独过多介绍。