android12 (sdk33) 以降は Bluetooth アプリを統合します

Bluetoothモジュール

Bluetooth 権限を宣言する

アプリでデバイスの検出を開始したり、Bluetooth 設定を操作したりする場合は、アクセス許可に加えてアクセス許可をBLUETOOTH宣言する必要があります。BLUETOOTH_ADMINほとんどのアプリケーションは、ローカル Bluetooth デバイスを検出するためにこの権限のみを必要とします。

AndroidManifest.xml ファイルに次の権限を追加します。

  	<!-- 安卓12之前的蓝牙权限需求-->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- 安卓12新增的蓝牙权限-->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <!-- 定位权限, 蓝牙搜索需要-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Bluetoothをセットアップする

1.Bluetoothアダプターを入手する

すべての Bluetooth アクティビティで必要ですBluetoothAdapterこれを取得するにはBluetoothAdapter、静的getDefaultAdapter()メソッドを呼び出します。このメソッドは、BluetoothAdapterデバイス自体の Bluetooth アダプター (Bluetooth ワイヤレス デバイス) を表すオブジェクトを返します。システム全体に対して Bluetooth アダプターは 1 つだけあり、アプリはこのオブジェクトを使用してそれと対話できます。getDefaultAdapter()が返された場合null、デバイスは Bluetooth をサポートしていません。

 	/**
     * 获取BluetoothAdapter对象,并判断蓝牙是否获取到
     */
    public boolean isBlueToothAvailable() {
    
    
        //获取BluetoothAdapter对象
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        // 判断蓝牙是否可用
        return bluetoothAdapter != null;
    }
2.Bluetoothを有効にする

次に、Bluetooth が有効になっていることを確認する必要があります。Bluetooth が現在有効になっているかどうかを確認するために呼び出されますisEnabled()このメソッドが false を返した場合、Bluetooth が無効になっていることを意味します。Bluetooth を有効にするように要求するには、 を呼び出してstartActivityForResult()、Intent オペレーションを渡しますACTION_REQUEST_ENABLEこの呼び出しでは、(アプリを停止せずに) システム設定を通じて Bluetooth を有効にするリクエストが行われます。

 	/**
     * 启用蓝牙
     *
     * @param activity 启动该方法的Activity
     */
    public void openBlueTooth(Activity activity) {
    
    
        if (!bluetoothAdapter.isEnabled()) {
    
    
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            activity.startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        } else {
    
    
            Toast.makeText(activity, "蓝牙已打开", Toast.LENGTH_SHORT).show();
        }
    }

デバイスの検索

1. ペアリングされたデバイスのクエリ

デバイス検出を実行する前に、ペアリングされたデバイスのセットをクエリして、目的のデバイスが検出状態かどうかを確認する必要があります。これを行うには、 に電話してくださいgetBondedDevices()BluetoothDeviceこのメソッドは、ペアになっているデバイスを表すオブジェクトの配列を返します。たとえば、ペアリングされたすべてのデバイスをクエリして、各デバイスの名前と MAC アドレスを取得できます。

 	/**
     * 打印已配对设备
     */
    public void printDevice() {
    
    
        //打印出已配对的设备
        Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
        if (pairedDevices.size() > 0) {
    
    
            for (BluetoothDevice device : pairedDevices) {
    
    
                listAdapter.add(device.getName() + "\n" + device.getAddress());
            }
        } else {
    
    
            listAdapter.add("没有已配对设备");
        }
    }
2. デバイスを検出する
 	/**
     * 广播接收者
     * 接收发现蓝牙设备和蓝牙设备扫描结束的广播
     */
    private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
    
            String action = intent.getAction();//获取蓝牙设备
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
    
      //发现设备
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                assert device != null;
                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
    
      //如果设备未绑定
                    listAdapter.add(device.getName() + "\n" + device.getAddress());
                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
    
      //扫描设备结束
                if (listAdapter.getCount() == 0) {
    
      //没有设备
                    Toast.makeText(BluetoothDeviceListActivity.this, "没有设备",
                            Toast.LENGTH_SHORT).show();
                }
            }
        }
    };

    @Override
    public void setRequestedOrientation(int requestedOrientation) {
    
    
        super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);
        //注册广播
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        this.registerReceiver(bluetoothReceiver, filter);

        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        this.registerReceiver(bluetoothReceiver, filter);

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        listAdapter = new ArrayAdapter<>(this, R.layout.device_name);
        ListView lv_device = findViewById(R.id.listView);
        Button bt_find = findViewById(R.id.bt_find);
        lv_device.setAdapter(listAdapter);

        printDevice();

        bt_find.setOnClickListener(new OnClickListener() {
    
    
            @Override
            public void onClick(View arg0) {
    
    
                bluetoothAdapter.startDiscovery();   //开始扫描
            }
        });

        //选择连接设备
        lv_device.setOnItemClickListener(new OnItemClickListener() {
    
    
            @Override
            public void onItemClick(AdapterView<?> arg0, View v, int arg2,
                                    long arg3) {
    
    
                String info = ((TextView) v).getText().toString();
                if (info.equals("没有已配对设备")) {
    
    
                    Toast.makeText(getApplicationContext(), "没有已配对设备", Toast.LENGTH_LONG)
                            .show();
                } else {
    
    
                    String address = info.substring(info.length() - 17);   //获取蓝牙设备地址

                    Intent intent = new Intent();
                    intent.putExtra(EXTRA_DEVICE_ADDRESS, address);   //将地址装入EXTRA_DEVICE_ADDRESS
                    setResult(Activity.RESULT_OK, intent); //将地址传送回MainActivity
                    finish();
                }
            }
        });

    }

