安卓端传统蓝牙串口通信小工具

前几天又完成了一个安卓端传统蓝牙串口通信小工具

安卓端传统蓝牙串口通信小工具_第1张图片

因为写博客的时候,蓝牙硬件已经寄回给客户了,所以无法截屏,只能看下面调试过程中拍的照片了。

安卓端传统蓝牙串口通信小工具_第2张图片

因为好久没做安卓开发了,开发过程中还是查了些资料的,其中有:自定义actionbar,recyclerview,eventbus,swiperefreshlayout的使用,当然还有最重要的蓝牙通信相关API。

部分关键代码如下,DeviceCommandManager.java(蓝牙连接及命令发送):

package com.meiyuan.bluetooth;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.text.TextUtils;
import android.util.Log;

import com.meiyuan.bluetooth.listener.BluetoothConnectCallback;
import com.meiyuan.bluetooth.listener.DeviceMessageReader;
import com.meiyuan.bluetooth.model.MessageWrap;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;

public class DeviceCommandManager implements BluetoothConnectCallback {
    private String TAG="cmd";
    private BluetoothSocket socket;
    private BluetoothDevice device;
    private String lastCommand;
    private int state=0;//0是未连接 1正在链接 2已连接
    private static DeviceCommandManager instance = new DeviceCommandManager();
    private BluetoothConnectThread currentThread;

