在Android系统中,SUPL(Secure User Plane Location)是一种用于辅助GPS定位的技术,它通过建立特定的APN(Access Point Name)连接来传输定位数据。
以下介绍Android Telephony发起SUPL APN的PDN(Packet Data Network)建立的详细过程。
SUPL APN通常由运营商在SIM卡中配置,或者在设备的APN设置中手动配置。
APN配置包括以下关键信息:
supl
。supl
。当应用需要使用SUPL服务时(例如,使用GPS定位),Android的定位服务(如LocationManager
)会请求建立SUPL连接。
Telephony层是Android系统中负责管理电话功能的核心模块,包括SIM卡管理、网络连接、通话状态等。
Telephony层负责处理APN的连接请求。主要流程描述如下:
检查当前网络状态:
default
APN)。创建APN连接请求:
DataConnection
对象,用于管理APN连接。发送连接请求到RIL(Radio Interface Layer):
RIL层负责与基带处理器通信,执行实际的PDN连接建立过程。
发送PDN连接请求:
RIL_REQUEST_SETUP_DATA_CALL
请求,包含APN配置信息。处理基带处理器的响应:
DataCallResponse
对象,包含连接的相关信息(如IP地址、DNS服务器等)。Telephony层接收到RIL的响应后,会进行以下处理:
更新连接状态:
DataConnection
对象的状态,标记为已连接。配置网络路由:
以下是一个简化的时序图,展示了SUPL APN的PDN建立过程:
应用层 -> Telephony层: 请求建立SUPL连接
Telephony层 -> RIL层: 发送PDN连接请求 (RIL_REQUEST_SETUP_DATA_CALL)
RIL层 -> 基带处理器: 发送PDN连接请求
基带处理器 -> 网络: 协商建立PDN连接
网络 -> 基带处理器: 返回PDN连接响应
基带处理器 -> RIL层: 返回DataCallResponse
RIL层 -> Telephony层: 返回PDN连接响应
Telephony层 -> 应用层: 通知SUPL连接已建立
以下是一些关键代码示例,展示了如何在Android Telephony中发起SUPL APN的PDN建立:
TelephonyManager
:提供访问设备电话功能的接口。SubscriptionManager
:管理设备的SIM卡订阅信息。DataConnection
:管理数据连接(如APN连接)的状态和配置。Phone
:表示一个电话实例,管理通话、数据连接等功能。DcTracker
:数据连接跟踪器,负责管理数据连接的建立、断开等操作。以下是Telephony层处理SUPL APN建立的主要步骤:
获取TelephonyManager实例:
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
检查设备是否支持双卡:
if (telephonyManager.getPhoneCount() > 1) {
// 设备支持双卡
}
获取SubscriptionManager实例:
SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
获取所有活跃的订阅信息:
List<SubscriptionInfo> subscriptionInfos = subscriptionManager.getActiveSubscriptionInfoList();
// 创建APN配置
ApnSetting apnSetting = new ApnSetting(
id, // ID
"supl", // APN名称
null, // Proxy
-1, // Port
null, // MMSC
null, // MMS Proxy
-1, // MMS Port
"supl", // APN类型
ApnSetting.PROTOCOL_IP, // 协议
ApnSetting.PROTOCOL_IP, // 漫游协议
true, // 启用状态
0, // 网络类型
true, // 可承载
false, // 漫游时启用
0, // 用户可见
null, // 用户
null, // 密码
0 // 认证类型
);
// 发起PDN连接请求
DataConnection dataConnection = new DataConnection(context, phone, apnSetting);
dataConnection.connect();
Note:在旧版本的Android上,是在DcTracker
中,调用setupDataCall
方法发起数据连接请求。(Android T/U已经不使用)
DcTracker dcTracker = phone.getDcTracker();
dcTracker.setupDataCall(apnSetting);
DcTracker
会监听数据连接的状态变化,并通过回调通知上层应用。
dcTracker.registerForDataStateChanged(handler, EVENT_DATA_STATE_CHANGED);
新版本在 DataNetwork
中注册监听(以下是Android V的代码案例)
for (int transport : mAccessNetworksManager.getAvailableTransports()) {
mDataServiceManagers.get(transport)
.registerForDataCallListChanged(getHandler(), EVENT_DATA_STATE_CHANGED);
}
RIL层是Android系统中负责与基带处理器通信的模块。它将Telephony层的请求转换为基带处理器可以理解的指令,并处理基带处理器的响应。
RIL
:实现与基带处理器的通信。RILRequest
:表示一个RIL请求。RILConstants
:定义RIL请求和响应的常量。DataCallResponse
:表示数据连接的响应。以下是RIL层处理SUPL APN建立的主要步骤:
RIL
中,创建一个RIL_REQUEST_SETUP_DATA_CALL
请求。RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
rr.mParcel.writeInt(radioTechnology);
rr.mParcel.writeString(apn);
rr.mParcel.writeString(protocol);
send(rr);
DataCallResponse
对象,包含连接的相关信息。DataCallResponse response = new DataCallResponse();
response.status = parcel.readInt();
response.suggestedRetryTime = parcel.readInt();
response.cid = parcel.readInt();
response.active = parcel.readInt();
response.type = parcel.readString();
response.ifname = parcel.readString();
response.addresses = parcel.readStringArray();
response.dnses = parcel.readStringArray();
response.gateways = parcel.readStringArray();
DataCallResponse
对象返回给Telephony层。if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, response, null);
rr.mResult.sendToTarget();
}
// 上层处理PDN连接响应
void onDataCallResponse(DataCallResponse response) {
if (response.status == DataCallResponse.STATUS_SUCCESS) {
// 更新连接状态
updateConnectionState(ConnectionState.CONNECTED);
// 配置网络路由
configureNetworkRouting(response);
// 通知上层应用
notifySuplConnectionEstablished();
} else {
// 处理连接失败
handleConnectionFailure(response);
}
}
ACCESS_FINE_LOCATION
、INTERNET
等。通过以上步骤,Android Telephony可以成功发起SUPL APN的PDN建立,从而支持SUPL定位服务。
// 获取TelephonyManager实例
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
// 检查设备是否支持双卡
if (telephonyManager.getPhoneCount() > 1) {
// 获取SubscriptionManager实例
SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
// 获取所有活跃的订阅信息
List<SubscriptionInfo> subscriptionInfos = subscriptionManager.getActiveSubscriptionInfoList();
// 创建APN配置
ApnSetting apnSetting = new ApnSetting(
id, // ID
"supl", // APN名称
null, // Proxy
-1, // Port
null, // MMSC
null, // MMS Proxy
-1, // MMS Port
"supl", // APN类型
ApnSetting.PROTOCOL_IP, // 协议
ApnSetting.PROTOCOL_IP, // 漫游协议
true, // 启用状态
0, // 网络类型
true, // 可承载
false, // 漫游时启用
0, // 用户可见
null, // 用户
null, // 密码
0 // 认证类型
);
// 发起数据连接请求
DcTracker dcTracker = phone.getDcTracker();
dcTracker.setupDataCall(apnSetting);
}
// 创建RIL请求
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
// 发送RIL请求
rr.mParcel.writeInt(radioTechnology);
rr.mParcel.writeString(apn);
rr.mParcel.writeString(protocol);
send(rr);
// 处理基带处理器的响应
DataCallResponse response = new DataCallResponse();
response.status = parcel.readInt();
response.suggestedRetryTime = parcel.readInt();
response.cid = parcel.readInt();
response.active = parcel.readInt();
response.type = parcel.readString();
response.ifname = parcel.readString();
response.addresses = parcel.readStringArray();
response.dnses = parcel.readStringArray();
response.gateways = parcel.readStringArray();
// 返回响应给Telephony层
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, response, null);
rr.mResult.sendToTarget();
}
在Android系统中,SUPL(Secure User Plane Location)协议的主要目的是辅助GPS定位,以提高定位的速度和精度。当SUPL APN的PDN建立成功后,设备可以通过SUPL协议从网络获取辅助数据(A-GPS数据),并结合GPS模块获取精确的定位信息。以下是详细的解释:
SUPL PDN建立后,设备可以通过以下方式获取定位信息:
以下是SUPL PDN建立后,设备获取定位信息的典型流程:
SUPL PDN建立:
请求A-GPS辅助数据:
GPS模块初始化:
GPS定位计算:
返回定位信息:
根据定位方式的不同,设备可能返回以下类型的定位信息:
LocationManager
的GPS_PROVIDER
获取。LocationManager
的NETWORK_PROVIDER
获取。LocationManager
的FUSED_PROVIDER
获取(需要Google Play服务支持)。以下是通过LocationManager
获取定位信息的代码示例:
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// 监听GPS定位
LocationListener gpsListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
double latitude = location.getLatitude(); // 纬度
double longitude = location.getLongitude(); // 经度
double altitude = location.getAltitude(); // 海拔
float speed = location.getSpeed(); // 速度
float bearing = location.getBearing(); // 方向
Log.d("GPS Location", "Lat: " + latitude + ", Lon: " + longitude);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {}
};
// 请求GPS定位更新
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, gpsListener);
LocationListener networkListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
double latitude = location.getLatitude(); // 纬度
double longitude = location.getLongitude(); // 经度
Log.d("Network Location", "Lat: " + latitude + ", Lon: " + longitude);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onProviderDisabled(String provider) {}
};
// 请求网络定位更新
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 0, networkListener);
以下是SUPL PDN建立后,设备获取定位信息的时序图:
设备 -> SUPL服务器: 建立SUPL PDN连接
设备 -> SUPL服务器: 请求A-GPS辅助数据
SUPL服务器 -> 设备: 返回A-GPS辅助数据
设备 -> GPS模块: 初始化GPS模块
GPS模块 -> 卫星: 接收卫星信号
GPS模块 -> 设备: 计算并返回GPS定位信息
设备 -> 应用层: 返回定位信息(经纬度等)
通过SUPL协议和GPS模块的结合,Android设备可以快速、准确地获取设备的精确位置信息。