天天看點

第9天藍牙裝置

第9天藍牙裝置

    • 一.藍牙介紹:
    • 二.藍牙的作用:
    • 三 .藍牙工作原理以及涉及到的類:
    • 四.藍牙用戶端代碼:
    • 五.藍牙服務端代碼:

一.藍牙介紹:

是一種無線技術标準,可實作固定裝置、移動裝置和樓宇個人域網之間的短距離資料交換,我們主要掌握這幾項技能:

  • 添權重限:
<!-- 用于進行網絡定位 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!-- 用于通路GPS定位 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
           
  • 打開藍牙并設定允許被搜尋
//調用系統開關藍牙彈窗->使用者手動允許
	Intent intent = new Intent();
	intent.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);//開啟藍
    intent.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//允許藍牙被搜尋
   intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,200);//設定允許被搜尋時間200s内可以被搜尋到
    startActivityForResult(intent,100);
           
  • 關閉藍牙
  • 搜尋附近的藍牙
  • 配對藍牙:
  • 獲得已經配對的藍牙裝置:
  • 使用藍牙傳輸資料:socket和ServerSocket傳輸資料
//1.獲得用戶端Socket
BluetoothSocket socket = bluetoothDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
//2.獲得服務端Socket
BluetoothServerSocket serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(bluetoothAdapter.getName(),uuid);
serverSocket.accpet();
           

二.藍牙的作用:

第9天藍牙裝置
第9天藍牙裝置

三 .藍牙工作原理以及涉及到的類:

第9天藍牙裝置
  • BluetoothManager 藍牙管理類,管理BluetoothAdapter。主要負責管理藍牙的本地連接配接。
  • BluetoothAdapter 藍牙擴充卡類:代表本藍牙裝置
  • BluetoothDevice 藍牙裝置,配對後的遠端藍牙裝置.
  • BluetoothServiceSocket 服務端連接配接類
  • BluetoothSocket:用戶端連接配接類
  • UUID(universal unique identifier , 全局唯一辨別符)

    格式如下:UUID格式一般是”xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”,可到http://www.uuidgenerator.com 申請。UUID分為5段,是一個8-4-4-4-12的字元串,這個字元串要求永不重複。藍牙建立連接配接時雙方必須使用固定的UUID

    例如:檔案傳輸服務

    OBEXFileTransferServiceClass_UUID = ‘{00001106-0000-1000-8000-00805F9B34FB}’

四.藍牙用戶端代碼:

如何區分用戶端和服務端?如果裝置A連接配接裝置B 那麼A就是用戶端,B就是服務端。

用戶端功能:打開藍牙/關閉藍牙/搜尋附近藍牙裝置/點選其中一個建立連接配接

第9天藍牙裝置

(0)添權重限:

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

(1)MainActivity代碼:

public class MainActivity extends AppCompatActivity implements View.OnClickListener,MainAdapter.OnItemClick{

    private Button mStart,mStop,mSearch;
    private RecyclerView mRv;
    private BluetoothManager manager;
    private BluetoothAdapter bluetoothAdapter;
    private List<BluetoothDevice>list=new ArrayList<>();
    private BluetoothReceiver receiver;
    private MainAdapter adapter;

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        initBluetooth();
    }

    private void init(){
        mStart = findViewById(R.id.startBtn);
        mStop = findViewById(R.id.stopBtn);
        mSearch = findViewById(R.id.searchBtn);
        mRv = findViewById(R.id.rv);
        mStart.setOnClickListener(this);
        mStop.setOnClickListener(this);
        mSearch.setOnClickListener(this);
        LinearLayoutManager manager = new LinearLayoutManager(this);
        manager.setOrientation(LinearLayoutManager.VERTICAL);
        mRv.setLayoutManager(manager);
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void initBluetooth(){
         manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
         bluetoothAdapter = manager.getAdapter();
         if (bluetoothAdapter == null){
             Toast.makeText(this,"藍牙裝置故障",Toast.LENGTH_SHORT).show();
             return;
         }
         receiver = new BluetoothReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_FOUND);//
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        registerReceiver(receiver,filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }

    @Override
    public void onClick(View view) {
        if (R.id.startBtn == view.getId()){
            Intent intent = new Intent();
            intent.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            intent.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,200);
            startActivityForResult(intent,100);
        }else if (R.id.stopBtn == view.getId()){
            bluetoothAdapter.disable();
        }else if (R.id.searchBtn == view.getId()){
            bluetoothAdapter.startDiscovery();//搜尋
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 100){
            if (bluetoothAdapter.isEnabled()){
                Toast.makeText(this,"藍牙啟動",Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(this,"藍牙未啟動",Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public void OnItem(int index) {
         //發起綁定->搜尋到的藍牙裝置中的一台
        BluetoothDevice device = list.get(index);
        device.createBond();
      
    }

    private class BluetoothReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            //綁定狀态改變;搜尋完成;搜尋到一台裝置

            if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)){
                //搜尋到一台裝置廣播
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                list.add(device);
            }else if (intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)){
                //搜尋完成
                //綁定擴充卡
                adapter = new MainAdapter(list);
                adapter.setClick(MainActivity.this);
                mRv.setAdapter(adapter);
            }else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
                //綁定狀态改變
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int state = device.getBondState();
                if (state == BluetoothDevice.BOND_BONDED){
                    //發起藍牙連接配接線程
                    new BluetoothThread(device).start();
                }
            }
        }
    }
}
           

(2)用戶端線程代碼

public class BluetoothThread extends Thread {

    private UUID uuid = UUID.fromString("00001106-0000-1000-8000-00805F9B34FB");
    private String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/xxyy.txt";
    private BluetoothDevice device;

    public BluetoothThread(BluetoothDevice device){
        this.device = device;
    }

    @Override
    public void run() {
        super.run();
        try {
            BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuid);
            socket.connect();//建立連接配接
            Log.e("ZXY","用戶端建立連接配接");
            FileInputStream inputStream = new FileInputStream(path);
            OutputStream out = socket.getOutputStream();
            byte[]buff = new byte[1024];
            int leng = 0;
            while ((leng=inputStream.read(buff))!=-1){
                out.write(buff,0,leng);
            }
            out.flush();
            out.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 
           

五.藍牙服務端代碼:

服務端是被連接配接者,隻有打開藍牙和關閉藍牙的功能

(0)添權重限:

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

(1)MainActivity代碼:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button mStart,mStop;
    private BluetoothManager manager;//藍牙管理器
    private BluetoothAdapter bluetoothAdapter;//藍牙擴充卡->開關搜尋等本機藍牙操作
    private BluetoothReceiver receiver;//藍牙綁定廣播接收器

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        initBluetooth();
    }

    private void init(){
          mStart = findViewById(R.id.startBtn);
          mStop = findViewById(R.id.stopBtn);
          mStart.setOnClickListener(this);
          mStop.setOnClickListener(this);
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void initBluetooth(){
         manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
         bluetoothAdapter = manager.getAdapter();//擷取本機藍牙擴充卡
         if (bluetoothAdapter==null){
             //本機無藍牙硬體子產品
             Toast.makeText(this,"本機藍牙裝置故障",Toast.LENGTH_SHORT).show();
             return;
         }
         //藍牙裝置可用
        receiver = new BluetoothReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        registerReceiver(receiver,filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }

    @Override
    public void onClick(View view) {
        if (bluetoothAdapter==null)
            return;
        if (R.id.startBtn == view.getId()){
//           bluetoothAdapter.enable();強制開啟->基本無效->手機系統是否允許
            //使用者手動允許開啟藍牙
            //調用系統開關藍牙彈窗->使用者手動允許
            Intent intent = new Intent();
            intent.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);//開啟藍牙
            intent.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//允許藍牙被搜尋
            intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,200);//設定允許被搜尋時間200s内可以被搜尋到
            startActivityForResult(intent,100);
        }else if (R.id.stopBtn == view.getId()){
            bluetoothAdapter.disable();//強制關閉藍牙
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode==100){
            String msg;
            //藍牙是否開啟
            if (bluetoothAdapter.isEnabled()){
                msg = "開啟成功";
            }else
                msg = "開啟失敗";
            Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
        }
    }

    //注冊藍牙配對廣播->通過廣播偵聽配對狀态
    private class BluetoothReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            //接收藍牙配對廣播
            if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
                //配對過來的藍牙裝置
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int state = device.getBondState();//擷取綁定狀态
                new BluetoothThread(bluetoothAdapter).start();
                if (state == BluetoothDevice.BOND_NONE){
                    //未綁定
                    Log.e("ZXY","未綁定");
                }else if (state == BluetoothDevice.BOND_BONDING){
                    //綁定中
                    Log.e("ZXY","綁定中");
                }else if (state == BluetoothDevice.BOND_BONDED){
                    //綁定完成
                    Log.i("lq","綁定完成");
                }
            }
        }
    }

}
           

(2)服務端線程代碼:

/**
 * 藍牙serversocket線程
 * */
public class BluetoothThread extends Thread{

    BluetoothAdapter adapter;//本機藍牙擴充卡
    UUID uuid = UUID.fromString("00001106-0000-1000-8000-00805F9B34FB");//系統随機産生string字元串35年内不重複->連接配接藍牙時秘鑰
    String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/xxyy.txt";
    //傳遞過來的txt檔案本地儲存路徑

    public BluetoothThread(BluetoothAdapter adapter){
        this.adapter = adapter;
    }

    @Override
    public void run() {
        super.run();
        try {
            BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord(adapter.getName(),uuid);
            //偵聽連接配接過來的socket
            BluetoothSocket socket = serverSocket.accept();
            Log.e("ZXY","藍牙連接配接成功");
            InputStream in = socket.getInputStream();
            //向本地sd卡儲存檔案的輸出流
            FileOutputStream out = new FileOutputStream(path);
            byte[]buff = new byte[1024];
            int leng = 0;
            while ((leng=in.read(buff))!=-1){
                out.write(buff,0,leng);
                Log.e("ZXY","伺服器邊讀邊儲存");
            }
            out.flush();
            out.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}