如何实现多个activity共用一个socket进行通信?请帮我看看代码

qq_493397330 2016-07-27 06:16:14
子线程code

package com.test.ceshi;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

public class ClientThread implements Runnable {
private Socket s;
// 定义向UI线程发送消息的Handler对象
Handler handler;
// 定义接收UI线程的Handler对象
Handler revHandler;
// 该线程处理Socket所对用的输入输出流
BufferedReader br = null;
OutputStream os = null;
String IP="192.168.1.199";
int port=5000;
int timeout=3000;
public ClientThread(Handler handler) {
this.handler = handler;
}
public ClientThread(Handler handler,String Ip,int port,int timeout) {
this.handler = handler;
this.IP=Ip;
this.port=port;
this.timeout=timeout;

}





@Override
public void run() {
s = new Socket();
try {
s.connect(new InetSocketAddress(IP,port ),timeout );
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
os = s.getOutputStream();
{
Message msg = new Message();
msg.what = 0x123;
msg.obj = "已连接";
handler.sendMessage(msg);
}

// 启动一条子线程来读取服务器相应的数据
Thread rcvThread= new Thread() {

@Override
public void run() {
String content = null;
// 不断的读取Socket输入流的内容
try {
while ((content = br.readLine()) != null) {
// 每当读取到来自服务器的数据之后,发送的消息通知程序
// 界面显示该数据
Message msg = new Message();
msg.what = 0x456;
msg.obj = content;
handler.sendMessage(msg);
}
} catch (IOException io) {
io.printStackTrace();
}
}

};
rcvThread.setDaemon(true);
rcvThread.start();
// 为当前线程初始化Looper
Looper.prepare();
// 创建revHandler对象
revHandler = new Handler() {

@Override
public void handleMessage(Message msg) {
// 接收到UI线程的中用户输入的数据
if (msg.what == 0x345) {
// 将用户在文本框输入的内容写入网络
try {
if(!s.isClosed()){
os.write((msg.obj.toString() + "\r\n")
.getBytes("gbk"));
}
} catch (Exception e) {
e.printStackTrace();
}
}

// 接收到UI线程的中用户输入的数据
if (msg.what == 0x678) {
// 断开连接
try {
os.close();
s.close();
Message ms = new Message();
ms.what = 0x123;
ms.obj = "网络断开";
handler.sendMessage(ms);

} catch (Exception e) {
e.printStackTrace();
}
}

}

};
// 启动Looper
Looper.loop();

} catch (SocketTimeoutException e) {
Message msg = new Message();
msg.what = 0x123;
msg.obj = "网络连接超时!";
handler.sendMessage(msg);
} catch (IOException io) {
io.printStackTrace();
}

}
}

...全文
276 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_493397330 2016-07-28
  • 打赏
  • 举报
回复
引用 4 楼 CJ_star 的回复:
看了一下你的代码,和你的问题,先忽略你自己的回复,会误导人。你想多给界面公用一个Socket,开启一个线程创建连接,用HandlerThread发消息,还是可以的,主要是你创建Socket的时候传了一个handle,当你进入下一个界面的时候你没有了上个界面的handler句柄,所以返回的消息你也没法处理。 所以你可以考虑两种方式: 一种是在Service里边去创建Socket,用广播的方式或者Intent和service通信。 二是用单例的形式管理Socket,在一个Activity创建以后,可以通过单例添加收到数据的回调或者发送数据。
您好 您的回答帮我理清了思路。请问如果用第一种方法的话,代码应该如何修改?
CJ_star 2016-07-27
  • 打赏
  • 举报
回复
看了一下你的代码,和你的问题,先忽略你自己的回复,会误导人。你想多给界面公用一个Socket,开启一个线程创建连接,用HandlerThread发消息,还是可以的,主要是你创建Socket的时候传了一个handle,当你进入下一个界面的时候你没有了上个界面的handler句柄,所以返回的消息你也没法处理。 所以你可以考虑两种方式: 一种是在Service里边去创建Socket,用广播的方式或者Intent和service通信。 二是用单例的形式管理Socket,在一个Activity创建以后,可以通过单例添加收到数据的回调或者发送数据。
qq_493397330 2016-07-27
  • 打赏
  • 举报
回复
求大神翻牌
qq_493397330 2016-07-27
  • 打赏
  • 举报
回复
那么请问主页面跳转以后的页面应该如何写代码??主要是一些button 当button被按下时,向服务器发送数据
qq_493397330 2016-07-27
  • 打赏
  • 举报
