2014-12-30 1 views
2

환경 : : 일대일/일대 다 장치에서 메시지를 중단없이 전달하려면 XMPPService를 백그라운드에서 STICKY 서비스로 실행해야합니다. 메시지를 받으려면 패킷이 장치에 도착할 때마다 발생하는 PacketListener가 있습니다. 클라이언트 측 구현을 위해 asmack 라이브러리를 사용하고 XMPP 서버로 OpenFire를 사용하고 있습니다.고정 서비스에서 영구 XMPP 연결을 유지할 수 없습니다.

public class XMPPService extends Service implements INetworkReceiver { 
private XMPPConnection mXmppConnection; 
private XMPPMethods xmpp; 
private DatabaseHandler db; 
private UserDetails user; 
private SmackAndroid smack; 
private Registrations registrations; 
private static final String TAG="XMPPService"; 

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

@Override 
public void onCreate() { 
    super.onCreate(); 
    registrations=new Registrations(getApplicationContext()); 
    xmpp=XMPPMethodsImpl.getInstance(getApplicationContext()); 
    db=DatabaseHandler.getInstance(getApplicationContext()); 
    if(db!=null){ 
     user=db.getUserDetails(); 
    } 
    createConnection();  
} 

public void createConnection() 
{ 
    ConnectionConfiguration connConfig = new ConnectionConfiguration(
      AppConstants.HOST, AppConstants.PORT); 
    connConfig.setSASLAuthenticationEnabled(false); 
    connConfig.setDebuggerEnabled(true); 
    connConfig.setReconnectionAllowed(true); 
    connConfig.setSecurityMode(SecurityMode.disabled); 
    mXmppConnection = new XMPPConnection(connConfig); 


    Thread thread=new Thread(new Runnable() { 
     private Handler handler=new Handler(); 
     @Override 
     public void run() { 

      try { 
       if(mXmppConnection!=null && !mXmppConnection.isConnected()){ 
        mXmppConnection.connect(); 
        Log.i("XMPPServiceAsync", 
          "Connected to " + mXmppConnection.getHost()); 
        xmpp.setConnection(mXmppConnection); 
       } 
      } catch (XMPPException e) { 
       e.printStackTrace(); 
      } 

      //mXmppConnection.addConnectionListener(new XmppConnectionListener()); 

      handler.post(new Runnable() { 

       @Override 
       public void run() { 
        try { 
         if(db!=null && user!=null && mXmppConnection!=null && !mXmppConnection.isAuthenticated()){ 
          if(user.getUserName()!=null && !user.getUserName().isEmpty()){ 
           mXmppConnection.login(user.getUserName(), "[email protected]!"); 
           xmpp.setPresence(2, mXmppConnection); 
           xmpp.setConnection(mXmppConnection); 
           Log.i("XMPPServiceAsync", 
             "Logged in as " + mXmppConnection.getUser()); 

          } 
         } 
        }catch (IllegalStateException e) { 
         e.printStackTrace(); 
        } catch (XMPPException ex) { 
         ex.printStackTrace(); 
        } 


        if(mXmppConnection.isConnected()){ 
         xmpp.rejoinGroups(); 
         registrations.registerMessageListener(mXmppConnection); 
         registrations.registerPacketListener(mXmppConnection); 
         registrations.registerMultiUserInvitationListener(mXmppConnection, db, user); 
         registrations.registerPingListener(mXmppConnection); 
        } 

       } 
      }); 
     } 
    }); 

    if (thread.getState() == Thread.State.NEW) 
    { 
     Log.i(TAG,"Thread State: "+ thread.getState()+""); 
     thread.start(); 
    } 
} 

@Override 
public int onStartCommand(final Intent intent, final int flags, 
     final int startId) { 
    //rejoining rooms 
    try{ 
     Log.v("XMPP Connection before rejoining",mXmppConnection+""); 
     if(mXmppConnection.isConnected()){ 
      registrations.registerMessageListener(mXmppConnection); 
      registrations.registerPacketListener(mXmppConnection); 
      registrations.registerMultiUserInvitationListener(mXmppConnection, db, user); 
      registrations.registerPingListener(mXmppConnection); 
     } 
    }catch(Exception e){ 
     e.printStackTrace(); 
    } 

    return Service.START_STICKY; 
} 


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

} 


@Override 
public void onDestroy() { 
    super.onDestroy(); 

} 

@Override 
public void reEstablishConnection() { 
    createConnection(); 
} 

}

문제 : 장치가 일정 기간 동안 유휴 상태 때, XMPP 서버와의 연결에서 장치의 연결이 끊어 XMPP 서버가 지속적인 연결을 유지한다고 XMPP 프로토콜의 사양에 대해 어떤 널 간다 우리가 강제로 로그 아웃 할 때까지 장치로 연결이 null이되는 이유는 알려져 있지 않습니다. 연결이 null이되면 PacketListener는 작동을 멈 춥니 다.

