我有一个 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);
}
}
}
行为应如下所示:
- 当用户启动我的服务时,该服务使用 LocalSocket.connect() 与 process_A 连接。连接成功后,服务会执行 AsyncTask,向 process_A 发送 INIT 消息,并等待 process_A 发送 INIT 消息。
- 当我的服务被用户停止时,该服务会执行另一个 AsyncTask,向 process_A 发送 TERM 消息,并等待来自 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 任务运行良好,写入和读取均成功。但是,当执行第二个AsyncTask(即LocalSockTermTask)时,似乎写入和读取都不成功。我已经对此行做了一些测试:
inChannel.read(recvBuf);
在第一次 AsyncTask 执行(LocalSockInitTask)中,如果没有任何内容可以读取,此方法将立即返回 -1,这就是为什么我设置了一个 while 循环并对尝试进行计数的原因。
在第二次执行AsyncTask(LocalSockTermTask)时,如果没有任何内容可以读取,则该方法将被阻塞,这使得我的while循环和尝试计数变得无用。这会导致 AsyncTask 永远不会完成。另外,我的 process_A 正在等待“MSG_TERM”终止,并且它仍然在运行,这就是为什么我认为 outChannel.write(sendBuf) 在 Term 任务中也失败了。
目前,我将 LocalSocket 对象传递给 AsyncTask,并在 AsyncTask 中创建一对输入/输出 FileChannel。我还尝试在服务中创建一对输入/输出 FileChannel 并将这两个 FileChannel 传递给 AsyncTask,但仍然面临同样的问题。
非常感谢任何帮助!
最佳答案
好吧,我刚刚发现这是我的粗心错误。问题解决了。
我的另一个进程错误地处理了 TERM 消息,因此它只是忽略了我的 AsyncTask 发送的 TERM 消息,因此它继续运行并等待消息。
由于它忽略 TERM 消息,因此不会向我的 AsyncTask 发回 TERM 消息,这会导致
inChannel.read(recvBuf)
没有任何内容可读取。inChannel.read(recvBuf)
的阻塞行为绝对正常,返回-1应该是我在改用FileChannel
之前使用BufferedReader
的情况。
关于java - Android FileChannel 在不同的 AsyncTask 中读写失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42319251/