开发多玩家 Android 游戏时如何处理连接问题

我们开发了一款Android聊天室应用演示,使用了AppWarp(译注:Appwarp 是创建实时多用户游戏的跨平台网络引擎),而AppWarp引擎阐明了怎样处理间歇性的网络链接故障。这个演示用到了AppWarp的具有网络弹性的API。

为什么需要网络弹性: 在移动设备中,数据连接一直是一个问题。 当用户在移动中,数据源将经常切换基站,或者在2G和3G之间降级/升级,或切换WiFi,或由于屏幕锁定或用户按下home键使得应用程序切换到后台运行。 这对依赖持续数据连接的应用程序/游戏带来影响。AppWarp 提供了 强大的功能 来处理 网络弹性 问题, 用户可以通过它 连接丢失的 情况下,保持 应用 之前的 状态

想知道更多有关appwarp弹性:点击这里

包含两个 Activities 的应用

MainActivity: Main Activity 允许用户连接到AppWarp服务端。用户输入他们的名字然后连接到AppWarp服务器。为了启用弹性特性(Resiliency Feature),你应该在初始化WarpClient之后设置默认恢复间隔(Recovery Allowance interval):

 

 
 
 
 
  1. private void init(){   
  2.  
  3.    WarpClient.initialize(Constants.apiKey, Constants.secretKey);   
  4.  
  5.     WarpClient.setRecoveryAllowance(120);   
  6.  
  7.    try {   
  8.  
  9.         theClient = WarpClient.getInstance();   
  10.  
  11.     } catch (Exception ex) {   
  12.  
  13.       Toast.makeText(this"Exception in Initilization", Toast.LENGTH_LONG).show();   
  14.  
  15.    }   
  16.  
  17. }  

这会告诉服务器默认恢复时间间隔,在这个时间内,即使在连接丢失的情况下,服务端也不会销毁用户session。我们用AppHq 控制台创建了一个静态变量room。一旦连接并注册到这个room,我们就转向ChatActivity。

 
 
 
 
  1. public static final String roomId = "1469583531"// static room id defined in Constant.java   
  2.  
  3.     
  4.  
  5.  @Override  
  6.  
  7.  public void onSubscribeRoomDone(RoomEvent event) {   
  8.  
  9.      if(event.getResult()==WarpResponseResultCode.SUCCESS){   
  10.  
  11.         Intent intent = new Intent(this, ChatActivity.class);   
  12.  
  13.          startActivity(intent);   
  14.  
  15.      }else{   
  16.  
  17.         showToastOnUIThread("onSubscribeRoomDone Failed with ErrorCode: "+event.getResult());   
  18.  
  19.     }   
  20.  
  21.  }  

ChatActivity.java 这个 Activity 包含了发送/接收聊天逻辑,并且也管理聊天日志。上半部分包含了同一个room中参与用户的列表。绿色的状态指示意思是用户在线,灰色的意思是暂停(临时连接错误)。屏幕下半部分包含了用户发送的聊天记录。在这个activity的启动后,要想获取房间中的在线用户,我们可以调用

 
 
 
 
  1. theClient.getLiveRoomInfo(Constants.roomId); 

随着onGetLiveRoomInfoDone的响应动作, 我们在用户列表适配器中加入参与用户。

 
 
 
 
  1. public void onGetLiveRoomInfoDone(final LiveRoomInfoEvent event) {   
  2.  
  3.      if(event.getResult()==WarpResponseResultCode.SUCCESS){   
  4.  
  5.          onlineUserList.clear();   
  6.  
  7.          if(event.getJoinedUsers().length>1){// if more than one user is online   
  8.  
  9.             final String onlineUser[] = Utils.removeLocalUserNameFromArray(event.getJoinedUsers());   
  10.  
  11.              for(int i=0;i<onlineUser.length;i++){   
  12.  
  13.                  User user = new User(onlineUser[i].toString(), true);   
  14.  
  15.                  Log.d(onlineUser[i].toString(), onlineUser[i].toString());   
  16.  
  17.                 onlineUserList.add(user);   
  18.  
  19.              }   
  20.  
  21.         resetAdapter();   
  22.  
  23.     }else{   
  24.  
  25.         showToastOnUIThread("No online user found");   
  26.  
  27.      }   
  28.  
  29.     }else{   
  30.  
  31.        showToastOnUIThread("onGetLiveRoomInfoDone Failed with ErrorCode: "+event.getResult());   
  32.  
  33.     }   
  34.  
  35. }  