    private DeviceCommandManager() {
    }
    public static DeviceCommandManager getInstance() {
        return instance;
    }
    public int getState(){
        return state;
    }
    public String getCurrentMac(){
        if(getState()==2&&device!=null){
            return device.getAddress();
        }
        return null;
    }
    public void ConnectDevice(BluetoothDevice device){
        try {
            if (getState() == 2 && this.device != null && this.device.getAddress().equals(device.getAddress())) {
                MessageWrap message = new MessageWrap(MessageWrap.message_device_connect_repeat, null);
                EventBus.getDefault().post(message);
                return;
            } else if (getState() == 2) {//当前已有链接
                Log.d("cmd", "当前已有链接,先断开");
                disConnect(this.device.getAddress());
                try {
                    if (currentThread != null) {
                        currentThread.cancel();
                        if (currentThread.isAlive()) {
                            currentThread.interrupt();
                        }
                    }
                } catch (Exception e) {

                } finally {
                    currentThread = null;
                }
            }
            MessageWrap message = new MessageWrap(MessageWrap.message_device_connecting, null);
            EventBus.getDefault().post(message);
            this.device = device;
            state = 1;
            currentThread = new BluetoothConnectThread(device, this);
            currentThread.start();
        }catch (Exception e){
            MessageWrap message = new MessageWrap(MessageWrap.message_exception, e.getMessage());
            EventBus.getDefault().post(message);
        }
    }
    public void disConnect(String mac){
        if(device!=null&&mac.equals(device.getAddress())) {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    socket = null;
                }
            }
            device = null;
            state = 0;
        }
    }
    public void sendCommand(String cmd){
        if(state==2) {
            lastCommand = cmd;
            Log.d("cmd","发送命令:"+cmd);
            MessageWrap message = new MessageWrap(MessageWrap.message_wait_for_device, "请稍后...");
            EventBus.getDefault().post(message);
            try {
                socket.getOutputStream().write(cmd.getBytes("utf-8"));
                socket.getOutputStream().flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            MessageWrap message=new MessageWrap(MessageWrap.message_device_disconnect);
            EventBus.getDefault().post(message);
            Log.e("cmd","链接已断开");
        }
    }
    public void sendLastCommand(){
        sendCommand(lastCommand);
    }
    @Override
    public void connectSuccess(BluetoothSocket socket) {
        try {
            this.socket=socket;
            state=2;
            String deviceName=device.getName();
            if(TextUtils.isEmpty(deviceName)){
                deviceName="N/A";
            }
            MessageWrap message=new MessageWrap(MessageWrap.message_device_connected,deviceName);
            EventBus.getDefault().post(message);
            Log.d(TAG,"蓝牙链接成功");
            try {
                new DeviceMessageReader(socket.getInputStream()).start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }catch (Exception ex){
            MessageWrap message = new MessageWrap(MessageWrap.message_exception, ex.getMessage());
            EventBus.getDefault().post(message);
        }
    }

    @Override
    public void connectFailed(String errorMsg) {
        state=0;
        Log.e(TAG,"蓝牙链接失败:"+errorMsg);
        MessageWrap message=new MessageWrap(MessageWrap.message_device_connect_error,"设备连接失败,请检查设备是否开启并在附近?");
        EventBus.getDefault().post(message);
    }

    @Override
    public void connectCancel() {
        state=0;
        Log.d(TAG,"蓝牙链接关闭");
    }
}
DeviceMessageReader.java(消息接收)
package com.meiyuan.bluetooth.listener;

import android.text.TextUtils;
import android.util.Log;

import com.meiyuan.bluetooth.model.MessageWrap;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.io.InputStream;

public class DeviceMessageReader extends Thread{
    private InputStream inputStream;
    private boolean read=true;
    public DeviceMessageReader(InputStream inputStream){
        this.inputStream=inputStream;
    }
    @Override
    public void run() {
        byte[] buffer = new byte[1024];
        int bytes;//定义长度变量
        while (read){
            try {
                if ((bytes = inputStream.read(buffer)) != 0) {
                    byte[] buf_data = new byte[bytes];
                    for (int i = 0; i < bytes; i++){
                        buf_data[i]=buffer[i];
                    }
                    String msg=new String(buf_data);
                    Log.d("cmd","收到蓝牙消息:"+msg);
                    MessageWrap message=new MessageWrap(MessageWrap.message_device_return,msg);
                    EventBus.getDefault().post(message);
                }
            }catch (Exception e){
                e.printStackTrace();
                if(!TextUtils.isEmpty(e.getMessage())&&e.getMessage().indexOf("socket closed")!=-1){
                    read=false;
                }
            }
        }
        try {
            if(inputStream!=null)
                inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

整个APP做起来其实还是很简单的,主要有些细节有点繁琐而已,比如要检测手机支持不支持蓝牙,蓝牙有没开启,其中有个坑,必须打开定位才能搜索附近蓝牙设备,一开始卡在这里整整一天,还以为程序哪里弄错了呢。

    /**
     * 判断定位服务是否开启
     *
     * @param
     * @return true 表示开启
     */
    public static boolean isLocationEnabled(Context context) {
        int locationMode = 0;
        String locationProviders;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
            } catch (Settings.SettingNotFoundException e) {
                e.printStackTrace();
                return false;
            }
            return locationMode != Settings.Secure.LOCATION_MODE_OFF;
        } else {
            locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            return !TextUtils.isEmpty(locationProviders);
        }
    }
    /**
     * 提示用户去开启定位服务
     **/
    public static void toOpenGPS(Activity activity) {
        new AlertDialog.Builder(activity)
                .setTitle("提示")
                .setMessage("手机定位服务未开启,无法发现附近蓝牙设备,是否前往开启?")
                .setNegativeButton("取消",null)
                .setPositiveButton("去开启", (dialogInterface,i)-> {
                        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        activity.startActivityForResult(intent,REQUEST_SERVICE_OPEN_LOCATION);
                        dialogInterface.dismiss();
                    }
                )
                .show();
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_SERVICE_OPEN_LOCATION) {
            if(!isLocationEnabled(this)){
                toOpenGPS(this);
            }else{
                checkBlueTooth();
            }
        }else if(requestCode == REQUEST_ENABLE_BT){
            checkBlueTooth();
        }
    }

另外在项目进入测试阶段的时候,为防止客户拿到APP后跑路,在APP里简单加了个服务器验证机制,有兴趣的童鞋可以下载源码看下,创作不易,有偿分享。

源码下载:下载源码

你可能感兴趣的:(android,android,蓝牙串口通信,蓝牙通信)