2017-09-21 4 views
0

私はsmack/xmppでチャットアプリケーションを作成しようとしています。 ejabberdサーバーをインストールしました。私のプログラムはそれにうまく接続し、 メッセージを他のクライアントに送ることができます。 XMPPサービスにはSTICKYプロパティがあります。 3Dゲームのような重いアプリケーションを実行した後に問題が表示されます。ゲーム、brokedサーバへのXMPP接続をプレイ中に 、ゲームの終了後にサービスが自動的に再起動し、再度接続しようとしているが、SMACKExceptionが表示されます。android smack java.net.ConnectException接続が拒否されました

09-20 15:46:06.540 31467-31533/home.chat E/(onCreate):SMACKException: The following addresses failed: '94.x.x.x:5222' failed because java.net.ConnectException: failed to connect to /94.x.x.x (port 5222) after 30000ms: isConnected failed: ECONNREFUSED (Connection refused) 

私は、このエラーの説明を読んで、それは意味:そのエラー 信号をソケットをリモートアドレスとポートに接続しようとしているときに発生しました。通常、接続はリモートから拒否されました(プロセスがリモートアドレス/ポートでリッスンしていないなど)。

私のxmppサービスには、再接続マネージャがあります。場合によっては正常に動作しますが、この場合は何も行いません。

この例外を捕まえた後、私はプログラムでサービスを再起動しようとしましたが、これは役に立ちません。 アプリケーションの手動アンロードと再起動のみが役立ちます。 タイムアウト30秒後にサーバがxmpp接続を閉じると思うのですが、なぜサービスをリロードしても結果が得られませんか? 誰かが自分のコードで何か問題があると知っていますか?

MyServiceクラス package home.chat;

import android.app.Service; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.net.ConnectivityManager; 
import android.net.NetworkInfo; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.util.Log; 

import java.io.File; 
import java.util.Date; 

public class MyService extends Service { 
private static String DOMAIN = GlobalVariables.server; 
private static String USERNAME = GlobalVariables.user_id; 
private static String PASSWORD = GlobalVariables.user_password; 
public static MyXMPP xmpp; 
String text = ""; 
private LocalDb ldb; 
private Boolean disconnectAppeared = false; 
BroadcastReceiver br = null; 
Date d1 = null; 
Date d2 = null; 
static MyService instance; 

public static MyService getInstance(){ 
    return instance; 
} 

@Override 
public IBinder onBind(final Intent intent) { 
    return new LocalBinder<MyService>(this); 
} 

@Override 
public void onCreate() { 
    super.onCreate(); 
    instance = this; 
    checkInternetConnection(); 
    xmpp = MyXMPP.getInstance(MyService.this, DOMAIN, USERNAME, PASSWORD); 
    connect(); 

    Log.e("MyService"," created"); 
} 

public static void connect(){ 
    xmpp.connect("onCreate"); 
} 

@Override 
public int onStartCommand(final Intent intent, final int flags, 
          final int startId) { 
    return Service.START_STICKY; 
} 

@Override 
public boolean onUnbind(final Intent intent) { 
    return super.onUnbind(intent); 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    Log.e("MyService"," destroyed"); 
    xmpp.disconnect(); 
    unregisterReceiver(br); 
    Log.i("EXIT", "ondestroy!"); 
    Intent broadcastIntent = new Intent("home.chat.ActivityRecognition.RestartService"); 
    sendBroadcast(broadcastIntent); 
} 

private void checkInternetConnection() { 
    if (br == null) { 
     br = new BroadcastReceiver() { 
      @Override 
      public void onReceive(Context context, Intent intent) { 
       Bundle extras = intent.getExtras(); 
       NetworkInfo info = (NetworkInfo) extras 
         .getParcelable("networkInfo"); 
       NetworkInfo.State state = info.getState(); 
       Log.d("TEST Internet", info.toString() + " " 
         + state.toString()); 
       if (state == NetworkInfo.State.CONNECTED & disconnectAppeared) { //on 
         xmpp.connect("After network changes"); 
        disconnectAppeared = false; 
       } 
       if (state == NetworkInfo.State.DISCONNECTED) { //off 
        disconnectAppeared = true; 
       } 
      } 
     }; 
     final IntentFilter intentFilter = new IntentFilter(); 
     intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 
     registerReceiver(br, intentFilter); 
    } 
} 
public void destroyService(){ 
    stopSelf(); 
} 
} 

