2017-01-15 19 views
0

В настоящее время я разрабатываю приложение электронной почты с фоновым сервисом, используемым в сочетании с функциональностью JavaMail Idle. Фоновая служба сохраняет работоспособность бездействия, выдавая проверку каждые 29 минут (поскольку сервер, используемый (сервер Exchange)), иногда может отключить соединение через 30 минут после подключения.Android JavaMail Detect If Server Goes Offline

Несмотря на то, что это работает отлично, если сервер Exchange отключен, приложение будет продолжать попытки повторно подключиться к папке IMAP на неопределенный срок. Я заметил всплески в использовании данных между часами 3AM & 6AM (типичное время обновления Exchange).

Чтобы избежать увеличения использования данных, я хочу реализовать функциональность, в которой приложение должно пытаться повторно подключиться к папке IMAP три раза, а затем отображать предупреждение пользователю о том, что сервер находится в автономном режиме, а новая попытка подключения будет за 30 минут.

Для этого, как бы определить, действительно ли сервер Exchange на самом деле отключен или обновлен &, будут ли исключены какие-либо исключения, если приложение не сможет подключиться к папке IMAP? Как если бы было исключено исключение, тогда я мог бы сохранить локальную переменную int и увеличивать ее на единицу каждый раз, когда генерируется исключение, и затем показывать предупреждение пользователю в третий раз.

Моя текущая реализация кода можно увидеть ниже:

public void checkInboxEmail(final String host, final String user, final String password) { 

    Log.d(TAG, "checkEmail"); 

    this.host = host; 
    this.user = user; 
    this.password = password; 

    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       Log.d(TAG, "checkEmail - run()"); 

       long databaseRecords; 

       //create properties field 
       Properties properties = new Properties(); 
       properties.put("mail.store.protocol", "imaps"); 
       properties.put("mail.imaps.ssl.trust", "*"); 
       properties.put("mail.debug", "true"); 

       emailSession = Session.getInstance(properties, new Authenticator() { 
        protected PasswordAuthentication getPasswordAuthentication() { 
         return new PasswordAuthentication(user, password); 
        } 
       }); 


       IMAPStore imapStore = (IMAPStore) emailSession.getStore("imaps"); 
       // imapStore.connect(); 

       imapStore.connect(host, user, password); 

       if (imapStore.isConnected()) { 
        Log.d("MailPush", "Successfully connected to IMAP"); 
       } else { 
        Log.d("MailPush", "Not connected to IMAP"); 
       } 

       final IMAPFolder folder = (IMAPFolder) imapStore.getFolder("Inbox"); 
       folder.open(IMAPFolder.READ_WRITE); 

       databaseRecords = dbManager.getReceivedEmailRecordsCount(); 

       if (databaseRecords < folder.getMessageCount()) { 
        Log.d(TAG, "Receiving Mail..."); 
        receiveMail(folder.getMessages()); 
       } else { 
        Log.d(TAG, "Records match."); 
       } 

       Folder[] fdr = imapStore.getDefaultFolder().list(); 
       for (Folder fd : fdr) 
        System.out.println(">> " + fd.getName()); 

       folder.addMessageCountListener(new MessageCountListener() { 

        public void messagesAdded(MessageCountEvent e) { 

         System.out.println("Message Added Event Fired"); 
         Log.d(TAG, "MESSAGE TYPE: " + e.getType()); 
         //ADDED = 1 & REMOVED = 2 

         try { 
          Message[] messages = e.getMessages(); 

          System.out.println("messages.length---" + messages.length); 

          for (Message message : messages) { 
           if (!message.getFlags().contains(Flags.Flag.SEEN)) { 

            //Message is new (hasn't been seen) > Message Details 
            System.out.println("---------------------------------"); 
            System.out.println("Email Number " + (message.getMessageNumber())); 
            System.out.println("Subject: " + message.getSubject()); 
            System.out.println("From: " + message.getFrom()[0]); 
            System.out.println("Text: " + message.getContent().toString()); 

            String from = message.getFrom()[0].toString(); 

            String cc = InternetAddress.toString(message.getRecipients(Message.RecipientType.CC)); 
            Log.d(TAG, "CC 1: " + cc); 

            Address[] recipients = message.getRecipients(Message.RecipientType.CC); 
            cc = InternetAddress.toString(recipients); 
            Log.d(TAG, "CC 2: " + cc); 

            //Check Encryption Details > Add SEEN Flag > Add to database 
            checkEncryption((MimeMessage) message, from, cc); 
           } 
          } 
         } catch (Exception ex) { 
          ex.printStackTrace(); 
         } 
        } 

        public void messagesRemoved(MessageCountEvent e) { 
         System.out.println("Message Removed Event fired"); 
        } 
       }); 

       folder.addMessageChangedListener(new MessageChangedListener() { 

        public void messageChanged(MessageChangedEvent e) { 
         System.out.println("Message Changed Event fired"); 
        } 
       }); 

       startListening(folder); 

       //close the store and folder objects 
       // emailFolder.close(false); 
       // store.close(); 

      } catch (NoSuchProviderException e) { 
       e.printStackTrace(); 
      } catch (MessagingException e) { 
       e.printStackTrace(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }).start(); 
} 

