藍芽客戶端和伺服器的實現

llj0201發表於2015-12-02

需要許可權:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

客戶端:

package com.pax.btclient;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.bluetooth.*;
import android.os.ConditionVariable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.Random;


public class MainActivity extends Activity {

    private BluetoothAdapter adapter = null;
    private BluetoothDevice remoteDevice = null;
    private BluetoothSocket socket = null;
    private ConditionVariable done = null;
    private Activity activity = null;
    private final static String TAG = "BTClient";
    final UUID MyUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    BluetoothStateChangeReceiver stateChangeReceiver;
    BluetoothDiscoveryReciver discoveryReciver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        adapter = BluetoothAdapter.getDefaultAdapter();
        done = new ConditionVariable();

        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        stateChangeReceiver = new BluetoothStateChangeReceiver();
        registerReceiver(stateChangeReceiver, filter);

        IntentFilter discoveryFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        discoveryFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        discoveryFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
        discoveryReciver = new BluetoothDiscoveryReciver();
        registerReceiver(discoveryReciver, discoveryFilter);

        Thread thread = new Thread(){

            @Override
            public void run() {
                // TODO Auto-generated method stub
                super.run();
                BluetoothTest();
            }
        };

        thread.start();
    }

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


    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        unregisterReceiver(stateChangeReceiver);
        unregisterReceiver(discoveryReciver);
    }


    void BluetoothTest(){
        Log.i(TAG,"start BT test\n");

        int i = 0;
        int j = 0;

        if(adapter != null){
            //開啟藍芽
            Log.i(TAG,"open BT...\n");
            if(!adapter.isEnabled()){
                adapter.enable();
                done.block();
                done.close();
            }

            //搜尋藍芽
            Log.i(TAG,"discovery BT...\n");
            adapter.startDiscovery();
            done.block();
            done.close();

            if(remoteDevice != null){
                byte[] sendData = new byte[1024];                   
                byte[] receiveData = new byte[1024];
                Random rand = new Random();

                for(j = 0;j < sendData.length; j++)
                {
                    sendData[j] = (byte)Math.abs(rand.nextInt());
                }

                BluetoothSocket socket = null;
                InputStream inputStream = null;
                OutputStream outputStream = null;
                int recvLen = 0;

                try {
                    Log.i(TAG,"create socket...\n");
                    socket = remoteDevice.createRfcommSocketToServiceRecord(MyUUID);
                    if(socket != null)
                    {
                        socket.connect();
                        outputStream = socket.getOutputStream();
                        inputStream = socket.getInputStream();

                        if(inputStream != null && outputStream != null){
                            //傳送資料
                            Log.i(TAG,"send data...\n");
                            outputStream.write(sendData);
                            outputStream.flush();

                            //接收資料
                            Log.i(TAG,"recive data...\n");
                            while(true){
                                if((inputStream.available() > 0) && (recvLen < 1024)){
                                    int len = inputStream.read(receiveData, recvLen, 1024-recvLen);
                                    recvLen += len;
                                    if(recvLen >= 1024){
                                        break;
                                    }
                                }
                            }


                            if(recvLen == 1024){
                                for(i = 0; i < 1024; i++){
                                    if(receiveData[i]!= sendData[i]){
                                        Log.e(TAG,"cmp error\n");
                                        break;
                                    }
                                }
                            }

                            inputStream.close();
                            inputStream = null;
                            outputStream.close();
                            outputStream = null;
                        }
                        socket.close();
                        socket = null;
                    }   

                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }   

                //解除繫結
                Log.i(TAG,"remove bond...\n");
                Method removeBondMethod;
                try {
                    removeBondMethod = BluetoothDevice.class.getMethod("removeBond");
                    Boolean result = (Boolean) removeBondMethod.invoke(remoteDevice); 
                    remoteDevice = null;
                } catch (NoSuchMethodException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }  
            }
            //關閉藍芽
            Log.i(TAG,"close BT...\n");
            adapter.disable();
        }
    }


    class BluetoothStateChangeReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context arg0, Intent arg1) {
            // TODO Auto-generated method stub
            if(arg1.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)){
                int state = arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                if(state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_OFF)
                {
                    done.open();
                }
            }
        }
    } 

    class BluetoothDiscoveryReciver extends BroadcastReceiver{

        @Override
        public void onReceive(Context arg0, Intent arg1) {
            // TODO Auto-generated method stub
            Log.i(TAG,arg1.getAction());
            if(arg1.getAction().equals(BluetoothDevice.ACTION_FOUND)){
                BluetoothDevice  device = arg1.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if(("00:17:6F:68:B0:91").equals(device.getAddress()))
                {
                    if(adapter.isDiscovering()){
                        adapter.cancelDiscovery();
                    }
                    int state = device.getBondState();
                    if(state == BluetoothDevice.BOND_NONE){
                        Log.i(TAG,"not bonded,create bond\n");
                        try {
                            //傳送配對請求
                            Method createBound = BluetoothDevice.class.getMethod("createBond");
                            createBound.invoke(device);
                        } catch (NoSuchMethodException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IllegalArgumentException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }else if(state == BluetoothDevice.BOND_BONDED){
                        remoteDevice = device;
                        done.open();
                    }   
                }
            }else if(arg1.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
                BluetoothDevice  device = arg1.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                remoteDevice = device;
                done.open();
                Log.i(TAG,"bonded\n");
            }else if(arg1.getAction().equals(BluetoothDevice.ACTION_PAIRING_REQUEST)){
                //自動確認配對
                BluetoothDevice  device = arg1.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if(("00:17:6F:68:B0:91").equals(device.getAddress())){
                    Log.i(TAG,"PairingConfirmation\n");
                    try{
                        Method setPairingConfirmationMethod = BluetoothDevice.class.getMethod("setPairingConfirmation",new Class[]{boolean.class});
                        setPairingConfirmationMethod.invoke(device,true);
                    }catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

伺服器:

package com.pax.btserver;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.bluetooth.*;
import android.os.ConditionVariable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.*;
import java.util.UUID;

import com.pax.btserver.R;

public class MainActivity extends Activity {

    private final static String TAG = "BTServer";
    private BluetoothAdapter adpter = null;
    private ConditionVariable done = null;
    private BluetoothReceiver bluetoothReceiver;
    static final UUID MyUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        done = new ConditionVariable();
        adpter = BluetoothAdapter.getDefaultAdapter();

        bluetoothReceiver = new BluetoothReceiver();
        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
        registerReceiver(bluetoothReceiver, filter);

        Thread thread = new Thread(){

            @Override
            public void run() {
                // TODO Auto-generated method stub
                super.run();
                bluetoothServer();
            }

        };
        thread.start();
    }

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


    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        unregisterReceiver(bluetoothReceiver);
    }

    void bluetoothServer(){

        Log.i(TAG,"start BT server\n");
        BluetoothServerSocket serverSocket = null;
        BluetoothSocket socket = null;
        InputStream in = null;
        OutputStream out = null;
        int len = 0;
        int recvLen = 0;
        byte[] recvdata = new byte[1024];

        if(adpter != null){
            //開啟藍芽
            Log.i(TAG,"open BT\n");
            if(!adpter.isEnabled()){
                adpter.enable();
                done.block();
                done.close();
            }

            try {
                Log.i(TAG,"create serverSocket\n");
                serverSocket = adpter.listenUsingRfcommWithServiceRecord("local1", MyUUID);
                while(serverSocket != null){
                    if(adpter.isDiscovering()){
                        adpter.cancelDiscovery();
                    }
                    //阻塞直到客戶端連線上伺服器
                    socket = serverSocket.accept();

                    in = socket.getInputStream();
                    out= socket.getOutputStream();
                    if(in != null && out != null){
                        try{
                            while(true){
                                if(in.available() > 0){
                                    len = in.read(recvdata);
                                    Log.i(TAG,new String(recvdata));
                                    if(len > 0){
                                        out.write(recvdata);
                                        out.flush();
                                        len = 0;
                                    }
                                }else{
                                    break;
                                }
                            }
                        }catch(Exception e){
                            e.printStackTrace();
                        }finally{
                            in.close();
                            in = null;
                            out.close();
                            out = null;
                            socket.close();
                            socket = null;
                        }
                    }
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

                if(serverSocket != null){
                    try {
                        serverSocket.close();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                    serverSocket = null;
                }
            }
        }       
    }


    class BluetoothReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context arg0, Intent arg1) {
            // TODO Auto-generated method stub

             Log.i(TAG,arg1.getAction());
             if(arg1.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)){
                 int state = arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                 if(state == BluetoothAdapter.STATE_ON){
                     done.open();
                 } 
             }else if(arg1.getAction().equals(BluetoothDevice.ACTION_PAIRING_REQUEST)){
                 Log.i(TAG,"request pairing\n");
                 //有配對請求,自動確定配對
                 BluetoothDevice device = arg1.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                 int mType = arg1.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
                 if(mType == BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION){       
                     try {
                        Method setParingConfirm = BluetoothDevice.class.getMethod("setPairingConfirmation", new Class[]{boolean.class});
                        setParingConfirm.invoke(device,true);
                    } catch (NoSuchMethodException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                 }
             }
        }
    }

}

通過這listenUsingInsecureRfcommWithServiceRecord和createInsecureRfcommSocketToServiceRecord兩個API,可以不配對藍芽裝置就進行通訊

相關文章