Android FileChannel阅读&在不同的AsyncTask中写入失败

时间:2017-02-18 18:46:38

标签: java android multithreading sockets android-asynctask

我有一个与我的另一个进程通信的Service类,让我们通过本地套接字说process_A。

我的服务类如下:

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以向process_A发送INIT消息并等待来自process_A的INIT消息。
  2. 当我的服务被用户停止时,该服务执行另一个AsyncTask以向Process_A发送TERM消息并等待来自process_A的TERM消息。
  3. 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一样,主要区别在于发送和接收的消息是&#34; MSG_TERM&#34;。

    Init任务完美无缺,写入和读取都成功。但是,当执行第二个AsyncTask(即LocalSockTermTask)时,写入和读取似乎都不成功。我在这条线上做了一些测试:

    inChannel.read(recvBuf);
    

    在第一个AsyncTask执行(LocalSockInitTask)中,如果无法读取任何内容,此方法将立即返回-1,这就是我设置while循环并计算尝试次数的原因。

    在第二个AsyncTask执行(LocalSockTermTask)中,如果无法读取任何内容,则此方法将被阻止,这使得我的while循环和尝试计数变得无用。这导致AsyncTask永远不会完成。此外,我的process_A正在等待&#34; MSG_TERM&#34;终止,它仍然在运行,这就是为什么我认为outChannel.write(sendBuf)在Term任务中也失败了。

    目前我将LocalSocket对象传递给AsyncTask并在AsyncTask中创建一对输入/输出FileChannel。我还尝试在服务中创建一对输入/输出FileChannel,并将两个FileChannel传递给AsyncTask,但仍面临同样的问题。

    非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

好吧,我发现这是我粗心的错误。问题解决了。

  1. 我的另一个进程错误地处理了TERM消息,因此它只是忽略了我的AsyncTask发送的TERM消息,因此它继续运行并等待消息。

  2. 由于它忽略了TERM消息,因此它不会向我的AsyncTask发回TERM消息,这导致inChannel.read(recvBuf)无法读取。

  3. inChannel.read(recvBuf)的阻止行为绝对正常,在我更改为使用BufferedReader之前,我应该使用FileChannel返回-1。

    < / LI>