Android Studio 蓝牙开发实例——基于Android 6.0

 

 

       因项目需要做一个Android 的蓝牙app来通过手机蓝牙传输数据以及控制飞行器,在此,我对这段时间里写的蓝牙app的代码进行知识梳理和出现错误的总结。

       该应用的Compile Sdk Version 和targetSdkVersion均为26,Min Sdk Version为22,基于Android studio平台开发。

 一、声明蓝牙权限

       首先,要在新建项目中的AndroidManifest.xml中声明两个权限:BLUETOOTH权限和BLUETOOTH_ADMIN权限。其中,BLUETOOTH权限用于请求连接和传送数据;BLUETOOTH_ADMIN权限用于启动设备、发现或进行蓝牙设置,如果要拥有该权限,必须现拥有BLUETOOTH权限。

       其次,因为android 6.0之后采用新的权限机制来保护用户的隐私,如果我们设置的targetSdkVersion大于或等于23,则需要另外添加ACCESS_COARSE_LOCATION和ACCESS_FINE_LOCATION权限,否则,可能会出现搜索不到蓝牙设备的问题。

 

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>

 


 二、 启动和关闭蓝牙

1.首先,要获取BluetoothAdapter蓝牙适配器的对象,然后检测设备是否支持蓝牙。

 

BluetoothAdapter blueadapter = BluetoothAdapter.getDefaultAdapter();
//获取蓝牙适配器

 

if(blueadapter==bull)
//表示手机不支持蓝牙
return;

 


2.启动蓝牙功能:isEnable()方法用来检查蓝牙当前状态,如果方法返回false,则蓝牙没启动。enable()方法用来打开本地蓝牙适配器。

 if (!blueadapter.isEnabled())
        //判断本机蓝牙是否打开
        {//如果没打开,则打开蓝牙
        blueadapter.enable();
        }

 

3.使用disable()可以关闭本地蓝牙适配器。

 

三、发现蓝牙设备

1.开启当前蓝牙的可见性
       Android 设备默认是不能被搜索的,如果想要本机设备可被搜索,可以以BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE动作为startActivity()方法的参数,这个方法会提交一个开启蓝牙可见的请求。默认的情况下,设备在120秒内可以被搜索,也可以自定义一个间隔时间,但是规定的最大值为300秒,0秒则表示设备可以一直被搜索,自定义时间通过EXTRA_DISCOVERABLE_DURATION来定义,代码如下。

if (blueadapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) //不在可被搜索的范围
        {
        Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//设置本机蓝牙在300秒内可见
        startActivity(discoverableIntent);
        }

 


2.调用startDiscover()搜索蓝牙

       开启蓝牙后,调用startDiscover()方法搜索蓝牙,注意,只有开启了蓝牙可见性的设备才会响应。该搜索过程为异步操作,调用后讲以广播的机制返回搜索到的对象,搜索的过程一般为12秒,搜索过程页面会显示搜索到的设备。

 

public void doDiscovry() {
    if (blueadapter.isDiscovering()) {
        //判断蓝牙是否正在扫描,如果是调用取消扫描方法;如果不是,则开始扫描
        blueadapter.cancelDiscovery();
    } else
        blueadapter.startDiscovery();

}

 


3.注册广播
       通过blueadapter.startDiscovery()来搜索蓝牙设备,要获取到搜索的结果需要注册广播。

 

       定义一个列表

public ArrayAdapter adapter;
ListView listView = (ListView) findViewById(R.id.list);//控件 列表

 

 

//定义一个列表,存蓝牙设备的地址。
public ArrayList<String> arrayList=new ArrayList<>();
//定义一个列表,存蓝牙设备地址,用于显示。
public ArrayList<String> deviceName=new ArrayList<>();

 

 

       将搜索到的显示在控件列表上

adapter = new ArrayAdapter(this, android.R.layout.simple_expandable_list_item_1, deviceName);
listView.setAdapter(adapter);

 

 

       定义广播和处理广播消息

IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);//注册广播接收信号
registerReceiver(bluetoothReceiver, intentFilter);//用BroadcastReceiver 来取得结果

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);
            deviceName.add("设备名:"+device.getName()+"\n" +"设备地址:"+device.getAddress() + "\n");//将搜索到的蓝牙名称和地址添加到列表。
            arrayList.add( device.getAddress());//将搜索到的蓝牙地址添加到列表。
            adapter.notifyDataSetChanged();//更新
        }
    }
 };

 


       搜索完设备后,要记得注销广播。注册后的广播对象在其他地方有强引用,如果不取消,activity会释放不了资源 。

protected void onDestroy(){
    super.onDestroy();//解除注册
    unregisterReceiver(bluetoothReceiver);
}



4.了解targetSdkVersion是否大于或等于23

       若是大于或等于23,除了添加了蓝牙权限外,还要动态获取位置权限,才能将搜索到的蓝牙设备显示出来。若是小于,则不需要动态获取权限。
动态申请权限,网上例子如下。

 

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == REQUEST_ENABLE_BT) {
        if (resultCode == RESULT_OK) {
            textView.setText("打开蓝牙成功");
        }
        if (resultCode == RESULT_CANCELED) {
            textView.setText("放弃打开蓝牙");
        }
    } else {
        textView.setText("蓝牙异常");
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_COARSE_LOCATION:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            }
            break;
    }
}

 

 

 四、配对蓝牙设备

       蓝牙的配对和连接有两种方式。一种是每个设备作为一个客户端去连接一个服务端,向对方发起连接。另一种则是作为服务端来接收客户端发来连接的消息。蓝牙之间的数据传输采用的是和TCP传输类似的传输机制。

1.作为客户端连接
       首先要获取一个代表远程设备BluetoothDevice的对象,然后使用该BluetoothDevice的对象来获取一个BluetoothSocket对象。BluetoothSocket对象调用connect()可以建立连接。

       蓝牙连接整个过程需要在子线程中执行的,并且要将 scoket.connect()放在一个新的子线程中,因为如果将这个方法也放在同一个子线程中解决的话,就会永远报错read failed, socket might closed or timeout, read ret: -1;借鉴网上的方法:再开一个子线程专门执行socket.connect()方法,问题可以解决;

       另外,借鉴网上方法和建议,在获得socket的时候 ,尽量不使用uuid方式;因为这样虽然能够获取到socket 但是不能进行自动,所以使用的前提是已经配对了的设备连接;

       使用反射的方式,能够自动提示配对,也适合手机间通信。

 

final BluetoothSocket socket = (BluetoothSocket) device.getClass().getDeclaredMethod("createRfcommSocket", new Class[]{int.class}).invoke(device, 1);

 


       代码中的device需要把注册广播时的device作为参数传进线程中。注意,传进来的device的值要为远程设备的地址,若不是或有出入,则可能会出现NullPointerException异常,并提示尝试调用一个空的对象。为了解决这个问题,可以把显示获得的device名字、地址和传入线程的device的地址分在不同的集合类。传入线程的device使用只有设备地址的集合类。

       在连接蓝牙之前,还要先取消蓝牙设备的扫描,否则容易连接失败。

 

adapter.cancelDiscovery();//adapter为获取到的蓝牙适配器
socket.connect();//连接

 

 

2.作为服务端连接
       服务端接收连接需要使用BluetoothServerSocket类,它的作用是监听进来的连接,在一个连接被接收之后,会返回一个BluetoothSocket对象,这个对象可以用来和客户端进行通信。

       与客户端一样,服务端也要在子线程中实现。通过调用listenUsingRfcommWithServiceRecord(String,UUID)方法可以得到一个BluetoothServerSocket的对象,然后再用这个对象来调用accept()来返回一个BluetoothSocket对象。由于accept()是个阻塞的方法,它会直到接收到一个连接或异常之后才会返回,所以要放在子线程中。

 
 
