封裝一個Android藍牙串口工具類

原文地址:https://www.shanya.world/archives/2fd981ea.html

把串口通信相關代碼封裝一下,省的每次都要重新寫那些囉嗦的代碼。

如何上傳 jitpack 參考: https://www.shanya.world/archives/c0a1d02b.html

源碼地址: https://github.com/Shanyaliux/SerialPortUtil

使用方法

  • 根目錄的 build.gradle 添加 maven { url 'https://jitpack.io' } , 位置如下
allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }
  • 添加依賴
implementation 'com.github.Shanyaliux:SerialPortUtil:1.0.0'
  • 調用方法
/**
* 獲取串口工具實例
*@param cntext
*@param new OnSerialPortListener() 收到消息監聽
*/
SerialPortUtil serialPortUtil = SerialPortUtil.getInstance(this, new SerialPortUtil.OnSerialPortListener() {
            @Override
            public void onReceivedData(String data) {
                // 這裏建議使用handler處理
            }
        });


/**
* 掃描可用設備
*/
serialPortUtil.doDiscovery();

/**
* 發送數據
*/
serialPortUtil.sendData("Hello World\n");

/**
* 獲取已配對設備列表給ListView顯示
*/
serialPortUtil.getPairedDevicesArrayAdapter()

/**
* 獲取未配對設備列表給ListView顯示
*/
serialPortUtil.getUnPairedDevicesArrayAdapter()

/**
* ListView 點擊連接設置監聽
*/
listView.setOnItemClickListener(serialPortUtil.getDevicesClickListener());

具體源碼

package com.shanya.serialportutil;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;

import androidx.core.content.ContextCompat;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.UUID;

public class SerialPortUtil {

    private final static String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";   //SPP服務UUID號
    private Context context;
    private BluetoothAdapter bluetoothAdapter;
    private BluetoothSocket bluetoothSocket;
    private ArrayAdapter<String> pairedDevicesArrayAdapter;
    private ArrayAdapter<String> unPairedDevicesArrayAdapter;
    private InputStream inputStream;
    private OnSerialPortListener onSerialPortListener;

    private static SerialPortUtil serialPortUtil;
    public static SerialPortUtil getInstance(Context context,OnSerialPortListener onSerialPortListener){
        if (serialPortUtil == null) {
            serialPortUtil = new SerialPortUtil(context,onSerialPortListener);
        }
        return serialPortUtil;
    }

    private SerialPortUtil(Context context, OnSerialPortListener onSerialPortListener) {
        this.context = context.getApplicationContext();
        this.onSerialPortListener = onSerialPortListener;
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        pairedDevicesArrayAdapter = new ArrayAdapter<>(context, R.layout.device_name);
        unPairedDevicesArrayAdapter = new ArrayAdapter<>(context,R.layout.device_name);
        BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    if (device != null) {
                        if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                            pairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
                        } else {
                            unPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
                        }
                    }
                } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                    //搜索完成
                    System.out.println("ok");
                    if (unPairedDevicesArrayAdapter.getCount() == 0) {
                        System.out.println("未找到新設備");
                    }
                }
            }
        };
        context.registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
        context.registerReceiver(receiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
        context.registerReceiver(receiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED));
        Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
        if (!pairedDevices.isEmpty()){
            for (BluetoothDevice device : pairedDevices) {
                pairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
            }
        }else {
            String noDevices = "未找到已配對設備";
            pairedDevicesArrayAdapter.add(noDevices);
        }
    }

    public void doDiscovery(){
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) !=
                PackageManager.PERMISSION_GRANTED){
            Toast.makeText(context,"沒有權限",Toast.LENGTH_SHORT).show();
        }else{
            if (bluetoothAdapter.isDiscovering()){
                bluetoothAdapter.cancelDiscovery();
            }
            bluetoothAdapter.startDiscovery();
        }
    }

    public void sendData(String data){
        if(!bluetoothAdapter.isEnabled()){
            Toast.makeText(context,"請先打開藍牙",Toast.LENGTH_SHORT).show();
            return;
        }
        if (bluetoothSocket == null){
            Toast.makeText(context,"請先連接設備",Toast.LENGTH_SHORT).show();
            return;
        }
        try{
            int n = 0;
            OutputStream outputStream = bluetoothSocket.getOutputStream();
            byte[] bos = data.getBytes();
            for (byte bo : bos) {
                if (bo == 0x0a) n++;
            }
            byte[] bos_new = new byte[bos.length + n];
            n = 0;
            for (byte bo : bos) { //手機中換行爲0a,將其改爲0d 0a後再發送
                if (bo == 0x0a) {
                    bos_new[n] = 0x0d;
                    n++;
                    bos_new[n] = 0x0a;
                } else {
                    bos_new[n] = bo;
                }
                n++;
            }

            outputStream.write(bos_new);
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    private AdapterView.OnItemClickListener devicesClickListener = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            bluetoothAdapter.cancelDiscovery();
            String info = ((TextView) view).getText().toString();
            String address = info.substring(info.length() - 17);

            //返回地址供於連接
            BluetoothDevice bluetoothDevice = bluetoothAdapter.getRemoteDevice(address);
            try{
                bluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
                bluetoothSocket.connect();
                Toast.makeText(context,"連接" + bluetoothDevice.getName() + "成功",Toast.LENGTH_SHORT).show();
                inputStream = bluetoothSocket.getInputStream();
                readThread.start();
            }catch (IOException e){
                Toast.makeText(context,"連接失敗",Toast.LENGTH_SHORT).show();
                try {
                    bluetoothSocket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }

            }
        }
    };

    private Thread readThread = new Thread(){

        public void run(){
            super.run();
            byte[] buffer = new byte[0];
            int len;
            String s;
            boolean flag = false;
            //noinspection InfiniteLoopStatement
            while(true){
                try {
                    sleep(100);
                    len = inputStream.available();
                    while(len != 0) {
                        flag = true;
                        buffer = new byte[len];
                        //noinspection ResultOfMethodCallIgnored
                        inputStream.read(buffer);
                        sleep(10);//讀入數據
                        len = inputStream.available();
                    }
                    if (flag){
                        s = new String(buffer, StandardCharsets.UTF_8);
                        onSerialPortListener.onReceivedData(s);
                        flag = false;
                    }
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    public ArrayAdapter<String> getPairedDevicesArrayAdapter() {
        return pairedDevicesArrayAdapter;
    }

    public ArrayAdapter<String> getUnPairedDevicesArrayAdapter() {
        return unPairedDevicesArrayAdapter;
    }

    public AdapterView.OnItemClickListener getDevicesClickListener() {
        return devicesClickListener;
    }

    public interface OnSerialPortListener{
        void onReceivedData(String data);
    }
}

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