開發多玩家 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):
- 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。
- 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的啟動后,要想獲取房間中的在線用戶,我們可以調用
- theClient.getLiveRoomInfo(Constants.roomId);
隨著onGetLiveRoomInfoDone的響應動作, 我們在用戶列表適配器中加入參與用戶。
- 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());
- }
- }
處理連接彈性:在任何原因任何用戶與AppWarp服務器連接中斷的情形下,服務端將維持連接直到預定義的恢復時間,不過它會給房間中的其他用戶發送一個通知,告知某用戶當前處于暫停狀態。如果用戶在定義的彈性時間內恢復連接狀態,那么其他用戶將獲得該用戶狀態繼續的通知。否則用戶將收到OnUserLeftRoom通知,并且將該用戶從OnlineUser列表中刪除。維護暫停/繼續狀態:如果我們使用AppWarp彈性特性,在任何用戶與AppWarp服務器中斷連接時,我們將收到一個通知。
- @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秒鐘嘗試進行一次重新連接。
- 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庫上進行下載或查看。如果你有什么問題或者需要進一步的幫助,請隨時跟我們聯系: support@shephertz.com。