2017-02-18 1 views
1

Ich habe eine Service-Klasse, die mit meinem anderen Prozess, sagen wir Process_A, von lokalen Socket kommuniziert.Android FileChannel lesen und schreiben schlägt in verschiedenen AsyncTask fehl

Meine Service-Klasse ist wie folgt:

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); 
     } 
    } 
} 

Das Verhalten sollte wie folgt lauten:

  1. Wenn mein Dienst durch den Benutzer gestartet wird, wird der Dienst verwendet LocalSocket.connect() verbinden mit Prozess_A. Sobald die Verbindung erfolgreich hergestellt wurde, führt der Dienst eine AsyncTask aus, um eine INIT-Nachricht an process_A zu senden und auf eine INIT-Nachricht von process_A zu warten.
  2. Wenn mein Dienst vom Benutzer angehalten wird, führt der Dienst eine weitere AsyncTask aus, um eine TERM-Nachricht an process_A zu senden und auf eine TERM-Nachricht von process_A zu warten.

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 fast tut das gleiche wie LocalSockInitTask.java, ist der große Unterschied nur die Nachricht "MSG_TERM" zu sein senden und empfangen.

Die Init-Aufgabe ist perfekt, sowohl schreiben als auch lesen sind erfolgreich. Wenn jedoch die zweite AsyncTask (LocalSockTermTask) ausgeführt wird, scheint sowohl das Schreiben als auch das Lesen nicht erfolgreich zu sein. Ich habe auf dieser Linie einige Tests gemacht:

inChannel.read(recvBuf); 

Im ersten AsyncTask Ausführung (LocalSockInitTask), wenn nichts gelesen werden kann, wird diese Methode sofort -1 zurück und deshalb habe ich eine While-Schleife gesetzt und zählen die Versuch.

In der zweiten AsyncTask-Ausführung (LocalSockTermTask), wenn nichts gelesen werden kann, wird diese Methode blockiert, und dies macht meine While-Schleife und Versuch zählen nutzlos. Dies führt dazu, dass die AsyncTask niemals abgeschlossen wird. Außerdem wartet My process_A auf "MSG_TERM" zu beenden, und es bleibt ausgeführt, deshalb denke ich OutChannel.write (sendBuf) fehlgeschlagen in Term Task.

Zur Zeit übergebe ich das LocalSocket-Objekt an beide AsyncTask und erstellen Sie ein Paar von In/Out FileChannel in der AsyncTask. Ich habe auch versucht, ein Paar in/out FileChannel im Dienst zu erstellen und die zwei FileChannel zu AsyncTask zu übergeben, aber immer noch das gleiche Problem.

Jede Hilfe wird sehr geschätzt!

Antwort

0

OK, ich habe gerade herausgefunden, dass dies mein unvorsichtiger Fehler ist. Das Problem ist behoben.

  1. Mein anderer Prozess übernimmt die TERM Nachricht falsch, so ist es einfach nur die TERM Nachricht von meinem AsyncTask gesendet ignorieren, und deshalb geht es weiter zu laufen und für Nachrichten warten.

  2. Da es die TERM-Nachricht ignoriert, sendet es keine TERM-Nachricht an meine AsyncTask zurück, und dies hat zur Folge, dass inChannel.read(recvBuf) nichts zu lesen hat.

  3. Das Sperrverhalten von inChannel.read(recvBuf) ist absolut normal, Rückgabe -1 sollte der Fall sein, dass ich BufferedReader verwenden, bevor ich geändert habe, um FileChannel zu verwenden.