MyXMPPクラス

package home.chat; 

import *; 

public class MyXMPP { 

public static boolean connected = false; 
public static boolean loggedin = false; 
public static boolean isconnecting = false; 
public static boolean isToasted = false; 
private boolean chat_created = false; 
private String serverAddress; 
public static XMPPTCPConnection connection; 
public static String loginUser; 
public static String passwordUser; 
Gson gson; 
static MyService context; 
public static MyXMPP instance = null; 
public static boolean instanceCreated = false; 
private Handler mHandler = new Handler(); 
public static ReconnectionManager connMgr; 
int[] rt_arr = {2,2,2,5,5,10,10}; 
int curr_delay = 0; 
public static ConnectivityManager cm = null; 
public NetworkInfo activeNetwork = null; 
public static Roster myRoster; 

static ArrayList<ChatMessage> msg_array = new ArrayList<ChatMessage>(); //буфер сообщений для отправки 
public static ArrayList<HashMap<String,String>> msg_queue = new ArrayList<>(); 
public static ArrayList<HashMap<String,String>> stat_list = new ArrayList<>(); 
public String senderName = ""; 

public MyXMPP(MyService context, String serverAdress, String logiUser, 
       String passwordser) { 
    this.serverAddress = serverAdress; 
    this.loginUser = logiUser; 
    this.passwordUser = passwordser; 
    this.context = context; 
    init(); 
} 

public static MyXMPP getInstance(MyService context, String server, 
           String user, String pass) { 
    if (instance == null) { 
     instance = new MyXMPP(context, server, user, pass); 
     instanceCreated = true; 
     Log.e("MyXMPP","create new instance"); 
    } 
    return instance; 
} 

public org.jivesoftware.smack.chat.Chat Mychat; 

ChatManagerListenerImpl mChatManagerListener; 
MMessageListener mMessageListener; 

String text = ""; 
String mMessage = "", mReceiver = ""; 

static { 
    try { 
     Class.forName("org.jivesoftware.smack.ReconnectionManager"); 
    } catch (ClassNotFoundException ex) { 
     Log.e("E:","problem loading reconnection manager"); 
     // problem loading reconnection manager 
    } 
} 

public void init() { 
    gson = new Gson(); 
    mMessageListener = new MMessageListener(); 
    mChatManagerListener = new ChatManagerListenerImpl(); 
    initialiseConnection(); 
} 

private void initialiseConnection() { 

    cm = 
      (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); 
    activeNetwork = cm.getActiveNetworkInfo(); 

    XMPPTCPConnectionConfiguration.Builder config = XMPPTCPConnectionConfiguration 
      .builder(); 
    config.setSendPresence(true); 
    config.setSecurityMode(XMPPTCPConnectionConfiguration.SecurityMode.required); 
    config.setCompressionEnabled(true); 
    config.setServiceName(GlobalVariables.service); 
    config.setHost(serverAddress); 
    config.setPort(5222); 
    config.setDebuggerEnabled(true); 

    try { 
     SSLContext sc = SSLContext.getInstance("TLS"); 
     MemorizingTrustManager mtm = new MemorizingTrustManager(context); 
     sc.init(null, new X509TrustManager[] { mtm }, new java.security.SecureRandom()); 
     config.setCustomSSLContext(sc); 
     config.setHostnameVerifier(mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier())); 
    } catch (NoSuchAlgorithmException e) { 
     throw new IllegalStateException(e); 
    } catch (KeyManagementException e) { 
     throw new IllegalStateException(e); 
    } 
    connection = new XMPPTCPConnection(config.build()); 
    XMPPConnectionListener connectionListener = new XMPPConnectionListener(); 
    connection.addConnectionListener(connectionListener); 

