安卓APP:利用AndroidStudio開發usb串口通信軟件【第3步】

打開後的第一個界面如下,點擊connect後開始連接,並跳到第二個節目:

第二個界面如下:

Connect.java

package com.example.usb_to_ttl;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import cn.wch.ch34xuartdriver.CH34xUARTDriver;

public class Connect extends AppCompatActivity implements View.OnClickListener {

    private Button connect_to_main;
    private boolean isOpen = false;
    private int retval;

    private Connect activity;
    public byte[] writeBuffer;
    public byte[] readBuffer;

    public int baudRate;
    public byte stopBit;
    public byte dataBit;
    public byte parity;
    public byte flowControl;

    public int totalrecv;
    private Handler handler;
    private static final String ACTION_USB_PERMISSION = "cn.wch.wchusbdriver.USB_PERMISSION";

   @Override
   protected void onCreate(Bundle savedInstanceState){
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_connect);

       connect_to_main = findViewById(R.id.button_connect);
       connect_to_main.setOnClickListener(this);

       //usb-ttl
       MyApp.driver = new CH34xUARTDriver(
               (UsbManager) getSystemService(Context.USB_SERVICE), this,
               ACTION_USB_PERMISSION);
       baudRate = 9600;
       stopBit = 1;
       dataBit = 8;
       parity = 0;
       flowControl = 0;

       if (!MyApp.driver.UsbFeatureSupported())// 判斷系統是否支持USB HOST
       {
           Dialog dialog = new AlertDialog.Builder(Connect.this)
                   .setTitle("提示")
                   .setMessage("您的手機不支持USB HOST,請更換其他手機再試!")
                   .setPositiveButton("確認",
                           new DialogInterface.OnClickListener() {

                               @Override
                               public void onClick(DialogInterface arg0,
                                                   int arg1) {
                                   System.exit(0);
                               }
                           }).create();
           dialog.setCanceledOnTouchOutside(false);
           dialog.show();
       }
       getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//keep screen always on
       writeBuffer = new byte[512];
       readBuffer = new byte[512];
       isOpen = false;
       activity = this;

       handler = new Handler() {

           public void handleMessage(Message msg) {
               MainActivity.editText_ele.setText((String) msg.obj);
           }
       };
   }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.button_connect:
                connect_to_main();
                break;
        }
    }

    private void connect_to_main(){
        Toast.makeText(Connect.this,"成功",Toast.LENGTH_LONG).show();
        openUSB();
        configUSB();
        Intent intent=new Intent(Connect.this, MainActivity.class);
        startActivityForResult(intent,0x01);
    }

    private class readThread extends Thread {
        public void run() {
            byte[] buffer = new byte[4096];
            while (true) {
                Message msg = Message.obtain();
                if (!isOpen) {
                    break;
                }
                int length = MyApp.driver.ReadData(buffer, buffer.length);
                if (length > 0) {
//					String recv = toHexString(buffer, length);
//					String recv = new String(buffer, 0, length);
                    totalrecv += length;
//                    String content = String.valueOf(totalrecv);
                    String content = new String(buffer);
                    //String content = hexStringToString(toHexString(buffer,length));
                    //String content = toHexString(buffer,length*2);
                    msg.obj = content+"";
                    handler.sendMessage(msg);
                }
            }
        }
    }

    private void openUSB(){
        if (!isOpen) {
            retval = MyApp.driver.ResumeUsbList();
            if (retval == -1)// ResumeUsbList方法用於枚舉CH34X設備以及打開相關設備
            {
                Toast.makeText(Connect.this, "打開設備失敗!",
                        Toast.LENGTH_SHORT).show();
                MyApp.driver.CloseDevice();
            } else if (retval == 0){
                if (!MyApp.driver.UartInit()) {//對串口設備進行初始化操作
                    Toast.makeText(Connect.this, "設備初始化失敗!",
                            Toast.LENGTH_SHORT).show();
                    Toast.makeText(Connect.this, "打開" +
                                    "設備失敗!",
                            Toast.LENGTH_SHORT).show();
                    return;
                }
                Toast.makeText(Connect.this, "打開設備成功!",
                        Toast.LENGTH_SHORT).show();
                isOpen = true;
                connect_to_main.setText("Close");
                new readThread().start();//開啓讀線程讀取串口接收的數據
            } else {

                AlertDialog.Builder builder = new AlertDialog.Builder(activity);
                builder.setIcon(R.mipmap.ic_launcher);
                builder.setTitle("未授權限");
                builder.setMessage("確認退出嗎?");
                builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub
//								MainFragmentActivity.this.finish();
                        System.exit(0);
                    }
                });
                builder.setNegativeButton("返回", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub

                    }
                });
                builder.show();

            }
        } else {
            connect_to_main.setText("Open");
            isOpen = false;
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            MyApp.driver.CloseDevice();
            totalrecv = 0;
        }

    }

    private  void configUSB(){
        if(isOpen) {
            if (MyApp.driver.SetConfig(baudRate, dataBit, stopBit, parity,//配置串口波特率,函數說明可參照編程手冊
                    flowControl)) {
                Toast.makeText(Connect.this, "串口設置成功!",
                        Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(Connect.this, "串口設置失敗!",
                        Toast.LENGTH_SHORT).show();
            }
        }
    }
}

