一、蓝牙搜索功能的实现
1.权限
AndroidManifest.xml
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
如果SDK_INT>=23需要动态申请权限
if(Build.VERSION.SDK_INT>=23){
//判断是否有权限
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {
//请求权限
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.BLUETOOTH,Manifest.permission.BLUETOOTH_ADMIN},
100);
//向用户解释,为什么要申请该权限
if(ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CONTACTS)) {
Toast.makeText(MainActivity.this,"shouldShowRequestPermissionRationale", Toast.LENGTH_SHORT).show();
}
}
}
2.基本使用
得到蓝牙适配器:
BluetoothAdapter mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();
若mBluetoothAdapter为 null,则说明当前手机不支持蓝牙功能
打开蓝牙:
//若没打开则打开蓝牙
mBluetoothAdapter.enable();
判断蓝牙是否打开:
mBluetoothAdapter.isEnabled()
关闭蓝牙:
mBluetoothAdapter.disable();
开始搜索:
mBluetoothAdapter.startDiscovery();
取消搜索:
mBluetoothAdapter.cancelDiscovery();
判断是否在搜索中:
mBluetoothAdapter.isDiscovering();
开始广播会触发广播接收器中的onReceiver()方法。
判断是否打开蓝牙
//1.判断是否打开蓝牙
if (!mBluetoothAdapter.isEnabled()) {
//若没打开则打开蓝牙
mBluetoothAdapter.enable();
Toast.makeText(MainActivity.this,"蓝牙已打开",Toast.LENGTH_SHORT).show();
tvName.setText("蓝牙已打开");
}
//2.判断是否打开蓝牙
mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter== null) {
Toast.makeText(this,"设备上没有发现有蓝牙设备",Toast.LENGTH_SHORT).show();
}else {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
}
}
3.广播
动态注册广播
IntentFilter iFilter = new IntentFilter(
BluetoothAdapter.ACTION_DISCOVERY_STARTED);
registerReceiver(mSearchReceiver, iFilter);
// 创建一个查找蓝牙设备的广播意图
iFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
// 注册一个广播接收者,开启查找蓝牙设备意图后将结果以广播的形式返回
registerReceiver(mSearchReceiver, iFilter);
// 创建一个结束查找蓝牙设备结束的广播意图
iFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mSearchReceiver, iFilter);
具体代码:
//开始搜索
public void startBlue(){
//正在搜索就先取消搜索
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
IntentFilter iFilter = new IntentFilter(
BluetoothAdapter.ACTION_DISCOVERY_STARTED);
registerReceiver(mSearchReceiver, iFilter);
// 创建一个查找蓝牙设备的广播意图
iFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
// 注册一个广播接收者,开启查找蓝牙设备意图后将结果以广播的形式返回
registerReceiver(mSearchReceiver, iFilter);
// 创建一个结束查找蓝牙设备结束的广播意图
iFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mSearchReceiver, iFilter);
}
创建广播:
private BroadcastReceiver mSearchReceiver = new BroadcastReceiver() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
//搜索前
data.clear();
break;
case BluetoothDevice.ACTION_FOUND:
//搜索中
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
for (int i = 0; i < data.size(); i++) {
if(data.get(i).equals(device.getName())) {
return;
}
}
data.add(device.getName());
Log.e("tag","name======"+device.getName());
break;
case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
//搜索完成
// 设置adapter
if(data.size()>0) {
mAdapter = new MyAdapter(data);
my_recycler_view.setAdapter(mAdapter);
}else {
Toast.makeText(SearchListActivity.this,"设备上没有发现有蓝牙设备",Toast.LENGTH_SHORT).show();
}
break;
}
}
};
解除注册:
@Override
protected void onDestroy() {
super.onDestroy();
//解除注册
unregisterReceiver(mSearchReceiver);
}
二、手机端蓝牙模块通信
1.创建连接
//创建连接
new ConnectTask().execute(address);
连接蓝牙设备的异步任务
class ConnectTask extends AsyncTask<String,String,String>
{
@Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(params[0]);
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
btSocket.connect();
Log.e("error", "ON RESUME: BT connection established, data transfer link open.");
} catch (IOException e) {
try {
btSocket.close();
return "Socket 创建失败";
} catch (IOException e2) {
Log .e("error","ON RESUME: Unable to close socket during connection failure", e2);
return "Socket 关闭失败";
}
}
//取消搜索
mBluetoothAdapter.cancelDiscovery();
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
Log.e("error", "ON RESUME: Output stream creation failed.", e);
return "Socket 流创建失败";
}
return "蓝牙连接正常,Socket 创建成功";
}
@Override //这个方法是在主线程中运行的,所以可以更新界面
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
//连接成功则启动监听
rThread=new ReceiveThread();
rThread.start();
statusLabel.setText(result);
super.onPostExecute(result);
}
}
从蓝牙接收信息的线程
class ReceiveThread extends Thread
{
String buffer="";
@Override
public void run() {
while(btSocket!=null )
{
//定义一个存储空间buff
byte[] buff=new byte[1024];
try {
inStream = btSocket.getInputStream();
System.out.println("waitting for instream");
if(null!=inStream) {
inStream.read(buff); //读取数据存储在buff数组中
processBuffer(buff,1024);
}
// System.out.println("buff receive :"+buff.length);
//System.out.println("receive content:"+ReceiveData);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void processBuffer(byte[] buff,int size)
{
int length=0;
for(int i=0;i<size;i++)
{
if(buff[i]>'\0')
{
length++;
}
else
{
break;
}
}
// System.out.println("receive fragment size:"+length);
byte[] newbuff=new byte[length]; //newbuff字节数组,用于存放真正接收到的数据
for(int j=0;j<length;j++)
{
newbuff[j]=buff[j];
}
ReceiveData=ReceiveData+new String(newbuff);
Log.e("Data",ReceiveData);
// System.out.println("result :"+ReceiveData);
Message msg= Message.obtain();
msg.what=1;
handler.sendMessage(msg); //发送消息:系统会自动调用handleMessage( )方法来处理消息
}
}
发送数据的异步任务
new SendInfoTask().execute(etSend.getText().toString());
//发送数据到蓝牙设备的异步任务
class SendInfoTask extends AsyncTask<String,String,String>
{
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
statusLabel.setText(result);
//将发送框清空
etSend.setText("");
}
@Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
if(btSocket==null)
{
return "还没有创建连接";
}
if(arg0[0].length()>0)//不是空白串
{
//String target=arg0[0];
byte[] msgBuffer = arg0[0].getBytes();
try {
// 将msgBuffer中的数据写到outStream对象中
outStream.write(msgBuffer);
} catch (IOException e) {
Log.e("error", "ON RESUME: Exception during write.", e);
return "发送失败";
}
}
return "发送成功";
}
}