bluetoothServerSocket=bluetoothAdapter.listenUsingRfcommWithServiceRecord(bluetoothAdapter.getDefaultAdapter().getName(), UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
//bluetoothServerSocket= (BluetoothServerSocket) bluetoothAdapter.getClass().getMethod("listenUsingRfcommOn",new Class[]{int.class}).invoke(bluetoothAdapter,10);
socket=bluetoothServerSocket.accept();//接收连接

 


       代码中注释掉的内容是通过反射的方式来接收,由于我使用时出现了异常,所以暂时不考虑这个方法。

       还有,与TCP不同的是,这个连接时只允许一个客户端连接,因此在BluetoothServerSocket对象接收到一个连接请求时就要立刻调用close()方法把服务端关闭。


五、客户端发送数据

       当两个设备成功连接之后,双方都会有一个BluetoothSocket对象,这时,就可以在设备之间传送数据了。

       1.使用getOutputStream()方法来获取输出流来处理传输。

       2.调用write()。

os = socket.getOutputStream();//获取输出流
if (os != null) {//判断输出流是否为空
    os.write(message.getBytes("UTF-8"));
}
os.flush();//将输出流的数据强制提交
os.close();//关闭输出流
}

 

       将输出流中的数据提交后,要记得关闭输出流,否则,可能会造成只能发送一次数据。

 

六、服务端接收数据

       1.使用getInputStream()方法来获取输入流来处理传输。

       2.调用read()。

 

   

