private BluetoothAdapter btAdapt;
private List listDevices = new ArrayList();
private List listDeviceName = new ArrayList();
private boolean bIsConnected;
private BluetoothDevice myBluetooth;
private public BluetoothGatt mBluetoothGatt;
private TextView tv_seacher_ble;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//锁屏
tv_seacher_ble = (LinearLayout) findViewById(R.id.tv_seacher_ble);//linear Layout
BluetoothAdapter btAdapt = BluetoothAdapter.getDefaultAdapter();// 初始化本机蓝牙功能
IntentFilter intent = new IntentFilter();
intent.addAction(BluetoothDevice.ACTION_FOUND);// 用BroadcastReceiver来取得搜索结果
intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
mActivity.registerReceiver(searchDevicesBroadcast, intent);
tv_seacher_ble.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
btAdapt.startDiscovery();
}
});
}
//搜索到的蓝牙设备在这里
private BroadcastReceiver searchDevicesBroadcast = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (TextUtils.isEmpty(device.getName())) {
return;
}
ToastUtil.showToast(mActivity, "蓝牙设备 " + device.getName());
String str = device.getName() + "|" + device.getAddress();
if (listDeviceName.indexOf(str) == -1) {// 防止重复添加
listDevices.add(device); // 获取设备名称和mac地址
listDeviceName.add(new TieBean(str));
}
}
};
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
//断开设备
if (msg.what == 1) {
mBluetoothGatt.disconnect();
//连接设备
} else if (msg.what == 2) {
ToastUtil.showToast(mActivity, "开始搜索蓝牙设备");
if (btAdapt.getState() == BluetoothAdapter.STATE_OFF) {// 如果蓝牙还没开启
ToastUtil.showToast(mActivity, "请先打开蓝牙");
return;
}
if (btAdapt.isDiscovering())
btAdapt.cancelDiscovery();
listDevices.clear();
listDeviceName.clear();
btAdapt.startDiscovery();
//定时器操作
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//ToastUtil.showToast(mActivity,"搜索蓝牙完毕");
btAdapt.cancelDiscovery();
closeProgressDialog();
//其中BuildBean,TieAdapter是在app的build.gradle中dependencies {compile 'com.dou361.dialogui:jjdxm-dialogui:1.0.3'};
TieAdapter adapter = new TieAdapter(mContext, listDeviceName, true);
BuildBean buildBean = DialogUIUtils.showMdBottomSheet(mActivity, true, "", listDeviceName, 0, new DialogUIItemListener() {
@Override
public void onItemClick(CharSequence text, int position) {
myBluetooth = listDevices.get(position);
//根据蓝牙地址获取远程蓝牙设备
final BluetoothDevice device = btAdapt.getRemoteDevice(myBluetooth.getAddress());
if (device == null) {
return;
}
mBluetoothGatt = device.connectGatt(mActivity, false, mGattCallback);
}
});
buildBean.mAdapter = adapter;
buildBean.show();
}
}, 8000); //延时8s执行
} else if (msg.what == 3) {
tv_seacher_ble.setText("断开蓝牙");
} else if (msg.what == 4) {
tv_seacher_ble.setText("连接蓝牙");
mBluetoothGatt.close();
}
super.handleMessage(msg);
}
};
两个项目中的蓝牙适配器的获取,去发现,动态注册广播、广播接收蓝牙搜索结果、蓝牙连接都一样,至于手机是否支持ble4.0,蓝牙是否开启的逻辑,连接上对数据的处理、断开mBluetoothGatt.disconnect(),关闭mBluetoothGatt.close() 的逻辑网上有很多,我这里就不在详说;
package com.hand.hand16.activity;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import com.dou361.dialogui.DialogUIUtils;
import com.dou361.dialogui.adapter.TieAdapter;
import com.dou361.dialogui.bean.BuildBean;
import com.dou361.dialogui.bean.TieBean;
import com.dou361.dialogui.listener.DialogUIItemListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView tv_seacher_ble;
public boolean bIsConnected;
private TieAdapter tieAdapter;
private Vibrator vibrator;
private BluetoothDevice mBluetoothDevice;
private BluetoothAdapter btAdapt;
List listDevices = new ArrayList();
List listDeviceName = new ArrayList();
private BluetoothDevice myBluetooth;
public BluetoothGatt mBluetoothGatt;//中央使用和处理数据
public BluetoothGattCharacteristic mNotifyCharacteristic;
private boolean mScanning;
//蓝牙服务
private String strDevice = "";
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
//断开设备
mBluetoothGatt.disconnect();
} else if (msg.what == 2) {
//连接设备
if (btAdapt == null || !btAdapt.isEnabled() || btAdapt.getState() == BluetoothAdapter.STATE_OFF) {// 如果蓝牙还没开启
Toast.makeText(MainActivity.this,"请先打开蓝牙",Toast.LENGTH_SHORT).show();
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 0);
return;
}
if (mScanning) {
btAdapt.stopLeScan(getmLeScanCallback);
}
listDevices.clear();
listDeviceName.clear();
mScanning = true;
btAdapt.startLeScan(getmLeScanCallback); //开始搜索
//定时器操作
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mScanning = false;
btAdapt.stopLeScan(getmLeScanCallback);
//其中BuildBean,TieAdapter是在build.gradle中dependencies {compile 'com.dou361.dialogui:jjdxm-dialogui:1.0.3'};
tieAdapter = new TieAdapter(mContext, listDeviceName, true);
BuildBean buildBean = DialogUIUtils.showMdBottomSheet(mActivity, true, "", listDeviceName, 0, new DialogUIItemListener() {
@Override
public void onItemClick(CharSequence text, int position) {
mBluetoothDevice = btAdapt.getRemoteDevice(listDevices.get(position).getAddress());
if (mBluetoothDevice == null) {
return;
}
mBluetoothGatt = mBluetoothDevice.connectGatt(mActivity, false, mGattCallback);
}
});
if (listDevices.size() > 0) {
buildBean.mAdapter = tieAdapter;
buildBean.show();
} else {
Toast.makeText(MainActivity.this,"未搜索到蓝牙设备",Toast.LENGTH_SHORT).show();
}
}
}, 2000); //延时2s执行
} else if (msg.what == 3) {
tv_seacher_ble.setText("断开蓝牙");
bIsConnected = true;
Toast.makeText(MainActivity.this,"蓝牙连接成功",Toast.LENGTH_SHORT).show();
} else if (msg.what == 4) {
tv_seacher_ble.setText("连接蓝牙");
bIsConnected = false;
mBluetoothGatt.close();
mBluetoothGatt = null;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//锁屏
tv_seacher_ble = (TextView) findViewById(R.id.tv_main_id);
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
btAdapt = bluetoothManager.getAdapter();
// btAdapt = BluetoothAdapter.getDefaultAdapter();// 初始化本机蓝牙功能,除了搜索方法欢了,获取蓝牙适配器的方法也换了
//添加了震动
vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
tv_seacher_ble.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final AlertDialog.Builder myDialog = new AlertDialog.Builder(MainActivity.this);
//nomalDialog.setIcon(R.drawable.icon_dialog);
myDialog.setTitle("提示");
myDialog.setMessage("是否断开蓝牙设备?");
myDialog.setPositiveButton("是", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
});
myDialog.setNegativeButton("否", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
myDialog.show();
} else {
vibrator.vibrate(200);//震动指定时间
//蓝牙搜索
Message message = new Message();
message.what = 2;
handler.sendMessage(message);
}
}
});
BluetoothAdapter.LeScanCallback getmLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
runOnUiThread(new Runnable() {
@Override
public void run() {
boolean isSame = true;
if (bluetoothDevice != null && bluetoothDevice.getName() != null) {
LogUtil.e("蓝牙设备==" + bluetoothDevice.getName() + "|" + bluetoothDevice.getAddress());
strDevice = bluetoothDevice.getName() + "|" + bluetoothDevice.getAddress();
//去重
for (BluetoothDevice bd : listDevices) {
if (bd.getAddress().equalsIgnoreCase(bluetoothDevice.getAddress())) {
isSame = false;
}
}
if (isSame) {
listDevices.add(bluetoothDevice);
listDeviceName.add(new TieBean(strDevice));
// tieAdapter.notifyDataSetChanged();
}
}
}
});
}
};
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, final int status, final int newState) {
LogUtil.e("StateChange,status=" + status + ",newState==" + newState + ",Services=" + mBluetoothGatt.discoverServices());
if (status == BluetoothGatt.GATT_SUCCESS) {
if (newState == BluetoothProfile.STATE_CONNECTED) {//2
LogUtil.e("去连接GATT server");
} else if (newState == BluetoothProfile.STATE_CONNECTING) {
LogUtil.e("连接中");
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
LogUtil.e("已断开断开蓝牙Disconnected");
Message message = new Message();
message.what = 4;
handler.sendMessage(message);
} else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
LogUtil.e("断开中");
}
} else if (status == 133) {
//防止出现133,搜索到列表连接不上
LogUtil.e("出现133");
Message message = new Message();
message.what = 5;
handler.sendMessage(message);
} else if (status == 8) {
//自动断开
LogUtil.e("自动断开了");
Message message = new Message();
message.what = 6;
handler.sendMessage(message);
} else if (status == 40) {
//距离太远
Message message = new Message();
message.what = 7;
handler.sendMessage(message);
}else {
//其他连接不到设备的情况
}Message message = new Message();
message.what = 8;
handler.sendMessage(message);
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
LogUtil.e("ServicesDiscovered状态status==" + status + ",Services==" + gatt.getServices());
if (status == BluetoothGatt.GATT_SUCCESS) {
Message message = new Message();
message.what = 3;
handler.sendMessage(message);
//激活要开启的服务
displayGattServices(gatt.getServices());
LogUtil.e("Discovered获取GATT_SUCCESS");
} else {
LogUtil.e("onServicesDiscovered received: " + status);
bIsConnected = false;
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
}
};
//打开服务
private void displayGattServices(List gattServices) {
if (gattServices == null)
return;
String uuid = null;
for (BluetoothGattService gattService : gattServices) {
uuid = gattService.getUuid().toString();
List gattCharacteristics = gattService.getCharacteristics();
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
uuid = gattCharacteristic.getUuid().toString();
if (uuid.equals(SPP_UUID)) {
final BluetoothGattCharacteristic characteristic = gattCharacteristic;
final int charaProp = characteristic.getProperties();
//这里根据charaProp 去做读、写、通知,真正的连接成功是在这里做判断的
// Message message = new Message();
//message.what = 3;
// handler.sendMessage(message)
}
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mScanning) {
btAdapt.stopLeScan(getmLeScanCallback);
}
if (NotNull.isNotNull(mBluetoothGatt)) {
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
}
android.os.Process.killProcess(android.os.Process.myPid());
}
}
BluetoothLeScanner scanner = btAdapt.getBluetoothLeScanner();
scanner.startScan(scanCallback);
喜出过望,难道是用的方法过时了,所以需要定位权限,上代码:
ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
final BluetoothDevice bluetoothDevice = result.getDevice();
runOnUiThread(new Runnable() {
@Override
public void run() {
boolean isSame = true;
if (bluetoothDevice != null && bluetoothDevice.getName() != null) {
LogUtil.e("蓝牙设备==" + bluetoothDevice.getName() + bluetoothDevice.getAddress());
strDevice =bluetoothDevice.getName() + "|" + bluetoothDevice.getAddress();
for (BluetoothDevice bd : listDevices) {
if (bd.getAddress().equalsIgnoreCase(bluetoothDevice.getAddress())) {
isSame = false;
}
}
if (isSame) {
listDevices.add(bluetoothDevice);
listDeviceName.add(new TieBean(strDevice));
if (bleDeviceAdapter != null) {
bleDeviceAdapter.notifyDataSetChanged();
}
}
}
}
});
}
@Override
public void onBatchScanResults(final List results) {
super.onBatchScanResults(results);
runOnUiThread(new Runnable() {
@Override
public void run() {
LogUtil.d("扫描onBatchScanResults==" + results.size());
}
});
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
LogUtil.e("扫描失败onScanFailed, errorCode==" + errorCode);
}
};
停止扫描的方法是:
scanner.stopScan(scanCallback);
然而,虽然使用了新方法,速度也是一样快,但是还是需要定位权限,魅族6和华为畅享7还得打开GPS,看来这个也不是正解,当然项目中的扫描外围蓝牙设备的方法也都换成了scanner.startScan(scanCallback);
defaultConfig {
applicationId "com.demo.ble"
minSdkVersion 18
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
中的 targetSdkVersion 25改成 targetSdkVersion 22,就不需要定位权限也可以搜索道蓝牙设备了,看到网上很少有人这样说的,搜了那么多资料,就一篇这样说的,带着半信半疑将targetSdkVersion改成 22, 编译,也没报任何错,运行,还真是又出奇迹,测试了手上的所有手机,都不需要定位,不要GPS就可以搜索到蓝牙设备。