Android藍牙實例(和單片機藍牙模塊通信)

来源:http://www.cnblogs.com/luoxn28/archive/2016/05/01/5440882.html
-Advertisement-
Play Games

最近做畢設,需要寫一個簡單的藍牙APP進行交互,在網上也找了很多資料,終於給搞定了,這裡分享一下^_^。 1、Android藍牙編程 藍牙3.0及以下版本編程需要使用UUID,UUID是通用唯一識別碼(Universally Unique Identifier),這是一個軟體構建的標準,也是被開源基 ...


  最近做畢設,需要寫一個簡單的藍牙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() + "\n" + 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 + "\n");
                    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 + "\n");
                }
                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已經開發完成,親測可用,如果有什麼錯誤,歡迎評論指正談論^_^。

參考資料

   1、BLE和經典藍牙Android開發

   2、http://developer.android.com/intl/zh-cn/guide/topics/connectivity/bluetooth.html

  3、《Android第一行代碼》


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 代碼: 代理方法: ...
  • <merge /> 標簽在你嵌套 Layout 時取消了 UI 層級中冗餘的 ViewGroup 。比如,如果你有一個 Layout 是一個豎直方向的 LinearLayout,其中包含兩個連續的 View 可以在別的 Layout 中重用,那麼你會做一個 LinearLayout 來包含這兩個 V ...
  • eclipse自動退出 今天打開eclipse的時候出現自動退出,也就是打不開了 我上網查了一下,把工作區間改了一下就好了 修改預設工作區間的如下:(不是預設的話直接修改就好) eclipse\configuration\.settings目錄下,有一個“org.eclipse.ui.ide.pre ...
  • 在 oncreateView 裡面 進行頁面初始化 view view.findViewById this 改成 getActivity() ...
  • UITableViewCell圖片視差效果 效果 源碼 https://github.com/YouXianMing/Animations 細節 OffsetImageCell.m OffsetCellViewController.m ...
  • 1. 類型安全和類型推測 1> 類型安全 Swift 是一個 _類型安全(type safe)_ 的語言。類型安全的語言可以讓你清楚地知道代碼要處理的值的類型。如果你的代碼需要一個`String`,你絕對不可能不小心傳進去一個`Int`。 由於 Swift 是類型安全的,所以它會在編譯你的代碼時進行 ...
  • 多進程 多線程 優點 安全 穩定 擴大記憶體空間 節約CPU時間 AIDL=Android Interface definition language 多進程 多線程 優點 安全 穩定 擴大記憶體空間 節約CPU時間 使用情況:做一個下載,不想讓你的下載拖垮你的應用;播放器;ADK; 目的 =Aidl接 ...
  • 1. 整數 整數就是沒有小數部分的數字,比如`42`和`-23`。整數可以是`有符號`(正、負、零)或者`無符號`(正、零)。 Swift 提供了8,16,32和64位的有符號和無符號整數類型。這些整數類型和 C語言的命名方式很像,比如8位無符號整數類型是`UInt8`,32位有符號整數類型是`In ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...