我正在尝试创建一个简单的应用,发送一条来自EditText
的消息,
使用Java Socket类。我正在尝试使用AsyncTask
,但它只能运行一次,我无法返回套接字以便在该类的另一个实例中重用。
你能给我一个后台服务的例子,它打开与服务器的通信并返回Socket吗?
修改
根据 nandsito 的要求;我打算使用Button
打开连接,因此该按钮调用beckground进程,该进程创建与服务器的连接,最后返回Socket
。当我按下另一个Button
我想开始另一个重用套接字的任务时,写入数据(例如Sring
)会从服务器接收响应并更新UI。
答案 0 :(得分:0)
看起来很简单,但我认为你有一个有趣且具有挑战性的问题。如果你想在通过它发送消息后保持套接字打开,你需要维护一个或多个线程来使用该套接字,因为,你知道,Android不允许在主线程上建立网络。
多线程编程很少简单,通常有多种方法可以实现。例如。在Android中,您可以将Handler
与Looper
s中的HandlerThread
或经典Java Thread
一起使用。还有AsyncTask
,但我认为它不适合这种情况。
您打算如何管理套接字生命周期(即何时打开或关闭),以及在哪些时刻从插槽读取/写入数据?请更好地解释这个问题,以便我建议实施。
修改强>
这是一个带有两个按钮的示例Activity
。一个按钮运行AsyncTask
,创建一个套接字及其流,另一个按钮运行另一个AsyncTask
,将数据写入套接字。这是一个过度简化的解决方案,但应该可行。请注意,代码需要同步,以便不同的线程访问套接字。
public class MainActivity extends Activity {
private SocketContainer mSocketContainer;
private final Object mSocketContainerLock = new Object();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// onClick attribute of one button.
public void onClickPushMe(View view) {
String serverAddress;
int serverPort;
new CreateSocketAsyncTask(serverAddress, serverPort).execute();
}
// onClick attribute of other button.
public void onClickPushMeToo(View view) {
String text;
new WriteSocketAsyncTask(text).execute();
}
// Class that contains the socket and its streams,
// so they can be passed from one thread to another.
private class SocketContainer {
private Socket mSocket;
private InputStream mSocketInputStream;
private OutputStream mSocketOutputStream;
private SocketContainer(Socket socket, InputStream socketInputStream, OutputStream socketOutputStream) {
mSocket = socket;
mSocketInputStream = socketInputStream;
mSocketOutputStream = socketOutputStream;
}
private Socket getSocket() {
return mSocket;
}
private InputStream getSocketInputStream() {
return mSocketInputStream;
}
private OutputStream getSocketOutputStream() {
return mSocketOutputStream;
}
}
// AsyncTask that creates a SocketContainer and sets in into MainActivity.
private class CreateSocketAsyncTask extends AsyncTask<Void, Void, SocketContainer> {
private final String mServerAddress;
private final int mServerPort;
private CreateSocketAsyncTask(String serverAddress, int serverPort) {
mServerAddress = serverAddress;
mServerPort = serverPort;
}
protected SocketContainer doInBackground(Void... params) {
try {
Socket socket = new Socket(mServerAddress, mServerPort);
return new SocketContainer(socket, socket.getInputStream(), socket.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void onPostExecute(SocketContainer socketContainer) {
super.onPostExecute(socketContainer);
synchronized (mSocketContainerLock) {
mSocketContainer = socketContainer;
}
}
}
private class WriteSocketAsyncTask extends AsyncTask<Void, Void, Void> {
private final String mText;
private WriteSocketAsyncTask(String text) {
mText = text;
}
@Override
protected Void doInBackground(Void... params) {
synchronized (mSocketContainerLock) {
try {
mSocketContainer.getSocketOutputStream().write(mText.getBytes(Charset.forName("UTF-8")));
mSocketContainer.getSocketOutputStream().flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return null;
}
}
}
答案 1 :(得分:0)
使用此代码我连接到聊天,因此您可以使用similliary连接您想要的内容
public class SocialConnectionManager extends AsyncTask<Void, Void, Void> {
public static final int SQL_STEP_LOGIN = 0;
public static final int SQL_STEP_LOGOUT = 1;
public static final int SQL_STEP_SEND = 2;
public static final int SQL_STEP_UPDATE = 3;
final int serverPort = 8080;
private String message, channel, userName, serverIp;
private int step;
private long uniqueId;
private Activity activity;
public SocialConnectionManager(String serverIp, long uniqueId, int step, String userName,
String channel, String message, Activity activity) {
this.message = message;
this.step = step;
this.uniqueId = uniqueId;
this.channel = channel;
this.userName = userName;
this.serverIp = serverIp;
this.activity = activity;
}
@Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
socket = new Socket(serverIp, serverPort);
DataOutputStream dataOut = new DataOutputStream(socket.getOutputStream());
switch (step) {
case SQL_STEP_LOGIN:
dataOut.writeInt(step);
dataOut.writeLong(uniqueId);
dataOut.writeUTF(channel);
dataOut.writeUTF(userName);
break;
case SQL_STEP_LOGOUT:
dataOut.writeInt(step);
dataOut.writeLong(uniqueId);
dataOut.writeUTF(channel);
dataOut.writeUTF(userName);
break;
case SQL_STEP_SEND:
long messageId = createRandomId();
messageIds.add(messageId);
dataOut.writeInt(step);
dataOut.writeLong(uniqueId);
dataOut.writeUTF(channel);
dataOut.writeUTF(userName);
dataOut.writeUTF(message);
dataOut.writeLong(messageId);
break;
case SQL_STEP_UPDATE:
dataOut.writeInt(step);
dataOut.writeUTF(message);
break;
}
dataOut.flush();
} catch (UnknownHostException e) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
((MainActivity) activity).showNetworkAlertDialog(context.getString
(R.string.social_chat_connection_failed));
}
});
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
private class ReceiveTask extends AsyncTask {
final int clientPort = 5050;
@Override
protected Object doInBackground(Object[] params) {
try {
serverSocket = new ServerSocket(clientPort);
while (true) {
final Socket socket = serverSocket.accept();
DataInputStream dataIn = new DataInputStream(socket.getInputStream());
final int step = dataIn.readInt();
final int userCount = dataIn.readInt();
final String message = dataIn.readUTF();
final String userName = dataIn.readUTF();
switch (step) {
case SocialConnectionManager.SQL_STEP_LOGIN:
if (isLogging) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
showProgress(false);
}
});
isLogging = false;
isLoggedIn = true;
}
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
userCountView.setText(Integer.toString(userCount));
addMessage(message, userName, step);
}
});
break;
case SocialConnectionManager.SQL_STEP_LOGOUT:
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
addMessage(message, userName, step);
}
});
break;
case SocialConnectionManager.SQL_STEP_SEND:
messageId = dataIn.readLong();
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
addMessage(message, userName, step);
}
});
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
BroadcastReceiver networkStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String ip = getIpAddress();
if (ip.equals("")) {
((MainActivity) activity).showNetworkAlertDialog(context.getString
(R.string.social_chat_connection_lost));
} else if (!deviceIp.equals(ip)) {
SocialConnectionManager socialConnectionManager =
new SocialConnectionManager(serverIp, 0,
SocialConnectionManager.SQL_STEP_UPDATE, null, null, deviceIp,
activity);
socialConnectionManager.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
};
}
答案 2 :(得分:0)
异步任务不值得实时聊天。 进入firebase以轻松使用。 这可能对你有帮助 - https://www.firebase.com/docs/android/examples.html