android进行串口操作

1、确保在 AndroidManifest.xml 文件中添加以下权限:

<!--    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

2、创建一个串口通信的类,例如 SerialPortUtils.java:

import android.util.Log;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class SerialPortUtils {

 private static final String TAG = "SerialPortUtils";

 private FileDescriptor mFd;
 private FileInputStream mInputStream;
 private FileOutputStream mOutputStream;

 // 设备路径
 private static final String DEVICE_PATH = "/dev/ttyS0";

 // 波特率
 private static final int BAUD_RATE = 115200;

 public void openSerialPort() {
     try {
         // 打开设备文件
         mFd = new FileDescriptor();
         mFd = open(DEVICE_PATH, BAUD_RATE);
         mInputStream = new FileInputStream(mFd);
         mOutputStream = new FileOutputStream(mFd);
         Log.i(TAG, "串口打开成功");
     } catch (Exception e) {
         Log.e(TAG, "串口打开失败:" + e.getMessage());
     }
 }

 public void closeSerialPort() {
     try {
         if (mInputStream != null) {
             mInputStream.close();
             mInputStream = null;
         }
         if (mOutputStream != null) {
             mOutputStream.close();
             mOutputStream = null;
         }
         close();
         Log.i(TAG, "串口关闭成功");
     } catch (IOException e) {
         Log.e(TAG, "串口关闭失败:" + e.getMessage());
     }
 }

 public void sendData(byte[] data) {
     try {
         if (mOutputStream != null) {
             mOutputStream.write(data);
             mOutputStream.flush();
             Log.i(TAG, "发送数据成功");
         } else {
             Log.e(TAG, "串口未打开,发送数据失败");
         }
     } catch (IOException e) {
         Log.e(TAG, "发送数据失败:" + e.getMessage());
     }
 }

 public byte[] receiveData() {
     byte[] buffer = new byte[1024];
     try {
         if (mInputStream != null) {
             int size = mInputStream.read(buffer);
             if (size > 0) {
                 byte[] data = new byte[size];
                 System.arraycopy(buffer, 0, data, 0, size);
                 Log.i(TAG, "接收到数据:" + new String(data));
                 return data;
             }
         } else {
             Log.e(TAG, "串口未打开,接收数据失败");
         }
     } catch (IOException e) {
         Log.e(TAG, "接收数据失败:" + e.getMessage());
     }
     return null;
 }

 // JNI方法,用于打开串口设备
 private native static FileDescriptor open(String path, int baudRate);

 // JNI方法,用于关闭串口设备
 private native void close();

 // 加载JNI库
 static {
     System.loadLibrary("serial_port");
 }
}

上述代码中使用了 JNI(Java Native Interface)来实现打开和关闭串口设备的方法。为了在 Java 代码中调用 JNI 方法,需要在项目的 src/main 目录下创建一个名为 jni 的文件夹,并在该文件夹下创建 serial_port.cAndroid.mk 文件。其中serial_port.c文件用于实现 JNI 方法,Android.mk 文件用于定义 JNI 模块。

下面是 serial_port.c 文件的示例代码:

#include "jni.h"
#include <fcntl.h>
#include <termios.h>

JNIEXPORT jobject JNICALL
Java_com_example_SerialPortUtils_open(JNIEnv *env, jclass type, jstring path, jint baudRate) {
    const char *path_utf = (*env)->GetStringUTFChars(env, path, NULL);
    int fd = open(path_utf, O_RDWR);
    (*env)->ReleaseStringUTFChars(env, path, path_utf);
    if (fd == -1) {
        return NULL;
    }

    struct termios options;
    tcgetattr(fd, &options);
    speed_t speed;
    switch (baudRate) {
        case 9600:
            speed = B9600;
            break;
        case 19200:
            speed = B19200;
            break;
        case 38400:
            speed = B38400;
            break;
        case 57600:
            speed = B57600;
            break;
        case 115200:
            speed = B115200;
            break;
        default:
            speed = B9600;
    }
    cfsetispeed(&options, speed);
    cfsetospeed(&options, speed);

    // 8N1
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    // 无硬件流控制
    options.c_cflag &= ~CRTSCTS;

    // 可读可写
    options.c_cflag |= CREAD | CLOCAL;

    // 无软流控制
    options.c_iflag &= ~(IXON | IXOFF | IXANY);

    // 非规范模式
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

    // 设置等待时间和最小接收字符
    options.c_cc[VTIME] = 1;
    options.c_cc[VMIN] = 1;

    tcflush(fd, TCIOFLUSH);
    tcsetattr(fd, TCSANOW, &options);

    jobject mFileDescriptor;
    jclass mFileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");
    jmethodID mFileDescriptorConstructor = (*env)->GetMethodID(env, mFileDescriptorClass,
                                                               "<init>", "()V");
    jfieldID mFileDescriptorDescriptor = (*env)->GetFieldID(env, mFileDescriptorClass,
                                                            "descriptor", "I");
    mFileDescriptor = (*env)->NewObject(env, mFileDescriptorClass, mFileDescriptorConstructor);
    (*env)->SetIntField(env, mFileDescriptor, mFileDescriptorDescriptor, (jint) fd);

    return mFileDescriptor;
}

JNIEXPORT void JNICALL
Java_com_example_SerialPortUtils_close(JNIEnv *env, jobject instance) {
    jclass mFileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");
    jfieldID mFileDescriptorDescriptor = (*env)->GetFieldID(env, mFileDescriptorClass,
                                                            "descriptor", "I");
    jint descriptor = (*env)->GetIntField(env, instance, mFileDescriptorDescriptor);
    close(descriptor);
}

Android.mk 文件的示例代码如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := serial_port
LOCAL_SRC_FILES := serial_port.c
include $(BUILD_SHARED_LIBRARY)

在编写 JNI 代码时,需要在项目的 src/main 目录下创建一个名为jniLibs的文件夹,并在该文件夹下创建 armeabi armeabi-v7a 两个文件夹,将编译生成的 .so 文件放置到对应文件夹中。注意,.so 文件的命名应与 LOCAL_MODULE 定义的模块名一致。

3、在你的活动(Activity)或服务(Service)中使用 SerialPortUtils 类来实现串口通信:

private SerialPortUtils serialPortUtils;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    try {
        // 打开串口
        serialPortUtils.openSerialPort();

        // 向串口写入数据
        byte[] sendData = "Hello, Serial Port!".getBytes();
        serialPortUtils.writeData(sendData);

        // 读取串口数据
        serialPortUtils.readData();
    } catch (IOException | InvalidParameterException e) {
        e.printStackTrace();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();

    // 关闭串口
    serialPortUtils.closeSerialPort();
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android系统中进行串口通信,需要先获取串口权限,然后通过串口设备节点进行数据的读写。 以下是Android串口通信的基本步骤: 1. 获取串口设备节点 串口设备节点通常位于“/dev/tty”目录下,可以通过Java代码获取设备节点的文件描述符,例如: ``` // 打开串口设备节点 File device = new File("/dev/ttyS0"); FileInputStream inputStream = new FileInputStream(device); FileOutputStream outputStream = new FileOutputStream(device); ``` 2. 配置串口参数 串口设备的通信参数包括波特率、数据位、停止位、校验位等,需要根据具体的设备进行配置。可以使用Android提供的SerialPort类来配置串口参数,例如: ``` // 配置串口参数 SerialPort serialPort = new SerialPort(inputStream, outputStream, baudrate, flags, databits, stopbits, parity); ``` 3. 读写数据 可以使用Java的输入输出流来进行串口数据的读写操作,例如: ``` // 读取串口数据 byte[] buffer = new byte[1024]; int size = inputStream.read(buffer); // 发送串口数据 byte[] data = "Hello World".getBytes(); outputStream.write(data); ``` 4. 关闭串口设备 使用完毕后需要关闭串口设备,释放资源,例如: ``` // 关闭串口设备 inputStream.close(); outputStream.close(); ``` 需要注意的是,Android系统中的串口设备节点权限通常是属于系统管理员或root用户,普通应用程序无法直接访问串口设备节点。因此,在进行串口通信时需要获取串口设备的读写权限,可以通过Android系统的JNI接口或者第三方库进行获取。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值