安卓 串口开发

上图:

上码:

在APP grable添加

    // 串口  需要配合在项目build.gradle中的repositories添加   maven {url "https://jitpack.io" }
    implementation 'com.github.licheedev.Android-SerialPort-API:serialport:1.0.1'
    implementation 'com.jakewharton:butterknife:8.4.0'
    //XRecyclerView 框架
    implementation 'com.jcodecraeer:xrecyclerview:1.3.2'

在项目 geable添加

allprojects {
    repositories {
        google()
        jcenter()
        maven {url "https://jitpack.io" }
        
    }
}

layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/edit_sendvalue"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <Button
            android:id="@+id/btn_sendata"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="发送" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/edit_rend"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:cursorVisible="false"
            android:hint="接受数据 " />

    </LinearLayout>

    <Button
        android:id="@+id/brn_cleanLogcat"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="清除日志" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/lv_AT"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/lv_AT_logcat"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

    </LinearLayout>


</LinearLayout>

activity:

package youli.com.example.administrator.serialport;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private EditText mEditSendvalue;
    private Button mBtnSendata, brn_cleanLogcat;
    private EditText mEditRend;
    private RecyclerView mLvAT, lv_AT_logcat;
    private RYAdapter ryAdapter;
    private RYAdapterLogcat adapterLogcat;
    private List<String> list_Log = new ArrayList<>();


    private MSeriaLport seriaLport;

    //14个药曹uid、电压
    private String[] array = new String[]{
            "555901080000EAFF",
            "555902080000EAFF",
            "555903080000EAFF",
            "555904080000EAFF",
            "555905080000EAFF",
            "555906080000EAFF",
            "555907080000EAFF",
            "555908080000EAFF",
            "555909080000EAFF",
            "55590A080000EAFF",
            "55590B080000EAFF",
            "55590C080000EAFF",
            "55590D080000EAFF",
            "55590E080000EAFF",
            "555901090000EAFF",
            "555902090000EAFF",
            "555903090000EAFF",
            "555904090000EAFF",
            "555905090000EAFF",
            "555906090000EAFF",
            "555907090000EAFF",
            "555908090000EAFF",
            "555909090000EAFF",
            "55590A090000EAFF",
            "55590B090000EAFF",
            "55590C090000EAFF",
            "55590D090000EAFF",
            "55590E090000EAFF"
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        setReceiver();
    }

    private void initView() {
        mEditSendvalue = (EditText) findViewById(R.id.edit_sendvalue);
        brn_cleanLogcat = (Button) findViewById(R.id.brn_cleanLogcat);
        mBtnSendata = (Button) findViewById(R.id.btn_sendata);
        mBtnSendata.setOnClickListener(listener);
        brn_cleanLogcat.setOnClickListener(listener);
        seriaLport = MSeriaLport.getSeriaLport(this);
        mEditRend = (EditText) findViewById(R.id.edit_rend);
        mLvAT = findViewById(R.id.lv_AT);
        mLvAT.setLayoutManager(new LinearLayoutManager(this));
        ryAdapter = new RYAdapter(this, Array.getList_AT(), Array.getList_value());
        mLvAT.setAdapter(ryAdapter);

        ryAdapter.getMSeriaLportAT(new RYAdapter.MSeriaLportAT() {
            @Override
            public void setOnClickListenerAdapter(int position) {
                final String ATValue = Array.getList_AT().get(position);
                Log.i("TAG", "发送指令:" + ATValue);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        seriaLport.getWriteSeriaLportData(ATValue);
                    }
                }).start();
                ryAdapter.getPosition(position);
                ryAdapter.notifyDataSetChanged();
            }
        });

        lv_AT_logcat = findViewById(R.id.lv_AT_logcat);
        lv_AT_logcat.setLayoutManager(new LinearLayoutManager(this));
        adapterLogcat = new RYAdapterLogcat(this, list_Log);
        lv_AT_logcat.setAdapter(adapterLogcat);
    }


    View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_sendata:
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < array.length; i++) {
                                Log.i("TAG", "发送指令:" + array[i]);
                                seriaLport.getWriteSeriaLportData(array[i]);
                            }
                        }
                    }).start();

//                    mEditSendvalue.setText("555902080000EAFF");
//                    String AT = mEditSendvalue.getText().toString().trim();
//                    seriaLport.getWriteSeriaLportData(AT);
                    break;

                case R.id.brn_cleanLogcat:
                    list_Log.clear();
                    adapterLogcat.notifyDataSetChanged();
                    break;

                default:
                    break;

            }
        }
    };
    private ReceiverData receiverData;

    public static final String RECEIVER_REFRESH = "WWW.ANDROID.RECEIVER_REFRESH";

    //注册广播
    public void setReceiver() {
        if (receiverData == null) {
            receiverData = new ReceiverData();
            IntentFilter filter = new IntentFilter();
            filter.addAction(RECEIVER_REFRESH);
            registerReceiver(receiverData, filter);
        }
    }

    //注销广播
    public void setCancellationReceiver() {
        if (receiverData != null) {
            unregisterReceiver(receiverData);
        }
    }

    String value;

    private class ReceiverData extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case RECEIVER_REFRESH:
                    value = intent.getStringExtra(RECEIVER_REFRESH);
                    mEditRend.setText(value);
                    list_Log.add(value);
                    adapterLogcat.notifyDataSetChanged();
                    //刷新后定位最后一条数据
                    int itemCount = adapterLogcat.getItemCount() - 1;
                    lv_AT_logcat.smoothScrollToPosition(itemCount);
                default:
                    Log.i("TAG", "接受指令:" + value);
                    break;
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        setCancellationReceiver();
        seriaLport.getClean();
    }
}
MSeriaLport串口控制类:
package youli.com.example.administrator.serialport;

