我们开发了一款Android聊天室应用演示,使用了AppWarp(译注:Appwarp 是创建实时多用户游戏的跨平台网络引擎),而AppWarp引擎阐明了怎样处理间歇性的网络链接故障。这个演示用到了AppWarp的具有网络弹性的API。
为什么需要网络弹性: 在移动设备中,数据连接一直是一个问题。 当用户在移动中,数据源将经常切换基站,或者在2G和3G之间降级/升级,或切换WiFi,或由于屏幕锁定或用户按下home键使得应用程序切换到后台运行。 这对依赖持续数据连接的应用程序/游戏带来影响。AppWarp 提供了 强大的功能 来处理 网络弹性 问题, 用户可以通过它 在 连接丢失的 情况下,保持 应用 之前的 状态 。
包含两个 Activities 的应用
MainActivity: Main Activity 允许用户连接到AppWarp服务端。用户输入他们的名字然后连接到AppWarp服务器。为了启用弹性特性(Resiliency Feature),你应该在初始化WarpClient之后设置默认恢复间隔(Recovery Allowance interval):
这会告诉服务器默认恢复时间间隔,在这个时间内,即使在连接丢失的情况下,服务端也不会销毁用户session。我们用AppHq 控制台创建了一个静态变量room。一旦连接并注册到这个room,我们就转向ChatActivity。
ChatActivity.java 这个 Activity 包含了发送/接收聊天逻辑,并且也管理聊天日志。上半部分包含了同一个room中参与用户的列表。绿色的状态指示意思是用户在线,灰色的意思是暂停(临时连接错误)。屏幕下半部分包含了用户发送的聊天记录。在这个activity的启动后,要想获取房间中的在线用户,我们可以调用
随着onGetLiveRoomInfoDone的响应动作, 我们在用户列表适配器中加入参与用户。
处理连接弹性:在任何原因任何用户与AppWarp服务器连接中断的情形下,服务端将维持连接直到预定义的恢复时间,不过它会给房间中的其他用户发送一个通知,告知某用户当前处于暂停状态。如果用户在定义的弹性时间内恢复连接状态,那么其他用户将获得该用户状态继续的通知。否则用户将收到OnUserLeftRoom通知,并且将该用户从OnlineUser列表中删除。维护暂停/继续状态:如果我们使用AppWarp弹性特性,在任何用户与AppWarp服务器中断连接时,我们将收到一个通知。
恢复连接:如果用户的网络连接由于某些原因中断了,比如在2G/3G/WiFi/towers之间进行切换,或者其它原因,我们会在ConnectonRequestListener中得到一个连接错误,其错误代码为WarpResponseResultCode.CONNECTION_ERROR_RECOVERABLE,通过检测该错误代码我们可以调用恢复连接的API来恢复我们之间的session。我们建议每隔5秒钟尝试进行一次重新连接。
源代码可以从我们的 git库 上进行下载或查看。
为什么需要网络弹性: 在移动设备中,数据连接一直是一个问题。 当用户在移动中,数据源将经常切换基站,或者在2G和3G之间降级/升级,或切换WiFi,或由于屏幕锁定或用户按下home键使得应用程序切换到后台运行。 这对依赖持续数据连接的应用程序/游戏带来影响。AppWarp 提供了 强大的功能 来处理 网络弹性 问题, 用户可以通过它 在 连接丢失的 情况下,保持 应用 之前的 状态 。
包含两个 Activities 的应用
MainActivity: Main Activity 允许用户连接到AppWarp服务端。用户输入他们的名字然后连接到AppWarp服务器。为了启用弹性特性(Resiliency Feature),你应该在初始化WarpClient之后设置默认恢复间隔(Recovery Allowance interval):
01
02
03
04
05
06
07
08
09
|
private
void
init(){
WarpClient.initialize(Constants.apiKey, Constants.secretKey);
WarpClient.setRecoveryAllowance(120);
try
{
theClient = WarpClient.getInstance();
}
catch
(Exception ex) {
Toast.makeText(
this
,
"Exception in Initilization"
, Toast.LENGTH_LONG).show();
}
}
|
这会告诉服务器默认恢复时间间隔,在这个时间内,即使在连接丢失的情况下,服务端也不会销毁用户session。我们用AppHq 控制台创建了一个静态变量room。一旦连接并注册到这个room,我们就转向ChatActivity。
01
02
03
04
05
06
07
08
09
10
11
|
public
static
final
String roomId =
"1469583531"
;
// static room id defined in Constant.java
@Override
public
void
onSubscribeRoomDone(RoomEvent event) {
if
(event.getResult()==WarpResponseResultCode.SUCCESS){
Intent intent =
new
Intent(
this
, ChatActivity.
class
);
startActivity(intent);
}
else
{
showToastOnUIThread(
"onSubscribeRoomDone Failed with ErrorCode: "
+event.getResult());
}
}
|
ChatActivity.java 这个 Activity 包含了发送/接收聊天逻辑,并且也管理聊天日志。上半部分包含了同一个room中参与用户的列表。绿色的状态指示意思是用户在线,灰色的意思是暂停(临时连接错误)。屏幕下半部分包含了用户发送的聊天记录。在这个activity的启动后,要想获取房间中的在线用户,我们可以调用
01
|
theClient.getLiveRoomInfo(Constants.roomId);
|
随着onGetLiveRoomInfoDone的响应动作, 我们在用户列表适配器中加入参与用户。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
public
void
onGetLiveRoomInfoDone(
final
LiveRoomInfoEvent event) {
if
(event.getResult()==WarpResponseResultCode.SUCCESS){
onlineUserList.clear();
if
(event.getJoinedUsers().length>
1
){
// if more than one user is online
final
String onlineUser[] = Utils.removeLocalUserNameFromArray(event.getJoinedUsers());
for
(
int
i=
0
;i<onlineUser.length;i++){
User user =
new
User(onlineUser<i>.toString(),
true
);
Log.d(onlineUser<i>.toString(), onlineUser<i>.toString());
onlineUserList.add(user);
}
resetAdapter();
}
else
{
showToastOnUIThread(
"No online user found"
);
}
}
else
{
showToastOnUIThread(
"onGetLiveRoomInfoDone Failed with ErrorCode: "
+event.getResult());
}
}</i></i></i>
|
处理连接弹性:在任何原因任何用户与AppWarp服务器连接中断的情形下,服务端将维持连接直到预定义的恢复时间,不过它会给房间中的其他用户发送一个通知,告知某用户当前处于暂停状态。如果用户在定义的弹性时间内恢复连接状态,那么其他用户将获得该用户状态继续的通知。否则用户将收到OnUserLeftRoom通知,并且将该用户从OnlineUser列表中删除。维护暂停/继续状态:如果我们使用AppWarp弹性特性,在任何用户与AppWarp服务器中断连接时,我们将收到一个通知。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@Override
public
void
onUserPaused(String locid,
boolean
isLobby, String userName) {
for
(
int
i=
0
;i<onlineUserList.size();i++){
User user = onlineUserList.get(i);
if
(user.getName().equals(userName)){
user.setStatus(
false
);
}
}
resetAdapter();
}
@Override
public
void
onUserResumed(String locid,
boolean
isLobby, String userName) {
for
(
int
i=
0
;i<onlineUserList.size();i++){
User user = onlineUserList.get(i);
if
(user.getName().equals(userName)){
user.setStatus(
true
);
}
}
resetAdapter();
}
|
恢复连接:如果用户的网络连接由于某些原因中断了,比如在2G/3G/WiFi/towers之间进行切换,或者其它原因,我们会在ConnectonRequestListener中得到一个连接错误,其错误代码为WarpResponseResultCode.CONNECTION_ERROR_RECOVERABLE,通过检测该错误代码我们可以调用恢复连接的API来恢复我们之间的session。我们建议每隔5秒钟尝试进行一次重新连接。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
theClient.RecoverConnection();
@Override
public
void
onConnectDone(
final
ConnectEvent event) {
if
(event.getResult() == WarpResponseResultCode.SUCCESS){
showToastOnUIThread(
"Connection success"
);
}
else
if
(event.getResult() == WarpResponseResultCode.SUCCESS_RECOVERED){
showToastOnUIThread(
"Connection recovered"
);
runOnUiThread(
new
Runnable() {
@Override
public
void
run() {
if
(progressDialog!=
null
){
progressDialog.dismiss();
}
progressDialog = ProgressDialog.show(ChatActivity.
this
,
""
,
"Please wait.."
);
}
});
theClient.getLiveRoomInfo(Constants.roomId);
}
else
if
(event.getResult() == WarpResponseResultCode.CONNECTION_ERROR_RECOVERABLE){
runOnUiThread(
new
Runnable() {
@Override
public
void
run() {
progressDialog = ProgressDialog.show(ChatActivity.
this
,
""
,
"Recoverable connection error. Recovering session after 5 seconds"
);
}
});
handler.postDelayed(
new
Runnable() {
@Override
public
void
run() {
progressDialog.setMessage(
"Recovering..."
);
theClient.RecoverConnection();
}
},
5000
);
}
else
{
showToastOnUIThread(
"Non-recoverable connection error."
+event.getResult());
handleLeaveRoom();
this
.finish();
}
}
|
源代码可以从我们的 git库 上进行下载或查看。