回复
主页面code package com.test.ceshi; //import java.io.BufferedReader; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.net.Socket; import java.net.SocketAddress; import java.net.UnknownHostException; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity implements Button.OnClickListener { public static MainActivity instance = null; private final String TAG="TTTTTT"; private static final int DATA_GET_ERROR = 2; private static final int DATA_GET_FAILED = 1; private static final int DATA_GET_OK = 0; private final String HEAD_MODE = "/setsource:d,"; private final String END_MODE = ","; private final String HEAD_OUT = "/SetPRESET:d,"; private final String END_OUT = ";\r\n"; private Button but_con; private ImageButton ib0; private ImageButton ib1; private Spinner sp; private EditText ip1; private EditText port1; private TextView text1; private Handler mHandler; private HandlerThread mHandlerThread; public PrintStream mOut = null; public InputStreamReader mRev = null; public Socket mSocket = null; private BufferedReader mIn = null; public OutputStreamWriter mOs=null; public BufferedWriter mBw=null; // 定义与服务器通信的子线程 ClientThread clientThread; public String mstr = "TEST wait for info"; private void initui() { text1 = ((TextView)findViewById(R.id.TS));//提示信息框 ip1 = ((EditText)findViewById(R.id.ip));//ip地址输入框 ip1.setText("192.168.1.199"); port1 = ((EditText)findViewById(R.id.port));//端口地址输入端 port1.setText("5000"); text1.setText("TEST MODE"); but_con = ((Button)findViewById(R.id.connect)); ib0=(ImageButton)findViewById(R.id.imageButton1); ib1=(ImageButton)findViewById(R.id.imageButton2); but_con.setOnClickListener(this); ib0.setOnClickListener(this); ib1.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { default: return; case R.id.imageButton1: try { Toast.makeText(this, "调出画面", Toast.LENGTH_SHORT).show(); Intent intent=new Intent(); intent.setClass(MainActivity.this,Diaochu.class); startActivity(intent); } catch (Exception e) { } return; case R.id.imageButton2: try { Toast.makeText(this, "切换画面输入源",Toast.LENGTH_SHORT).show(); Intent intent=new Intent(); intent.setClass(MainActivity.this,Qiehuan.class); startActivity(intent); } catch (Exception e) { } return;}} private void initClientSocket() { String ip=ip1.getText().toString(); int port=Integer.parseInt(port1.getText().toString()); //将端口输入数据转换为字符串 clientThread = new ClientThread(mHandler,ip,port,3000); // 客户端启动ClientThread线程创建网络连接、读取来自服务器的数据 Thread myThread =new Thread(clientThread); myThread.setDaemon(true); myThread.start(); } private void sendMessage(String cmd) { Message msg = new Message(); msg.what = 0x345; msg.obj =cmd; clientThread.revHandler.sendMessage(msg); } public void toastText(String message) { Toast.makeText(this, message, Toast.LENGTH_LONG).show(); } public void handleException(Exception e, String prefix) { e.printStackTrace(); toastText(prefix + e.toString()); } public void closeSocket() { try { mOut.close(); mSocket.close(); } catch (IOException e) { handleException(e, "close exception: "); } } //override onKeyDown 和 onOptionsMenuClosed这个两个函数就可以实现,具体代码如下: @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_MENU) { // 在这里做你想做的事情 super.openOptionsMenu(); // 调用这个,就可以弹出菜单 } return true; // 最后,一定要做完以后返回 true,或者在弹出菜单后返回true,其他键返回super,让其他键默认 } @Override public void onOptionsMenuClosed(Menu menu) { //在这里做你想做的事情 super.onOptionsMenuClosed(menu); } // 然后是对menu菜单的配置,如下: @Override public void openOptionsMenu() { // TODO Auto-generated method stub super.openOptionsMenu(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // TODO Auto-generated method stub super.onCreateOptionsMenu(menu); int group1 = 1; int gourp2 = 2; menu.add(group1, 1, 1, "退出"); // menu.add(group1, 2, 2, "item 12"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub switch (item.getItemId()) { case 1: // do something here Log.i("MenuTest:", "ItemSelected:1"); // 在Android应用开发中我们所知道的结束当前Activity可以使用finish();函数,但是要结束我们当前的这个应用程序(不一定是单个Activity.),需要用什么方法呢, 好多朋友应该还不知道,今天,给大家介绍两种退出的方法(kill Application). 看代码: /* 方法1 */ // android.os.Process.killProcess(android.os.Process.myPid()); /* 方法2 */ System.exit(0); break; case 2: // do something here Log.i("MenuTest:", "ItemSelected:2"); break; default: return super.onOptionsItemSelected(item); } return true; } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);//主函数程序起点 setContentView(R.layout.activity_main); instance = this; initui();//初始化 but_con.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { try { initClientSocket() ;//通信进程初始化 } catch (Exception e) { Log.e("TTTTTT", "connect server init failed --" + e); //mHandler.sendEmptyMessage(INIT_ERROR); } // but_con.setText("断开"); } }); mHandlerThread = new HandlerThread("DataGet"); mHandlerThread.start(); //mHandler = new DataGetHandler(mHandlerThread.getLooper()); mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.arg1) { case DATA_GET_OK: { Log.d(TAG, "get data from server Ok"); text1.setText(mstr); break; } case DATA_GET_FAILED: { Log.d(TAG, "get data from server failed"); text1.setText(mstr); break; } case DATA_GET_ERROR: { Log.d(TAG, "get data from server failed"); text1.setText(mstr); break; } } // 如果消息来自子线程 if (msg.what == 0x123) { Log.e("TTTTTT", "connect server init failed --" + msg.obj.toString()); // 将读取的内容追加显示在文本框中 text1.setText(msg.obj.toString()); } super.handleMessage(msg); } }; } protected void onPause() { super.onPause(); } protected void onResume() { super.onResume(); } protected void onStop() { super.onStop(); }}

80,490

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