2017-02-18 14 views
1

У меня есть класс Service, который связывается с моим другим процессом, скажем, process_A, локальным сокетом.Ошибка чтения и записи Android FileChannel в разных AsyncTask

класса

Моей службы выглядит следующим образом:

public class MyService extends Service { 
    private LocalSocket localSock; 
    private LocalSocketAddress localSockAddr; 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     if (intent.getAction().equals(START_SERVICE_ACTION)) { 
      localSock = new LocalSocket(); 
      localSockAddr = new LocalSocketAddress(LOCAL_SOCK_ADDR, LocalSocketAddress.Namespace.ABSTRACT); 
      try { 
       localSock.connect(localSockAddr); 
      } catch (IOException e) { 
       // Ignore 
      } 

      if (localSock.isConnected()) { 
       new LocalSockInitTask().execute(localSock); 
      } 
     } else if (intent.getAction().equals(STOP_SERVICE_ACTION)) { 
      new LocalSockTermTask().execute(localSock); 
     } 
    } 
} 

поведение должно быть следующим:

  1. Когда моя служба в настоящее время начата пользователем, служба использует LocalSocket.connect() для подключения с process_A. После успешного подключения служба выполняет AsyncTask, чтобы отправить сообщение INIT процессу_A и дождаться сообщения INIT от process_A.
  2. Когда моя служба останавливается пользователем, служба выполняет другую AsyncTask, чтобы отправить сообщение TERM процессу_A и дождаться сообщения TERM от process_A.

LocalSockInitTask.java:

public class LocalSockInitTask extends AsyncTask<LocalSocket, Void, Boolean> { 
    @Override 
    protected Boolean doInBackground(LocalSocket... params) { 
     LocalSocket localSock = params[0]; 
     FileChannel inChannel; 
     FileChannel outChannel; 
     ByteBuffer sendBuf, recvBuf; 
     byte[] bytes; 
     String result, recvMsg; 
     int attempt; 

     try { 
      inChannel = new FileInputStream(localSock.getFileDescriptor()).getChannel(); 
      outChannel = new FileOutputStream(localSock.getFileDescriptor()).getChannel(); 

      // Send INIT Message 
      sendBuf = ByteBuffer.wrap(MSG_INIT.getBytes()); 
      outChannel.write(sendBuf); 

      // Wait for INIT Message 
      recvBuf = ByteBuffer.allocate(BUFFER_SIZE); 
      attempt = 0; 
      while (inChannel.read(recvBuf) < 0) { 
       attempt++; 
       if(attempt == 5) 
        return false; 

       Thread.sleep(1000); 
      } 

      recvBuf.flip(); 
      bytes = new byte[recvBuf.remaining()]; 
      recvBuf.get(bytes); 

      result = new String(bytes); 
      if(!result.equals(MSG_INIT)) 
       return false; 

      inChannel.close(); 
      outChannel.close(); 

      return true; 
     } catch (IOException | InterruptedException e) { 
      e.printStackTrace(); 
     } 
     return false; 
    } 
} 

LocalSockTermTask.java почти делает то же самое, как LocalSockInitTask.java, основным отличием является только сообщение будучи отправлять и получать это "MSG_TERM".

Задача Init выполняется отлично, как запись, так и чтение успешны. Однако при выполнении второй AsyncTask (которая является LocalSockTermTask) кажется, что запись и чтение не увенчались успехом. Я сделал некоторые испытания на этой линии:

inChannel.read(recvBuf); 

В исполнении первой AsyncTask (LocalSockInitTask), если ничего не может быть прочитан, этот метод немедленно возвращает -1, и именно поэтому я установил время цикла и посчитать попытка.

Во втором выполнении AsyncTask (LocalSockTermTask), если ничего не может быть прочитано, этот метод будет заблокирован, и это сделает мой цикл while и попытку попыткой стать бесполезной. Это приведет к тому, что AsyncTask никогда не завершится. Кроме того, My process_A ждет завершения «MSG_TERM», и он остается запущенным, поэтому я думаю, что outChannel.write (sendBuf) также потерпел неудачу в задаче Term.

В настоящее время я передаю объект LocalSocket как AsyncTask, так и создаю пару в/из FileChannel в AsyncTask. Я также попытался создать пару in/out FileChannel в службе и передать два FileChannel в AsyncTask, но по-прежнему сталкивается с той же проблемой.

Любая помощь очень ценится!

ответ

0

ОК, я только узнал, что это моя неосторожная ошибка. Проблема решена.

  1. Мой другой процесс обрабатывает сообщение TERM неправильно, так что это просто игнорировать сообщение TERM посланного моего AsyncTask, и поэтому он продолжает работать и ждать сообщений.

  2. Поскольку он игнорирует сообщение TERM, он не отправляет сообщение TERM в мою AsyncTask, и это приводит к тому, что inChannel.read(recvBuf) не имеет ничего для чтения.

  3. Поведение блокировки inChannel.read(recvBuf) абсолютно нормальное, возврат -1 должен быть в том случае, если я использую BufferedReader, прежде чем я изменил использование FileChannel.