一、Android:Socket客户端开发
创建一个工程
我们要做的是按下按键之后,去往服务器
(服务器)
或者我们自己写的服务器
,给他发送一些预定好的东西
然后打开操作界面
然后修改一下
你要发送消息,需要
android:onClick="sendMessage"
然后在这里
修改一下
如何发送?
CTRL + shirt + o 打包
当按键被按下的时候,我们就做这些
把这些扔进来
当按键被按下的时候,我们调用 sendMessage 这个东西
调用这个东西我们干啥呢? 连接 Socket client = new Socket("192.168.70.1", 9002);
OutputStream out= client.getOutputStream();
连接以后我们不要用 Scanner sc = new Scanner(System.in);
String message = sc.next();
我们定义一个 String message = "message from Android";
out.write(message.getBytes()); 这句话也得改一下
然后
InputStream in = client.getInputStream();
int len;
byte[]data = new byte[128];
len = in.read(data);
System.out.println("获得服务端返回数据是:"+new String(data,0,len));
先不做, 获得数据我们先不做,先发一个数据
现在 的代码
运行一下
在夜神模拟器上显示的结果
点一下发送信息
然后我们试一下,之前写过的JavaSocket服务端
运行一下
显示 等待连接
然后,我们点击一下 夜神模拟器上面的发送消息
显示已经停止运行
然后logCat最大化
我们从第三行红字开始看
再看一下caused by
Network网络访问 onMainThreadException 放在主线程里面的异常
他不让你在主线程里面发送网络访问
开始我们看第三行,还以为方法找不到吗,实际上它找到了,找到以后进行网络访问的时候崩了,他不让你在主线程里面做网络访问
那如何解决呢?
把
try {
Socket client = new Socket("192.168.70.1",9002);
OutputStream out= client.getOutputStream();
String message = "message from Android";
out.write(message.getBytes());
//
// InputStream in = client.getInputStream();
// int len;
// byte[]data = new byte[128];
// len = in.read(data);
// System.out.println("获得服务端返回数据是:"+new String(data,0,len));
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
这个东西做成函数分装
public void sendMessageHandler()
{
}
然后在这个handler里面,做真正的网络请求,就是try那一部分
按键被按下的时候,我们是不是要启动一个线程呀 new Thread().strat();
在Thread(). 加上new runnable
变成了
在Runnable里面做你真正想要做的事
现在的代码:
JavaSocket服务端
安卓Socket客户端:
先运行一下JavaSocket服务端
显示
修改一下28行
String message = "message from Android";
然后在运行一下 安卓Socket客户端:
运行结果
点击发送消息
然后显示:有客户端接入
读到消息:message from Android
补充:
,这里最好不要直接从别的地方复制过来代码,要不然容易显示错误
二、Android 的Socket客户端优化
那么如果我们有多个按键
然后我们把这四个拖拽一下,在改一下名字
在改一下id
然后我们在 MainActivity上面要做一个处理
而不是所有的都是走它 new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
sendMessageHandler();
}
}).start();
你在这里想干什么事?
再来个后退
但是有点不妥,不管前进还是后退,他调用的api都是一样的,发送的消息都是一样的
如何办呢?传参呗。
同时: 变成public void sendMessageHandler(String command)
out.write(message.getBytes());改成 out.write(command.getBytes());
这样函数就分装了
然后
String message = "message from Android";这句话就不要了
同理做出来左右的代码‘
运行一下
然后(记得先运行JAVASocket服务端,然后在运行安卓Socket客户端)
现在的代码,还能进行优化
你每个都在new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
sendMessageHandler("goback");
}
}).start();
然后把
try {
Socket client = new Socket("192.168.70.1", 8810);
OutputStream out= client.getOutputStream();
out.write(command.getBytes());
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
copy一下,放到run里面
可是现在的command我们拿不到
解决方法
下面也可以修改一下
如果想变得整齐的话
思路: 按键被按下的时候,根据不同的id做不同的事情
运行一下
现在的代码
还可以改动一下
你会发现这个方法是单独的
我们可以
然后
在改动一下,变成静态的变量
这样你主线程里面的代码就会很舒服
稍加改动一下
记得还要ctrl + shirt +o 把包导进来
运行一下
三、Android非UI线程修改控件程序崩溃的问题
我们安卓客户端进行网络访问,难免会收到来自服务端的消息,我们上面只是负责发,没有负责收
如果收到消息的话,我们希望让他显示在控件上面
里面的内容
先把没用的去掉
在这个Activity里面有一个TextView
给他来个id android:id="@+id/textView"
那么xml 和前面如何关联呢? 在.java 里面 public TextView textview;
记得ctrl + shirt + o 打包
然后
然后
然后
做一个强制转换,CTRL + 1 然后回车
我们下一步拖个按键进来
比如这个按键的目标是修改textView android:text="修改textView为lzp" />
在作一个测试的函数 android:onClick="testFunc"
然后在.Java里面
记得ctrl + shirt + o 打包
然后
修改一下内容
运行一下
点击一下
那如果我现在想要动态的 刷新
还需要try catch
然后
把 textView.setText("lizhaopeng"); 改成 textView.setText("lizhaopeng"+i);
运行一下
发现卡在这里不动了
那他有没有再跑?
看看能不捕捉到
System.out.println("lizhaopeng"+i);
运行一下,发现一点也没动
那01234567哪去了?
在UI线程中,不要sleep ,你真的想sleep你应该创建一个线程sleep new Thread().start();
你是不是想把 textView.setText("lizhaopeng"+i);放进去
但是现在这个i不认识
修改一下
按下按键以后,启动一个线程,这个线程里面去数秒,每隔一秒,修改一次标签
现在的代码
这样主线程就不会阻塞,UI线程就不会被sleep影响,在UI线程之外去操控UI
运行一下
崩调了
我们在UI上显示网络请求,肯定是在线程里面
只是我把网络请求这个事情,我们用for循环做一个简单除暴的信息的变化,然后刷到textView上面去,原理都一样