IT技术互动交流平台

Android蓝牙实例(和单片机蓝牙模块通信)

作者:luoxn28  来源:IT165收集  发布日期:2016-05-03 22:36:49

  最近做毕设,需要写一个简单的蓝牙APP进行交互,在网上也找了很多资料,终于给搞定了,这里分享一下^_^。

1、Android蓝牙编程

  蓝牙3.0及以下版本编程需要使用UUID,UUID是通用唯一识别码(Universally Unique Identifier),这是一个软件构建的标准,也是被开源基金会组织应用在分布式计算环境领域的一部分。在蓝牙3.0及下一版本中,UUID被用于唯一标识一个服务,比如文件传输服务,串口服务、打印机服务等,如下:

#蓝牙串口服务 
SerialPortServiceClass_UUID = '{00001101-0000-1000-8000-00805F9B34FB}' 
LANAccessUsingPPPServiceClass_UUID = '{00001102-0000-1000-8000-00805F9B34FB}'

#拨号网络服务 
DialupNetworkingServiceClass_UUID = '{00001103-0000-1000-8000-00805F9B34FB}'

#信息同步服务 
IrMCSyncServiceClass_UUID = '{00001104-0000-1000-8000-00805F9B34FB}' 
SDP_OBEXObjectPushServiceClass_UUID = '{00001105-0000-1000-8000-00805F9B34FB}'

#文件传输服务 
OBEXFileTransferServiceClass_UUID = '{00001106-0000-1000-8000-00805F9B34FB}' 
IrMCSyncCommandServiceClass_UUID = '{00001107-0000-1000-8000-00805F9B34FB}'

  蓝牙的连接有主从设备,提供服务的可以认为是从设备。主设备通过UUID访问从设备提供具有相同UUID的服务,从而建立客服端—服务器(C/S)模式。

 2、编程步骤

Android使用蓝牙,需要获得权限,蓝牙权限获得代码如下:

<!-- 蓝牙权限 -->
<uses-permission android:name='android.permission.BLUETOOTH'/>
<uses-permission android:name='android.permission.BLUETOOTH_ADMIN'/>

获取本地蓝牙适配器,如果蓝牙未开启,开启蓝牙设备:

bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (bluetoothAdapter == null) {
    // Device does not support Bluetooth
    return;
}
// 开启蓝牙
int REQUEST_ENABLE_BT = 1;
if (!bluetoothAdapter.isEnabled()) {
    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(intent, REQUEST_ENABLE_BT);
}

 搜索已配对的蓝牙设备,并添加到已配对列表中:

// 查询配对设备
List<String> devices = new ArrayList<String>();
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice device : bondedDevices) {
    devices.add(device.getName() + '-' + device.getAddress());
}

搜索未配对蓝牙设备,并添加到未配对列表:

mBluetoothAdapter.startDiscovery();
//开始收索 搜索接收函数:  
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {                   
       String action = intent.getAction();                   // When discovery finds a device                    
       if (BluetoothDevice.ACTION_FOUND.equals(action)) {
           // Get the BluetoothDevice object from the Intent  
           BluetoothDevice device =  intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  
           // Add the name and address to an array adapter to show  in a ListView  
           mArrayAdapter.add(device.getName() + '
' + device.getAddress());    
       }
    }
};
// 收索接收函数需要注册:    
// Register the BroadcastReceiver      
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);  
registerReceiver(mReceiver, filter); // Don't forget to unregister  during onDestroy

如果是服务器端,需要建立监听,注意监听的是某个服务的UUID,服务器监听类如下:

private class ConnectThread extends Thread {
    private final String MY_UUID = '00001101-0000-1000-8000-00805F9B34FB';
    private final BluetoothSocket socket;
    private final BluetoothDevice device;

