Android项目笔记四:Android端的socket客户端建立
2016-06-02 14:35
615 查看
Android的UI线程(主线程)不能操作费时、阻塞的操作,会影响用户体验,所以socket的创建不能再UI线程中;
Android中除了UI线程外,其它线程不能操作UI控件显示,但是可以直接调用创建它所在UI线程内其它变量;
Android线程间通信,用handler,handler中可以Bundle消息;
Android中socket接收不能再UI线程中,发送可以在任意线程;
思路:
1、单独创建一个线程,创建socket,一旦成功,本线程自动退出,销毁;
2、一旦创建socket成功,创建一个监听线程,用于监听从HOST发过来数据;
3、在UI线程中,通过 handleMessage处理从其它线程传进来的消息;
代码:
创建socket:
public void setMy_MainActivityCreateSocketThread(){
//起一个监听 socket 线程
my_mian_socket_create_thread = new Thread(new Runnable() {
@Override
public void run() {
CreateSocketThreadisRun = true;
while (CreateSocketThreadisRun) {
Message CreateSocketThreadtoMainUI = new Message();
CreateSocketThreadtoMainUI.what = 255;
String result;
if (my_MainActivitySocket()) {
CreateSocketThreadtoMainUI.arg1 = 1;
CreateSocketThreadisRun = false;
result = "连接主机成功!!!";
} else {
CreateSocketThreadtoMainUI.arg1 = 2;
result = "连接主机失败!!!";
CreateSocketThreadisRun = true;
}
if(CreateSocketThreadisRun) {
try {
if(my_main_wifi.isWiFiActive(MainActivity.this)) {
my_mian_socket_create_thread.sleep(4000);
}else {
CreateSocketThreadisRun = false;
CreateSocketThreadtoMainUI.arg1 = 3;
result = "wifi断开连接!!!";
}
} catch (InterruptedException e) {
//其它线程中断当前线程异常
e.printStackTrace();
CreateSocketThreadisRun = false;
}
}
CreateSocketThreadtoMainUI.obj = result;
my_MainActivityClient.sendMessage(CreateSocketThreadtoMainUI);
CreateSocketThreadtoMainUI = null;
}
my_mian_socket_create_thread = null;
SocketThreadisCreating = false;
}
});
my_mian_socket_create_thread.start();
}
//创建Socke通信
public boolean my_MainActivitySocket(){
if(!my_MainActivitySocketClose()){
return false;
}
my_mainSocketReceiveThread=null;
//尝试创建一个Socket
/* try {
String HostiIP=my_main_wifi.my_getHOSTIp_String(MainActivity.this);
my_main_clientSocket = new Socket(HostiIP,my_HOST_port); //异常抛出时间为15s
*//*my_main_clientSocket.connect(new InetSocketAddress(HostiIP,my_HOST_port),3000);*//*
}catch (UnknownHostException e){
e.printStackTrace();
return false;
}catch (IOException e){
e.printStackTrace();
return false;
}*/
try {
String HostiIP=my_main_wifi.my_getHOSTIp_String(MainActivity.this);
my_main_clientSocket = new Socket();
my_main_clientSocket.connect(new InetSocketAddress(HostiIP,my_HOST_port),3000);
}catch (IllegalArgumentException e){
my_main_clientSocket=null;
return false;
}catch (IOException e){
e.printStackTrace();
my_main_clientSocket=null;
return false;
}
my_mainSocketReceiveThread = new SocketReceiveThread(my_main_clientSocket,my_MainActivityClient);
my_mainSocketReceiveThread.start();
return true;
}
要点:
1、创建新的socket前,一定判断之前有没有创建,如果有,一定要线关闭;
2、在关闭socket之前,先关闭输入流;
socket发送:
private void my_SocketSend(byte[] snedData,String sendStr){
if(null == my_main_clientSocket){
Toast.makeText(MainActivity.this,"未连接主机",Toast.LENGTH_SHORT).show();
return;
}
OutputStream sendSocketStream=null;
try {
if(null != sendStr){
snedData = sendStr.getBytes("GB2312");
}
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}
try {
sendSocketStream = my_main_clientSocket.getOutputStream();
}catch (IOException e){
e.printStackTrace();
}
try {
sendSocketStream.write(snedData);
}catch (IOException e){
e.printStackTrace();
}
}
要点:
sendSocketStream不要调用sendSocketStream.close(),否则HOST接收那边异常;
监听线程:
监听线程我写了一个CLASS
/**
* Created by Administrator on 2016/5/19.
*/
public class SocketReceiveThread extends Thread {
private InputStream receiveStream = null;
private boolean isStop=false;
String receiveStr;
private byte receivebuf[]=null;
protected Handler UIHandler=null;
private Socket threadSocket=null;
private MyMath myMath = new MyMath();
SocketReceiveThread(Socket socket,Handler handler){
try {
UIHandler=handler;
this.receiveStream = socket.getInputStream();
threadSocket=socket;
isStop=false;
}catch (IOException e){
e.printStackTrace();
}
}
@Override
public void run(){
this.receivebuf = new byte[200];
byte[] tempDATA;
int receivebufLong=0;
while(!isStop){
if(isStop) {
return;
}
try {
receivebufLong=this.receiveStream.read(this.receivebuf);//线程阻塞
}catch (IOException e){
e.printStackTrace();
Message msg = new Message();
msg.what=1;
msg.arg1=1;//出现异常
UIHandler.sendMessage(msg);
return;
}catch (NullPointerException e){
e.printStackTrace();
Message msg = new Message();
msg.what=1;
msg.arg1=1;//出现异常
UIHandler.sendMessage(msg);
return;
}
if(isStop) {
return;
}
//判断出异常
if((-1 == receivebufLong) || (0 == receivebufLong)){
Message msg = new Message();
msg.what=1;
msg.arg1=2;//Host意外断开
UIHandler.sendMessage(msg);
return;
}
tempDATA = RingBuffer(this.receivebuf);
if(null == tempDATA){
continue;
}
Bundle msgBundle = myBusinessLogic(tempDATA);
if(null == msgBundle){
continue;
}
Message msg = new Message();
msg.what=0;
msg.arg1=tempDATA[2];
msg.setData(msgBundle);
UIHandler.sendMessage(msg);
/* try {
this.receiveStr = new String(this.receivebuf,"GB2312").trim();
}catch (UnsupportedEncodingException e){
e.printStackTrace();
continue;
}
Message msg = new Message();
msg.what=0;
msg.obj=this.receiveStr;
UIHandler.sendMessage(msg);*/
//清除资源
msgBundle = null;
msg = null;
tempDATA = null;
receivebufLong=0;
}
}
public void SocketReceiveThread_Stop(){
this.isStop = true;
try {
this.receiveStream.close();
}catch (IOException e){
e.printStackTrace();
}
/* try {
threadSocket.close();
}catch (IOException e){
e.printStackTrace();
}*/
this.receiveStream = null;
this.receivebuf=null;
threadSocket=null;
/*UIHandler=null;*/
}
//业务逻辑
private Bundle myBusinessLogic(byte[] inData){
Bundle bundleBusiness = null;
float mValue=0;
float mTemp=0;
int temp=0;
int tempH = 0;
int tempL = 0;
if(null == inData){
return bundleBusiness;
}
//读取数值
if(0x05 == inData[4]){
temp = myMath.myMathClass_rand(20000);
}else if (0x07 == inData[4]){
tempH = inData[8];
tempH = (tempH << 8) & 0x0000FF00;
tempL = inData[9];
tempL = tempL & 0x000000FF;
temp = tempH | tempL | 0x00000000;
}else {
return bundleBusiness;
}
mValue = temp;
mValue = mValue/10;
String strNoteValue = "NoteValue";
String strNoteValue_Value = mValue +"";
//读取温度
tempH = inData[6];
tempH = (tempH << 8) & 0x0000FF00;
tempL = inData[7];
tempL = tempL & 0x000000FF;
if((inData[6] == 0x80) && (inData[7] == 0x00)){
//得到最大的负数
temp = -32768;
}else if((inData[6] & 0x80) == 0x80){
//负数
temp = tempH | tempL | 0xFFFF0000;
}else {
//正数
temp = tempH | tempL | 0x00000000;
}
mTemp = temp;
mTemp = mTemp/10;
String strNoteTemp = "NoteTemp";
String strNoteTemp_Value = mTemp +"";
bundleBusiness = new Bundle();
bundleBusiness.putCharSequence(strNoteValue,strNoteValue_Value);
bundleBusiness.putCharSequence(strNoteTemp,strNoteTemp_Value);
return bundleBusiness;
}
//环形缓存区
public byte[] RingBuffer(byte[] inData){
byte[] userData = null;
int inDataLong=0;
int i=0;
int ProtocolFrame_Heard;
int ProtocolFrame_Long;
int tempCRC=0;
inDataLong = inData.length;
for(i=0;i<inDataLong;i++){
if((0x68 == inData[i]) && (0x68 == inData[i+3])){
break;
}
}
if(i >= inDataLong){
return userData;
}
ProtocolFrame_Heard = i;
if((ProtocolFrame_Heard+4) > inDataLong){
return userData;
}
ProtocolFrame_Long = inData[ProtocolFrame_Heard+4] + 5;
if((ProtocolFrame_Long + ProtocolFrame_Heard) > inDataLong){
return userData;
}
userData = new byte[ProtocolFrame_Long];
for(i=0;i<ProtocolFrame_Long;i++){
userData[i] = inData[ProtocolFrame_Heard + i];
}
int tempCRCH = 0;
int tempCRCL = 0;
tempCRCH = userData[ProtocolFrame_Long - 2];
tempCRCH = (tempCRCH << 8) & 0x0000FF00;
tempCRCL = userData[ProtocolFrame_Long - 1];
tempCRCL = tempCRCL & 0x000000FF;
tempCRC = (tempCRCH | tempCRCL) & 0x0000FFFF;
if(!myMath.CRC16(userData,ProtocolFrame_Long - 2,tempCRC)){
userData = null;
}
return userData;
}
}
要点:
receivebufLong=this.receiveStream.read(this.receivebuf);//在正常情况下是阻塞的,
HOST突然断电,receivebufLong = -1;
HOST关闭端口,可能是异常,我没有仔细测试;
根据这些,把消息发给上层,重新发起socket连接;
UI接收消息处理:
my_MainActivityClient = new Handler(){
@Override
public void handleMessage(Message msg){
switch (msg.what){
case 0://socke接收到服务器消息
my_Main_BusinessLogic_Receicve(msg.getData(),msg.arg1);
break;
case 1://socket接收监听线程异常消息
//my_MainActivitySocketClose();
switch (msg.arg1){
case 1://接收线程发出消息,在SocketReceiveThread
System.out.println("Host 出现异常!");
break;
case 2://接收线程发出消息,在SocketReceiveThread
System.out.println("Host 断开连接!");
break;
case 3://业务逻辑发出消息,在MainActivity
System.out.println("socket接收超时");
break;
}
if(!my_main_APPisClose && (!SocketThreadisCreating)) {
setMy_MainActivityCreateSocketThread();//防止关闭socket引起的异常导致重新建立连接
SocketThreadisCreating = true;
}
break;
case 255://创建socket线程消息
System.out.println(msg.obj.toString());
switch (msg.arg1){
case 1://主机连接成功
//应该添加消息过滤,防止重复发送,怎么添加呢???
my_MainActivityHandler.postDelayed(my_MainActivityStartBusiness, 10);
break;
case 2://主机连接失败
break;
case 3://wifi断开
MainActivity.this.my_toMySocketActivity(null,0);
break;
}
break;
}
super.handleMessage(msg);
}
};//END handleMessage(Message msg)
Android中除了UI线程外,其它线程不能操作UI控件显示,但是可以直接调用创建它所在UI线程内其它变量;
Android线程间通信,用handler,handler中可以Bundle消息;
Android中socket接收不能再UI线程中,发送可以在任意线程;
思路:
1、单独创建一个线程,创建socket,一旦成功,本线程自动退出,销毁;
2、一旦创建socket成功,创建一个监听线程,用于监听从HOST发过来数据;
3、在UI线程中,通过 handleMessage处理从其它线程传进来的消息;
代码:
创建socket:
public void setMy_MainActivityCreateSocketThread(){
//起一个监听 socket 线程
my_mian_socket_create_thread = new Thread(new Runnable() {
@Override
public void run() {
CreateSocketThreadisRun = true;
while (CreateSocketThreadisRun) {
Message CreateSocketThreadtoMainUI = new Message();
CreateSocketThreadtoMainUI.what = 255;
String result;
if (my_MainActivitySocket()) {
CreateSocketThreadtoMainUI.arg1 = 1;
CreateSocketThreadisRun = false;
result = "连接主机成功!!!";
} else {
CreateSocketThreadtoMainUI.arg1 = 2;
result = "连接主机失败!!!";
CreateSocketThreadisRun = true;
}
if(CreateSocketThreadisRun) {
try {
if(my_main_wifi.isWiFiActive(MainActivity.this)) {
my_mian_socket_create_thread.sleep(4000);
}else {
CreateSocketThreadisRun = false;
CreateSocketThreadtoMainUI.arg1 = 3;
result = "wifi断开连接!!!";
}
} catch (InterruptedException e) {
//其它线程中断当前线程异常
e.printStackTrace();
CreateSocketThreadisRun = false;
}
}
CreateSocketThreadtoMainUI.obj = result;
my_MainActivityClient.sendMessage(CreateSocketThreadtoMainUI);
CreateSocketThreadtoMainUI = null;
}
my_mian_socket_create_thread = null;
SocketThreadisCreating = false;
}
});
my_mian_socket_create_thread.start();
}
//创建Socke通信
public boolean my_MainActivitySocket(){
if(!my_MainActivitySocketClose()){
return false;
}
my_mainSocketReceiveThread=null;
//尝试创建一个Socket
/* try {
String HostiIP=my_main_wifi.my_getHOSTIp_String(MainActivity.this);
my_main_clientSocket = new Socket(HostiIP,my_HOST_port); //异常抛出时间为15s
*//*my_main_clientSocket.connect(new InetSocketAddress(HostiIP,my_HOST_port),3000);*//*
}catch (UnknownHostException e){
e.printStackTrace();
return false;
}catch (IOException e){
e.printStackTrace();
return false;
}*/
try {
String HostiIP=my_main_wifi.my_getHOSTIp_String(MainActivity.this);
my_main_clientSocket = new Socket();
my_main_clientSocket.connect(new InetSocketAddress(HostiIP,my_HOST_port),3000);
}catch (IllegalArgumentException e){
my_main_clientSocket=null;
return false;
}catch (IOException e){
e.printStackTrace();
my_main_clientSocket=null;
return false;
}
my_mainSocketReceiveThread = new SocketReceiveThread(my_main_clientSocket,my_MainActivityClient);
my_mainSocketReceiveThread.start();
return true;
}
要点:
1、创建新的socket前,一定判断之前有没有创建,如果有,一定要线关闭;
2、在关闭socket之前,先关闭输入流;
socket发送:
private void my_SocketSend(byte[] snedData,String sendStr){
if(null == my_main_clientSocket){
Toast.makeText(MainActivity.this,"未连接主机",Toast.LENGTH_SHORT).show();
return;
}
OutputStream sendSocketStream=null;
try {
if(null != sendStr){
snedData = sendStr.getBytes("GB2312");
}
}catch (UnsupportedEncodingException e){
e.printStackTrace();
}
try {
sendSocketStream = my_main_clientSocket.getOutputStream();
}catch (IOException e){
e.printStackTrace();
}
try {
sendSocketStream.write(snedData);
}catch (IOException e){
e.printStackTrace();
}
}
要点:
sendSocketStream不要调用sendSocketStream.close(),否则HOST接收那边异常;
监听线程:
监听线程我写了一个CLASS
/**
* Created by Administrator on 2016/5/19.
*/
public class SocketReceiveThread extends Thread {
private InputStream receiveStream = null;
private boolean isStop=false;
String receiveStr;
private byte receivebuf[]=null;
protected Handler UIHandler=null;
private Socket threadSocket=null;
private MyMath myMath = new MyMath();
SocketReceiveThread(Socket socket,Handler handler){
try {
UIHandler=handler;
this.receiveStream = socket.getInputStream();
threadSocket=socket;
isStop=false;
}catch (IOException e){
e.printStackTrace();
}
}
@Override
public void run(){
this.receivebuf = new byte[200];
byte[] tempDATA;
int receivebufLong=0;
while(!isStop){
if(isStop) {
return;
}
try {
receivebufLong=this.receiveStream.read(this.receivebuf);//线程阻塞
}catch (IOException e){
e.printStackTrace();
Message msg = new Message();
msg.what=1;
msg.arg1=1;//出现异常
UIHandler.sendMessage(msg);
return;
}catch (NullPointerException e){
e.printStackTrace();
Message msg = new Message();
msg.what=1;
msg.arg1=1;//出现异常
UIHandler.sendMessage(msg);
return;
}
if(isStop) {
return;
}
//判断出异常
if((-1 == receivebufLong) || (0 == receivebufLong)){
Message msg = new Message();
msg.what=1;
msg.arg1=2;//Host意外断开
UIHandler.sendMessage(msg);
return;
}
tempDATA = RingBuffer(this.receivebuf);
if(null == tempDATA){
continue;
}
Bundle msgBundle = myBusinessLogic(tempDATA);
if(null == msgBundle){
continue;
}
Message msg = new Message();
msg.what=0;
msg.arg1=tempDATA[2];
msg.setData(msgBundle);
UIHandler.sendMessage(msg);
/* try {
this.receiveStr = new String(this.receivebuf,"GB2312").trim();
}catch (UnsupportedEncodingException e){
e.printStackTrace();
continue;
}
Message msg = new Message();
msg.what=0;
msg.obj=this.receiveStr;
UIHandler.sendMessage(msg);*/
//清除资源
msgBundle = null;
msg = null;
tempDATA = null;
receivebufLong=0;
}
}
public void SocketReceiveThread_Stop(){
this.isStop = true;
try {
this.receiveStream.close();
}catch (IOException e){
e.printStackTrace();
}
/* try {
threadSocket.close();
}catch (IOException e){
e.printStackTrace();
}*/
this.receiveStream = null;
this.receivebuf=null;
threadSocket=null;
/*UIHandler=null;*/
}
//业务逻辑
private Bundle myBusinessLogic(byte[] inData){
Bundle bundleBusiness = null;
float mValue=0;
float mTemp=0;
int temp=0;
int tempH = 0;
int tempL = 0;
if(null == inData){
return bundleBusiness;
}
//读取数值
if(0x05 == inData[4]){
temp = myMath.myMathClass_rand(20000);
}else if (0x07 == inData[4]){
tempH = inData[8];
tempH = (tempH << 8) & 0x0000FF00;
tempL = inData[9];
tempL = tempL & 0x000000FF;
temp = tempH | tempL | 0x00000000;
}else {
return bundleBusiness;
}
mValue = temp;
mValue = mValue/10;
String strNoteValue = "NoteValue";
String strNoteValue_Value = mValue +"";
//读取温度
tempH = inData[6];
tempH = (tempH << 8) & 0x0000FF00;
tempL = inData[7];
tempL = tempL & 0x000000FF;
if((inData[6] == 0x80) && (inData[7] == 0x00)){
//得到最大的负数
temp = -32768;
}else if((inData[6] & 0x80) == 0x80){
//负数
temp = tempH | tempL | 0xFFFF0000;
}else {
//正数
temp = tempH | tempL | 0x00000000;
}
mTemp = temp;
mTemp = mTemp/10;
String strNoteTemp = "NoteTemp";
String strNoteTemp_Value = mTemp +"";
bundleBusiness = new Bundle();
bundleBusiness.putCharSequence(strNoteValue,strNoteValue_Value);
bundleBusiness.putCharSequence(strNoteTemp,strNoteTemp_Value);
return bundleBusiness;
}
//环形缓存区
public byte[] RingBuffer(byte[] inData){
byte[] userData = null;
int inDataLong=0;
int i=0;
int ProtocolFrame_Heard;
int ProtocolFrame_Long;
int tempCRC=0;
inDataLong = inData.length;
for(i=0;i<inDataLong;i++){
if((0x68 == inData[i]) && (0x68 == inData[i+3])){
break;
}
}
if(i >= inDataLong){
return userData;
}
ProtocolFrame_Heard = i;
if((ProtocolFrame_Heard+4) > inDataLong){
return userData;
}
ProtocolFrame_Long = inData[ProtocolFrame_Heard+4] + 5;
if((ProtocolFrame_Long + ProtocolFrame_Heard) > inDataLong){
return userData;
}
userData = new byte[ProtocolFrame_Long];
for(i=0;i<ProtocolFrame_Long;i++){
userData[i] = inData[ProtocolFrame_Heard + i];
}
int tempCRCH = 0;
int tempCRCL = 0;
tempCRCH = userData[ProtocolFrame_Long - 2];
tempCRCH = (tempCRCH << 8) & 0x0000FF00;
tempCRCL = userData[ProtocolFrame_Long - 1];
tempCRCL = tempCRCL & 0x000000FF;
tempCRC = (tempCRCH | tempCRCL) & 0x0000FFFF;
if(!myMath.CRC16(userData,ProtocolFrame_Long - 2,tempCRC)){
userData = null;
}
return userData;
}
}
要点:
receivebufLong=this.receiveStream.read(this.receivebuf);//在正常情况下是阻塞的,
HOST突然断电,receivebufLong = -1;
HOST关闭端口,可能是异常,我没有仔细测试;
根据这些,把消息发给上层,重新发起socket连接;
UI接收消息处理:
my_MainActivityClient = new Handler(){
@Override
public void handleMessage(Message msg){
switch (msg.what){
case 0://socke接收到服务器消息
my_Main_BusinessLogic_Receicve(msg.getData(),msg.arg1);
break;
case 1://socket接收监听线程异常消息
//my_MainActivitySocketClose();
switch (msg.arg1){
case 1://接收线程发出消息,在SocketReceiveThread
System.out.println("Host 出现异常!");
break;
case 2://接收线程发出消息,在SocketReceiveThread
System.out.println("Host 断开连接!");
break;
case 3://业务逻辑发出消息,在MainActivity
System.out.println("socket接收超时");
break;
}
if(!my_main_APPisClose && (!SocketThreadisCreating)) {
setMy_MainActivityCreateSocketThread();//防止关闭socket引起的异常导致重新建立连接
SocketThreadisCreating = true;
}
break;
case 255://创建socket线程消息
System.out.println(msg.obj.toString());
switch (msg.arg1){
case 1://主机连接成功
//应该添加消息过滤,防止重复发送,怎么添加呢???
my_MainActivityHandler.postDelayed(my_MainActivityStartBusiness, 10);
break;
case 2://主机连接失败
break;
case 3://wifi断开
MainActivity.this.my_toMySocketActivity(null,0);
break;
}
break;
}
super.handleMessage(msg);
}
};//END handleMessage(Message msg)
相关文章推荐
- android图形系统详解
- Android6.0 wakelock深入分析
- Android开发者指南-运动传感器Motion Sensor[原创译文]
- Android性能优化之渲染篇
- 关于android.os.SystemProperties的使用
- Android 文件打开方式(转)
- Android省市区三级联动滚轮选择
- word/excel在android读取,写入,更新数据
- Android应用性能优化之使用SparseArray替代HashMap
- android WindowLeaked异常的解决方法
- Android 自定义带有清除按钮的Edittext
- Android代码实现状态选择器
- android-PullRefreshLayout——Android下拉刷新布局组件
- android Debug模式如何签名
- AndroidViewHover(Android高斯模糊低版本兼容)使用总结
- Android跨进程通信二——AIDL
- 【Android新手笔记四】activity之间的数据共享
- ionic ng-src 在网页显示,但是导出apk在android手机中运行不显示图片
- Android设备中实现陀螺仪(Orientation Sensor)
- Android开发实战总结--编程规范(持续更新中...)