import android.content.Context;
import android.content.Intent;
import android.serialport.SerialPort;
import android.serialport.SerialPortFinder;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class MSeriaLport extends SerialPort {

    private static Context contexts;

    //device物理地址错误会报错 Caused by: java.lang.SecurityException
    private static String device = "/dev/ttyS1"; //串口地址
    private static int baudrate = (int) 115200l;  // 波特率
    private static int flags = 0;                   //奇偶校验
    private boolean flag = true;

    private static InputStream inputStream;
    private static OutputStream outputStream;

    private static MSeriaLport seriaLport;

    public static MSeriaLport getSeriaLport(Context context) {
        contexts = context;
        if (seriaLport == null) {
            try {
                seriaLport = new MSeriaLport(new File(device), baudrate, flags);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return seriaLport;
    }

    static Thread sp_Thread;

    /**
     * 打开串口
     *
     * @param device   串口的具体物理地址
     * @param baudrate
     * @param flags
     * @throws SecurityException
     * @throws IOException
     */
    public MSeriaLport(File device, int baudrate, int flags) throws IOException {
        super(device, baudrate, flags);

        getRendSeriaLportData(); //读取数据
    }

    private String test;

    /**
     * 发送串口数据
     */
    public void getWriteSeriaLportData(String valueS) {
        outputStream = this.getOutputStream();
        try {
            while (!TextUtils.isEmpty(test)) {
                Thread.sleep(100);
            }
            test = valueS;

            byte[] b = utils.hexStr2bytes(valueS);
            outputStream.write(b);

            int abc = 0;
            while (!AT_value.contains("56") && !AT_value.contains("EAFF")) {
                Thread.sleep(200);
                abc++;
                if (abc == 10) {
                    break;//超时
                }
            }
            Log.i("TAG"," AT接受:"+ AT_value);
            AT_value = "";
            test = "";
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private StringBuffer buffer = new StringBuffer();
    private String valeu;
    private String AT_value = "";

    /**
     * 读取串口数据
     */
    private void getRendSeriaLportData() {
        inputStream = this.getInputStream();
        sp_Thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (flag) {
                    int index;
                    try {
                        Thread.sleep(100);
                        index = inputStream.available();
                        if (index > 0) {
                            byte[] bytes = new byte[index];
                            inputStream.read(bytes, 0, bytes.length);
                            valeu = utils.bytes2HexStr(bytes);
//                            Log.i("TAG", "读取到的数据:" + valeu);
                            buffer = buffer.append(valeu);
                            AT_value = buffer.toString();
                            if (AT_value.contains("56") && AT_value.contains("EAFF")) {
                                sendReceive(AT_value);
                                buffer = new StringBuffer();
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        sp_Thread.start();

    }

    /**
     * 发送广播
     *
     * @param value
     */
    void sendReceive(String value) {
        Intent intent = new Intent();
        intent.setAction(MainActivity.RECEIVER_REFRESH);
        intent.putExtra(MainActivity.RECEIVER_REFRESH, value);
        contexts.sendBroadcast(intent);
    }


    /**
     * 关闭流
     */
    public void getClean() {
        if (seriaLport != null) {
            seriaLport.getClean();
            flag = false;
        }
    }

    /**
     * 获取在设备目录下的,所有串口的具体物理地址
     * /dev/ttyGS3
     * /dev/ttyGS2
     * /dev/ttyGS1
     * /dev/ttyGS0
     * /dev/ttyS0
     * /dev/ttyS1
     */
    public static String[] getAllDevicesPath() {
        String[] devices = new SerialPortFinder().getAllDevicesPath();
        for (int i = 0; i < devices.length; i++)
            Log.i("TAG", devices[i]);
        return devices;
    }
}

东西不多 ,没啥可说的。有不会的小伙伴可以提问。

热门文章

暂无图片
编程学习 ·

那些年让我们目瞪口呆的bug

程序员一生与bug奋战&#xff0c;可谓是杀敌无数&#xff0c;见怪不怪了&#xff01;在某知识社交平台中&#xff0c;一个“有哪些让程序员目瞪口呆的bug”的话题引来了6700多万的阅读&#xff0c;可见程序员们对一个话题的敏感度有多高。 1、麻省理工“只能发500英里的邮件” …
暂无图片
编程学习 ·

redis的下载与安装

下载redis wget http://download.redis.io/releases/redis-5.0.0.tar.gz解压redis tar -zxvf redis-5.0.0.tar.gz编译 make安装 make install快链方便进入redis ln -s redis-5.0.0 redis
暂无图片
编程学习 ·

《大话数据结构》第三章学习笔记--线性表(一)

线性表的定义 线性表&#xff1a;零个或多个数据元素的有限序列。 线性表元素的个数n定义为线性表的长度。n为0时&#xff0c;为空表。 在比较复杂的线性表中&#xff0c;一个数据元素可以由若干个数据项组成。 线性表的存储结构 顺序存储结构 可以用C语言中的一维数组来…
暂无图片
编程学习 ·

对象的扩展

文章目录对象的扩展属性的简洁表示法属性名表达式方法的name属性属性的可枚举性和遍历可枚举性属性的遍历super关键字对象的扩展运算符解构赋值扩展运算符AggregateError错误对象对象的扩展 属性的简洁表示法 const foo bar; const baz {foo}; baz // {foo: "bar"…
暂无图片
编程学习 ·

让程序员最头疼的5种编程语言

世界上的编程语言&#xff0c;按照其应用领域&#xff0c;可以粗略地分成三类。 有的语言是多面手&#xff0c;在很多不同的领域都能派上用场。大家学过的编程语言很多都属于这一类&#xff0c;比如说 C&#xff0c;Java&#xff0c; Python。 有的语言专注于某一特定的领域&…
暂无图片
编程学习 ·

写论文注意事项

参考链接 给研究生修改了一篇论文后&#xff0c;该985博导几近崩溃…… 重点分析 摘要与结论几乎重合 这一条是我见过研究生论文中最常出现的事情&#xff0c;很多情况下&#xff0c;他们论文中摘要部分与结论部分重复率超过70%。对于摘要而言&#xff0c;首先要用一小句话引…
暂无图片
编程学习 ·

2021-2027年中国铪市场调研与发展趋势分析报告

2021-2027年中国铪市场调研与发展趋势分析报告 本报告研究中国市场铪的生产、消费及进出口情况&#xff0c;重点关注在中国市场扮演重要角色的全球及本土铪生产商&#xff0c;呈现这些厂商在中国市场的铪销量、收入、价格、毛利率、市场份额等关键指标。此外&#xff0c;针对…
暂无图片
编程学习 ·

Aggressive cows题目翻译

描述&#xff1a; Farmer John has built a new long barn, with N (2 < N < 100,000) stalls.&#xff08;John农民已经新建了一个长畜棚带有N&#xff08;2<N<100000&#xff09;个牛棚&#xff09; The stalls are located along a straight line at positions…
暂无图片
编程学习 ·

剖析组建PMO的6个大坑︱PMO深度实践

随着事业环境因素的不断纷繁演进&#xff0c;项目时代正在悄悄来临。设立项目经理转岗、要求PMP等项目管理证书已是基操&#xff0c;越来越多的组织开始组建PMO团队&#xff0c;大有曾经公司纷纷建造中台的气质&#xff08;当然两者的本质并不相同&#xff0c;只是说明这个趋势…
暂无图片
编程学习 ·

Flowable入门系列文章118 - 进程实例 07

1、获取流程实例的变量 GET运行时/进程实例/ {processInstanceId} /变量/ {变量名} 表1.获取流程实例的变量 - URL参数 参数需要值描述processInstanceId是串将流程实例的id添加到变量中。变量名是串要获取的变量的名称。 表2.获取流程实例的变量 - 响应代码 响应码描述200指…
暂无图片
编程学习 ·

微信每天自动给女[男]朋友发早安和土味情话

微信通知&#xff0c;每天给女朋友发早安、情话、诗句、天气信息等~ 前言 之前逛GitHub的时候发现了一个自动签到的小工具&#xff0c;b站、掘金等都可以&#xff0c;我看了下源码发现也是很简洁&#xff0c;也尝试用了一下&#xff0c;配置也都很简单&#xff0c;主要是他有一…
暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

项目经理,你有什么优势吗?

大侠被一个问题问住了&#xff1a;你和别人比&#xff0c;你的优势是什么呢? 大侠听到这个问题后&#xff0c;脱口而出道&#xff1a;“项目管理能力和经验啊。” 听者抬头看了一下大侠&#xff0c;显然听者对大侠的这个回答不是很满意&#xff0c;但也没有继续追问。 大侠回家…
暂无图片
编程学习 ·

nginx的负载均衡和故障转移

#注&#xff1a;proxy_temp_path和proxy_cache_path指定的路径必须在同一分区 proxy_temp_path /data0/proxy_temp_dir; #设置Web缓存区名称为cache_one&#xff0c;内存缓存空间大小为200MB&#xff0c;1天没有被访问的内容自动清除&#xff0c;硬盘缓存空间大小为30GB。 pro…
暂无图片
编程学习 ·

业务逻辑漏洞

身份认证安全 绕过身份认证的几种方法 暴力破解 测试方法∶在没有验证码限制或者一次验证码可以多次使用的地方&#xff0c;可以分为以下几种情况︰ (1)爆破用户名。当输入的用户名不存在时&#xff0c;会显示请输入正确用户名&#xff0c;或者用户名不存在 (2)已知用户名。…