private void startListening(IMAPFolder imapFolder) { 
    Log.d(TAG, "startListening"); 

    // We need to create a new thread to keep alive the connection 
    Thread t = new Thread(
      new KeepAliveRunnable(imapFolder), "IdleConnectionKeepAlive" 
    ); 

    t.start(); 

    while (!Thread.interrupted()) { 
     Log.d(TAG, "Starting IDLE"); 
     try { 
      Log.d(TAG, "Setting IDLE"); 
      imapFolder.idle(); 
     } catch (FolderClosedException fex) { 
      //Server closes connection. 
      Log.d(TAG, "FolderClosedException. Server potentially dropped connection. Retrying connection..."); 
      fex.printStackTrace(); 

      if (!isServiceRunning(MyService.class)) { 
       Log.d(TAG, "Service isn't running. Starting service..."); 

       //Start service 
       Intent intent = new Intent(context, MyService.class); 
       intent.putExtra("host", host); 
       intent.putExtra("email", user); 
       intent.putExtra("password", password); 

       context.startService(intent); 
      } else { 
       Log.d(TAG, "Service is already running. Checking email..."); 
       checkInboxEmail(host, user, password); 
      } 
     } catch (MessagingException e) { 
      //Idle isn't supported by server. 
      Log.d(TAG, "Messaging exception during IDLE: "); 
      e.printStackTrace(); 
     } 
    } 

    // Shutdown keep alive thread 
    if (t.isAlive()) { 
     Log.d(TAG, "Interrupting thread"); 
     t.interrupt(); 
    } 
} 

private static class KeepAliveRunnable implements Runnable { 

    private final String TAG = getClass().getName(); 

    private static final long KEEP_ALIVE_FREQ = 60000 * 29; // 29 minutes (Exchange connection drops after 20-30 minutes) 

    private IMAPFolder folder; 

    KeepAliveRunnable(IMAPFolder folder) { 
     this.folder = folder; 
    } 

    @Override 
    public void run() { 
     while (!Thread.interrupted()) { 
      try { 
       Thread.sleep(KEEP_ALIVE_FREQ); 

       // Perform a messageCount check just to keep alive the connection 
       Log.d(TAG, "Performing a messageCount check to keep the connection alive"); 
       folder.getMessageCount(); 
      } catch (InterruptedException e) { 
       // Ignore, just aborting the thread... 
       Log.d(TAG, "Interrupted..."); 
       e.printStackTrace(); 
      } catch (MessagingException e) { 
       // Shouldn't really happen... 
       Log.d(TAG, "Unexpected exception while keeping alive the IDLE connection"); 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

private void receiveMail(Message[] messages) { 
    try { 

     System.out.println("messages.length---" + messages.length); 

     for (Message message : messages) { 
      if (!message.getFlags().contains(Flags.Flag.SEEN)) { 

       //Message is new (hasn't been seen) > Message Details 
       System.out.println("---------------------------------"); 
       System.out.println("Email Number " + (message.getMessageNumber())); 
       System.out.println("Subject: " + message.getSubject()); 
       System.out.println("From: " + message.getFrom()[0]); 
       System.out.println("Text: " + message.getContent().toString()); 

       String from = message.getFrom()[0].toString(); 
       String cc = InternetAddress.toString(message.getRecipients(Message.RecipientType.CC)); 

       //Check Encryption Details > Add SEEN Flag > Add to database 
       checkEncryption((MimeMessage) message, from, cc); 
      } 
     } 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 

ответ

1

Если сервер запущен, но не принимает подключения, то подключения не получится сразу (за исключением). Если сервер выключен, и вы установили таймаут соединения, соединение завершится после таймаута (с исключением).

+0

Какие исключения будут такими? –

+1

MessagingException, возможно, некоторый подкласс, такой как com.sun.mail.util.MailConnectException. –

1

Для уточнения @ ответ BillShannon, в случае, если сервер хозяин вверх, но обмен не принимает соединения, то подключения не получится сразу с ConnectException: connection refused. Если хост сервера отключен, соединение будет терпеть неудачу после таймаута с ConnectException: connect timeout (или, возможно, SocketTimeoutException), независимо от того, установлен ли тайм-аут подключения, так как платформа всегда имеет один.

+0

@BillShannon, я добавил сообщениеExceptionException как улов для моей функции checkinboxEmail, чтобы затем пользователю было показано предупреждение (после того, как исключение было поймано три раза), но как я могу остановить JavaMail, пытающийся повторно подключиться? Будет ли это просто использование разных тайм-аутов, а затем использовать обработчик для postDelay, выполняющего функцию, до 30 минут от текущего времени? –