处理连接弹性:在任何原因任何用户与AppWarp服务器连接中断的情形下,服务端将维持连接直到预定义的恢复时间,不过它会给房间中的其他用户发送一个通知,告知某用户当前处于暂停状态。如果用户在定义的弹性时间内恢复连接状态,那么其他用户将获得该用户状态继续的通知。否则用户将收到OnUserLeftRoom通知,并且将该用户从OnlineUser列表中删除。维护暂停/继续状态:如果我们使用AppWarp弹性特性,在任何用户与AppWarp服务器中断连接时,我们将收到一个通知。

 
 
 
 
  1. @Override  
  2.  
  3. public void onUserPaused(String locid, boolean isLobby, String userName) {   
  4.  
  5.    for(int i=0;i<onlineUserList.size();i++){   
  6.  
  7.         User user = onlineUserList.get(i);   
  8.  
  9.         if(user.getName().equals(userName)){   
  10.  
  11.            user.setStatus(false);   
  12.  
  13.         }   
  14.  
  15.    }   
  16.  
  17.     resetAdapter();   
  18.  
  19. }   
  20.  
  21.       
  22.  
  23.  @Override  
  24.  
  25.     
  26.  
  27.  public void onUserResumed(String locid, boolean isLobby, String userName) {   
  28.  
  29.      for(int i=0;i<onlineUserList.size();i++){   
  30.  
  31.         User user = onlineUserList.get(i);   
  32.  
  33.          if(user.getName().equals(userName)){   
  34.  
  35.            user.setStatus(true);   
  36.  
  37.          }   
  38.  
  39.      }   
  40.  
  41.    resetAdapter();   
  42.  
  43. }  

恢复连接:如果用户的网络连接由于某些原因中断了,比如在2G/3G/WiFi/towers之间进行切换,或者其它原因,我们会在ConnectonRequestListener中得到一个连接错误,其错误代码为WarpResponseResultCode.CONNECTION_ERROR_RECOVERABLE,通过检测该错误代码我们可以调用恢复连接的API来恢复我们之间的session。我们建议每隔5秒钟尝试进行一次重新连接。 

 
 
 
 
  1. theClient.RecoverConnection();   
  2.  
  3.      
  4.  
  5. @Override  
  6.  
  7. public void onConnectDone(final ConnectEvent event) {   
  8.  
  9.    if(event.getResult() == WarpResponseResultCode.SUCCESS){   
  10.  
  11.         showToastOnUIThread("Connection success");   
  12.  
  13.   }   
  14.  
  15.    else if(event.getResult() == WarpResponseResultCode.SUCCESS_RECOVERED){   
  16.  
  17.         showToastOnUIThread("Connection recovered");   
  18.  
  19.         runOnUiThread(new Runnable() {   
  20.  
  21.         @Override  
  22.  
  23.          public void run() {   
  24.  
  25.         if(progressDialog!=null){   
  26.  
  27.              progressDialog.dismiss();   
  28.  
  29.         }   
  30.  
  31.         progressDialog = ProgressDialog.show(ChatActivity.this"""Please wait..");   
  32.  
  33.      }   
  34.  
  35.    });   
  36.  
  37.     theClient.getLiveRoomInfo(Constants.roomId);   
  38.  
  39.     }   
  40.  
  41.     else if(event.getResult() == WarpResponseResultCode.CONNECTION_ERROR_RECOVERABLE){   
  42.  
  43.         runOnUiThread(new Runnable() {   
  44.  
  45.         @Override  
  46.  
  47.         public void run() {   
  48.  
  49.            progressDialog = ProgressDialog.show(ChatActivity.this"""Recoverable connection error. Recovering session after 5 seconds");   
  50.  
  51.         }   
  52.  
  53.     });   
  54.  
  55.      handler.postDelayed(new Runnable() {   
  56.  
  57.      @Override  
  58.  
  59.     public void run() {   
  60.  
  61.          progressDialog.setMessage("Recovering...");   
  62.  
  63.          theClient.RecoverConnection();   
  64.  
  65.     }   
  66.  
  67.     }, 5000);   
  68.  
  69.      }   
  70.  
  71.      else{   
  72.  
  73.        showToastOnUIThread("Non-recoverable connection error."+event.getResult());   
  74.         handleLeaveRoom();   
  75.  
  76.        this.finish();   
  77.  
  78.      }   
  79.  
  80.      
  81.  
  82.  }  

源代码可以从我们的 git库上进行下载或查看。如果你有什么问题或者需要进一步的帮助,请随时跟我们联系: [email protected]

THE END