You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio(Java)蓝牙扫描器开发求助:获取设备硬件信息

Android蓝牙设备扫描应用开发指导

我有一项作业要求使用Android Studio开发一款移动应用,需实现扫描附近蓝牙设备,并在扫描完成后获取设备的硬件名称、型号及厂商名称。参考资料自行实现后未能成功,使用Java开发,附上我的代码求指导:

我的Java类代码

package com.example.bluetoothvulnerabilityscanner;

import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;

import android.os.Build;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.view.View;
import android.widget.Button;

import java.util.ArrayList;
import java.util.Set;

public class ScanAroundDevices extends AppCompatActivity {

    BluetoothAdapter bluetoothAdapter;
    ArrayAdapter<String> arrayAdapter;
    ArrayList<String> arrayList;
    ListView listView; // 修正:原变量名11为Java非法标识符

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scan_around_devices);
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        listView = findViewById(R.id.listView);
        arrayList = new ArrayList<>();

        arrayAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, arrayList);
        listView.setAdapter(arrayAdapter);

        findPairedDevices();
    }

    private void findPairedDevices() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.BLUETOOTH_CONNECT}, 100);
            return;
        }
        Set<BluetoothDevice> bluetoothSet = bluetoothAdapter.getBondedDevices();

        if (bluetoothSet.size() > 0) {
            arrayList.clear();
            for (BluetoothDevice device : bluetoothSet) {
                arrayList.add("已配对:" + device.getName() + "\n地址:" + device.getAddress());
            }
            arrayAdapter.notifyDataSetChanged();
        }
    }

    public void discoverDevices(View v) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.BLUETOOTH_SCAN}, 101);
                return;
            }
        }
        arrayList.clear();
        bluetoothAdapter.startDiscovery();
        Toast.makeText(this, "开始扫描蓝牙设备", Toast.LENGTH_SHORT).show();
    }

    BroadcastReceiver broadcastReceiver = 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);
                if (ActivityCompat.checkSelfPermission(ScanAroundDevices.this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
                    return;
                }
                // 扫描到的基础信息,型号/厂商需连接后获取
                String deviceInfo = "名称:" + (device.getName() != null ? device.getName() : "未知设备") 
                        + "\n地址:" + device.getAddress();
                if (!arrayList.contains(deviceInfo)) {
                    arrayList.add(deviceInfo);
                    arrayAdapter.notifyDataSetChanged();
                }
            }
        }
    };

    @Override
    protected void onStart() {
        super.onStart();
        IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(broadcastReceiver, intentFilter); // 修正:广播注册参数错误
    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(broadcastReceiver); // 补充:避免内存泄漏
    }

    public void on(View v) {
        if (bluetoothAdapter == null) {
            Toast.makeText(getApplicationContext(), "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
            return;
        }
        if (!bluetoothAdapter.isEnabled()) { // 修正:判断条件逻辑错误
            Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(i, 1);
        } else {
            Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1) {
            if (resultCode == RESULT_OK) {
                Toast.makeText(getApplicationContext(), "蓝牙已开启", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(getApplicationContext(), "用户拒绝开启蓝牙", Toast.LENGTH_SHORT).show();
            }
        } else if (requestCode == 2) {
            if (resultCode == RESULT_OK) {
                Toast.makeText(getApplicationContext(), "蓝牙已关闭", Toast.LENGTH_SHORT).show();
            }
        }
    }

    public void off(View v) {
        if (bluetoothAdapter == null) {
            Toast.makeText(getApplicationContext(), "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
            return;
        }
        if (bluetoothAdapter.isEnabled()) {
            Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_DISABLE); // 修正:关闭蓝牙的Intent错误
            startActivityForResult(i, 2);
        } else {
            Toast.makeText(this, "蓝牙已关闭", Toast.LENGTH_SHORT).show();
        }
    }
}

我的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="match_parent"
    tools:context=".ScanAroundDevices">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="25dp"
        android:onClick="on"
        android:text="开启蓝牙"/>

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignTop="@+id/btn1"
        android:onClick="off"
        android:text="关闭蓝牙"/>

    <Button
        android:id="@+id/btn_scan"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btn1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:onClick="discoverDevices"
        android:text="扫描设备"/>

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/btn_scan"
        android:layout_marginTop="20dp"/>

</RelativeLayout>

关键修复与说明

  • 变量命名修正:将非法的11变量名改为listView,符合Java语法规范
  • 广播注册修正:修复onStart()中广播注册的参数错误,补充onStop()注销广播避免内存泄漏
  • 蓝牙开关逻辑修正:
    • 开启蓝牙时,仅在蓝牙未开启时发起请求,避免重复操作
    • 关闭蓝牙使用正确的ACTION_REQUEST_DISABLE Intent,并用startActivityForResult处理用户操作结果
  • 权限处理:
    • Android 12及以上添加BLUETOOTH_SCAN权限,动态申请扫描权限
    • 修正BroadcastReceiver中的权限检查上下文,使用Activity实例而非内部类的this
  • 布局补充:添加扫描按钮和ListView,实现扫描触发和结果展示
  • 设备信息说明:扫描阶段仅能获取设备名称、MAC地址;型号及厂商信息需要与设备建立GATT连接后,通过BluetoothGattCharacteristic读取(不同设备支持的属性存在差异)

清单文件需添加的权限

在AndroidManifest.xml中添加以下权限:

<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>

内容的提问来源于stack exchange,提问作者JustAnAmateurCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 10:18:33