2017-02-18 2 views
1

私は別のプロセスと通信するServiceクラスを持っています。これはローカルソケットによってprocess_Aと言いましょう。別のAsyncTaskでAndroid FileChannelの読み込みと書き込みが失敗する

次のように私のサービスクラスがある:次のように

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メッセージをprocess_Aに送信し、process_AからのINITメッセージを待機します。
  2. サービスがユーザーによって停止されている場合、サービスは別のAsyncTaskを実行してTERMメッセージをprocess_Aに送信し、process_AからのTERMメッセージを待機します。

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タスクが完全に実行されています。書き込みと読み取りの両方が成功しています。しかし、2番目のAsyncTask(LocalSockTermTask)を実行すると、書き込みと読み取りの両方がうまくいかないようです。 Iこのライン上のいくつかのテストをやった:何も読むことができない場合、最初のAsyncTaskの実行(LocalSockInitTask)で

inChannel.read(recvBuf); 

を、このメソッドはすぐに戻ります-1と私はwhileループを設定する理由ですとカウント試みる。

2回目のAsyncTask実行(LocalSockTermTask)では、何も読み込めない場合、このメソッドはブロックされ、これによりwhileループと試行回数が無駄になります。これにより、AsyncTaskは決して完了しません。また、私のprocess_Aは "MSG_TERM"が終了するのを待っていて、実行中のままです。そのため、outChannel.write(sendBuf)もTermタスクで失敗したと思います。

現在、私はLocalSocketオブジェクトをAsyncTaskに渡して、AsyncTaskにin/out FileChannelのペアを作成しています。また、サービス内にIn/Out FileChannelのペアを作成し、AsyncTaskに2つのFileChannelを渡しましたが、同じ問題に直面していました。

ご協力いただきありがとうございます。

答えて

0

OK、これは私の不注意なミスであることがわかりました。問題は解決された。

  1. 私の別のプロセスが間違ってTERMメッセージを処理し、それは単に私のAsyncTaskにより送信されたTERMメッセージを無視し、したがって、それが実行され、メッセージを待ち続けています。

  2. TERMメッセージを無視するので、Tyncメッセージを自分のAsyncTaskに返送せず、inChannel.read(recvBuf)には何も読み込めません。

  3. inChannel.read(recvBuf)のブロック動作は絶対に正常です。FileChannelに変更する前に-1を返した場合は、BufferedReaderを使用してください。

関連する問題