一、 BluetoothAdapter类介绍
BluetoothAdapter类简单点来说就是代表了本设备(手机、电脑等)的蓝牙适配器对象,通过它我们可以蓝牙设备进行基本
开发了,主要有如下功能:
1、开关蓝牙设备;
2、扫描蓝牙设备;
3、设置/获取蓝牙状态信息,例如:蓝牙状态值、蓝牙Name、蓝牙Mac地址等;
BluetoothAdapter的一些常用API函数:
1、BluetoothAdapter STATE 状态值 , 即开关状态
STATE_OFF 蓝牙已经关闭
STATE_ON 蓝牙已经打开
STATE_TURNING_OFF 蓝牙处于关闭过程中 ,关闭ing
STATE_TURNING_ON 蓝牙处于打开过程中 ,打开ing
2、BluetoothAdapter SCAN_MOD状态值 ,即扫描状态
首先说明,可以扫描其他设备的,当然它同时能被其他蓝牙设备扫码。
SCAN_MODE_CONNECTABLE 表明该蓝牙可以扫描其他蓝牙设备
SCAN_MODE_CONNECTABLE_DISCOVERABLE 表明该蓝牙设备同时可以扫码其他蓝牙设备,并且可以被其他蓝牙设备扫描到。
SCAN_MODE_NONE : 该蓝牙不能扫描以及被扫描。
3、获得蓝牙适配器实例
public static synchronized BluetoothAdapter getDefaultAdapter ()
功能:获得本设备的蓝牙适配器实例。
返回值:如果设备具备蓝牙功能,返回BluetoothAdapter 实例;否则,返回null对象。
4、打开/关闭蓝牙的两种方法:
4.1、打开蓝牙:
①、直接调用函数enable()去打开蓝牙设备 ;
②、系统API去打开蓝牙设备,该方式会弹出一个对话框样式的Activity供用户选择是否打开蓝牙设备。
注意:如果蓝牙已经开启,不会弹出该Activity界面。
PS:在目前Android手机中,是不支持在飞行模式下开启蓝牙的。如果蓝牙已经开启,那么蓝牙的开关状态会随着飞行模式
的状态而发生改变。
代码示例分别如下:
//第一种打开方法: 调用enable 即可
boolean result = mBluetoothAdapter.enable();
//
/第二种打开方法 ,调用系统API去打开蓝牙
if (!mBluetoothAdapter.isEnabled()) //未打开蓝牙,才需要打开蓝牙
{
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_OPEN_BT_CODE);
//会以Dialog样式显示一个Activity , 我们可以在onActivityResult()方法去处理返回值
}
4.2、关闭蓝牙
直接调用API 函数即disable()即可。
public boolean disable ()
功能:关闭蓝牙设备。
返回值:该函数会立即返回。
true 表示关闭操作成功
false 表示蓝牙操作失败 , ①、当前蓝牙已经关闭 ; ②、其他一些异常情况
5、扫描蓝牙设备
public boolean startDiscovery ()
扫描蓝牙设备
注意: 如果蓝牙没有开启,该方法会返回false ,即不会开始扫描过程。
public boolean cancelDiscovery ()
功能: 取消扫描过程。
注意: 如果蓝牙没有开启,该方法会返回false。
public boolean isDiscovering ()
功能: 是否正在处于扫描过程中。
注意: 如果蓝牙没有开启,该方法会返回false。
6、 获取蓝牙相关信息
public String getName ()
功能:获取蓝牙设备Name
public String getAddress ()
功能:获取蓝牙设备的硬件地址(MAC地址),例如:00:11:22:AA:BB:CC
public boolean setName (String name)
功能:设置蓝牙设备的Name,
public Set<BluetoothDevice> getBondedDevices ()
功能:获取与本机蓝牙所有绑定的远程蓝牙信息,以BluetoothDevice类实例(稍后讲到)返回。
注意:如果蓝牙为开启,该函数会返回一个空集合 。
public static boolean checkBluetoothAddress (String address)
功能: 验证蓝牙设备MAC地址是否有效。所有设备地址的英文字母必须大写,48位,形如:00:43:A8:23:10:F1 。
返回值: true 设备地址有效
false 设备地址无效
public BluetoothDevice getRemoteDevice (String address)
功能:以给定的MAC地址去创建一个 BluetoothDevice 类实例(代表远程蓝牙实例)。即使该蓝牙地址不可见,也会产生
一个BluetoothDevice 类实例。
返回:BluetoothDevice 类实例 。注意,如果该蓝牙设备MAC地址不能被识别,其蓝牙Name为null。
异常:如果MAC address无效,抛出IllegalArgumentException。
7、蓝牙相关广播
Action值 说明
ACTION_STATE_CHANGED
ACTION_SCAN_MODE_CHANGED 蓝牙扫描状态(SCAN_MODE)发生改变
ACTION_DISCOVERY_STARTED 蓝牙扫描过程开始
ACTION_DISCOVERY_FINISHED 蓝牙扫描过程结束
ACTION_LOCAL_NAME_CHANGED 蓝牙设备Name发生改变
ACTION_REQUEST_DISCOVERABLE 请求用户选择是否使该蓝牙能被扫描
PS:如果蓝牙没有开启,用户点击确定后,会首先开启蓝牙,继而设置蓝牙能被扫描。
ACTION_REQUEST_ENABLE 请求用户选择是否打开蓝牙
ACTION_FOUND(该常量字段位于BluetoothDevice类中,稍后讲到)
说明:蓝牙扫描时,扫描到任一远程蓝牙设备时,会发送此广播。
通过注册这个广播,我们可以获取扫描到的蓝牙信息。方法如下:
//扫描到了任一蓝牙设备
if(BluetoothDevice.ACTION_FOUND.equals(intent.getAction()))
{
Log.v(TAG, "### BT BluetoothDevice.ACTION_FOUND ##");
BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(btDevice != null){
Log.v(TAG , "Name : " + btDevice.getName() + " Address: " + btDevice.getAddress());
}
else if(BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction()))
{
Log.v(TAG, "### BT ACTION_BOND_STATE_CHANGED ##");
int cur_bond_state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
int previous_bond_state = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.BOND_NONE);
Log.v(TAG, "### cur_bond_state ##" + cur_bond_state + " ~~ previous_bond_state" + previous_bond_state);
}
}
最后,在使用这两个类时,需要以下两个权限:
BLUETOOTH 值为 "android.permission.BLUETOOTH"
BLUETOOTH_ADMIN 值为 "android.permission.BLUETOOTH_ADMIN"
二、 BluetoothDevice类介绍
该类就是关于远程蓝牙设备的一个描述。通过它可以和本地蓝牙设备---BluetoothAdapter连接通信。
1、 蓝牙绑定(Bound)状态 , 即蓝牙设备是否与其他蓝牙绑定
BOND_BONDED 表明蓝牙已经绑定
BOND_BONDING 表明蓝牙正在绑定过程中 , bounding
BOND_NONE
更多关于BluetoothDevice类的更多介绍,请参考该农民伯伯的该篇博客:
以下是完整代码:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/btDesc" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="@string/hello" />
<Button android:id="@+id/btOpen" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="打开蓝牙" />
<Button android:id="@+id/btClose" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="关闭蓝牙" />
<Button android:id="@+id/btOpenBySystem" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="调用系统API打开蓝牙" />
<Button android:id="@+id/btDiscoveryDevice" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="搜索蓝牙设备" />
<Button android:id="@+id/btCancelDiscovery" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="停止搜索蓝牙设备" />
<Button android:id="@+id/btDiscoveryBySystem" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="调用系统API搜索蓝牙设备" />
</LinearLayout>
MainActivity.java
package com.cn;
import android.app.Activity;
import android.os.Bundle;
import java.util.Iterator;
import java.util.Set;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private static String TAG = "Bluetooth_State";
private BluetoothAdapter mBluetoothAdapter; // 本机蓝牙适配器对象
private TextView btDesc;
private Button btOpen;
private Button btClose;
private Button btOpenBySystem; // 调用系统API去打开蓝牙
private Button btDiscoveryDevice;
private Button btCancelDiscovery;
private Button btDiscoveryBySystem; // 调用系统Api去扫描蓝牙设备
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 获得本机蓝牙适配器对象引用
if (mBluetoothAdapter == null) {
toast("对不起 ,您的机器不具备蓝牙功能");
return;
}
IntentFilter bluetoothFilter = new IntentFilter();
bluetoothFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
bluetoothFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
this.registerReceiver(BluetoothReciever, bluetoothFilter);
// 蓝牙扫描相关设备
IntentFilter btDiscoveryFilter = new IntentFilter();
btDiscoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
btDiscoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
btDiscoveryFilter.addAction(BluetoothDevice.ACTION_FOUND);
btDiscoveryFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
this.registerReceiver(BTDiscoveryReceiver, btDiscoveryFilter);
int initialBTState = mBluetoothAdapter.getState();
printBTState(initialBTState); // 初始时蓝牙状态
initialViews();
btDesc.setText(" Name : " + mBluetoothAdapter.getName() + " Address : "
+ mBluetoothAdapter.getAddress() + " Scan Mode --"
+ mBluetoothAdapter.getScanMode());
// 打印处当前已经绑定成功的蓝牙设备
Set<BluetoothDevice> bts = mBluetoothAdapter.getBondedDevices();
Iterator<BluetoothDevice> iterator = bts.iterator();
while (iterator.hasNext()) {
BluetoothDevice bd = iterator.next();
Log.i(TAG,
" Name : " + bd.getName() + " Address : " + bd.getAddress());
;
Log.i(TAG, "Device class" + bd.getBluetoothClass());
}
BluetoothDevice findDevice = mBluetoothAdapter
.getRemoteDevice("00:11:22:33:AA:BB");
Log.i(TAG, "findDevice Name : " + findDevice.getName()
+ " findDevice Address : " + findDevice.getAddress());
;
Log.i(TAG, "findDevice class" + findDevice.getBluetoothClass());
}
private void initialViews() {
btDesc = (TextView) findViewById(R.id.btDesc);
btOpen = (Button) findViewById(R.id.btOpen);
btClose = (Button) findViewById(R.id.btClose);
btOpenBySystem = (Button) findViewById(R.id.btOpenBySystem);
btDiscoveryDevice = (Button) findViewById(R.id.btDiscoveryDevice);
btCancelDiscovery = (Button) findViewById(R.id.btCancelDiscovery);
btDiscoveryBySystem = (Button) findViewById(R.id.btDiscoveryBySystem);
btOpen.setOnClickListener(this);
btClose.setOnClickListener(this);
btOpenBySystem.setOnClickListener(this);
btDiscoveryDevice.setOnClickListener(this);
btCancelDiscovery.setOnClickListener(this);
btDiscoveryBySystem.setOnClickListener(this);
}
// 蓝牙开个状态以及扫描状态的广播接收器
private BroadcastReceiver BluetoothReciever = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (BluetoothAdapter.ACTION_STATE_CHANGED
.equals(intent.getAction())) {
Log.v(TAG, "### Bluetooth State has changed ##");
int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.STATE_OFF);
printBTState(btState);
} else if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent
.getAction())) {
Log.v(TAG, "### ACTION_SCAN_MODE_CHANGED##");
int cur_mode_state = intent.getIntExtra(
BluetoothAdapter.EXTRA_SCAN_MODE,
BluetoothAdapter.SCAN_MODE_NONE);
int previous_mode_state = intent.getIntExtra(
BluetoothAdapter.EXTRA_PREVIOUS_SCAN_MODE,
BluetoothAdapter.SCAN_MODE_NONE);
Log.v(TAG, "### cur_mode_state ##" + cur_mode_state
+ " ~~ previous_mode_state" + previous_mode_state);
}
}
};
// 蓝牙扫描时的广播接收器
private BroadcastReceiver BTDiscoveryReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent
.getAction())) {
Log.v(TAG, "### BT ACTION_DISCOVERY_STARTED ##");
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent
.getAction())) {
Log.v(TAG, "### BT ACTION_DISCOVERY_FINISHED ##");
} else if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) {
Log.v(TAG, "### BT BluetoothDevice.ACTION_FOUND ##");
BluetoothDevice btDevice = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (btDevice != null)
Log.v(TAG, "Name : " + btDevice.getName() + " Address: "
+ btDevice.getAddress());
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent
.getAction())) {
Log.v(TAG, "### BT ACTION_BOND_STATE_CHANGED ##");
int cur_bond_state = intent.getIntExtra(
BluetoothDevice.EXTRA_BOND_STATE,
BluetoothDevice.BOND_NONE);
int previous_bond_state = intent.getIntExtra(
BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE,
BluetoothDevice.BOND_NONE);
Log.v(TAG, "### cur_bond_state ##" + cur_bond_state
+ " ~~ previous_bond_state" + previous_bond_state);
}
}
};
private void printBTState(int btState) {
switch (btState) {
case BluetoothAdapter.STATE_OFF:
toast("蓝牙状态:已关闭");
Log.v(TAG, "BT State : BluetoothAdapter.STATE_OFF ###");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
toast("蓝牙状态:正在关闭");
Log.v(TAG, "BT State : BluetoothAdapter.STATE_TURNING_OFF ###");
break;
case BluetoothAdapter.STATE_TURNING_ON:
toast("蓝牙状态:正在打开");
Log.v(TAG, "BT State :BluetoothAdapter.STATE_TURNING_ON ###");
break;
case BluetoothAdapter.STATE_ON:
toast("蓝牙状态:已打开");
Log.v(TAG, "BT State :BluetoothAdapter.STATE_ON ###");
break;
default:
break;
}
}
private final int REQUEST_OPEN_BT_CODE = 1;
private final int REQUEST_DISCOVERY_BT_CODE = 2;
@Override
public void onClick(View v) {
boolean wasBtOpened = mBluetoothAdapter.isEnabled(); // 是否已经打开
switch (v.getId()) {
case R.id.btOpen: // 打开蓝牙
boolean result = mBluetoothAdapter.enable();
if (result)
toast("蓝牙打开操作成功");
else if (wasBtOpened)
toast("蓝牙已经打开了");
else
toast("蓝牙打开失败");
break;
case R.id.btClose: // 关闭蓝牙
boolean result1 = mBluetoothAdapter.disable();
if (result1)
toast("蓝牙关闭操作成功");
else if (!wasBtOpened)
toast("蓝牙已经关闭");
else
toast("蓝牙关闭失败.");
break;
case R.id.btOpenBySystem: // 调用系统API打开蓝牙设备
// 未打开蓝牙,才需要打开蓝牙
if (!wasBtOpened) {
Intent intent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_OPEN_BT_CODE);
} else
toast("Hi ,蓝牙已经打开了,不需要在打开啦 ~~~");
break;
case R.id.btDiscoveryDevice: // 扫描时,必须先打开蓝牙
if (!mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.startDiscovery();
} else
toast("蓝牙正在搜索设备了 ---- ");
break;
case R.id.btCancelDiscovery: // 取消扫描
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
} else
toast("蓝牙并未搜索设备 ---- ");
break;
case R.id.btDiscoveryBySystem: // 使蓝牙能被扫描
Intent discoveryintent = new Intent(
BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoveryintent.putExtra(
BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivityForResult(discoveryintent, REQUEST_DISCOVERY_BT_CODE);
break;
}
}
// 请求码
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OPEN_BT_CODE) {
if (resultCode == RESULT_CANCELED) {
toast("Sorry , 用户拒绝了您的打开蓝牙请求.");
} else
toast("Year , 用户允许了您的打开蓝牙请求.");
} else if (requestCode == REQUEST_DISCOVERY_BT_CODE) {
if (resultCode == RESULT_CANCELED) {
toast("Sorry , 用户拒绝了,您的蓝牙不能被扫描.");
} else
toast("Year , 用户允许了,您的蓝牙能被扫描");
}
}
private void toast(String str) {
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cn" android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity android:name=".MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
</manifest>
运行结果:
最后关于如果连接某个蓝牙设备,就需要利用蓝牙部分的隐藏API了,关于这方面,大家可以看看hellogv的博客:
《Android提高第十三篇之探秘蓝牙隐藏API》