判断手机是否支持蓝牙,是否开启蓝牙
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
// Intent intent = new Intent(getActivity(), ShackActivity.class);
// startActivity(intent);
Toast.makeText(getActivity(), "您的手机不支持寻宝活动",Toast.LENGTH_SHORT).show();
} else if (!bluetoothAdapter.isEnabled()){
final AlertDialog alertDialog = new AlertDialog.Builder(getActivity()).create();
alertDialog.show();
alertDialog.getWindow().setContentView(R.layout.bluetooth_enable_dialog);
TextView buttonOpenBlueTooth = (TextView) alertDialog.getWindow().findViewById(R.id.openbluetooth);
buttonOpenBlueTooth.requestFocus();
buttonOpenBlueTooth.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivityForResult(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS), BLUETOOTH_SETTING);
alertDialog.dismiss();
}
});
TextView buttonIgnorebluetooth = (TextView)alertDialog.getWindow().findViewById(R.id.ignorebluetooth);
buttonIgnorebluetooth.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertDialog.dismiss();
}
});
}else {
Intent intent2 = new Intent(getActivity(), ShackActivity.class);
startActivity(intent2);
}
ShackActivity 摇一摇界面
public class ShackActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager sensorManager;
private Vibrator vibrator;
private int shackCount = 0;
private long lastScanTime = 0;
private long lastShowTime = 0;
//iBeacon参数
private int major=6101;
private String UUID = "fda50693-a4e2-4fb1-afcf-c6eb07647825";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shake_activity);
//获取到系统服务
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
}
@Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
handler.removeMessages(0);
}
@Override
public void onSensorChanged(SensorEvent event) {
int sensorType = event.sensor.getType();
//values[0]:X轴,values[1]:Y轴,values[2]:Z轴
float[] values = event.values;
if (sensorType == Sensor.TYPE_ACCELEROMETER) {
if ((Math.abs(values[0]) > 17 || Math.abs(values[1]) > 17 || Math
.abs(values[2]) > 17)) {
shackCount++;
//记录大于17的次数
if (shackCount == 2) {
shackCount = 0;
//震动的毫秒数
vibrator.vibrate(500);
//记录最后一次摇动的时间
lastScanTime = System.currentTimeMillis();
//扫描蓝牙
scanBeacon();
} else if (shackCount == 0) {
}
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private int REQUEST_OPEN_BT_CODE = 1;
private boolean mScanning = false;
private BleDevicesScanner mScanner = null;
private Map ibeaconMap = new HashMap<>();
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
mScanner.stop();
mScanning = false;
dealWithBeacons();
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_OPEN_BT_CODE && resultCode == RESULT_OK) {
scanBeacon();
} else if (requestCode == REQUEST_OPEN_BT_CODE && resultCode != RESULT_OK) {
Toast.makeText(this, "Failed to open the BlueTooth!", Toast.LENGTH_SHORT).show();
}
}
/**
* 扫描蓝牙信息
*/
private void scanBeacon() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
return;
}
if (mScanning) {
return;
}
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!bluetoothAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_OPEN_BT_CODE);
return;
}
ibeaconMap.clear();
mScanner = new BleDevicesScanner(bluetoothAdapter,
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {
final iBeaconClass.iBeacon ibeacon = iBeaconClass.fromScanData(device, rssi, scanRecord);
//对扫描到的蓝牙进行赛选
if (ibeacon != null && ibeacon.proximityUuid.equals(UUID)&&major==ibeacon.major) {
String bleName = ibeacon.proximityUuid + "-" + ibeacon.major + "-" + ibeacon.minor;
//将符合条件的蓝牙进行加入map中进行后续处理
ibeaconMap.put(bleName, ibeacon.rssi);
}
}
});
//设置扫描时长,单位毫秒,默认 10 秒
mScanner.setScanPeriod(500);
mScanner.start();
//扫描一秒后将扫描到的蓝牙信息进行处理
handler.sendEmptyMessageDelayed(0, 1000);
mScanning = true;
}
/**
* 对符合条件的蓝牙信息进行处理
*/
private void dealWithBeacons() {
long currentTime = System.currentTimeMillis();
//符合条件的蓝牙信息为0时
if (ibeaconMap.size() == 0) {
if (currentTime - lastScanTime < 3000) {
scanBeacon();
} else {
}
} else {
//扫描间隔时间小于3秒
if (currentTime - lastShowTime < 3000) {
return;
}
int maxrssi = -100;
String maxbeacon = "";
//选出信号最好的一个进行处理
for (String key : ibeaconMap.keySet()) {
if (ibeaconMap.get(key) > maxrssi) {
maxbeacon = key;
maxrssi = ibeaconMap.get(key);
}
}
//获取到信号最好的一个传到服务器
// matchBeacon(maxbeacon);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
iBeaconClass
public class iBeaconClass {
static public class iBeacon {
public String name;
public int major;
public int minor;
public String proximityUuid;
public String bluetoothAddress;
public int txPower;
public int rssi;
}
public static iBeacon fromScanData(BluetoothDevice device, int rssi,
byte[] scanData) {
int startByte = 2;
boolean patternFound = false;
while (startByte <= 5) {
if (((int) scanData[startByte + 2] & 0xff) == 0x02
&& ((int) scanData[startByte + 3] & 0xff) == 0x15) {
// yes! This is an iBeacon
patternFound = true;
break;
} else if (((int) scanData[startByte] & 0xff) == 0x2d
&& ((int) scanData[startByte + 1] & 0xff) == 0x24
&& ((int) scanData[startByte + 2] & 0xff) == 0xbf
&& ((int) scanData[startByte + 3] & 0xff) == 0x16) {
iBeacon iBeacon = new iBeacon();
iBeacon.major = 0;
iBeacon.minor = 0;
iBeacon.proximityUuid = "00000000-0000-0000-0000-000000000000";
iBeacon.txPower = -55;
return iBeacon;
} else if (((int) scanData[startByte] & 0xff) == 0xad
&& ((int) scanData[startByte + 1] & 0xff) == 0x77
&& ((int) scanData[startByte + 2] & 0xff) == 0x00
&& ((int) scanData[startByte + 3] & 0xff) == 0xc6) {
iBeacon iBeacon = new iBeacon();
iBeacon.major = 0;
iBeacon.minor = 0;
iBeacon.proximityUuid = "00000000-0000-0000-0000-000000000000";
iBeacon.txPower = -55;
return iBeacon;
}
startByte++;
}
if (patternFound == false) {
// This is not an iBeacon
return null;
}
iBeacon iBeacon = new iBeacon();
iBeacon.major = (scanData[startByte + 20] & 0xff) * 0x100
+ (scanData[startByte + 21] & 0xff);
iBeacon.minor = (scanData[startByte + 22] & 0xff) * 0x100
+ (scanData[startByte + 23] & 0xff);
iBeacon.txPower = (int) scanData[startByte + 24]; // this one is signed
iBeacon.rssi = rssi;
// AirLocate:
// 02 01 1a 1a ff 4c 00 02 15 # Apple's fixed iBeacon advertising prefix
// e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon profile
// uuid
// 00 00 # major
// 00 00 # minor
// c5 # The 2's complement of the calibrated Tx Power
// Estimote:
// 02 01 1a 11 07 2d 24 bf 16
// 394b31ba3f486415ab376e5c0f09457374696d6f7465426561636f6e00000000000000000000000000000000000000000000000000
byte[] proximityUuidBytes = new byte[16];
System.arraycopy(scanData, startByte + 4, proximityUuidBytes, 0, 16);
String hexString = bytesToHexString(proximityUuidBytes);
StringBuilder sb = new StringBuilder();
sb.append(hexString.substring(0, 8));
sb.append("-");
sb.append(hexString.substring(8, 12));
sb.append("-");
sb.append(hexString.substring(12, 16));
sb.append("-");
sb.append(hexString.substring(16, 20));
sb.append("-");
sb.append(hexString.substring(20, 32));
iBeacon.proximityUuid = sb.toString();
if (device != null) {
iBeacon.bluetoothAddress = device.getAddress();
iBeacon.name = device.getName();
}
return iBeacon;
}
private static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}
BleDevicesScanner
@SuppressLint("NewApi")
public class BleDevicesScanner implements Runnable, BluetoothAdapter.LeScanCallback {
private static final String TAG = BleDevicesScanner.class.getSimpleName();
private static final long DEFAULT_SCAN_PERIOD = 500L;
public static final long PERIOD_SCAN_ONCE = -1;
private final BluetoothAdapter bluetoothAdapter;
private final Handler mainThreadHandler = new Handler(Looper.getMainLooper());
private final LeScansPoster leScansPoster;
private long scanPeriod = DEFAULT_SCAN_PERIOD;
private Thread scanThread;
private volatile boolean isScanning = false;
public BleDevicesScanner(BluetoothAdapter adapter, BluetoothAdapter.LeScanCallback callback) {
bluetoothAdapter = adapter;
leScansPoster = new LeScansPoster(callback);
}
public synchronized void setScanPeriod(long scanPeriod) {
this.scanPeriod = scanPeriod < 0 ? PERIOD_SCAN_ONCE : scanPeriod;
}
public boolean isScanning() {
return scanThread != null && scanThread.isAlive();
}
public synchronized void start() {
if (isScanning())
return;
if (scanThread != null) {
scanThread.interrupt();
}
scanThread = new Thread(this);
scanThread.setName(TAG);
scanThread.start();
}
public synchronized void stop() {
isScanning = false;
if (scanThread != null) {
scanThread.interrupt();
scanThread = null;
}
bluetoothAdapter.stopLeScan(this);
}
public void run() {
// TODO Auto-generated method stub
try {
isScanning = true;
do {
synchronized (this) {
bluetoothAdapter.startLeScan(this);
}
if (scanPeriod > 0)
Thread.sleep(scanPeriod);
synchronized (this) {
bluetoothAdapter.stopLeScan(this);
}
} while (isScanning && scanPeriod > 0);
} catch (InterruptedException ignore) {
} finally {
synchronized (this) {
bluetoothAdapter.stopLeScan(this);
}
}
}
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
// TODO Auto-generated method stub
synchronized (leScansPoster) {
leScansPoster.set(device, rssi, scanRecord);
mainThreadHandler.post(leScansPoster);
}
}
private static class LeScansPoster implements Runnable {
private final BluetoothAdapter.LeScanCallback leScanCallback;
private BluetoothDevice device;
private int rssi;
private byte[] scanRecord;
private LeScansPoster(BluetoothAdapter.LeScanCallback leScanCallback) {
this.leScanCallback = leScanCallback;
}
public void set(BluetoothDevice device, int rssi, byte[] scanRecord) {
this.device = device;
this.rssi = rssi;
this.scanRecord = scanRecord;
}
public void run() {
// TODO Auto-generated method stub
leScanCallback.onLeScan(device, rssi, scanRecord);
}
}
}
需要的权限
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.VIBRATE"/>