最近在项目开发中,需要用到一台android设备去控制另一台android设备的显示。
第一次尝试的做法是使用组播的方式,由一台主控设备发消息给受控设备。
但是,由于组播发送消息的模式是发送一个数据包,也就是udp。
了解过一点网络方面知识的人都知道,udp传输是不可靠的,数据包发过去了,接不接收得到是不管的,
所以这样的做法导致,虽然数据包发过去了,但是不能每次都能成功接收到。但是项目必须是每次发都能接收到数据的,所以不采用组播的方式。
最后选择使用TCP连接的方式来做,这种方式就是可靠的。
具体的udp,tcp的知识,有需要了解的就在网上查找吧,这里就不做解释了。
一、首先先上图
1、控制端,无连接状态
打开控制端的界面是这样显示的,因为只是个例子,所以请自动忽略美观吧。
2、再来张无连接状态的受控端图
但是这个无连接状态是在没有打开控制端的时候才这样显示的,当控制端先打开的时候,受控端界面是这样的
然后控制端界面立即显示
当看到两端的界面如上图所示,则代表两端已经连接,这时候就可以开始操作发送数据了。
二、接下来就让控制端发个消息给受控端
其实发消息很简单,只需要点击一下控制端界面中的 “发送数据给客户端” 即可,
然后受控端就能接收到消息
这样受控端就成功收到消息了,这时候受控端可以根据收到的数据进行显示了,
例子就是这么简单粗暴。
三、好像还缺少了点什么?
看到这里应该会发出 “我勒个去,没代码说个毛线啊!!!”。
第一次写文章,先包涵着看嘛。
代码来了:
1、控制端
首先,tcp连接是需要设备的ip的,所以先贴出查设备ip的代码先
/***
* 使用WIFI时,获取本机IP地址
*
* @param mContext
* @return
*/
private static String getWIFILocalIpAddress(Context mContext) {
//获取wifi服务
WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
//判断wifi是否开启
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
String ip = formatIpAddress(ipAddress);
return ip;
}
private static String formatIpAddress(int ipAdress) {
return (ipAdress & 0xFF) + "." +
((ipAdress >> 8) & 0xFF) + "." +
((ipAdress >> 16) & 0xFF) + "." +
(ipAdress >> 24 & 0xFF);
}
这代码也是网上看到的,具体在哪篇文章看到的忘记了,如果作者看到这篇文章后需要我写明出处的,请联系我,我好贴出来,包涵啊。
当然,读取ip是需要手机权限的,我就把这个小项目需要用到的权限先贴出来了,也不多,就几个
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.INTERNET"/>
好了,先获取到ip,接下来有用。
那么监听tcp的连接请求:
try {
Boolean endFlag = false;
ServerSocket ss = new ServerSocket(8800);
while (!endFlag) {
// 等待客户端连接
Socket s = ss.accept();
addIPToList(s);
//读取客户端发来的消息
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
String message = input.readLine();
Log.e("来自客户端的消息 : ", message);
//向客户端发送消息
//注意第二个参数据为true将会自动flush,否则需要需要手动操作output.flush()
mOutput = new PrintWriter(s.getOutputStream(), true);
mOutput.println("已连接到服务器!!!");
}
ss.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
当然,记得这段代码需要放在子线程中运行。
发送消息:
if (ips != null && ips.size() > 0) {
for (int i = 0; i < ips.size(); i++) {
try {
Socket next = ips.get(i);
PrintWriter out=new PrintWriter(new BufferedWriter(new OutputStreamWriter(next.getOutputStream(),"UTF-8")),true);
out.println(s);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
到这里,你可能发现了一个 ips 的变量了吧,这个是一个存放受控端Socket的集合,Socket就是从连接请求代码中的 addIPToList(s) 方法中添加进去的,
既然是个集合,你应该想到这也可以发送给多个受控端吧,也就是可以控制多个设备的意思了。
2、受控端
请求连接的代码:
new Thread(new Runnable() {
@Override
public void run() {
try {
mS = new Socket(ip, 8800);
// outgoing stream redirect to socket
OutputStream out = mS.getOutputStream();
// 注意第二个参数据为true将会自动flush,否则需要需要手动操作out.flush()
mOutput = new PrintWriter(out, true);
mOutput.println("Hello IdeasAndroid!");
mInput = new BufferedReader(new InputStreamReader(mS
.getInputStream(),"UTF-8"));
String mMessage;
while (true) {
try {
if ((mMessage = mInput.readLine()) != null) {
String decode = URLDecoder.decode(mMessage, "UTF-8");
//这里加“-”是为了避免得到的字符串前面有多了奇怪的字符,测试中有遇到过,加“-”完再截取让得到的字符串准确
if (decode.contains("{") && decode.contains("}")){
decode = "-"+decode+"-";
int i = decode.indexOf("{");
int j = decode.lastIndexOf("}");
decode = decode.substring(i, j+1);
}
Message message1 = Message.obtain();
message1.obj = decode;
mHandler.sendMessage(message1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
看到上面的ip变量了吧,这个就是上面说需要用到的控制端ip了。
中间那段对字符串的判断,由于发送的是java对象的json字符串,如果不是json字符串,也同样可以收到。
显示收到的信息:
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e("接收到字符串 === ", (String) msg.obj);
String beanString = (String) msg.obj;
if (beanString.contains("{")){
mGson = new Gson();
Bean bean = mGson.fromJson(beanString, Bean.class);
mTvShow.setText("名字 = "+bean.getName()+"\n"+"时间 : "+bean.getTime());
}else {
mTvShow.setText(beanString);
}
}
};
好了,基本上关键代码都贴出来了。
因为是第一次写,写的不好。好想很多都将详细,但是好像那样太啰嗦了点。