接続する

1. デバイスを接続します
    /**
     * 连接设备
     * @param device 蓝牙设备
     * @return 连接状态
     */
    public boolean connectThread(BluetoothDevice device) {
    
    
        try {
    
    
            bluetoothSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
            bluetoothAdapter.cancelDiscovery();
            bluetoothSocket.connect();
            connectStatus = true;  //连接成功
            // 接收数据进程
            new Thread(new Runnable() {
    
      //读线程
                @Override
                public void run() {
    
    
                    int bytes;
                    byte[] buffer = new byte[256];
                    while (true) {
    
    
                        if (bluetoothSocket != null && bluetoothSocket.isConnected()) {
    
    
                            try {
    
     // 接收数据
                                bytes = bluetoothSocket.getInputStream().read(buffer);
                                final String readStr = new String(buffer, 0, bytes); //读出的数据
                            } catch (IOException e) {
    
    
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }).start();
        } catch (IOException e) {
    
    
            connectStatus = false;  //连接失败
            try {
    
    
                bluetoothSocket.close();
            } catch (IOException e2) {
    
    
                e.printStackTrace();
            }
        }
        return connectStatus;
    }
2. 接続をキャンセルする
 /**
     * 取消连接
     */
    public void cancelConnect() {
    
    
        try {
    
    
            bluetoothSocket.close();
            connectStatus = false;
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }

データ送信

1. 青はデータを送信します
 /**
     * 蓝牙发送数据
     *
     * @param str 待发送的字符串
     */
    public void write(String str) {
    
    
        if (connectStatus) {
    
    
            byte[] buffer = str.getBytes();
            try {
    
    
                bluetoothSocket.getOutputStream().write(buffer);
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }

Bluetooth通信テスト結果

SDK バージョン 33 の落とし穴に注意してください

  • Android 12 以降では動的許可アプリケーションが必要です。そうでないと、接続された Bluetooth デバイスを取得するときにエラーが報告され、クラッシュします。
  • コードは赤で報告されますが、Bluetooth を呼び出す前に動的許可アプリケーションを設定するだけで使用できます。もっと良い解決策があるはずです...
1. まずファイルディレクトリを確認します。

画像の説明を追加してください

  • BluetoothUtils Bluetooth 初期設定のいくつかの方法
  • BluetoothDeviceListActivity Bluetooth接続リスト表示
  • メインアクティビティのホームページ
  • レイアウトの下には UI インターフェイスがあります。
2. 試験方法
1. 携帯電話を使用してラップトップ Bluetooth に接続し、次のように受信 COM ポートを開きます。

画像の説明を追加してください

2. シリアル ポート デバッグ ツールを開き、ポート番号 (たとえば、私のポートは COM6 ポート) を選択し、シリアル ポートを開きます。

画像の説明を追加してください

3. Android プログラムをコンパイルして携帯電話にインストールし、左側で [Bluetooth に接続] をクリックし、右側でコンピュータの Bluetooth デバイスを選択します。

画像の説明を追加してください

4. [送信] ボタンをクリックして、デバッグ ツールへの影響を確認します。

画像の説明を追加してください

拡大する

Android 側で Bluetooth データ送信を実装することに成功すると、ハードウェアを統合していくつかの機能を実装できます。

  • Bluetooth カーは指示を送信することで車の動きを制御します。
  • 照明のオンオフやエアコン、カーテンなどの制御といったスマートホームは、当然ながらマイコン上でしか遊べず、実用化にはまだまだ遠い。

詳細については、公式ドキュメントを参照してください: Bluetooth の概要 | Android 開発者 | Android 開発者 (google.cn)

完全なコード リポジトリ: https://gitee.com/chafaner

おすすめ

転載: blog.csdn.net/weixin_45833112/article/details/129799278