【发布时间】:2014-11-26 15:00:30
【问题描述】:
我的目标是创建作为服务器的 Java 应用程序和 Android(客户端)套接字连接,并使 Android 手机监听我从服务器发送的命令。我的问题是,我应该如何让我的 Android 手机始终监听从 Java 应用程序推送的传入命令(字符串)。什么是最佳选择?线程,服务?
这是我的代码:Java 中的服务器:
public class Server extends JFrame {
private JTextField userText;
private JTextArea chatWindow;
private ObjectOutputStream output;
private ObjectInputStream input;
// private DataInputStream input;
private Socket connection;
ServerSocket server;
public Server() {
super("GUI");
userText = new JTextField();
userText.setEditable(false);
userText.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
sendMessage(e.getActionCommand());
userText.setText("");
}
});
add(userText, BorderLayout.NORTH);
chatWindow = new JTextArea();
add(new JScrollPane(chatWindow), BorderLayout.CENTER);
setSize(300, 150);
setVisible(true);
}
// connect to server
public void startRunning() {
try {
server = new ServerSocket(9000, 100);
while (true) {
try {
waitForConnection();
setupStreams();
whileChatting();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (EOFException e) {
showMessage("\n Connection lost");
} catch (IOException e) {
e.printStackTrace();
} finally {
closeCrap();
}
}
// connect to server
private void waitForConnection() throws IOException {
showMessage(" \nWaiting for connection \n");
connection = server.accept();
showMessage(" now connected to "
+ connection.getInetAddress().getHostName());
}
private void setupStreams() throws IOException {
showMessage("\n Setting up streams \n");
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
// input = new DataInputStream(connection.getInputStream());
input = new ObjectInputStream(connection.getInputStream());
showMessage(" Streams are good \n");
}
private void whileChatting() throws IOException {
ableToType(true);
String message = "You are now connected ";
sendMessage(message);
do {// have conversation
try {
message = (String) input.readObject();
// message = (String) input.readLine();
showMessage("\n" + message);
} catch (ClassNotFoundException e) {
showMessage("Dont know that object type ");
// TODO: handle exception
}
} while (!message.equals("server - end"));
}
// close everything
private void closeCrap() {
showMessage("\n Closing..");
ableToType(false);
try {
output.close();
input.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// send message to server
private void sendMessage(String message) {
try {
output.writeObject("CLIENT - " + message);
output.flush();
showMessage("\n" + "CLIENT - " + message);
} catch (IOException e) {
chatWindow.append("\n Smth is wrong sending message");
}
}
private void showMessage(final String m) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
chatWindow.append(m);
}
});
}
private void ableToType(final boolean tof) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
userText.setEditable(tof);
}
});
}
}
Android 客户端代码:
public class MainActivity extends ActionBarActivity {
TextView text;
Socket socket;
DataInputStream is;
DataOutputStream os;
public final String TAG = "CLIENT";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
ConnectThread thread = new ConnectThread();
thread.execute();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class ConnectThread extends AsyncTask<String, String, String> {
public ConnectThread() {
}
@Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
Log.i(TAG,"Do in background");
return connect();
}
public String connect() {
try {
Log.i(TAG," creating socket");
socket = new Socket("192.168.1.10", 9000);
Log.i(TAG," socket created");
os = new DataOutputStream(socket.getOutputStream());
is = new DataInputStream(socket.getInputStream());
Log.i(TAG," Streams are set");
Log.i(TAG,"::"+is.readUTF().toString());
text.setText(is.readLine().toString());
return is.readLine().toString();
} catch (UnknownHostException e) {
e.printStackTrace();
Log.d("fail", e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("fail", e.toString());
}
return "nothing";
}
}
}
【问题讨论】:
-
如果没有更多关于你想要做什么的信息,我会说你最好的解决方案是一个后台服务,它用你的套接字调度一个单独的线程。你试过什么了?您有更具体的问题吗?
-
当您使用线程时,您的应用需要打开。如果您使用服务,则独立于应用程序启动。您可以让服务始终运行。处理网络时是个坏主意。定期访问更好。考虑您要执行的数据和操作,然后决定谁将成为服务器和客户端,以及如何减少对手机电池的影响
-
应用程序的思想,是通过从java应用程序发送一个命令,或更具体地说,从Android手机获取呼叫列表。我从 java 发送请求,手机发送我请求的数据。