MainActivity.java

package com.example.usb_to_ttl;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.widget.Toast;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.os.Handler;
import android.os.Message;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.hardware.usb.UsbManager;
import android.view.WindowManager;
import cn.wch.ch34xuartdriver.CH34xUARTDriver;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button connect;
    //number 0-9
    private Button n_0;
    private Button n_1;
    private Button n_2;
    private Button n_3;
    private Button n_4;
    private Button n_5;
    private Button n_6;
    private Button n_7;
    private Button n_8;
    private Button n_9;
    //other symbol
    private Button clear_all;
    private Button equal;
    boolean clean;
    public static EditText editText_table;
    public static EditText editText_ele;
    private Context context;

    private String usbNumber;

    private static final String ACTION_USB_PERMISSION = "cn.wch.wchusbdriver.USB_PERMISSION";

    private boolean isOpen = false;

    private Handler handler;

    private int retval;
    private MainActivity activity;
    public byte[] writeBuffer;
    public byte[] readBuffer;

    public int baudRate;
    public byte stopBit;
    public byte dataBit;
    public byte parity;
    public byte flowControl;

    public int totalrecv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /*
        //usb-ttl
        MyApp.driver = new CH34xUARTDriver(
                (UsbManager) getSystemService(Context.USB_SERVICE), this,
                ACTION_USB_PERMISSION);
        baudRate = 9600;
        stopBit = 1;
        dataBit = 8;
        parity = 0;
        flowControl = 0;

        if (!MyApp.driver.UsbFeatureSupported())// 判斷系統是否支持USB HOST
        {
            Dialog dialog = new AlertDialog.Builder(MainActivity.this)
                    .setTitle("提示")
                    .setMessage("您的手機不支持USB HOST,請更換其他手機再試!")
                    .setPositiveButton("確認",
                            new DialogInterface.OnClickListener() {

                                @Override
                                public void onClick(DialogInterface arg0,
                                                    int arg1) {
                                    System.exit(0);
                                }
                            }).create();
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();
        }
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//keep screen always on
        writeBuffer = new byte[512];
        readBuffer = new byte[512];
        isOpen = false;
        activity = this;
        */
        connect = findViewById(R.id.button10);
        //the instantiation of number 0-9
        n_0 = findViewById(R.id.button0);
        n_1 = findViewById(R.id.button1);
        n_2 = findViewById(R.id.button2);
        n_3 = findViewById(R.id.button3);
        n_4 = findViewById(R.id.button4);
        n_5 = findViewById(R.id.button5);
        n_6 = findViewById(R.id.button6);
        n_7 = findViewById(R.id.button7);
        n_8 = findViewById(R.id.button8);
        n_9 = findViewById(R.id.button9);
        //the instantiation of others
        clear_all = findViewById(R.id.button11);
        equal = findViewById(R.id.button12);

        editText_table = findViewById(R.id.editText);
        editText_ele = findViewById(R.id.editText2);

        //unable to edit
        editText_ele.setFocusable(false);
        editText_ele.setFocusableInTouchMode(false);
        editText_table.setFocusable(false);
        editText_table.setFocusableInTouchMode(false);

        //click
        n_0.setOnClickListener(this);
        n_1.setOnClickListener(this);
        n_2.setOnClickListener(this);
        n_3.setOnClickListener(this);
        n_4.setOnClickListener(this);
        n_5.setOnClickListener(this);
        n_6.setOnClickListener(this);
        n_7.setOnClickListener(this);
        n_8.setOnClickListener(this);
        n_9.setOnClickListener(this);

        connect.setOnClickListener(this);

       // sb = new StringBuilder();//usb

        clear_all.setOnClickListener(this);
        equal.setOnClickListener(this);
        context = this;

        handler = new Handler() {

            public void handleMessage(Message msg) {
                editText_ele.setText((String) msg.obj);
            }
        };

    }

    public void onClick(View view){
        //get the input
        String input = editText_table.getText().toString();
        //Determine which key is being pressed
        switch (view.getId()){
            case R.id.button0:
            case R.id.button1:
            case R.id.button2:
            case R.id.button3:
            case R.id.button4:
            case R.id.button5:
            case R.id.button6:
            case R.id.button7:
            case R.id.button8:
            case R.id.button9:
                if(clean){
                    clean = false;
                    editText_table.setText("");
                }
                editText_table.setText(input+((Button)view).getText()+"");
                break;
            //clean
            case R.id.button11:
                if(clean){
                    clean = false;
                    input = "";
                    editText_table.setText("");
                }
                if(!input.equals("")){
                    editText_table.setText(input.substring(0,input.length() - 1));
                    break;
                }
                break;
            case R.id.button12:
                sendToUSB();
                break;
            case R.id.button10:
                openUSB();
                configUSB();
                break;
        }
    }

    private class readThread extends Thread {
        public void run() {
            byte[] buffer = new byte[4096];
            while (true) {
                Message msg = Message.obtain();
                if (!isOpen) {
                    break;
                }
                int length = MyApp.driver.ReadData(buffer, buffer.length);
                if (length > 0) {
//					String recv = toHexString(buffer, length);
//					String recv = new String(buffer, 0, length);
                    totalrecv += length;
//                    String content = String.valueOf(totalrecv);
                    String content = new String(buffer);
                    //String content = hexStringToString(toHexString(buffer,length));
                    //String content = toHexString(buffer,length*2);
                    msg.obj = content+"";
                    handler.sendMessage(msg);
                }
            }
        }
    }

    private String toHexString(byte[] arg, int length) {
        String result = new String();
        if (arg != null) {
            for (int i = 0; i < length; i++) {
                result = result
                        + (Integer.toHexString(
                        arg[i] < 0 ? arg[i] + 256 : arg[i]).length() == 1 ? "0"
                        + Integer.toHexString(arg[i] < 0 ? arg[i] + 256
                        : arg[i])
                        : Integer.toHexString(arg[i] < 0 ? arg[i] + 256
                        : arg[i])) + " ";
            }
            return result;
        }
        return "";
    }
    /*
    private byte[] toByteArray(String arg) {
        if (arg != null) {
            // 1.先去除String中的' ',然後將String轉換爲char數組
            char[] NewArray = new char[1000];
            char[] array = arg.toCharArray();
            int length = 0;
            for (int i = 0; i < array.length; i++) {
                if (array[i] != ' ') {
                    NewArray[length] = array[i];
                    length++;
                }
            }
            // 將char數組中的值轉成一個實際的十進制數組
            int EvenLength = (length % 2 == 0) ? length : length + 1;
            if (EvenLength != 0) {
                int[] data = new int[EvenLength];
                data[EvenLength - 1] = 0;
                for (int i = 0; i < length; i++) {
                    if (NewArray[i] >= '0' && NewArray[i] <= '9') {
                        data[i] = NewArray[i] - '0';
                    } else if (NewArray[i] >= 'a' && NewArray[i] <= 'f') {
                        data[i] = NewArray[i] - 'a' + 10;
                    } else if (NewArray[i] >= 'A' && NewArray[i] <= 'F') {
                        data[i] = NewArray[i] - 'A' + 10;
                    }
                }
                //將 每個char的值每兩個組成一個16進制數據
                byte[] byteArray = new byte[EvenLength / 2];
                for (int i = 0; i < EvenLength / 2; i++) {
                    byteArray[i] = (byte) (data[i * 2] * 16 + data[i * 2 + 1]);
                }
                return byteArray;
            }
        }
        return new byte[] {};
    }
    */

    private byte[] toByteArray2(String arg) {
        if (arg != null) {
            /* 1.先去除String中的' ',然後將String轉換爲char數組 */
            char[] NewArray = new char[1000];
            char[] array = arg.toCharArray();
            int length = 0;
            for (int i = 0; i < array.length; i++) {
                if (array[i] != ' ') {
                    NewArray[length] = array[i];
                    length++;
                }
            }
            NewArray[length] = 0x0D;
            NewArray[length + 1] = 0x0A;
            length += 2;

            byte[] byteArray = new byte[length];
            for (int i = 0; i < length; i++) {
                byteArray[i] = (byte)NewArray[i];
            }
            return byteArray;

        }
        return new byte[] {};
    }

    private void openUSB(){
        if (!isOpen) {
            retval = MyApp.driver.ResumeUsbList();
            if (retval == -1)// ResumeUsbList方法用於枚舉CH34X設備以及打開相關設備
            {
                Toast.makeText(MainActivity.this, "打開設備失敗!",
                        Toast.LENGTH_SHORT).show();
                MyApp.driver.CloseDevice();
            } else if (retval == 0){
                if (!MyApp.driver.UartInit()) {//對串口設備進行初始化操作
                    Toast.makeText(MainActivity.this, "設備初始化失敗!",
                            Toast.LENGTH_SHORT).show();
                    Toast.makeText(MainActivity.this, "打開" +
                                    "設備失敗!",
                            Toast.LENGTH_SHORT).show();
                    return;
                }
                Toast.makeText(MainActivity.this, "打開設備成功!",
                        Toast.LENGTH_SHORT).show();
                isOpen = true;
                connect.setText("Close");
                new readThread().start();//開啓讀線程讀取串口接收的數據
            } else {

                AlertDialog.Builder builder = new AlertDialog.Builder(activity);
                builder.setIcon(R.mipmap.ic_launcher);
                builder.setTitle("未授權限");
                builder.setMessage("確認退出嗎?");
                builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub
//								MainFragmentActivity.this.finish();
                        System.exit(0);
                    }
                });
                builder.setNegativeButton("返回", new DialogInterface.OnClickListener() {

                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub

                    }
                });
                builder.show();

            }
        } else {
            connect.setText("Open");
            isOpen = false;
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            MyApp.driver.CloseDevice();
            totalrecv = 0;
        }

    }

    private  void configUSB(){
        if(isOpen) {
            if (MyApp.driver.SetConfig(baudRate, dataBit, stopBit, parity,//配置串口波特率,函數說明可參照編程手冊
                    flowControl)) {
                Toast.makeText(MainActivity.this, "串口設置成功!",
                        Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(MainActivity.this, "串口設置失敗!",
                        Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void sendToUSB() {
        usbNumber = editText_table.getText().toString();
        //byte[] to_send = toByteArray(usbNumber);
        if(usbNumber.length() < 3) {
            byte[] to_send2 = toByteArray2(usbNumber);
            //txtContent.setText(new String(to_send)+"---"+new String(to_send2));
            int retval = MyApp.driver.WriteData(to_send2, to_send2.length);//寫數據,第一個參數爲需要發送的字節數組,第二個參數爲需要發送的字節長度,返回實際發送的字節長度
            if (retval < 0)
                Toast.makeText(MainActivity.this, "寫失敗!", Toast.LENGTH_SHORT).show();
            Toast t = Toast.makeText(context, "Succeed to send " + usbNumber, Toast.LENGTH_LONG);
            t.show();
        }else {
            Toast t = Toast.makeText(context, "Error :input too long " + usbNumber, Toast.LENGTH_LONG);
            t.show();
            editText_table.setText("");
        }
    }

}

activity_connect.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/button_connect"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Connect"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.499" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.usb_to_ttl">

    <uses-permission android:name="android.permission.WRITE_SETTINGS" />

    <!-- 基礎模塊(必須加入以下聲明)START -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <!-- 統計分析權限 -->
    <uses-permission android:name="android.permission.READ_LOGS" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/train"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".Connect">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.media.action.IMAGE_CAPTURE"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>

            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />
        </activity>
        <activity android:name=".MainActivity"/>

    </application>

</manifest>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章