布局文件activity_socket.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SocketActivity">
<ImageView
android:id="@+id/socket_actionBar_bg"
android:layout_width="match_parent"
android:layout_height="64dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:background="@color/colorModel"/>
<ImageView
android:id="@+id/socket_back_bt"
android:layout_width="25dp"
android:layout_height="25dp"
app:layout_constraintBottom_toBottomOf="@+id/socket_actionBar_bg"
app:layout_constraintLeft_toLeftOf="@+id/socket_actionBar_bg"
android:layout_marginLeft="5dp"
android:layout_marginBottom="7dp"
android:padding="3dp"
android:src="@mipmap/back"
android:onClick="socket_backClick"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="@+id/socket_actionBar_bg"
app:layout_constraintBottom_toBottomOf="@+id/socket_actionBar_bg"
app:layout_constraintRight_toRightOf="@+id/socket_actionBar_bg"
android:layout_marginBottom="5dp"
android:text="@string/SocketActivity_title"
android:textColor="@color/colorWhite"
android:textSize="12pt"/>
<Button
android:id="@+id/socket_send_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/socket_actionBar_bg"
app:layout_constraintRight_toRightOf="@+id/socket_actionBar_bg"
android:layout_marginTop="20dp"
android:layout_marginRight="20dp"
android:text="Send"
android:textColor="@color/colorWhite"
android:background="@color/colorSelect"
android:onClick="socket_SendMessage"/>
<EditText
android:id="@+id/socket_command"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@+id/socket_send_button"
app:layout_constraintRight_toLeftOf="@+id/socket_send_button"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"/>
<TextView
android:id="@+id/socket_content"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@+id/socket_command"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_margin="20dp"
android:background="@color/colorBlack"
android:textColor="@color/colorWhite"
android:scrollbars="vertical"/>
</androidx.constraintlayout.widget.ConstraintLayout>
SocketActivity.java:
import android.content.Context;
import android.os.Bundle;
import android.os.Message;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SocketActivity extends AppCompatActivity implements MyHandler.InMyHandler{
//主线程Handler,用于将从服务器获取的消息显示出来
private MyHandler myHandler;
//采用线程池进行线程管理
private ExecutorService mThreadPool;
//Socket变量
private Socket socket;
//输出流
private OutputStream outputStream;
//服务器返回的数据转化为StringBuffer
private StringBuffer responseBuffer;
//UI控件
private EditText editText;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_socket);
//控件
editText = findViewById(R.id.socket_command);
textView = findViewById(R.id.socket_content);
textView.setMovementMethod(ScrollingMovementMethod.getInstance());
//初始化线程池
mThreadPool = Executors.newCachedThreadPool();
//获取处理消息的Handler单例
myHandler = MyHandler.getInstance();
//设置接口监听
myHandler.setInMyHandler(this);
//开启socket线程
socket_thread();
}
/**
*开启socket线程,连接,获取输入输出流
*/
private void socket_thread(){
//利用线程池开启一个线程并执行该线程
mThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
//创建Socket
socket = new Socket("192.168.0.xxx",1000);
//判断客户端和服务器是否连接成功
if (socket.isConnected()){
//连接成功,message.what=1
myHandler.sendEmptyMessage(1);
//获取socket的输出流
outputStream = socket.getOutputStream();
//输入流,读取服务器返回的数据
InputStream inputStream = socket.getInputStream();
//创建一个字节数组用来接收服务端发来的字节流,多大自己说了算
byte[] b = new byte[1024];
//写一个死循环,不停的接收服务端发来的数据
while (socket.isConnected()) {
//将数据读入字节数组,返回长度
int length = inputStream.read(b);
//如果服务端没发数据就return不在往下执行,继续读数据
if (length <= 0) return;
//如果服务端发的数据不为空,则把字节数组转成字符串
// String str = new String(b, 0, length, "gb2312");
String str = new String(b, 0, length);
responseBuffer = new StringBuffer(str);
myHandler.sendEmptyMessage(2);
}
}else {
//连接失败,message.what=0
myHandler.sendEmptyMessage(0);
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/**
*socket发送数据
*/
private void socketSendMessage(String str){
//利用线程池开启一个线程并执行该线程
mThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
//首先判断一下socket是不是已经创建连接了,如果没有就不管它
if (socket == null) return;
if (outputStream == null) return;
outputStream.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
/**
*连接结果
*/
private void handlerConnectResult(int result){
if (result==0){
Toast.makeText(this,"Connect Failed",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this,"Connect Success",Toast.LENGTH_SHORT).show();
}
}
/**
*socket接收数据
*/
private void handlerDataFeedBack(){
StringBuffer stringBuffer = new StringBuffer(textView.getText().toString());
stringBuffer.append(responseBuffer);
textView.setText(stringBuffer);
textView.setGravity(Gravity.BOTTOM);
}
/**
*更新UI
*/
@Override
public void InHandleMessage(Message message) {
switch (message.what) {
case 0:
handlerConnectResult(0);
break;
case 1:
handlerConnectResult(1);
break;
case 2:
handlerDataFeedBack();
break;
}
}
/**
*发送按钮点击事件处理
*/
public void socket_SendMessage(View view){
String str = editText.getText().toString();
editText.setText("");
InputMethodManager im = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(this.getWindow().getDecorView().getWindowToken(),0);
//判断传入字符串为空则不作处理
if (str.length()<=0) return;
//发送socket数据
socketSendMessage(str);
}
public void socket_backClick(View view){
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
//视图销毁时断开socket连接
try {
outputStream = null;//关闭输出流
socket.close();//关闭socket
socket = null;
} catch (IOException e) {
e.printStackTrace();
}
mThreadPool = null;//销毁线程池
myHandler.removeInMyHandler();//移除接口监听
myHandler = null;
responseBuffer = null;
}
}
MyHandler.java:
import android.os.Handler;
import android.os.Message;
/**
* Handler单例的封装
*/
public class MyHandler extends Handler {
private MyHandler(){}
private static class MyHandlerHolder{
private static final MyHandler INSTANCE = new MyHandler();
}
static MyHandler getInstance(){
return MyHandlerHolder.INSTANCE;
}//返回线程安全的单例
@Override
public void handleMessage(Message message){//重写handleMessage方法
super.handleMessage(message);
if (inMyHandler!=null){
inMyHandler.InHandleMessage(message);//调用接口方法
}
}
private static InMyHandler inMyHandler;//定义接口变量
public interface InMyHandler{//定义接口
void InHandleMessage(Message message);//定义接口方法
}
void setInMyHandler(InMyHandler inMyHandler){//注册接口的方法
MyHandler.inMyHandler = inMyHandler;//接口的引用指向它的实例化对象,传入的参数inMyHandler为实现该接口的类的实例化对象
}
void removeInMyHandler(){//取消注册接口的方法
MyHandler.inMyHandler = null;//inMyHandler置为null,inMyHandler将不再持有外部类引用
}
}
网友评论