天天看點

雜七雜八APK-藍牙

        客戶要求一個能判斷藍牙是否正常工作的apk,故寫了一個特别簡單的收發藍牙資料的demo,藍牙需要先打開并綁定,再次點選是停止發送資料,客戶要求比較簡單,搜尋藍牙和切換綁定裝置發送資料都沒做。

雜七雜八APK-藍牙
雜七雜八APK-藍牙

啟動的時候添加所有已綁定過的藍牙裝置,并将其加入到資料清單

 Set<BluetoothDevice> devices;

  devices = mBluetoothAdapter.getBondedDevices();  

        if (devices.size() > 0) {  

            for (BluetoothDevice bluetoothDevice : devices) {  

                // 儲存到arrayList集合中  

                bluetoothDevices.add(bluetoothDevice.getName() + ":"  

                        + bluetoothDevice.getAddress() + "\n");  

            }  

        } 

然後開啟一個循環接收資料的線程

// 服務端接收資訊線程  

    private class AcceptThread extends Thread {  

        private BluetoothServerSocket serverSocket;// 服務端接口  

        private BluetoothSocket socket;// 擷取到用戶端的接口  

        private InputStream is;// 擷取到輸入流  

        private OutputStream os;// 擷取到輸出流  

        public AcceptThread() {  

            try {  

                // 通過UUID監聽請求,然後擷取到對應的服務端接口  

                serverSocket = mBluetoothAdapter  

                        .listenUsingRfcommWithServiceRecord(NAME, MY_UUID);  //用戶端和服務端的UUID要一緻

            } catch (Exception e) {  

                // TODO: handle exception  

            }  

        }  

        public void run() {  

            try {  

                // 接收其用戶端的接口  

                socket = serverSocket.accept();  

                // 擷取到輸入流  

                is = socket.getInputStream();  

                // 擷取到輸出流  

                os = socket.getOutputStream();  

                // 無線循環來接收資料  

                while (true) {  

                    // 建立一個128位元組的緩沖  

                    byte[] buffer = new byte[128];  

                    // 每次讀取128位元組,并儲存其讀取的角标  

                    int count = is.read(buffer);  

                    // 建立Message類,向handler發送資料  

                    Message msg = new Message();  

                    // 發送一個String的資料,讓他向上轉型為obj類型  

                    msg.obj = new String(buffer, 0, count, "utf-8");  

                    // 發送資料  

                    handler.sendMessage(msg);  

                }  

            } catch (Exception e) {  

                // TODO: handle exception  

                e.printStackTrace();  

            }  

        }  

    } 

在onItemClick點選之後開啟一個不斷發送資料的線程,代碼比較,簡單貼一下

            // 判斷用戶端接口是否為空  

            if (clientSocket == null) {  

                // 擷取到用戶端接口  

                clientSocket = selectDevice  

                        .createRfcommSocketToServiceRecord(MY_UUID);  //不能重複綁定

                // 向服務端發送連接配接  

                clientSocket.connect();  

                // 擷取到輸出流,向外寫資料  

                os = clientSocket.getOutputStream();  

                os.write(text.getBytes("UTF-8"));

            } 

PS,藍牙連接配接需要UUID來建立連接配接,我這沒有找到如何解除這個綁定,又不能重複綁定,是以想給其他裝置發送資料需要背景關掉該應用。以下是完整代碼,搜尋功能被我注掉了,有需要的可以自己打開,如其他地方找到了解綁的api,可以留言。

public class MainActivity extends Activity implements OnItemClickListener {  

    // 擷取到藍牙擴充卡  

    private BluetoothAdapter mBluetoothAdapter;  

    // 用來儲存搜尋到的裝置資訊  

    private List<String> bluetoothDevices = new ArrayList<String>();  

    // ListView元件  

    private ListView lvDevices;  

    // ListView的字元串數組擴充卡  

    private ArrayAdapter<String> arrayAdapter;  

    // UUID,藍牙建立連結需要的  

    private final UUID MY_UUID = UUID  

            .fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3");  

    // 為其連結建立一個名稱  

    private final String NAME = "Bluetooth_Socket";  

    // 選中發送資料的藍牙裝置,全局變量,否則連接配接在方法執行完就結束了  

    private BluetoothDevice selectDevice;  

    // 擷取到選中裝置的用戶端序列槽,全局變量,否則連接配接在方法執行完就結束了  

    private BluetoothSocket clientSocket;  