    public ConnectThread(BluetoothDevice device) {
        this.device = device;
        BluetoothSocket tmp = null;

        try {
            tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.socket = tmp;
    }

    public void run() {
        bluetoothAdapter.cancelDiscovery();
        try {
            socket.connect();
            connectedThread = new ConnectedThread(socket);
            connectedThread.start();
        } catch (IOException e) {
            try {
                socket.close();
            } catch (IOException ee) {
                ee.printStackTrace();
            }
            return;
        }
        //manageConnectedSocket(socket);
    }

    public void cancel() {
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端与服务器端建立连接成功后,需要ConnectedThread类接收发送数据:

// 客户端与服务器建立连接成功后,用ConnectedThread收发数据
private class ConnectedThread extends Thread {
    private final BluetoothSocket socket;
    private final InputStream inputStream;
    private final OutputStream outputStream;

    public ConnectedThread(BluetoothSocket socket) {
        this.socket = socket;
        InputStream input = null;
        OutputStream output = null;

        try {
            input = socket.getInputStream();
            output = socket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.inputStream = input;
        this.outputStream = output;
    }

    public void run() {
        byte[] buff = new byte[1024];
        int bytes;

        while (true) {
            try {
                bytes = inputStream.read(buff);
                String str = new String(buff, 'ISO-8859-1');
                str = str.substring(0, bytes);

                Log.e('recv', str);
            } catch (IOException e) {
                e.printStackTrace();
                break;
            }
        }
    }

    public void write(byte[] bytes) {
        try {
            outputStream.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void cancel() {
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  到此为止就是蓝牙开发的大致步骤,其中没有涉及到蓝牙客户端建立连接类,不过可查阅BLE和经典蓝牙Android开发。

 3、毕设蓝牙APP介绍

  毕设蓝牙APP需要接收单片机通过蓝牙模块发送上来的数据,并且蓝牙APP也可以给单片机发送数据来进行控制。页面布局如下,一个是整体页面,一个是设置页面,测试手机是魅蓝note。因为毕设做的是十字路口红绿灯控制系统,所有页面布局有4个LED灯,分别代表路口的4个红绿灯,会根据时间不同显示不同的颜色(红/绿/黄),并且会显示倒计时,最后来一张红绿灯系统整体图。

   

activity_main.xml文件如下:

<?xml version='1.0' encoding='utf-8'?>
<RelativeLayout xmlns:android='http://schemas.android.com/apk/res/android'
    xmlns:tools='http://schemas.android.com/tools' android:layout_width='match_parent'
    android:layout_height='wrap_content' android:paddingLeft='@dimen/activity_horizontal_margin'
    android:paddingRight='@dimen/activity_horizontal_margin'
    android:paddingTop='@dimen/activity_vertical_margin'
    android:paddingBottom='@dimen/activity_vertical_margin' tools:context='.MainActivity'>

    <LinearLayout
        android:id='@+id/linear_layout_top'
        android:layout_alignParentTop='true'
        android:layout_width='match_parent'
        android:layout_height='40dp'>

        <TextView
            android:id='@+id/notice_view'
            android:layout_width='0dp'
            android:layout_height='40dp'
            android:text='蓝牙未开启'
            android:layout_weight='3'/>
        <TextView
            android:id='@+id/notice_recv_view'
            android:layout_width='0dp'
            android:layout_height='30dp'
            android:layout_weight='3'/>
        <TextView
            android:id='@+id/notice_send_view'
            android:layout_width='0dp'
            android:layout_height='30dp'
            android:layout_weight='3'/>
        <Button
            android:id='@+id/turn_on_off'
            android:layout_width='0dp'
            android:layout_height='40dp'
            android:layout_weight='2'
            android:text='ON'/>
    </LinearLayout>


    <TextView
        android:id='@+id/led1'
        android:layout_centerHorizontal='true'
        android:layout_below='@+id/linear_layout_top'
        android:layout_width='40dp'
        android:layout_height='20dp'
        android:gravity='center'
        android:text='LED1'/>
    <TextView
        android:id='@+id/led0'
        android:layout_centerHorizontal='true'
        android:layout_below='@+id/led1'
        android:layout_width='40dp'
        android:layout_height='20dp'
        android:gravity='center'
        android:text='+'/>
    <TextView
        android:id='@+id/led3'
        android:layout_below='@+id/led1'
        android:layout_toLeftOf='@+id/led1'
        android:layout_width='40dp'
        android:layout_height='20dp'
        android:gravity='center'
        android:text='LED3'/>
    <TextView
        android:id='@+id/led2'
        android:layout_centerHorizontal='true'
        android:layout_below='@+id/led3'
        android:layout_width='40dp'
        android:layout_height='20dp'
        android:gravity='center'
        android:text='LED2'/>
    <TextView
        android:id='@+id/led4'
        android:layout_below='@+id/led1'
        android:layout_toRightOf='@+id/led1'
        android:layout_width='40dp'
        android:layout_height='20dp'
        android:gravity='center'
        android:text='LED4'/>

    <ScrollView
        android:id='@+id/scroll_view'
        android:layout_below='@+id/led2'
        android:layout_above='@+id/linear_layout_bottom'
        android:layout_width='match_parent'
        android:layout_height='match_parent'>

        <TextView
            android:id='@+id/recv_view'
            android:text=''
            android:layout_width='wrap_content'
            android:layout_height='wrap_content' />
    </ScrollView>

    <LinearLayout
        android:id='@+id/linear_layout_bottom'
        android:layout_alignParentBottom='true'
        android:layout_width='match_parent'
        android:layout_height='50dp'>

        <Button
            android:id='@+id/clear_recv_view'
            android:layout_width='0dp'
            android:layout_height='match_parent'
            android:layout_weight='1'
            android:text='clear' />

        <EditText
            android:id='@+id/send_text'
            android:layout_width='0dp'
            android:layout_height='wrap_content'
            android:layout_weight='3'
            android:hint='输入框,默认@#结尾'/>

        <Button
            android:id='@+id/send'
            android:layout_width='0dp'
            android:layout_height='match_parent'
            android:layout_weight='1'
            android:text='send' />
    </LinearLayout>

</RelativeLayout>

MainActivity.java文件如下:

package com.luoxn28.bluetooth;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Message;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

public class MainActivity extends ActionBarActivity implements View.OnClickListener {
    public static final int RECV_VIEW = 0;
    public static final int NOTICE_VIEW = 1;

    private BluetoothAdapter bluetoothAdapter = null;

    private ConnectThread connectThread = null;
    private ConnectedThread connectedThread = null;

    private TextView noticeView = null;
    private Button turnOnOff = null;
    private TextView led0, led1, led2, led3, led4;
    ScrollView scrollView = null;
    private TextView recvView = null;
    private Button clearRecvView = null;
    private EditText sendText = null;
    private Button send = null;

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

        // 获取BluetoothAdapter
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            // Device does not support Bluetooth
            return;
        }

        // 注册监听事件
        noticeView = (TextView) findViewById(R.id.notice_view);
        turnOnOff = (Button) findViewById(R.id.turn_on_off);

        led0 = (TextView) findViewById(R.id.led0);
        led1 = (TextView) findViewById(R.id.led1);
        led2 = (TextView) findViewById(R.id.led2);
        led3 = (TextView) findViewById(R.id.led3);
        led4 = (TextView) findViewById(R.id.led4);
        scrollView = (ScrollView) findViewById(R.id.scroll_view);
        recvView = (TextView) findViewById(R.id.recv_view);
        clearRecvView = (Button) findViewById(R.id.clear_recv_view);
        sendText = (EditText) findViewById(R.id.send_text);
        send = (Button) findViewById(R.id.send);

        turnOnOff.setOnClickListener(this);
        clearRecvView.setOnClickListener(this);
        send.setOnClickListener(this);

        if (!bluetoothAdapter.isEnabled()) {
            noticeView.setText('蓝牙未开启');
        }
        else {
            noticeView.setText('蓝牙已开启');
        }
        noticeView.setBackgroundColor(Color.GRAY);
        led0.setBackgroundColor(Color.GRAY);
        led1.setBackgroundColor(Color.GRAY);
        led2.setBackgroundColor(Color.GRAY);
        led3.setBackgroundColor(Color.GRAY);
        led4.setBackgroundColor(Color.GRAY);
    }

    private boolean isOn = false;
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.turn_on_off: // 发送'0'或者'1'都可以
                if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
                    Toast.makeText(this, '蓝牙未开启', Toast.LENGTH_SHORT).show();
                    break;
                }
                if (connectedThread == null) {
                    Toast.makeText(this, '未连接设备', Toast.LENGTH_SHORT).show();
                    break;
                }

                String turn_string = '1@#';
                connectedThread.write(turn_string.getBytes());
                if (isOn == false) {
                    isOn = true; // 打开了
                    turnOnOff.setText('OFF');
                    led1.setText('');
                    led2.setText('');
                    led3.setText('');
                    led4.setText('');
                }
                else {
                    isOn = false; // 关闭了
                    turnOnOff.setText('ON');
                    led1.setText('LED1');
                    led2.setText('LED2');
                    led3.setText('LED3');
                    led4.setText('LED4');
                }
                break;

            case R.id.clear_recv_view: // 清空接收框
                recvView.setText('');
                break;

            case R.id.send: // 发送数据,默认以'@#'结尾
                if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
                    Toast.makeText(this, '蓝牙未开启', Toast.LENGTH_SHORT).show();
                    return;
                }
                if (connectedThread == null) {
                    Toast.makeText(this, '未连接设备', Toast.LENGTH_SHORT).show();
                    break;
                }
                String inputText = sendText.getText().toString() + '@#'; // 发送给单片机数据以'@#结尾',这样单片机知道一条数据发送结束
                //Toast.makeText(MainActivity.this, inputText, Toast.LENGTH_SHORT).show();
                connectedThread.write(inputText.getBytes());
                break;

            default:
                break;
        }
    }

    private android.os.Handler handler = new android.os.Handler() {
        public void handleMessage(Message msg) {
            Bundle bundle = null;
            switch (msg.what) {
                case RECV_VIEW:
                    if (isOn == false) {
                        isOn = true;
                        turnOnOff.setText('OFF');
                    }
                    bundle = msg.getData();
                    String recv = bundle.getString('recv');
                    recvView.append(recv + '
');
                    scrollView.fullScroll(ScrollView.FOCUS_DOWN); // 滚动到底部


                    if (recv.isEmpty() || recv.contains(' ') || recv.contains('#')) {
                        break;
                    }
                    int num = Integer.valueOf(recv) / 2; // 0-60s
                    if (num <= 20) {
                        led1.setText('');
                        led2.setText('');
                        led3.setText('');
                        led4.setText('');
                        led1.setBackgroundColor(Color.RED);
                        led2.setBackgroundColor(Color.RED);
                        led3.setBackgroundColor(Color.GREEN);
                        led4.setBackgroundColor(Color.GREEN);
                    }
                    else if (num < 30) {
                        int n = 30 - num;
                        led1.setText('' + n);
                        led2.setText('' + n);
                        if (num < 28) {
                            led3.setBackgroundColor(Color.GREEN);
                            led4.setBackgroundColor(Color.GREEN);
                        }
                        else {
                            led3.setBackgroundColor(Color.YELLOW);
                            led4.setBackgroundColor(Color.YELLOW);
                        }
                    }
                    else if (num <= 50) {
                        led1.setText('');
                        led2.setText('');
                        led3.setText('');
                        led4.setText('');
                        led1.setBackgroundColor(Color.GREEN);
                        led2.setBackgroundColor(Color.GREEN);
                        led3.setBackgroundColor(Color.RED);
                        led4.setBackgroundColor(Color.RED);
                    }
                    else {
                        int n = 60 - num;
                        led3.setText('' + n);
                        led4.setText('' + n);

                        if (num < 58) {
                            led1.setBackgroundColor(Color.GREEN);
                            led2.setBackgroundColor(Color.GREEN);
                        }
                        else {
                            led1.setBackgroundColor(Color.YELLOW);
                            led2.setBackgroundColor(Color.YELLOW);
                        }
                    }
                    break;

                case NOTICE_VIEW:
                    bundle = msg.getData();
                    String notice = bundle.getString('notice');
                    noticeView.setText(notice);
                    break;

                default:
                    break;
            }
        }
    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.start_bluetooth) {
            if (bluetoothAdapter != null) {
                // 开启蓝牙
                int REQUEST_ENABLE_BT = 1;
                if (!bluetoothAdapter.isEnabled()) {
                    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                    startActivityForResult(intent, REQUEST_ENABLE_BT);
                    noticeView.setText('开启蓝牙成功');
                    //Toast.makeText(this, '开启蓝牙成功', Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(this, '蓝牙已开启', Toast.LENGTH_SHORT).show();
                }
            }

            return true;
        }
        else if (id == R.id.show_devices) {
            if (bluetoothAdapter != null) {
                if (!bluetoothAdapter.isEnabled()) {
                    Toast.makeText(this, '蓝牙未开启', Toast.LENGTH_SHORT).show();
                    return true;
                }

                // 查询配对设备
                List<String> devices = new ArrayList<String>();
                Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
                for (BluetoothDevice device : bondedDevices) {
                    devices.add(device.getName() + '-' + device.getAddress());
                }
                StringBuilder text = new StringBuilder();
                for (String device : devices) {
                    text.append(device + '
');
                }
                Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
            }
            return true;
        }
        else if (id == R.id.find_devices) {
            Toast.makeText(this, '该功能暂时不可用', Toast.LENGTH_SHORT).show();
        }
        else if (id == R.id.connect_devices) {
            if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
                Toast.makeText(this, '蓝牙未开启', Toast.LENGTH_SHORT).show();
                return true;
            }

            // 查询配对设备 建立连接,只能连接第一个配对的设备
            List<String> devices = new ArrayList<String>();
            Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
            for (BluetoothDevice device : bondedDevices) {
                connectThread = new ConnectThread(device);
                connectThread.start();
                //Toast.makeText(this, '连接成功', Toast.LENGTH_SHORT).show();
                break;
            }
        }

        return super.onOptionsItemSelected(item);
    }

    private class ConnectThread extends Thread {
        private final String MY_UUID = '00001101-0000-1000-8000-00805F9B34FB';
        private final BluetoothSocket socket;
        private final BluetoothDevice device;

        public ConnectThread(BluetoothDevice device) {
            this.device = device;
            BluetoothSocket tmp = null;

            try {
                tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));
            } catch (IOException e) {
                e.printStackTrace();
            }
            this.socket = tmp;
        }

        public void run() {
            bluetoothAdapter.cancelDiscovery();
            try {
                socket.connect();
                connectedThread = new ConnectedThread(socket);
                connectedThread.start();
            } catch (IOException e) {
                try {
                    socket.close();
                } catch (IOException ee) {
                    ee.printStackTrace();
                }
                return;
            }
            //manageConnectedSocket(socket);
        }

        public void cancel() {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 客户端与服务器建立连接成功后,用ConnectedThread收发数据
    private class ConnectedThread extends Thread {
        private final BluetoothSocket socket;
        private final InputStream inputStream;
        private final OutputStream outputStream;

        public ConnectedThread(BluetoothSocket socket) {
            this.socket = socket;
            InputStream input = null;
            OutputStream output = null;

            try {
                input = socket.getInputStream();
                output = socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            this.inputStream = input;
            this.outputStream = output;
        }

        public void run() {
            StringBuilder recvText = new StringBuilder();
            byte[] buff = new byte[1024];
            int bytes;

            Bundle tmpBundle = new Bundle();
            Message tmpMessage = new Message();
            tmpBundle.putString('notice', '连接成功');
            tmpMessage.what = NOTICE_VIEW;
            tmpMessage.setData(tmpBundle);
            handler.sendMessage(tmpMessage);
            while (true) {
                try {
                    bytes = inputStream.read(buff);
                    String str = new String(buff, 'ISO-8859-1');
                    str = str.substring(0, bytes);

                    // 收到数据,单片机发送上来的数据以'#'结束,这样手机知道一条数据发送结束
                    //Log.e('read', str);
                    if (!str.endsWith('#')) {
                        recvText.append(str);
                        continue;
                    }
                    recvText.append(str.substring(0, str.length() - 1)); // 去除'#'

                    Bundle bundle = new Bundle();
                    Message message = new Message();

                    bundle.putString('recv', recvText.toString());
                    message.what = RECV_VIEW;
                    message.setData(bundle);
                    handler.sendMessage(message);
                    recvText.replace(0, recvText.length(), '');
                } catch (IOException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }

        public void write(byte[] bytes) {
            try {
                outputStream.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void cancel() {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 menu_main.xml文件如下:

<menu 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' tools:context='.MainActivity'>

    <item
        android:id='@+id/show_devices'
        android:title='@string/show_devices'
        android:orderInCategory='100'
        app:showAsAction='never' />
    <item
        android:id='@+id/start_bluetooth'
        android:title='@string/start_bluetooth'
        android:orderInCategory='100'
        app:showAsAction='never' />
    <item
        android:id='@+id/find_devices'
        android:title='@string/find_devices'
        android:orderInCategory='100'
        app:showAsAction='never' />
    <item
        android:id='@+id/connect_devices'
        android:title='@string/connect_devices'
        android:orderInCategory='100'
        app:showAsAction='never' />
</menu>

strings.xml文件如下:

<resources>
    <string name='app_name'>BlueTooth</string>
    <string name='action_settings'>Settings</string>

    <string name='start_bluetooth'>开启蓝牙</string>
    <string name='show_devices'>查询配对设备</string>
    <string name='find_devices'>搜索设备</string>
    <string name='connect_devices'>连接设备</string>
</resources>

   到这里整个APP已经开发完成,亲测可用,如果有什么错误,欢迎评论指正谈论^_^。

 

Tag标签: 蓝牙   单片机   实例  
  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规