简体   繁体   English

Android FileChannel读取和写入在不同的AsyncTask中失败

[英]Android FileChannel read & write fails in different AsyncTask

I have a Service class that communicates with my another process, let's say process_A, by local socket. 我有一个Service类,通过本地套接字与我的另一个进程通信,比如说process_A。

My Service class is as follows: 我的服务类如下:

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

The behaviour should be as follows: 行为应如下:

  1. When my service is being started by user, the service uses LocalSocket.connect() to connect with process_A. 当用户启动我的服务时,该服务使用LocalSocket.connect()连接process_A。 Once connected successfully, the service executes an AsyncTask to send an INIT message to process_A and wait for an INIT message from process_A. 成功连接后,服务执行AsyncTask以向process_A发送INIT消息并等待来自process_A的INIT消息。
  2. When my service is being stopped by user, the service executes another AsyncTask to send a TERM message to process_A and wait for a TERM message from process_A. 当我的服务被用户停止时,该服务执行另一个AsyncTask以向Process_A发送TERM消息并等待来自process_A的TERM消息。

LocalSockInitTask.java: 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 is nearly doing the same as LocalSockInitTask.java, the major difference is just the message being send and receive is "MSG_TERM". LocalSockTermTask.java几乎和LocalSockInitTask.java一样,主要区别在于发送和接收的消息是“MSG_TERM”。

The Init task is doing perfectly, both write and read are successful. Init任务完美无缺,写入和读取都是成功的。 However, when executing the second AsyncTask (which is LocalSockTermTask), seems both write and read are unsuccessful. 但是,当执行第二个AsyncTask(即LocalSockTermTask)时,写入和读取似乎都不成功。 I've done some testing on this line: 我在这条线上做了一些测试:

inChannel.read(recvBuf);

In the first AsyncTask execution (LocalSockInitTask), if nothing can be read, this method will immediately return -1 and that's why I set a while loop and count the attempt. 在第一个AsyncTask执行(LocalSockInitTask)中,如果无法读取任何内容,此方法将立即返回-1,这就是我设置while循环并计算尝试次数的原因。

In the second AsyncTask execution (LocalSockTermTask), if nothing can be read, this method will be blocked, and this makes my while loop and attempt count become useless. 在第二个AsyncTask执行(LocalSockTermTask)中,如果无法读取任何内容,则此方法将被阻止,这使得我的while循环和尝试计数变得无用。 This cause the AsyncTask never complete. 这导致AsyncTask永远不会完成。 Also, My process_A is waiting for "MSG_TERM" to terminate, and it remains running, that's why I think outChannel.write(sendBuf) also failed in Term task. 此外,我的process_A正在等待“MSG_TERM”终止,并且它仍然在运行,这就是为什么我认为outChannel.write(sendBuf)在Term任务中也失败了。

Currently I am passing the LocalSocket object to both AsyncTask and create a pair of in/out FileChannel in the AsyncTask. 目前我将LocalSocket对象传递给AsyncTask并在AsyncTask中创建一对输入/输出FileChannel。 I've also tried to create a pair of in/out FileChannel in the service and pass the two FileChannel to AsyncTask, but still facing the same problem. 我还尝试在服务中创建一对输入/输出FileChannel,并将两个FileChannel传递给AsyncTask,但仍面临同样的问题。

Any help is greatly appreciated! 任何帮助是极大的赞赏!

OK, I just found out that this is my careless mistake. 好的,我发现这是我粗心的错误。 The problem is solved. 问题已经解决了。

  1. My another process handles the TERM message incorrectly, so it just simply ignore the TERM message sent by my AsyncTask, and therefore it continues to run and wait for messages. 我的另一个进程错误地处理了TERM消息,因此它只是忽略了我的AsyncTask发送的TERM消息,因此它继续运行并等待消息。

  2. Since it ignores the TERM message, it won't send back a TERM message to my AsyncTask, and this cause the inChannel.read(recvBuf) has nothing to read. 由于它忽略了TERM消息,因此它不会向我的AsyncTask发回TERM消息,这导致inChannel.read(recvBuf)无法读取。

  3. The blocking behavior of inChannel.read(recvBuf) is absolutely normal, returning -1 should be the case that I use BufferedReader before I changed to use FileChannel . inChannel.read(recvBuf)的阻塞行为是绝对正常的,返回-1应该是我在更改为使用FileChannel之前使用BufferedReader的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM