Android11.0封装串口api供app层调用

编程入门 行业动态 更新时间:2024-10-26 16:35:37

Android11.0封装<a href=https://www.elefans.com/category/jswz/34/1769224.html style=串口api供app层调用"/>

Android11.0封装串口api供app层调用

Android11.0封装串口api供app层调用

  • RK3568 Android11.0串口服务
    • 自定义服务中封装串口服务
    • 添加权限
    • SDK中添加上层应用调用API

RK3568 Android11.0串口服务

Android11.0已自带串口服务,官方demo在frameworks/base/tests/SerialChat

自定义服务中封装串口服务

如上目录,对SerialManager、SerialPort进行封装:

  1. hardware/SerialHelper.java
import android.content.Context;
import android.hardware.SerialPort;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.hardware.SerialManager;
import android.hardware.SerialPort;
import android.os.ServiceManager;
import android.util.ArrayMap;
import android.hardware.ISerialManager;
import android.util.Log;import java.io.IOException;import com.yjz.demo.hardware.serial.SerialImpl;
import com.yjz.demo.hardware.serial.ISerial;public final class SerialHelper {private static final String TAG = SerialHelper.class.getSimpleName();private Context mContext;private SerialManager mSerialManager;public SerialHelper(Context context) {this.mContext = context;mSerialManager = (SerialManager) context.getSystemService(Context.SERIAL_SERVICE);}public ISerial createSerial() {return new SerialImpl(mSerialManager);}
}
  1. /hardware/serial/ISerial.java;
import java.io.IOException;public interface ISerial {void open(String name, int speed, SerialCallback callback) throws IOException;void write(byte[] buffer);void close();void release();
}
  1. /hardware/serial/SerialCallback.java
public interface SerialCallback {void onRead(byte[] buffer);
}
  1. /hardware/serial/SerialImpl.java
import android.hardware.SerialManager;
import android.hardware.SerialPort;
import android.util.Log;import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;public final class SerialImpl implements ISerial {private static final String TAG = SerialImpl.class.getSimpleName();private String mName;private int mSpeed;private SerialCallback mCallback;private SerialPort mSerialPort;private SerialManager mSerialManager;private volatile boolean mIsClose;public SerialImpl(SerialManager serialManager) {mSerialManager = serialManager;}@Overridepublic void open(String name, int speed, SerialCallback callback) throws IOException {mCallback = callback;mSerialPort = mSerialManager.openSerialPort(name, speed);if (null == mSerialPort) {throw new IOException("Could not open serial port " + name);}Log.d(TAG, "serial open success");mIsClose = false;new Thread() {@Overridepublic void run() {Log.d(TAG, "serial read thread run " + Thread.currentThread().getName());int ret = 0;ByteBuffer inputBuffer = ByteBuffer.allocate(1024);byte[] buffer = new byte[1024];while (ret >= 0) {if (mIsClose) {Log.d(TAG, "serial had close " + Thread.currentThread().getName());break;}try {
//                        Log.d(TAG, "calling read");inputBuffer.clear();ret = mSerialPort.read(inputBuffer);
//                        Log.d(TAG, "serial read returned " + ret + " " + Thread.currentThread().getName());inputBuffer.get(buffer, 0, ret);byte[] rtArray = Arrays.copyOf(buffer, ret);if (null != mCallback && ret > 0) {mCallback.onRead(rtArray);}} catch (Exception e) {Log.w(TAG, "serial read failed " + Thread.currentThread().getName(), e);break;}  }Log.d(TAG, "serial read thread out" + Thread.currentThread().getName());}}.start();}@Overridepublic void write(byte[] buffer) {if (null != buffer && buffer.length > 0) {ByteBuffer outputBuffer = ByteBuffer.allocate(buffer.length);outputBuffer.put(buffer);if (null != mSerialPort) {try {mSerialPort.write(outputBuffer, buffer.length);} catch (Exception e) {Log.e(TAG, "serial write fail ", e);}} else {Log.d(TAG, "serial had close");}} else {Log.d(TAG, "serial no write data");}}@Overridepublic void close() {Log.d(TAG, "serial close");mIsClose = true;if (mSerialPort != null) {try {mSerialPort.close();} catch (IOException e) {e.printStackTrace();}mSerialPort = null;}if (null != mCallback) {mCallback = null;}}@Overridepublic void release() {Log.d(TAG, "serial release");close();mSerialManager = null;}
}
  1. 修改SerialService /frameworks/base/services/core/java/com/android/server/SerialService.java;
    SerialService服务默认只允许系统app调用,第三方应用调用,需要删除权限检查语句;
    默认串口设置号是从/frameworks/base/core/res/values/config.xml文件中定义的config_serialPorts数组中获取,这里修改成上层调用者传入;
public String[] getSerialPorts() {
//        注释掉权限检查语句
//        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SERIAL_PORT, null);ArrayList<String> ports = new ArrayList<String>();for (int i = 0; i < mSerialPorts.length; i++) {String path = mSerialPorts[i];if (new File(path).exists()) {ports.add(path);}}String[] result = new String[ports.size()];ports.toArray(result);return result;}public ParcelFileDescriptor openSerialPort(String path) {
//         注释掉权限检查,设备号使用传入参数
//        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SERIAL_PORT, null);
//        for (int i = 0; i < mSerialPorts.length; i++) {
//            if (mSerialPorts[i].equals(path)) {
//                return native_open(path);
//            }
//        }
//        throw new IllegalArgumentException("Invalid serial port " + path);return native_open(path);}
  1. 修改android_hardware_SerialPort /frameworks/base/core/jni/android_hardware_SerialPort.cpp;
    默认串口的read方法等待读取最少字符模式,此模式下当关闭串口时,读线程无法立即退出,在次获取串口后,读方法会报一次错,需要修改为读取超时模式;
static void
android_hardware_SerialPort_open(JNIEnv *env, jobject thiz, jobject fileDescriptor, jint speed)//*****省略代码******/* no timeout but request at least one character per read *///默认为://tio.c_cc[VTIME] = 0;//tio.c_cc[VMIN] = 1;//修改为:tio.c_cc[VTIME] = 1;//1 * 100毫秒tio.c_cc[VMIN] = 0;//*****省略代码******
}
  1. 自定义服务中添加获取串口接口对象的方法:
public ISerial createSerial() {return mSerialHelper.createSerial();}
  1. 修改hiddenapi-greylist-packages.txt,
    /frameworks/base/config/hiddenapi-greylist-packages.txt,
    默认添加的类及方法都是隐藏api,上层应用无法直接调用,需要在文件中添加相应包名:
com.yjz.demo//只包括包下的类文件,子包不包含,需要单独声明,如下
com.yjz.demo.hardware.serial

添加权限

  1. 添加SEAndroid权限,文件路径:
    /device/rockchip/rk356x/sepolicy_vendor/serial.te
allow untrusted_app serial_device:chr_file { open read write ioctl};
  1. 为串口设备添加权限,文件路径:
    /device/rockchip/rk356x/init.rk356x.rc
on boot//****省略代码chmod 0777 /dev/ttyS3chmod 0777 /dev/ttyS4chmod 0777 /dev/ttyS5chmod 0777 /dev/ttyS7chmod 0777 /dev/ttyS8chmod 0777 /dev/ttyS9

SDK中添加上层应用调用API

SDK最终编译成jar包,供应用导入调用相关api。

SDK中目录如上:

  1. /sdk/api/serial/ImplSerial.java
import com.yjz.demo.DemoManager;
import java.io.IOException;public final class ImplSerial implements ISerial {private static final String TAG = ImplSerial.class.getSimpleName();private String mName;private int mSpeed;private com.yjz.demo.hardware.serial.ISerial mISerial;public ImplSerial(DemoManager manager) {mISerial = manager.createSerial();}@Overridepublic void open(String name, int speed, SerialListener listener) throws IOException {mISerial.open(name, speed, new com.yjz.demo.hardware.serial.SerialCallback() {@Overridepublic void onRead(byte[] buffer) {if (null != listener) {listener.onRead(buffer);}}});}@Overridepublic void write(byte[] buffer) {mISerial.write(buffer);}@Overridepublic void close() {mISerial.close();}@Overridepublic void release() {mISerial.release();mISerial = null;}
}
  1. /sdk/api/serial/Iserial.java
import java.io.IOException;public interface ISerial {void open(String name, int speed, SerialListener listener) throws IOException;void write(byte[] buffer);void close();void release();
}
  1. /sdk/api/serial/SerialListener.java
public interface SerialListener {void onRead(byte[] buffer);
}
  1. /sdk/api/ImplIApi.java
import android.content.Context;
import com.yjz.demo.DemoManager;
import com.yjz.sdk.api.gpio.Gpio;
import com.yjz.sdk.api.serial.ISerial;
import com.yjz.sdk.api.serial.ImplSerial;final class ImplIApi implements IApi {private DemoManager mDemoManager;public ImplIApi(Context context) {mDemoManager = (DemoManager) context.getSystemService(Context.DEMO_SERVICE);}@Overridepublic Gpio createGpio(int gpioNum) {return new Gpio(mDemoManager, gpioNum);}@Overridepublic boolean setRelay(int type, String value) {return mDemoManager.writeRelayValue(type, value);}@Overridepublic ISerial createSerial() {return new ImplSerial(mDemoManager);}
}

更多推荐

Android11.0封装串口api供app层调用

本文发布于:2024-02-11 14:13:45,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1681414.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:串口   app   api

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!