    // 擷取到向裝置寫的輸出流,全局變量,否則連接配接在方法執行完就結束了  

    private OutputStream os;  

    // 服務端利用線程不斷接受用戶端資訊  

    private AcceptThread thread;  

    int count = 1;//發送的資料次數

    boolean isPause = true;

    Set<BluetoothDevice> devices;

    private  String bondedDevice;

    @Override  

    protected void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        setContentView(R.layout.activity_main);  

        // 擷取到藍牙預設的擴充卡  

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();  

        // 擷取到ListView元件  

        lvDevices = (ListView) findViewById(R.id.lvdevices);  

       if (!mBluetoothAdapter.isEnabled()) {

           mBluetoothAdapter.enable();

       }

        // 為listview設定字元換數組擴充卡  

        arrayAdapter = new ArrayAdapter<String>(this,  

                android.R.layout.simple_list_item_1, android.R.id.text1,  

                bluetoothDevices);  

        // 為listView綁定擴充卡  

        lvDevices.setAdapter(arrayAdapter);  

        // 為listView設定item點選事件偵聽  

        lvDevices.setOnItemClickListener(this);  

        // 用Set集合保持已綁定的裝置  

       devices = mBluetoothAdapter.getBondedDevices();  

        if (devices.size() > 0) {  

            for (BluetoothDevice bluetoothDevice : devices) {  

                // 儲存到arrayList集合中  

                bluetoothDevices.add(bluetoothDevice.getName() + ":"  

                        + bluetoothDevice.getAddress() + "\n");  

            }  

        }  

        // 因為藍牙搜尋到裝置和完成搜尋都是通過廣播來告訴其他應用的  

        // 這裡注冊找到裝置和完成搜尋廣播  

        IntentFilter filter = new IntentFilter(  

                BluetoothAdapter.ACTION_DISCOVERY_FINISHED);  

        registerReceiver(receiver, filter);  

        filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);  

        registerReceiver(receiver, filter);  

        // 執行個體接收用戶端傳過來的資料線程  

        thread = new AcceptThread();  

        // 線程開始  

        thread.start();  

    }  

    public void onClick_Search(View view) {  

    }  

    // 注冊廣播接收者  

    private BroadcastReceiver receiver = new BroadcastReceiver() {  

        @Override  

        public void onReceive(Context arg0, Intent intent) {  

            // 擷取到廣播的action  

            String action = intent.getAction();  

            // 判斷廣播是搜尋到裝置還是搜尋完成  

            if (action.equals(BluetoothDevice.ACTION_FOUND)) {  

                // 找到裝置後擷取其裝置  

                BluetoothDevice device = intent  

                        .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  

                // 判斷這個裝置是否是之前已經綁定過了,如果是則不需要添加,在程式初始化的時候已經添加了  

                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {  

                    // 裝置沒有綁定過,則将其保持到arrayList集合中  

                    if (bluetoothDevices.contains(device.getName() + ":"  

                                + device.getAddress() + "\n")) {

                        bluetoothDevices.add(device.getName() + ":"  

                                + device.getAddress() + "\n");  

                        // 更新字元串數組擴充卡,将内容顯示在listView中  

                        arrayAdapter.notifyDataSetChanged();  

                    }

                }  

            } else if (action  

                    .equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {  

                setTitle("搜尋完成");  

            }  

        }  

    };  

    SimpleDateFormat   formatter ;

    Date curDate ;

    String str;

    // 點選listView中的裝置,傳送資料  

    @Override  

    public void onItemClick(AdapterView<?> parent, View view, int position,  

            long id) {  

        // 擷取到這個裝置的資訊  

        isPause = !isPause;//是否發送資料

        String s = arrayAdapter.getItem(position);  

        // 對其進行分割,擷取到這個裝置的位址  

        String address = s.substring(s.indexOf(":") + 1).trim();  

        // 判斷目前是否還是正在搜尋周邊裝置,如果是則暫停搜尋  

        if (mBluetoothAdapter.isDiscovering()) {  

            mBluetoothAdapter.cancelDiscovery();  

        }  

        // 如果選擇裝置為空則代表還沒有選擇裝置  

        if (selectDevice == null ) {  

            //通過位址擷取到該裝置  

            selectDevice = mBluetoothAdapter.getRemoteDevice(address);  

            String string = bluetoothDevices.get(position);

           bluetoothDevices.set(position, string+ "-- 已綁定");

           bondedDevice = string+ "-- 已綁定";

           arrayAdapter.notifyDataSetChanged();

        }  

        // 這裡需要try catch一下,以防異常抛出  

           formatter   =   new   SimpleDateFormat   ("yyyy年MM月dd日   HH:mm:ss");     

        try {  

            // 判斷用戶端接口是否為空  

            if (clientSocket == null) {  

                // 擷取到用戶端接口  

                clientSocket = selectDevice  

                        .createRfcommSocketToServiceRecord(MY_UUID);  

                // 向服務端發送連接配接  

                clientSocket.connect();  

                // 擷取到輸出流,向外寫資料  

                os = clientSocket.getOutputStream();  

            }  

            // 判斷是否拿到輸出流

            new Thread(new Runnable() {

                @Override

                public void run() {

                    // TODO Auto-generated method stub

                    while (!isPause) {

                        if (os != null) {  

                            // 需要發送的資訊  

                            curDate =  new Date(System.currentTimeMillis());

                            str   =   formatter.format(curDate);  

                            String text = Integer.toString(count) + "  " + str;  

                            // 以utf-8的格式發送出去  

                            try {

                                os.write(text.getBytes("UTF-8"));

                                Thread.sleep(1000);

                            } catch (UnsupportedEncodingException e) {

                                // TODO Auto-generated catch block

                                e.printStackTrace();

                            } catch (IOException e) {

                                // TODO Auto-generated catch block

                                e.printStackTrace();

                            } catch (InterruptedException e) {

                                // TODO Auto-generated catch block

                                e.printStackTrace();

                            }  

                            count++;

                        }  

                    }

                }

            }).start();

            // 吐司一下,告訴使用者發送成功  

            Toast.makeText(this, "發送資訊成功,請查收", 0).show();  

        } catch (IOException e) {  

            // TODO Auto-generated catch block  

            e.printStackTrace();  

            // 如果發生異常則告訴使用者發送失敗  

            Toast.makeText(this, "發送資訊失敗", 0).show();  

        }  

    }  

    // 建立handler,因為我們接收是采用線程來接收的,線上程中無法操作UI,是以需要handler  

    Handler handler = new Handler() {  

        @Override  

        public void handleMessage(Message msg) {  

            // TODO Auto-generated method stub  

            super.handleMessage(msg);  

            // 通過msg傳遞過來的資訊,吐司一下收到的資訊  

            if (bluetoothDevices.size() >= 10) {//界面資料太多就清除資料,并重新添加綁定的藍牙資料

                bluetoothDevices.clear();

                bluetoothDevices.add(bondedDevice);  

                arrayAdapter.notifyDataSetChanged();

            }

            bluetoothDevices.add(msg.obj.toString());

            arrayAdapter.notifyDataSetChanged();

            //Toast.makeText(MainActivity.this, (String) msg.obj, 0).show();  

        }  

    };  

    // 服務端接收資訊線程  

    private class AcceptThread extends Thread {  

        private BluetoothServerSocket serverSocket;// 服務端接口  

        private BluetoothSocket socket;// 擷取到用戶端的接口  

        private InputStream is;// 擷取到輸入流  

        private OutputStream os;// 擷取到輸出流  

        public AcceptThread() {  

            try {  

                // 通過UUID監聽請求,然後擷取到對應的服務端接口  

                serverSocket = mBluetoothAdapter  

                        .listenUsingRfcommWithServiceRecord(NAME, MY_UUID);  

            } catch (Exception e) {  

                // TODO: handle exception  

            }  

        }  

        public void run() {  

            try {  

                // 接收其用戶端的接口  

                socket = serverSocket.accept();  

                // 擷取到輸入流  

                is = socket.getInputStream();  

                // 擷取到輸出流  

                os = socket.getOutputStream();  

                // 無線循環來接收資料  

                while (true) {  

                    // 建立一個128位元組的緩沖  

                    byte[] buffer = new byte[128];  

                    // 每次讀取128位元組,并儲存其讀取的角标  

                    int count = is.read(buffer);  

                    // 建立Message類,向handler發送資料  

                    Message msg = new Message();  

                    // 發送一個String的資料,讓他向上轉型為obj類型  

                    msg.obj = new String(buffer, 0, count, "utf-8");  

                    // 發送資料  

                    handler.sendMessage(msg);  

                }  

            } catch (Exception e) {  

                // TODO: handle exception  

                e.printStackTrace();  

            }  

        }  

    }  

繼續閱讀