InputStream im=null;
im=bluetoothSocket.getInputStream();
byte buf[] = new byte[1024];
if (is != null) {
    is.read(buf, 0, buf.length);//读取发来的数据
    String message = new String(buf);//把发来的数据转化为String类型
    BuletoothMainActivity.UpdateRevMsg(message);//更新信息在显示文本框
    is.close();//关闭输入流

 

 

       使用服务端接收数据时,要先从客户端向服务端发起连接,只有接收到连接请求之后,才会返回一个BluetoothSocket对象。有BluetoothSocket对象才能获取到输入流。

 

       下面是将接收到数据显示在界面的方法:

        在Activity中定义Handler类的对象handler。

public static void UpdateRevMsg(String revMsg) {
    mRevMsg=revMsg;
    handler.post(RefreshTextView);
}

private static Runnable RefreshTextView=new Runnable() {
    @Override
    public void run() {
        textView2.setText(mRevMsg);
    }
};

 

转载于:https://www.cnblogs.com/lwkdbk/p/9939643.html

  • 9
    点赞
  • 129
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android Studio蓝牙应用程序示例可以用于创建具有蓝牙功能的Android应用程序。该示例可以帮助开发人员了解如何使用Android Studio和Java编程语言来创建蓝牙应用程序。该示例包括了蓝牙设备的搜索、连接和数据传输等功能。开发人员可以根据自己的需求对该示例进行修改和扩展,以创建自己的蓝牙应用程序。 ### 回答2: Android Studio是一种常用的Android开发工具,开发者们可以使用它来开发各种类型的应用程序,包括蓝牙应用程序。 蓝牙是一种无线通信技术,广泛应用于智能手机、平板电脑等设备。开发者可以使用Android Studio来创建蓝牙应用程序,实现设备之间的通信。 下面将介绍一个蓝牙应用程序的实例,帮助读者快速了解如何使用Android Studio创建蓝牙应用程序。 步骤一:创建新项目 在Android Studio中创建一个新项目,选择“Empty Activity”作为模板。在创建新项目的过程中,要确保选择最新版本的Android操作系统(目前是Android 11)。 步骤二:添加蓝牙权限 在AndroidManifest.xml文件中添加蓝牙权限,以便应用程序可以访问蓝牙设备。添加以下代码: <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 步骤三:添加蓝牙代码 在MainActivity.java文件中添加蓝牙代码。首先需要定义BluetoothAdapter变量,并在onCreate()方法中初始化。接下来,需要编写代码来搜索并连接蓝牙设备。最后,可以添加代码来读取和写入数据。 这是示例代码: private BluetoothAdapter mBluetoothAdapter; private BluetoothDevice mDevice; private UUID mUuid; private BluetoothSocket mSocket; // 初始化蓝牙适配器 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 搜索蓝牙设备 Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { for (BluetoothDevice device : pairedDevices) { if (device.getName().equals("MyDevice")) { mDevice = device; break; } } } // 连接蓝牙设备 try { mSocket = mDevice.createRfcommSocketToServiceRecord(mUuid); mSocket.connect(); } catch (IOException e) { e.printStackTrace(); } // 读取数据 InputStream inputStream = null; byte[] buffer = new byte[1024]; int bytes; try { inputStream = mSocket.getInputStream(); bytes = inputStream.read(buffer); String message = new String(buffer, 0, bytes); } catch (IOException e) { e.printStackTrace(); } // 写入数据 OutputStream outputStream = null; byte[] message = "Hello, world".getBytes(); try { outputStream = mSocket.getOutputStream(); outputStream.write(message); } catch (IOException e) { e.printStackTrace(); } 步骤四:测试应用程序 使用Android Studio内置的模拟器或真实的Android设备,测试创建的应用程序。确保应用程序可以搜索并连接蓝牙设备,并能正常读写数据。 总结 通过以上步骤,开发者们可以使用Android Studio创建基于蓝牙的应用程序。当然,以上示例代码只是一个基本的蓝牙应用程序,实际开发中,开发者们需要根据实际情况添加更多的功能。 ### 回答3: Android Studio开发蓝牙应用程序的例子非常有帮助,因为它可以教你如何使用Android上的Bluetooth API。这些API允许你编写蓝牙应用程序,以便你的设备可以与其他设备通信。下面是一个简单的Android Studio蓝牙应用程序的例子,来展示如何使用Bluetooth API。 首先,你需要在Android Studio中创建一个新的项目。在创建过程中,你需要将"Minimum SDK"设置为Android 4.3(API级别18)或更高版本。在应用程序中,你需要添加以下权限: android.permission.BLUETOOTH android.permission.BLUETOOTH_ADMIN 接下来,在MainActivity.java中添加以下代码: ```java public class MainActivity extends AppCompatActivity { private BluetoothAdapter mBluetoothAdapter; private BluetoothDevice mBluetoothDevice; private BluetoothSocket mBluetoothSocket; private static final int REQUEST_ENABLE_BT = 1; // 定义蓝牙开关动作返回码 private static final String DEVICE_ADDRESS = "98:D3:31:F8:07:80"; // 定义蓝牙设备地址 private static final UUID DEFAULT_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // 定义蓝牙设备UUID @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { // 设备不支持蓝牙 return; } // 如果蓝牙没有打开 if (!mBluetoothAdapter.isEnabled()) { // 请求打开蓝牙 Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } // 根据蓝牙设备地址获取蓝牙设备 mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(DEVICE_ADDRESS); // 根据UUID创建蓝牙socket try { mBluetoothSocket = mBluetoothDevice.createInsecureRfcommSocketToServiceRecord(DEFAULT_UUID); } catch (IOException e) { e.printStackTrace(); } // 连接蓝牙设备 try { mBluetoothSocket.connect(); } catch (IOException e) { e.printStackTrace(); } } @Override protected void onDestroy() { super.onDestroy(); // 关闭蓝牙socket try { mBluetoothSocket.close(); } catch (IOException e) { e.printStackTrace(); } // 关闭蓝牙 if (mBluetoothAdapter.isEnabled()) { mBluetoothAdapter.disable(); } } } ``` 以上代码初始化了BluetoothAdapter并检查了设备是否支持蓝牙。如果蓝牙没有打开,Request Enable Bt Intent将启动一个窗口,使用户能够轻松地启用蓝牙,并根据Device address获取BluetoothDevice。它还定义了UUID和BluetoothSocket以在连接设备时使用。当应用程序销毁时,它会关闭蓝牙socket并禁用蓝牙。 这个例子中,我们没有使用蓝牙发送或接收数据,但我们可以使用BluetoothGatt类来实现这一点。BluetoothGatt是Bluetooth API的一个子类,它提供了与远程蓝牙设备通信的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值