    PingManager pingManager = PingManager.getInstanceFor(connection); 
    pingManager.setPingInterval(900); // 15 min 
    pingManager.registerPingFailedListener(new PingFailedListener(){ 
     @Override 
     public void pingFailed() { 
      // Do operation to handle if ping fail like force reconnect etc 
      Log.e("PingManager","Ping Failed, reconnection"); 
      connected = false; 
      chat_created = false; 
      loggedin = false; 
      //disconnect(); 
      connect("ping_manager"); 
     } 

    }); 
    ServerPingWithAlarmManager.getInstanceFor(connection).isEnabled(); //для пинга во время глубокого сна 
} 

public void disconnect() { 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      connection.disconnect(); 
     } 
    }).start(); 
} 

public void connect(final String caller) { 
    AsyncTask<Void, Void, Boolean> connectionThread = new AsyncTask<Void, Void, Boolean>() { 
     @Override 
     protected synchronized Boolean doInBackground (Void...arg0){ 
      if (connection.isConnected()) 
       return false; 
      isconnecting = true; 
      if (isToasted) 
       new Handler(Looper.getMainLooper()).post(new Runnable() { 

        @Override 
        public void run() { 

         Toast.makeText(context, caller + "=>connecting....", Toast.LENGTH_LONG).show(); 
        } 
       }); 
      Log.e("Connect() Function", caller + "=&gt;connecting...."); 

      try { 
       connection.setPacketReplyTimeout(20000); 
       // Enable automatic reconnection 
       connMgr = ReconnectionManager.getInstanceFor(connection); 
       connMgr.enableAutomaticReconnection(); 
       connMgr.setFixedDelay(2); 
       //connMgr.setDefaultFixedDelay(1); 
       //connMgr.setReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.FIXED_DELAY); 
       connection.connect(); 
       DeliveryReceiptManager dm = DeliveryReceiptManager 
         .getInstanceFor(connection); 
       dm.setAutoReceiptMode(AutoReceiptMode.always); 
       dm.addReceiptReceivedListener(new ReceiptReceivedListener() { 

        @Override 
        public void onReceiptReceived(final String fromid, 
                final String toid, final String msgid, 
                final Stanza packet) { 

        } 
       }); 
       connected = true; 
       MainActivity.fConn = true; 
      } catch (IOException e) { 
       if (isToasted) 
        new Handler(Looper.getMainLooper()) 
          .post(new Runnable() { 

           @Override 
           public void run() { 

            Toast.makeText(
              context, 
              "(" + caller + ")" 
                + "IOException: ", 
              Toast.LENGTH_SHORT).show(); 
           } 
          }); 

       Log.e("(" + caller + ")", "IOException: " + e.getMessage()); 
      } catch (SmackException e) { 
       new Handler(Looper.getMainLooper()).post(new Runnable() { 
        @Override 
        public void run() { 
         // Toast.makeText(context, "(" + caller + ")" + "SMACKException: ", Toast.LENGTH_SHORT).show(); 
        } 
       }); 
       Log.e("(" + caller + ")", 
         "SMACKException: " + e.getMessage()); 
       //mHandler.post(checkConn); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!<-- Problem place 
       //instance = null; 
       //MyService.getInstance().destroyService(); 
      } catch (XMPPException e) { 
       if (isToasted) 

        new Handler(Looper.getMainLooper()) 
          .post(new Runnable() { 

           @Override 
           public void run() { 

            Toast.makeText(
              context, 
              "(" + caller + ")" 
                + "XMPPException: ", 
              Toast.LENGTH_SHORT).show(); 
           } 
          }); 
       Log.e("connect(" + caller + ")", 
         "XMPPException: " + e.getMessage()); 

      } 
      return isconnecting = false; 
     } 
    } ; 
    connectionThread.execute(); 
} 

