{"id":1843,"date":"2023-03-29T21:55:17","date_gmt":"2023-03-29T13:55:17","guid":{"rendered":"https:\/\/www.appblog.cn\/?p=1843"},"modified":"2023-04-22T09:11:43","modified_gmt":"2023-04-22T01:11:43","slug":"android-scanner-serial-communication","status":"publish","type":"post","link":"https:\/\/www.appblog.cn\/index.php\/2023\/03\/29\/android-scanner-serial-communication\/","title":{"rendered":"Android\u626b\u7801\u5668\u4e32\u53e3\u901a\u8baf"},"content":{"rendered":"<p>\u5bf9\u63a5\u4e32\u53e3\u626b\u7801\u5668\uff0c\u53c2\u8003 Github\u4e0a\u5f00\u6e90\u7684\u4e32\u53e3\u901a\u8baf\u5e93<code>https:\/\/github.com\/cepr\/android-serialport-api<\/code>\u5b9e\u73b0\u626b\u7801\u5668\u901a\u8baf\u3002<\/p>\n<h2>\u96c6\u6210<\/h2>\n<p>Android Studio\u4f7f\u7528 cmake\u7f16\u8bd1\uff0c\u5c06<code>SerialPort.c\/SerialPort.h<\/code>\u4e24\u4e2a\u6587\u4ef6\u62f7\u8d1d\u5230 cpp \u6587\u4ef6\u5939\u4e0b\uff0c<code>SerialPort.java<\/code>\u62f7\u8d1d\u5230 <code>android.serialport<\/code>\u5305\u4e0b\uff0c\u8bb0\u5f97\u5305\u540d\u8981\u548c<code>SerialPort.h<\/code>\u4e2d\u7684\u65b9\u6cd5\u540d\u4e2d\u7684\u5305\u540d\u4e00\u81f4\u3002<\/p>\n<p><!-- more --><\/p>\n<p>\u6e90\u7801\uff1a<a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/github.com\/iyezhou\/AndroidSerialPort\">https:\/\/github.com\/iyezhou\/AndroidSerialPort<\/a><\/p>\n<h3>CMakeLists.txt<\/h3>\n<pre><code># Sets the minimum version of CMake required to build your native library.\n# This ensures that a certain set of CMake features is available to\n# your build.\n\ncmake_minimum_required(VERSION 3.4.1)\n\n# Specifies a library name, specifies whether the library is STATIC or\n# SHARED, and provides relative paths to the source code. You can\n# define multiple libraries by adding multiple add.library() commands,\n# and CMake builds them for you. When you build your app, Gradle\n# automatically packages shared libraries with your APK.\n\nadd_library( # Specifies the name of the library.\n        serial_port\n\n        # Sets the library as a shared library.\n        SHARED\n\n        # Provides a relative path to your source file(s).\n        src\/main\/cpp\/SerialPort.c)\n\nfind_library( # Sets the name of the path variable.\n        log-lib\n\n        # Specifies the name of the NDK library that\n        # you want CMake to locate.\n        log)\n\n# Specifies libraries CMake should link to your target library. You\n# can link multiple libraries, such as libraries you define in this\n# build script, prebuilt third-party libraries, or system libraries.\n\ntarget_link_libraries( # Specifies the target library.\n        serial_port\n\n        # Links the target library to the log library\n        # included in the NDK.\n        ${log-lib})<\/code><\/pre>\n<h3>native\u63a5\u53e3<\/h3>\n<pre><code class=\"language-java\">public class SerialPort {\n\n    private static final String TAG = &quot;SerialPort&quot;;\n\n    private static final String DEFAULT_SU_PATH = &quot;\/system\/bin\/su&quot;;\n\n    private static String sSuPath = DEFAULT_SU_PATH;\n\n    static {\n        System.loadLibrary(&quot;serial_port&quot;);\n    }\n\n    \/*\n     * Do not remove or rename the field mFd: it is used by native method close();\n     *\/\n    private FileDescriptor mFd;\n    private FileInputStream mFileInputStream;\n    private FileOutputStream mFileOutputStream;\n\n    public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {\n\n        \/* Check access permission *\/\n        if (!device.canRead() || !device.canWrite()) {\n            try {\n                \/* Missing read\/write permission, trying to chmod the file *\/\n                Process su;\n                su = Runtime.getRuntime().exec(sSuPath);\n                String cmd = &quot;chmod 666 &quot; + device.getAbsolutePath() + &quot;\\n&quot; + &quot;exit\\n&quot;;\n                su.getOutputStream().write(cmd.getBytes());\n                if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {\n                    throw new SecurityException();\n                }\n            } catch (Exception e) {\n                e.printStackTrace();\n                throw new SecurityException();\n            }\n        }\n\n        mFd = open(device.getAbsolutePath(), baudrate, flags);\n        if (mFd == null) {\n            Log.e(TAG, &quot;native open returns null&quot;);\n            throw new IOException();\n        }\n        mFileInputStream = new FileInputStream(mFd);\n        mFileOutputStream = new FileOutputStream(mFd);\n    }\n\n    public SerialPort(String devicePath, int baudrate, int flags)\n            throws SecurityException, IOException {\n        this(new File(devicePath), baudrate, flags);\n    }\n\n    public SerialPort(File device, int baudrate) throws SecurityException, IOException {\n        this(device, baudrate, 0);\n    }\n\n    public SerialPort(String devicePath, int baudrate) throws SecurityException, IOException {\n        this(new File(devicePath), baudrate, 0);\n    }\n\n    \/**\n     * Set the su binary path, the default su binary path is {@link #DEFAULT_SU_PATH}\n     *\n     * @param suPath su binary path\n     *\/\n    public static void setSuPath(String suPath) {\n        if (suPath == null) {\n            return;\n        }\n        sSuPath = suPath;\n    }\n\n    \/\/ JNI\n    private native static FileDescriptor open(String path, int baudrate, int flags);\n\n    \/\/ Getters and setters\n    public InputStream getInputStream() {\n        return mFileInputStream;\n    }\n\n    public OutputStream getOutputStream() {\n        return mFileOutputStream;\n    }\n\n    public native void close();\n}<\/code><\/pre>\n<h3>\u4f7f\u7528<\/h3>\n<pre><code class=\"language-java\">public SerialPort getSerialPort()\n        throws SecurityException, IOException, InvalidParameterException {\n    if (mSerialPort == null) {\n        \/\/\u4e32\u53e3\uff1a\/dev\/ttyS4\uff0c\u6ce2\u7279\u7387\uff1a115200\n        mSerialPort = new SerialPort(new File(&quot;\/dev\/ttyS4&quot;), 115200);\n    }\n    return mSerialPort;\n}\n\npublic void closeSerialPort() {\n    if (mSerialPort != null) {\n        mSerialPort.close();\n        mSerialPort = null;\n    }\n}\n\nprivate void openSerialPort() {\n    try {\n        mSerialPort = getSerialPort();\n        mInputStream = mSerialPort.getInputStream();\n        mReadThread = new ReadThread();\n        mReadThread.start();\n    } catch (SecurityException e) {\n        e.printStackTrace();\n        ToastCompat.makeText(this, R.string.error_security, Toast.LENGTH_SHORT).show();\n    } catch (IOException e) {\n        e.printStackTrace();\n        ToastCompat.makeText(this, R.string.error_unknown, Toast.LENGTH_SHORT).show();\n    } catch (InvalidParameterException e) {\n        e.printStackTrace();\n        ToastCompat.makeText(this, R.string.error_configuration, Toast.LENGTH_SHORT).show();\n    }\n}\n\nprivate class ReadThread extends Thread {\n\n    public ReadThread() {\n    }\n\n    @Override\n    public void run() {\n        super.run();\n        while (!isInterrupted()) {\n            int size;\n            try {\n                byte[] buffer = new byte[64];\n                if (mInputStream == null) return;\n                size = mInputStream.read(buffer);\n                if (size &gt; 0) {\n                    String goodsCode = new String(buffer, 0, size);\n                    EventBus.getDefault().post(new GoodsMsgEvent(goodsCode));\n                }\n            } catch (IOException e) {\n                e.printStackTrace();\n                return;\n            }\n        }\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u5bf9\u63a5\u4e32\u53e3\u626b\u7801\u5668\uff0c\u53c2\u8003 Github\u4e0a\u5f00\u6e90\u7684\u4e32\u53e3\u901a\u8baf\u5e93https:\/\/github.com\/cepr\/andro [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[311],"tags":[474,473],"class_list":["post-1843","post","type-post","status-publish","format-standard","hentry","category-android-advance","tag-474","tag-473"],"_links":{"self":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/comments?post=1843"}],"version-history":[{"count":0,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/posts\/1843\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/media?parent=1843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/categories?post=1843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appblog.cn\/index.php\/wp-json\/wp\/v2\/tags?post=1843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}