3. 打开数据连接 - OPhone新增接口 DataConnection 介绍
Android 平台默认仅支持一个PDP,即某个时刻只能打开一个数据连接。比如典型的一个用例是,当用户有 WiFi 接入的时候,可以优先使用 WiFi,否则使用移动数据连接(比如GPRS),当有 MMS 等特殊应用需要时,会自动切换到 MMS 专用的连接(很多运营商都会提供专门的 MMS 连接设置,在实际的 2G 网络中也是一个 GPRS 连接),等 MMS 数据收发完毕后再切换回 WiFi 或者是 GPRS 连接。这种设计可以封装并简化连接管理,应用开发者只需要通过设置一个 listener 或者 receiver 来监听 网络的切换以及网络状态的变化即可。
但是这种设计在某些现实环境中可能并不适用,有时候几个应用可能需要独立运行并且同时通过不同的网关从网络侧收发数据。OPhone 平台实现了多 PDP 复用的功能,不同的应用可以根据自身需要,通过 DataConnection 接口打开不同的网络连接,通过这种方式我们就可以在浏览网页的同时接收 MMS。
下面是一段示例代码,我们在代码注释中说明如何使用 DataConnection 的相关接口。
// 进程(注意不是 Activity )空间之内,生命周期与进程相同
DataConnection connection = DataConnection.getInstance();
// 注册一个消息监听接口以便处理打开数据连接成功/失败,以及数据
// 连接状态的变化。注意打开数据连接这一操作是异步的,其结果不会
// 直接返回而是通过这个监听接口来通知应用
conn.setNetworkStatusListener(new NetworkListener());
// 请求系统打开某个数据连接时,需要提供该数据连接的 ID ,也就是这条
// 记录在数据库表中的 ID 。 OMS 平台有预置的几条数据连接,包括
// 中国移动的 cmnet 和 cmwap 网关等,用户也可自行添加其它数据连接,
// 并通过 Settings 提供的相关接口,查询得到某个数据连接记录所对应的
// 数据库表 ID
boolean ret = conn.openConnection(your_app_context, data_connection_id);
// 注意我们在打开数据连接时会关心两种类型的结果,一类是客户端(也就是手机)
// 报的错误,另一类则是网络侧的错误。前者是同步返回的,也就是下边这段代码
// 中应该处理的错误,而后者则是异步(通过上边注册的监听接口)返回的。
if(!ret) {
switch(connection.getErrorCode()) {
case DataConnection.ERROR_PROF_NOT_FOUND:
// 数据库中未找到指定的数据连接 ID
break;
case DataConnection.ERROR_NO_SIGNAL:
// 这个错误的原因与其字面意思可能不是很相符,具体发生这个错误
// 的原因除了手机无信号之外,可能还包括软件 RIL 层产生的内部逻辑错误
break;
case DataConnection.ERROR_AIRPLANE_MODE:
// 飞行模式下无法打开数据连接
break;
default:
// 未明原因的错误
break;
}
}
以下是一个典型的数据连接监听接口,需要实现两个接口来分别处理打开数据连接的(异步)返回结果,以及数据连接的状态变化。由于这些回调函数都不是运行在应用的主线程(即通常情况下的 UI 线程)中的,所以最好通过 android.os.Handler 的 post 接口将相应的处理函数挂到 Activity 的缺省消息队列中去,通过这种方式就可以让自己的处理函数在主线程中得到执行了。
...
};
private class NetworkListener implements
DataConnection.OnNetworkStatusListener {
public NetworkListener() { }
public void onOpenResult(boolean success) {
mHandler.post(your_runnable_handler_1);
}
public void onStatusChanged(int status) {
mHandler.post(your_runnable_handler_2);
}
}
// 比较典型的一个监听接口如下所示,我们在这个接口中通过前边介绍的
// HttpClient 从网络侧读取数据
class your_runnable_handler_1 implements Runnable {
public void run() {
try {
HttpClient httpClient = new HttpClient();
GetMethod getMethod = new GetMethod
("http://www.test_test.com/");
httpClient.getHttpConnectionManager().
getParams().setConnectionTimeout(3000);
getMethod.getParams().setParameter
(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
int statusCode = client.executeMethod(getMethod);
if (statusCode != HttpStatus.SC_OK) {
// 错误处理
}
Header[] headers=getMethod.getResponseHeaders();
byte[] responseBody = getMethod.getResponseBody();
} catch (Exception ee) {
//
} finally {
// 释放连接
getMethod.releaseConnection();
}
}
}
// 当不再使用该数据连接时,应该将其关闭。
DataConnection.getInstance().closeConnection();
关于数据连接的更详细信息和其它接口更参考 OPhone 的 SDK 文档。在OPhone平台上,某一个数据连接是通过引用计数来进行不同应用之间的复用的,具体的一个用例是,假设有3个应用A,B,C需要打开同一个数据连接,那么系统只会在第一个请求时激活 PDP ,同时在最后一个关闭请求时在去激活这个 PDP ,以此保证3个应用都能无缝使用这个数据连接。当应用忘记通知系统关闭数据连接时,系统会通过 Android binder 的机制在应用的进程退出时自动为其减少一个引用计数,以保证 PDP 被正确去激活。
使用OPhone 数据连接的另外一个作用是能够保证应用在多 PDP 的情况下能通过正确的网络设备(这种情况下一般存在一个以上的网络设备)与网络侧通信。没有调用OPhone数据连接的应用理论上也能在 PDP 已激活的情况下与网络侧通信,只是这些通信只能依赖于平台的缺省路由机制。