public static void login() { 
    try { 
     Log.e(loginUser,passwordUser); 
     loginUser = GlobalVariables.user_id; 
     passwordUser = GlobalVariables.user_password; 
     connection.login(loginUser, passwordUser); 
     Log.e("LOGIN", "Yey! We're connected to the Xmpp server!"); 
     sendBufMessages(); 
     myRoster = Roster.getInstanceFor(connection); 
     if (!myRoster.isLoaded()) { 
      try{ myRoster.reloadAndWait(); } 
      catch (Exception e) {System.out.println(e);} 
     } 
     myRoster.setDefaultSubscriptionMode(Roster.SubscriptionMode.accept_all); 
     myRoster.addRosterListener(new RosterListener() { 
      public void entriesAdded(Collection<String> addresses) {} 
      public void entriesDeleted(Collection<String> addresses) {} 
      public void entriesUpdated(Collection<String> addresses) {} 
      public void presenceChanged(Presence presence) { 
       Log.e("Roster","Presence changed: " + presence.getFrom() + " " + presence); 
       String uname = presence.getFrom(); 
       int pos = uname.indexOf('@',0); 
       uname = uname.substring(0,pos); 
       Presence.Type ptype = presence.getType(); //Presence.type.available 
       for(int i=0;i<stat_list.size();i++){ 
        HashMap<String,String> item = new HashMap<String, String>(); 
        item = stat_list.get(i); 
        if (uname.equals(item.get("user_id").toString())) { stat_list.remove(i); break;} 
       } 
       HashMap<String,String> item = new HashMap<>(); 
       item.put("user_id",uname); 
       if (ptype == Presence.Type.available){ item.put("onl","true"); } 
       if (ptype == Presence.Type.unavailable){ item.put("onl","false"); } 
       stat_list.add(0,item); 
       if (MainActivity.chatlist_selected) { ChatList.getInstance().startStatProc(); } 
       if (GlobalVariables.onchat == true & GlobalVariables.vuser_id.equals(uname)){ 
        if (ptype == Presence.Type.available) { Chat.setUserStatus("onl"); } 
        if (ptype == Presence.Type.unavailable) {Chat.setUserStatus("offl");} 
       } 
      } 
     }); 
    } catch (XMPPException | SmackException | IOException e) { 
     e.printStackTrace(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

private class ChatManagerListenerImpl implements ChatManagerListener { 
    @Override 
    public void chatCreated(final org.jivesoftware.smack.chat.Chat chat, 
          final boolean createdLocally) { 
     if (!createdLocally) 
      chat.addMessageListener(mMessageListener); 

    } 

} 

public void sendMessage(ChatMessage chatMessage) { 
..... 
} 

public class XMPPConnectionListener implements ConnectionListener { 
    @Override 
    public void connected(final XMPPConnection connection) { 

     Log.e("xmpp", "Connected!"); 
     connected = true; 
     curr_delay = 0; connMgr.setFixedDelay(2); 
      login(); 
    } 

    @Override 
    public void connectionClosed() { 
     if (isToasted) 

      new Handler(Looper.getMainLooper()).post(new Runnable() { 

       @Override 
       public void run() { 
        // TODO Auto-generated method stub 

        Toast.makeText(context, "ConnectionCLosed!", 
          Toast.LENGTH_SHORT).show(); 

       } 
      }); 
     Log.d("xmpp", "ConnectionCLosed!"); 
     connected = false; 
     chat_created = false; 
     loggedin = false; 
    } 

    @Override 
    public void connectionClosedOnError(Exception arg0) { 
     if (isToasted) 
      new Handler(Looper.getMainLooper()).post(new Runnable() { 

       @Override 
       public void run() { 
        Toast.makeText(context, "ConnectionClosedOn Error!!", 
          Toast.LENGTH_SHORT).show(); 

       } 
      }); 
     Log.e("xmpp", "ConnectionClosedOn Error!"); 
     connected = false; 
     chat_created = false; 
     loggedin = false; 
    } 

    @Override 
    public void reconnectingIn(int arg0) { 

     Log.e("xmpp", "Reconnectingin " + arg0); 
     if (arg0==0 & curr_delay<5){ 
      curr_delay++; 
      connMgr.setFixedDelay(rt_arr[curr_delay]); 
     } 
     loggedin = false; 
    } 

    @Override 
    public void reconnectionFailed(Exception arg0) { 
     if (isToasted) 

      new Handler(Looper.getMainLooper()).post(new Runnable() { 

       @Override 
       public void run() { 

        Toast.makeText(context, "ReconnectionFailed!", 
          Toast.LENGTH_SHORT).show(); 

       } 
      }); 
     Log.d("xmpp", "ReconnectionFailed!"); 
     connected = false; 

     chat_created = false; 
     loggedin = false; 
    } 

    @Override 
    public void reconnectionSuccessful() { 
     if (isToasted) 

      new Handler(Looper.getMainLooper()).post(new Runnable() { 

       @Override 
       public void run() { 
        // TODO Auto-generated method stub 

        Toast.makeText(context, "REConnected!", 
          Toast.LENGTH_SHORT).show(); 

       } 
      }); 
     Log.d("xmpp", "ReconnectionSuccessful"); 
     curr_delay = 0; connMgr.setFixedDelay(2); 
     connected = true; 
     //MainActivity.fConn = true; 
     chat_created = false; 
     loggedin = false; 
    } 

    @Override 
    public void authenticated(XMPPConnection arg0, boolean arg1) { 
     Log.d("xmpp", "Authenticated!"); 
     loggedin = true; 

     ChatManager.getInstanceFor(connection).addChatListener(
       mChatManagerListener); 

     chat_created = false; 
     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       try { 
        sleep(500); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 

      } 
     }).start(); 
     if (isToasted) 

      new Handler(Looper.getMainLooper()).post(new Runnable() { 

       @Override 
       public void run() { 
        // TODO Auto-generated method stub 

        Toast.makeText(context, "Connected!",Toast.LENGTH_SHORT).show(); 

       } 
      }); 
    } 
} 

private class MMessageListener implements ChatMessageListener { 

    @Override 
    public void processMessage(final org.jivesoftware.smack.chat.Chat chat, 
           final Message message) { 
     Log.i("MyXMPP_MESSAGE_LISTENER", "Xmpp message received: '" 
       + message); 

... 
     } 
    } 



private Runnable checkConn = new Runnable() { 
    public void run() { 
     try { 
      Socket socket = new Socket(host, 5222); 
      socket.shutdownInput(); 
      socket.shutdownOutput(); 
      socket.close(); 
     } catch(Exception e){Log.e("Socket",e.toString());} 
     disconnect(); 
     Log.e("MyXMPP","disconnect"); 
     mHandler.postDelayed(checkConn2,3000); 
    } 
}; 
private Runnable checkConn2 = new Runnable() { 
    public void run() { 
     connect("After SmackException"); 
    } 
}; 


} 

