2014-12-30 3 views
2

Окружающая среда: Для бесперебойной доставки сообщений от устройств «один-к-одному»/«один-ко-многим» у меня есть служба XMPPService, работающая в фоновом режиме как служба STICKY. Чтобы получать сообщения, у меня есть PacketListener, который срабатывает всякий раз, когда пакет поступает на устройство. Я использую библиотеку asmack для реализации на стороне клиента и OpenFire как мой сервер XMPP.Не удается поддерживать постоянное соединение XMPP с липким сервисом android

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, неизвестна. Когда соединение становится нулевым, PacketListener перестает работать.

Что все, что я пробовал:

  1. Реализовано липкий сервис для подключения к серверу и инициализации слушателей.
  2. Реализован AlarmManager, чтобы проверить, работает ли служба в фоновом режиме. Он также проверяет, жива ли соединение и периодически проверяется подлинность. (Батарея отвода)
  3. Реализованный менеджер Ping в соответствии со спецификацией XMPP XEP-0199.

Может кто-то посмотреть на это.

+0

Вы можете решить проблему, у меня такая же проблема – kondal

+0

еще нет. можете ли вы точно объяснить, что вы испытываете? – subhendupsingh

+0

В том же выпуске я зарегистрировал прослушиватель пакетов в сервисе, не прослушивая через несколько минут – kondal

ответ

1

Когда устройство не используется в течение некоторого времени, отключает устройство от сервера XMPP и подключение идет нулевой

Скорее всего, ваш процесс был прекращен. This is perfectly normal.

, который противоречит спецификациям протокола 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