[
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\nMySerialPort/.idea/"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 白如白牙\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "MySerialPort/.gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
  },
  {
    "path": "MySerialPort/app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "MySerialPort/app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 26\n    buildToolsVersion \"26.0.1\"\n    defaultConfig {\n        applicationId \"cn.humiao.myserialport\"\n        minSdkVersion 14\n        targetSdkVersion 26\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n    sourceSets {\n        main {\n            jniLibs.srcDirs = ['libs']\n        }\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {\n        exclude group: 'com.android.support', module: 'support-annotations'\n    })\n    compile 'com.android.support:appcompat-v7:26.+'\n    compile 'com.android.support.constraint:constraint-layout:1.0.2'\n    testCompile 'junit:junit:4.12'\n    compile 'org.greenrobot:eventbus:3.0.0'\n}\n"
  },
  {
    "path": "MySerialPort/app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in D:\\AndroidSdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "MySerialPort/app/src/androidTest/java/cn/humiao/myserialport/ExampleInstrumentedTest.java",
    "content": "package cn.humiao.myserialport;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumentation test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() throws Exception {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getTargetContext();\n\n        assertEquals(\"cn.humiao.myserialport\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "MySerialPort/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"cn.humiao.myserialport\">\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "MySerialPort/app/src/main/java/android_serialport_api/SerialPort.java",
    "content": "package android_serialport_api;\n\nimport android.util.Log;\n\nimport java.io.File;\nimport java.io.FileDescriptor;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\n\n/**\n * Google官方代码\n * 此类的作用为，JNI的调用，用来加载.so文件的\n * 获取串口输入输出流\n */\n\npublic class SerialPort {\n\n    private static final String TAG = \"SerialPort\";\n\n    /*\n     * Do not remove or rename the field mFd: it is used                                                                                                                                                                            by native method\n     * close();\n     */\n    private FileDescriptor mFd;\n    private FileInputStream mFileInputStream;\n    private FileOutputStream mFileOutputStream;\n\n    public SerialPort(File device, int baudrate, int flags)\n            throws SecurityException, IOException {\n\n\t\t/* 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(\"/system/bin/su\");\n                String cmd = \"chmod 666 \" + device.getAbsolutePath() + \"\\n\"\n                        + \"exit\\n\";\n                su.getOutputStream().write(cmd.getBytes());\n                if ((su.waitFor() != 0) || !device.canRead()\n                        || !device.canWrite()) {\n                    throw new SecurityException();\n                }\n            } catch (Exception e) {\n                e.printStackTrace();\n                throw new SecurityException();\n            }\n        }\n\n        System.out.println(device.getAbsolutePath()\n                + \"==============================\");\n\n        mFd = open(device.getAbsolutePath(), baudrate, flags);\n        if (mFd == null) {\n            Log.e(TAG, \"native open returns null\");\n            throw new IOException();\n        }\n        mFileInputStream = new FileInputStream(mFd);\n        mFileOutputStream = new FileOutputStream(mFd);\n    }\n\n    // Getters and setters\n    public InputStream getInputStream() {\n        return mFileInputStream;\n    }\n\n    public OutputStream getOutputStream() {\n        return mFileOutputStream;\n    }\n\n\n    // JNI\n    private native static FileDescriptor open(String path, int baudrate,\n                                              int flags);\n\n    public native void close();\n\n    static {\n        System.out.println(\"==============================\");\n        System.loadLibrary(\"serial_port\");\n        System.out.println(\"********************************\");\n    }\n}\n"
  },
  {
    "path": "MySerialPort/app/src/main/java/android_serialport_api/SerialPortFinder.java",
    "content": "package android_serialport_api;\n\nimport android.util.Log;\n\nimport java.io.File;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.io.LineNumberReader;\nimport java.util.Iterator;\nimport java.util.Vector;\n\n/**\n * Google官方代码\n * 此类的作用为，寻找得到有效的串口的物理地址。\n * 如果你本身就知道串口的地址如：ttyS1、ttyS2，那么这个类就可以不用了。\n *\n */\n\npublic class SerialPortFinder {\n\n\tpublic class Driver {\n\t\tpublic Driver(String name, String root) {\n\t\t\tmDriverName = name;\n\t\t\tmDeviceRoot = root;\n\t\t}\n\t\tprivate String mDriverName;\n\t\tprivate String mDeviceRoot;\n\t\tVector<File> mDevices = null;\n\t\tpublic Vector<File> getDevices() {\n\t\t\tif (mDevices == null) {\n\t\t\t\tmDevices = new Vector<File>();\n\t\t\t\tFile dev = new File(\"/dev\");\n\t\t\t\tFile[] files = dev.listFiles();\n\t\t\t\tint i;\n\t\t\t\tfor (i=0; i<files.length; i++) {\n\t\t\t\t\tif (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {\n\t\t\t\t\t\tLog.d(TAG, \"Found new device: \" + files[i]);\n\t\t\t\t\t\tmDevices.add(files[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn mDevices;\n\t\t}\n\t\tpublic String getName() {\n\t\t\treturn mDriverName;\n\t\t}\n\t}\n\n\tprivate static final String TAG = \"SerialPort\";\n\n\tprivate Vector<Driver> mDrivers = null;\n\n\tVector<Driver> getDrivers() throws IOException {\n\t\tif (mDrivers == null) {\n\t\t\tmDrivers = new Vector<Driver>();\n\t\t\tLineNumberReader r = new LineNumberReader(new FileReader(\"/proc/tty/drivers\"));\n\t\t\tString l;\n\t\t\twhile((l = r.readLine()) != null) {\n\t\t\t\t// Issue 3:\n\t\t\t\t// Since driver name may contain spaces, we do not extract driver name with split()\n\t\t\t\tString drivername = l.substring(0, 0x15).trim();\n\t\t\t\tString[] w = l.split(\" +\");\n\t\t\t\tif ((w.length >= 5) && (w[w.length-1].equals(\"serial\"))) {\n\t\t\t\t\tLog.d(TAG, \"Found new driver \" + drivername + \" on \" + w[w.length-4]);\n\t\t\t\t\tmDrivers.add(new Driver(drivername, w[w.length-4]));\n\t\t\t\t}\n\t\t\t}\n\t\t\tr.close();\n\t\t}\n\t\treturn mDrivers;\n\t}\n\n\tpublic String[] getAllDevices() {\n\t\tVector<String> devices = new Vector<String>();\n\t\t// Parse each driver\n\t\tIterator<Driver> itdriv;\n\t\ttry {\n\t\t\titdriv = getDrivers().iterator();\n\t\t\twhile(itdriv.hasNext()) {\n\t\t\t\tDriver driver = itdriv.next();\n\t\t\t\tIterator<File> itdev = driver.getDevices().iterator();\n\t\t\t\twhile(itdev.hasNext()) {\n\t\t\t\t\tString device = itdev.next().getName();\n\t\t\t\t\tString value = String.format(\"%s (%s)\", device, driver.getName());\n\t\t\t\t\tdevices.add(value);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn devices.toArray(new String[devices.size()]);\n\t}\n\n\tpublic String[] getAllDevicesPath() {\n\t\tVector<String> devices = new Vector<String>();\n\t\t// Parse each driver\n\t\tIterator<Driver> itdriv;\n\t\ttry {\n\t\t\titdriv = getDrivers().iterator();\n\t\t\twhile(itdriv.hasNext()) {\n\t\t\t\tDriver driver = itdriv.next();\n\t\t\t\tIterator<File> itdev = driver.getDevices().iterator();\n\t\t\t\twhile(itdev.hasNext()) {\n\t\t\t\t\tString device = itdev.next().getAbsolutePath();\n\t\t\t\t\tdevices.add(device);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\treturn devices.toArray(new String[devices.size()]);\n\t}\n}\n"
  },
  {
    "path": "MySerialPort/app/src/main/java/cn/humiao/myserialport/Cmd.java",
    "content": "package cn.humiao.myserialport;\n\n/**\n * @author by AllenJ on 2018/5/3.\n */\n\npublic interface Cmd {\n    String OPEN_DOOR = \"010100000000FFFF\";\n}\n"
  },
  {
    "path": "MySerialPort/app/src/main/java/cn/humiao/myserialport/DataUtils.java",
    "content": "package cn.humiao.myserialport;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 串口数据转换工具类\n * Created by Administrator on 2016/6/2.\n */\npublic class DataUtils {\n    //-------------------------------------------------------\n    // 判断奇数或偶数，位运算，最后一位是1则为奇数，为0是偶数\n    public static int isOdd(int num) {\n        return num & 1;\n    }\n\n    //-------------------------------------------------------\n    //Hex字符串转int\n    public static int HexToInt(String inHex) {\n        return Integer.parseInt(inHex, 16);\n    }\n\n    public static String IntToHex(int intHex){\n        return Integer.toHexString(intHex);\n    }\n\n    //-------------------------------------------------------\n    //Hex字符串转byte\n    public static byte HexToByte(String inHex) {\n        return (byte) Integer.parseInt(inHex, 16);\n    }\n\n    //-------------------------------------------------------\n    //1字节转2个Hex字符\n    public static String Byte2Hex(Byte inByte) {\n        return String.format(\"%02x\", new Object[]{inByte}).toUpperCase();\n    }\n\n    //-------------------------------------------------------\n    //字节数组转转hex字符串\n    public static String ByteArrToHex(byte[] inBytArr) {\n        StringBuilder strBuilder = new StringBuilder();\n        for (byte valueOf : inBytArr) {\n            strBuilder.append(Byte2Hex(Byte.valueOf(valueOf)));\n            strBuilder.append(\" \");\n        }\n        return strBuilder.toString();\n    }\n\n    //-------------------------------------------------------\n    //字节数组转转hex字符串，可选长度\n    public static String ByteArrToHex(byte[] inBytArr, int offset, int byteCount) {\n        StringBuilder strBuilder = new StringBuilder();\n        int j = byteCount;\n        for (int i = offset; i < j; i++) {\n            strBuilder.append(Byte2Hex(Byte.valueOf(inBytArr[i])));\n        }\n        return strBuilder.toString();\n    }\n\n    //-------------------------------------------------------\n    //转hex字符串转字节数组\n    public static byte[] HexToByteArr(String inHex) {\n        byte[] result;\n        int hexlen = inHex.length();\n        if (isOdd(hexlen) == 1) {\n            hexlen++;\n            result = new byte[(hexlen / 2)];\n            inHex = \"0\" + inHex;\n        } else {\n            result = new byte[(hexlen / 2)];\n        }\n        int j = 0;\n        for (int i = 0; i < hexlen; i += 2) {\n            result[j] = HexToByte(inHex.substring(i, i + 2));\n            j++;\n        }\n        return result;\n    }\n\n    /**\n     * 按照指定长度切割字符串\n     *\n     * @param inputString 需要切割的源字符串\n     * @param length      指定的长度\n     * @return\n     */\n    public static List<String> getDivLines(String inputString, int length) {\n        List<String> divList = new ArrayList<>();\n        int remainder = (inputString.length()) % length;\n        // 一共要分割成几段\n        int number = (int) Math.floor((inputString.length()) / length);\n        for (int index = 0; index < number; index++) {\n            String childStr = inputString.substring(index * length, (index + 1) * length);\n            divList.add(childStr);\n        }\n        if (remainder > 0) {\n            String cStr = inputString.substring(number * length, inputString.length());\n            divList.add(cStr);\n        }\n        return divList;\n    }\n\n    /**\n     * 计算长度，两个字节长度\n     *\n     * @param val value\n     * @return 结果\n     */\n    public static String twoByte(String val) {\n        if (val.length() > 4) {\n            val = val.substring(0, 4);\n        } else {\n            int l = 4 - val.length();\n            for (int i = 0; i < l; i++) {\n                val = \"0\" + val;\n            }\n        }\n        return val;\n    }\n\n    /**\n     * 校验和\n     *\n     * @param cmd 指令\n     * @return 结果\n     */\n    public static String sum(String cmd) {\n        List<String> cmdList = DataUtils.getDivLines(cmd, 2);\n        int sumInt = 0;\n        for (String c : cmdList) {\n            sumInt += DataUtils.HexToInt(c);\n        }\n        String sum = DataUtils.IntToHex(sumInt);\n        sum = DataUtils.twoByte(sum);\n        cmd += sum;\n        return cmd.toUpperCase();\n    }\n\n}\n"
  },
  {
    "path": "MySerialPort/app/src/main/java/cn/humiao/myserialport/MainActivity.java",
    "content": "package cn.humiao.myserialport;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.view.View;\nimport android.widget.Button;\nimport android.widget.TextView;\n\nimport org.greenrobot.eventbus.EventBus;\nimport org.greenrobot.eventbus.Subscribe;\nimport org.greenrobot.eventbus.ThreadMode;\n\n\npublic class MainActivity extends AppCompatActivity {\n    private String TAG = \"MainActivity\";\n    private Button button;\n    private TextView tv;\n    private SerialPortUtil serialPortUtil;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        button = (Button) findViewById(R.id.btn);\n        tv = (TextView) findViewById(R.id.tv);\n        serialPortUtil = new SerialPortUtil();\n        serialPortUtil.openSerialPort();\n        //注册EventBus\n        EventBus.getDefault().register(this);\n        button.setOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                serialPortUtil.sendSerialPort(Cmd.OPEN_DOOR);\n            }\n        });\n    }\n\n    /**\n     * 用EventBus进行线程间通信，也可以使用Handler\n     * @param string\n     */\n    @Subscribe(threadMode = ThreadMode.MAIN)\n    public void onEventMainThread(String string){\n        Log.d(TAG,\"获取到了从传感器发送到Android主板的串口数据\");\n        tv.setText(string);\n    }\n}\n"
  },
  {
    "path": "MySerialPort/app/src/main/java/cn/humiao/myserialport/SerialPortUtil.java",
    "content": "package cn.humiao.myserialport;\n\nimport android.util.Log;\n\nimport org.greenrobot.eventbus.EventBus;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\n\nimport android_serialport_api.SerialPort;\n\n/**\n * @author by AllenJ on 2018/4/20.\n *\n * 通过串口用于接收或发送数据\n */\n\npublic class SerialPortUtil {\n\n    private SerialPort serialPort = null;\n    private InputStream inputStream = null;\n    private OutputStream outputStream = null;\n    private ReceiveThread mReceiveThread = null;\n    private boolean isStart = false;\n\n    /**\n     * 打开串口，接收数据\n     * 通过串口，接收单片机发送来的数据\n     */\n    public void openSerialPort() {\n        try {\n            serialPort = new SerialPort(new File(\"/dev/ttyS0\"), 9600, 0);\n            //调用对象SerialPort方法，获取串口中\"读和写\"的数据流\n            inputStream = serialPort.getInputStream();\n            outputStream = serialPort.getOutputStream();\n            isStart = true;\n\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        getSerialPort();\n    }\n\n    /**\n     * 关闭串口\n     * 关闭串口中的输入输出流\n     */\n    public void closeSerialPort() {\n        Log.i(\"test\", \"关闭串口\");\n        try {\n            if (inputStream != null) {\n                inputStream.close();\n            }\n            if (outputStream != null) {\n                outputStream.close();\n            }\n            isStart = false;\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n\n    }\n\n    /**\n     * 发送数据\n     * 通过串口，发送数据到单片机\n     *\n     * @param data 要发送的数据\n     */\n    public void sendSerialPort(String data) {\n        try {\n            byte[] sendData = DataUtils.HexToByteArr(data);\n            outputStream.write(sendData);\n            outputStream.flush();\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n    }\n\n    private void getSerialPort() {\n        if (mReceiveThread == null) {\n\n            mReceiveThread = new ReceiveThread();\n        }\n        mReceiveThread.start();\n    }\n\n    /**\n     * 接收串口数据的线程\n     */\n\n    private class ReceiveThread extends Thread {\n        @Override\n        public void run() {\n            super.run();\n            //条件判断，只要条件为true，则一直执行这个线程\n            while (isStart) {\n                if (inputStream == null) {\n                    return;\n                }\n                byte[] readData = new byte[1024];\n                try {\n                    int size = inputStream.read(readData);\n                    if (size > 0) {\n                        String readString = DataUtils.ByteArrToHex(readData, 0, size);\n                        EventBus.getDefault().post(readString);\n                    }\n\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n\n        }\n    }\n\n}\n"
  },
  {
    "path": "MySerialPort/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\">\n\n    <Button\n        android:id=\"@+id/btn\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"点击进行串口发送\"\n        android:textSize=\"25px\" />\n\n    <TextView\n        android:id=\"@+id/tv\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginTop=\"10dp\"\n        android:text=\"接受串口返回的信息并显示\"\n        android:textSize=\"30px\" />\n</LinearLayout>\n"
  },
  {
    "path": "MySerialPort/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "MySerialPort/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">MySerialPort</string>\n</resources>\n"
  },
  {
    "path": "MySerialPort/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "MySerialPort/app/src/test/java/cn/humiao/myserialport/ExampleUnitTest.java",
    "content": "package cn.humiao.myserialport;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "MySerialPort/build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.3.3'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "MySerialPort/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu May 03 19:12:00 CST 2018\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-3.3-all.zip\n"
  },
  {
    "path": "MySerialPort/gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\norg.gradle.jvmargs=-Xmx1536m\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n"
  },
  {
    "path": "MySerialPort/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "MySerialPort/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "MySerialPort/settings.gradle",
    "content": "include ':app'\n"
  },
  {
    "path": "README.md",
    "content": "## 说明\n\n1. 学会如何使用JNI的调用\n2. 知道如何利用串口接收和发送数据\n3. 了解Google的设计思维\n\n"
  }
]