更新26.09.17。実験の数日後、私はまだ解決策を見つけることができません。 サービスを再作成するのに、フォアグラウンドサービス、PingManager、broadcastreceiverを使用しようとしましたが、結果はありませんでした。今私はシステムのメモリが不足しているときにアプリケーションに圧力信号を使用しようとします。 更新05.10.17まだ解決策が見つかりません。 Android 4.1.2でこのプログラムをテストしました。それはうまく動作します。 Android 5.1.1では、アクティビティを終了してから約3分後に接続が拒否されました。私が活動に戻ると、エラーが消えます。 Android 6.0.1の同様の状況では、エラーはjava.net.SocketTimeoutExceptionと若干異なります:10000ms後に/94.130.25.242(ポート80)への接続に失敗しました。私はシステムがしばらくしてサービスのネットワーク活動をブロックすると思うが、決して活動(?)では決してないと思う。

+0

私はちょうど、このエラーは大げさではない、単純なhttp要求は重いアプリケーションを実行した後、同じエラーを呼び出すことを見た。 java.net.ConnectException:15000ms後に/94.x.x.x(ポート80)への接続に失敗しました:isConnected failed:ECONNREFUSED(Connection refused) – xdamir79

答えて

0

Xiaomi電話機のバックグラウンドで長いネットワーク接続を使用することはできません。 MIUIは、しばらくしてからネットワーク接続をブロックします。クリティカルなネットワーク接続では、Androidシステムの優先度が高いFirebase Cloud Messagingを使用できます。必要なバックグラウンドジョブを開始できます。 また、受信メッセージについてユーザーに通知することもできます。このメッセージを受信すると、ユーザーはそれをクリックして自分の活動に戻り、xmpp接続が復元されます。

関連する問題