【发布时间】:2017-02-18 18:46:38
【问题描述】:
我有一个服务类,它通过本地套接字与我的另一个进程(比如说 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。我也尝试在服务中创建一对 in/out FileChannel 并将这两个 FileChannel 传递给 AsyncTask,但仍然面临同样的问题。
非常感谢任何帮助!
【问题讨论】:
标签: java android multithreading sockets android-asynctask