내가 시도 무엇 모든 : 서버에 연결하고 청취자를 초기화

  1. 구현 끈적 서비스를 제공합니다.
  2. AlarmManager를 구현하여 서비스가 백그라운드에서 실행 중인지 확인합니다. 또한 연결이 활성 상태이고 정기적으로 인증되는지 여부를 확인합니다. (배수구)
  3. XMPP 사양 XEP-0199에 따라 Ping 관리자가 구현되었습니다.

누군가가이 문제를 조사 할 수 있습니까?

+0

문제를 해결할 수 있습니까? 아직 문제가 없습니다. – kondal

+0

. 당신은 정확히 무엇을 경험하고 있는지 설명 할 수 있습니까? – subhendupsingh

+0

같은 문제 나는 약간의 분 후에 듣지 않는 서비스에서 패킷 수신기를 등록했다 – kondal

답변

1

장치가 일정 기간 동안 유휴 상태의 XMPP 서버와의 연결에서 장치 연결 해제가

대부분의 경우는 null 간다, 프로세스가 종료되었습니다. This is perfectly normal.

XMPP 서버가 강제로 로그 아웃 할 때까지 XMPP 서버가 장치와의 지속적인 연결을 유지한다는 XMPP 프로토콜 사양에 위배됩니다.

인터넷 액세스가 보장되지 않고 보편적이지 않기 때문에 XMPP 프로토콜 사양을 준수하는 모바일 장치는 없습니다. 또한 사용자는 사용자가 원할 때마다 프로세스를 제거 할 수 있습니다.

서버에 연결하고 리스너를 초기화하기 위해 구현 된 고정 서비스입니다.

이렇게하면 Android가 프로세스를 종료 한 후 언젠가 프로세스와 서비스가 재시작됩니다. 프로세스가 종료되고 프로세스가 다시 시작될 때까지의 시간 동안 XMPP 서버와 통신하지 않습니다.

+0

그러면 WhatsApp와 Telegram과 같은 응용 프로그램은 서버와의 지속적인 연결을 유지하고 장치에 도착한 새 패킷을 수신 대기 할 수 있습니다. 나는 그러한 것을 구현하는 방법을 알지 못한다. 서비스에서 연결을 초기화하고 연결에 리스너를 추가하는 것이 내가 생각할 수있는 유일한 것입니다. – subhendupsingh

+0

@subhendupsingh : 저는 그 앱을 사용하지 않습니다. Google Cloud Messaging을 사용할 수 있습니다. 그들은 전경 서비스를 사용할 수 있습니다. – CommonsWare

+0

GCM은 실시간 채팅 응용 프로그램을위한 솔루션이 아닙니다. 내 프로세스가 종료되고 있음을 알고 있지만 연결이 다시 시작될 때 연결 및 수신기가 다시 시작되어야하지만 애플리케이션을 다시 시작할 때까지 기다리지 않습니다. 백그라운드에서 연결 및 청취자를 어떻게 유지할 수 있습니까? 전경 서비스를 사용하고 싶지 않습니다. – subhendupsingh

0

일반적인 공유 내용. START_STICKY는 Android가 리소스가 필요한 경우 서비스를 종료 할 수 있음을 의미합니다. 잠시 후 서비스를 다시 시작합니다. 그러나 XMPP 연결이 다시 발생하면 사용자는 다시 연결해야합니다.

+0

내가 게시 한 코드에서 알 수 있듯이 서비스의 onCreate에서 연결을 설정하고 리스너를 초기화하는 코드를 작성했습니다. 테스트를 위해 서비스의 onStartCommand에있는 리스너를 초기화하는 코드도 작성했습니다. 장치가 언젠가는 유휴 상태 일 때 그 중 아무 것도 작동하지 않습니다. START_STICKY가 무엇을하는지 알지만 서비스가 다시 시작된 후에도 논리에 따라 연결을 다시 설정해야합니다. 난 단지 이것이 영구적 인 연결을 구축하고 리스너가 항상 작업하고 있거나 다른 접근법을 취할 필요가있는 올바른 방법인지 알고 싶습니다. – subhendupsingh

+0

그럼'createConnection()'이 작동하지 않는다고 생각합니다. 나는 그것을 훑어 본 후에 명백한 결점을 보지 못했지만, 이것에 대한 쓰레드와 핸들러를 가지는 것은 간결 해 보인다. – Flow

+0

createConnection()에 문제가 있었을 경우 앱이 처음 시작될 때도 처음에는 작동하지 않지만 작동하지는 않습니다. GCM을 xmpp와 함께 사용할 수 있습니까? 백그라운드 서비스가 전혀 필요하지 않기 때문입니다. 그렇지 않다면, 의도 된 패킷이 도착할 때마다 브로드 캐스트 리시버 자체가 작동하도록 서버에서 디바이스로 인 텐트를 보내는 방법이 있습니까? – subhendupsingh

관련 문제