添加串口资源:
项目已上传
报告
一、同一设备进行通信
1.服务端:SocketServiceApplication学号
manifests中AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.socketserviceappliacation03195020">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:name=".MyAPP"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
java中MainActivity.java
package com.example.socketserviceappliacation03195020;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity{
private EditText et_content, et_name;
private TextView tv_se;
private MyAPP myAPP;
@Override
protected void onCreate(Bundle saveInstanceState){
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_main);
et_content = (EditText) findViewById(R.id.et_content);
tv_se = (TextView) findViewById(R.id.tv_se);
et_name = (EditText) findViewById(R.id.et_name);
myAPP = (MyAPP)getApplication();
}
public void click1(View view){
myAPP.setOnConnectListener(new MyAPP.ConnectListener() {
@Override
public void onReceiveData(String data) {
tv_se.append(data + "\n");
}
});
}
public void click2(View view){
String name = et_name.getText().toString();
String a = name + ":" + et_content.getText().toString();
tv_se.append(a + "\n");
myAPP.send(a);
}
}
java中MyAPP.java
package com.example.socketserviceappliacation03195020;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
public class MyAPP extends android.app.Application {
//socket通信
private Socket socket = null;
private ServerSocket serverSocket = null;
public static OutputStream outputStream;
private static ConnectListener mListener;
final LinkedList<Socket> list = new LinkedList<Socket>();
private HandlerThread mHandlerThread;
//子线程中的Handle实例
private Handler mSubThreadHandler;
@Override
public void onCreate() {
super.onCreate();
//启动服务器
ServerListeners listeners = new ServerListeners();
listeners.start();
initHandlerThread();
}
public class ServerListeners extends Thread {
@Override
public void run() {
try {
serverSocket = new ServerSocket(7777);
while (true) {
System.out.println("等待客户端请求...");
socket = serverSocket.accept();
System.out.println("收到请求。服务器建立连接...");
System.out.println("客户端" + socket.getInetAddress().getHostAddress() + "连接成功");
System.out.println("客户端" + socket.getRemoteSocketAddress() + "连接成功");
list.add(socket);
//每次都启动一个新的线程
new Thread(new Task(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void initHandlerThread() {
//创建HandlerThread实例
mHandlerThread = new HandlerThread("handler_thread");
//开始运行线程
mHandlerThread.start();
//获取HandlerThread线程中的Iooper实例
Looper loop = mHandlerThread.getLooper();
//创建Handler与该线程绑定。
mSubThreadHandler = new Handler(loop) {
public void handleMessage(Message msg) {
writeMsg(msg.getData().getString("datal"));
}
};
}
/**
* 处理Socket请求的线程类
*/
class Task implements Runnable {
private Socket socket;
/**
* 构造函数
*
* @param socket
*/
public Task(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
while (true) {
int size;
try {
InputStream inputStream = null;//输入流
inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
size = inputStream.read(buffer);
if (size > 0) {
if (buffer[0] != (byte) 0xEE) {
//将读取的1024个字节构造成一个String类型的变量
String data = new String(buffer, 0, size, "gbk");
Message message = new Message();
message.what = 100;
Bundle bundle = new Bundle();
bundle.putString("data", data);
message.setData(bundle);
mHandler.sendMessage(message);
}
}
} catch (Exception e) {
e.printStackTrace();
return;
}
}
}
}
//接口回调
public interface ConnectListener {
void onReceiveData(String data);
}
public void setOnConnectListener(ConnectListener listener) {
this.mListener = listener;
}
Handler mHandler = new Handler(){
public void handleMessage(Message msg){
switch(msg.what){
case 100:
if(mListener!=null){
mListener.onReceiveData(msg.getData().getString("data"));
}
break;
}
}
};
/**
*发送数据
*
*@param
*/
public void send(String bytes){
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("datal",bytes);
msg.setData(bundle);
mSubThreadHandler.sendMessage(msg);
}
private void writeMsg(String msg){
for (Socket s :list){
System.out.println("客户端"+s.getInetAddress().getHostAddress());
try{
outputStream = s.getOutputStream();
if (outputStream != null){
outputStream.write(msg.getBytes("gbk"));
outputStream.flush();
}
}catch (IOException e){
//TODO Auto-generated catch block
e.printStackTrace();
}catch (Exception e){
System.out.println("客户端socket不存在。");
}
}
}
/**
* 断开连接
*/
public void disconnect()throws IOException{
System.out.println("客户端是否关闭1");
if (list.size() != 0){
for (Socket s: list){
s.close();
System.out.println("客户端是否关闭2");
}
}
if (outputStream != null)
outputStream.close();
list.clear();
}
}
drawable中kuang.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android = "http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="16dp"></corners>
<solid android:color="#ffff"></solid>
</shape>
layout中activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#EEE5DE"
android:fillViewport="true"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_margin="14dp"
android:background="@drawable/kuang"
android:hint="请输入昵称"
android:paddingLeft="6dp"
android:textSize="30dp"/>
<EditText
android:id="@+id/et_content"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_below="@+id/et_name"
android:layout_margin="14dp"
android:background="@drawable/kuang"
android:hint="输入要发送的内容"
android:paddingLeft="6dp"
android:textSize="30dp"/>
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="14dp"
android:layout_below="@+id/et_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:layout_weight="1"
android:background="#cccccc"
android:onClick="click1"
android:text="启动服务端"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:onClick="click2"
android:layout_weight="1"
android:background="#cccccc"
android:layout_marginLeft="20dp"
android:text="发送"/>
</LinearLayout>
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/linearLayout1"
android:layout_margin="14dp"
android:text="聊天记录:"/>
<TextView
android:id="@+id/tv_se"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_below="@+id/textView1"
android:layout_margin="14dp"
android:background="@drawable/kuang"/>
</RelativeLayout>
</ScrollView>
2.用户端
java中MainActivity.java
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class MainActivity extends AppCompatActivity {
private EditText etname, etneirong;
private TextView tvneirong;
private InputStream inputStream;
private OutputStream outputStream;
private HandlerThread mHandlerThread;
//子线程中的 Handler 实例。
private Handler mSubThreadHandler;
Handler handler = new Handler() {
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
String neirong = bundle.getString("neirong");
tvneirong.append(neirong + "\n");
}
;
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etname = (EditText) findViewById(R.id.edit_name);
etneirong = (EditText)
findViewById(R.id.myinternet_tcpclient_EditText02);
tvneirong = (TextView)
findViewById(R.id.myinternet_tcpclient_EditText01);
initHandlerThraed();
}
public void lianjie(View view) {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
//String ip = "192.168.1.249";(不同设备时:服务端的ip地址)
String ip = "localhost";(同一设备)
int duankou = 7777;
try {
Socket socket = new Socket(ip, duankou);
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
byte[] jieshou = new byte[1024];
int len = -1;
while ((len = inputStream.read(jieshou)) != -1) {
//将 byte 数组转换为 String 类型
String neirong = new String(jieshou, 0, len, "gbk");
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putString("neirong", neirong);
message.setData(bundle);
handler.sendMessage(message);
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
public void fasong(View view) {
// 得到昵称
String name = etname.getText().toString();
// 得到内容
String neirong = etneirong.getText().toString();
String all = name + ":" + neirong;
tvneirong.append(all + "\n");
etneirong.setText("");
Message msg = new Message();
msg.obj = all;
mSubThreadHandler.sendMessage(msg);
}
private void initHandlerThraed() {
//创建 HandlerThread 实例
mHandlerThread = new HandlerThread("handler_thread");
//开始运行线程
mHandlerThread.start();
//获取 HandlerThread 线程中的 Looper 实例
Looper loop = mHandlerThread.getLooper();
//创建 Handler 与该线程绑定。
mSubThreadHandler = new Handler(loop) {
public void handleMessage(Message msg) {
writeMsg((String) msg.obj);
}
};
}
private void writeMsg(String msg) {
try {
outputStream.write(msg.getBytes("gbk"));//发送
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
} }
drawable中edit_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="4dp"></corners>
<stroke android:color="#E1E1E1" android:width="1dp"></stroke>
<solid android:color="#F6F6F6"></solid>
</shape>
layout中activity.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=".MainActivity">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<EditText
android:id="@+id/edit_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/edit_bg"
android:hint="请输入昵称"
android:padding="10dp">
</EditText>
<EditText
android:id="@+id/myinternet_tcpclient_EditText02"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_bg"
android:hint="输入要发送的内容"
android:padding="10dp">
</EditText>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/myinternet_tcpclient_BtnIn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:onClick="lianjie"
android:text="连接服务端"/>
<Button
android:id="@+id/myinternet_tcpclient_BtnSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="1"
android:onClick="fasong"
android:text="发送"/>
</LinearLayout>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="聊天记录"/>
<!--fillViewport撑满全屏-->
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:layout_margin="10dp">
<TextView
android:id="@+id/myinternet_tcpclient_EditText01"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/edit_bg"
android:ems="10"
android:padding="10dp">
</TextView>
</ScrollView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
二、不同设备间通信
将服务端MainActivity中的ip地址改为服务端设备的静态ip地址即可。
注意:两设备需在相同网段下,即连接同一个wifi。
三、串口通信(实验箱)
manifests中AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.acchuankou03195020">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MyApplication">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
import android.os.Handler;
import android.os.Message;
//import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android_serialport_api.SerialPort;
public class MainActivity extends AppCompatActivity {
private MyApplication mApplication;
protected SerialPort mSerialPort;//串口
protected OutputStream mOutputStream;
private InputStream mInputStream;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mApplication = (MyApplication) getApplication();
textView = findViewById(R.id.tv);
try {
//打开串口
mSerialPort = mApplication.getSerialPort("/dev/ttyAMA5");
mOutputStream = mSerialPort.getOutputStream();
mInputStream = mSerialPort.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
byte[] shuju = new byte[16];
int len = -1;
try {
while ((len = mInputStream.read(shuju)) != -1) {
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putByteArray("data", shuju);
message.setData(bundle);
handler.sendMessage(message);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
byte[] data = msg.getData().getByteArray("data");
if (data[3] == (byte) 0x03 && data[4] == (byte) 0x01) {
byte byteXH = data[5];
byte byteXL = data[6];
textView.setText("温度:" + String
.valueOf((byteXH * 256 + byteXL) / 100));
}
}
};
}
MyApplication.java
import java.io.File;
import java.io.IOException;
import java.io.InvalidClassException;
import java.security.InvalidParameterException;
import java.util.HashMap;
import java.util.Map;
import android_serialport_api.SerialPort;
import android_serialport_api.SerialPortFinder;
public class MyApplication extends android.app.Application{
public SerialPortFinder mSerialPortFinder = new SerialPortFinder();
private Map<String, SerialPort> serialPortMap = new HashMap<String,SerialPort>();
private String tv = "/dev/ttyAMA2";
public SerialPort getSerialPort(String path) throws SecurityException, IOException, InvalidParameterException {
return getSerialPort(path, 115200);
}
public SerialPort getSerialPort(String path, int baudrate)
throws SecurityException, IOException, InvalidParameterException {
System.out.println("MyApplication启动");
SerialPort mSerialPort = serialPortMap.get(path);
if (mSerialPort == null) {
/*Check parameters检查参数*/
if ((path.length() == 0) || ( baudrate == -1)){
throw new InvalidParameterException();
}
/*打开串口 使用指定的串口名、波特率和奇偶校验位初始化*/
mSerialPort = new SerialPort(new File(path), baudrate, 0);
serialPortMap.put(path, mSerialPort);
}
return mSerialPort;
}
}
Utils.java
public class Utils {
//16进制转String
static final byte[] HEI_TABLE = {0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF};
static final char[] HEI_CHAR_TABLE = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
public static String toHexString(byte[] data) throws Exception{
if (data == null || data.length == 0)return null;
byte[] hex = new byte[data.length*2];
int index = 0;
for (byte b:data){
int v = b & 0xFF;
hex[index++] = (byte)HEI_CHAR_TABLE[v>>>4];
hex[index++] = (byte)HEI_CHAR_TABLE[v&0xF];
}
return new String(hex);
}
}
activity_main
<?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=".MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>