Android 6.0或更高版本中BleScanner的权限
我正在构建一个应用程序,尝试查找并连接到一个可扩展设备。我已经用安卓5.0在我的智能手机上测试过了,效果不错 然后我试着在安卓7.0上安装这个,但我无法在任何可扩展设备上连接。 这就是我的服务,它尝试连接一个可下载设备并下载所有信息。如何更改代码以使用Android 6和7的应用程序Android 6.0或更高版本中BleScanner的权限,android,bluetooth-lowenergy,Android,Bluetooth Lowenergy,我正在构建一个应用程序,尝试查找并连接到一个可扩展设备。我已经用安卓5.0在我的智能手机上测试过了,效果不错 然后我试着在安卓7.0上安装这个,但我无法在任何可扩展设备上连接。 这就是我的服务,它尝试连接一个可下载设备并下载所有信息。如何更改代码以使用Android 6和7的应用程序 public class BlePowerService extends Service { public DbLayer db; Setting settingApp; List<S
public class BlePowerService extends Service {
public DbLayer db;
Setting settingApp;
List<ScanFilter> filters;
String[] stringSequence = new String[] {CHARACTERISTIC_FORZA_STRING, CHARACTERISTIC_TEMPERATURA_STRING};
BluetoothAdapter mBluetoothAdapter;
BluetoothGatt mGatt;
BluetoothDevice currDevice;
static final long SCAN_PERIOD = 1000;
static String SPLIT_CHAR =";";
BluetoothLeScanner mLEScanner;
Handler mHandler;
int ReadQueueIndex;
List<BluetoothGattCharacteristic> ReadQueue;
BluetoothGattCharacteristic caratteristicaDaLeggere;
ScanSettings settings;
Integer ultimaForzaLetta,ultimaTemperaturaLetta;
boolean continuaLetturaForza, continuaLetturaTemperatura;
private final Object readLock = new Object();
boolean isReading = true;
String LOG_CODE = "NOTIFSRV";
GattClientCallback gattClientCallback;
public BlePowerService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
Context sharedContext = null;
try {
sharedContext = this.createPackageContext(
"com.eresult.diabesitycare.devicesensor",
Context.CONTEXT_INCLUDE_CODE);
if (sharedContext == null) {
return;
}
db=new DbLayer(sharedContext);
db.open();
} catch (Exception e) {
String error = e.getMessage();
// Log.d(LOG_CODE,"DB error : " + error);
return;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
//RECUPERO LE IMPOSTAZIONI SETTATE DALL'UTENTE
settingApp = db.fetchSetting();
if (settingApp != null && settingApp.getAddressBleSX()!=null) {
ScanFilter.Builder scanFilterMac = null;
scanFilterMac = new ScanFilter.Builder().setDeviceAddress(settingApp.getAddressBleSX());
if(filters==null)
filters = new ArrayList<ScanFilter>();
filters.add(scanFilterMac.build());
//FILTRO ANCHE PER LA CARATTERISTICA DI FORZA
ScanFilter filter = null;
filter = new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(CHARACTERISTIC_FORZA_STRING)).build();
filters.add(filter);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build();
scanLeDevice(true);
mTimer = new Timer();
int nMinuti = settingApp.getFrequenzaDownload()!= null ? settingApp.getFrequenzaDownload() : 1;
mTimer.schedule(timerTask, 10000, 60000 * nMinuti);
}
} catch (Exception e) {
// Log.e("POWER_SERVICE", e.getMessage());
}
return super.onStartCommand(intent, flags, startId);
}
public void connectToDevice(BluetoothDevice device) {
//VERIFICO SE IL DEVICE è QUELLO CHE VOGLIO IO
if (mGatt == null && settingApp != null
&& device.getAddress().equals(settingApp.getAddressBleSX())) {
currDevice = device;
gattClientCallback = new GattClientCallback();
mGatt = currDevice.connectGatt(getBaseContext(), false, gattClientCallback);
scanLeDevice(false);// will stop after first device detection
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
Handler h = new Handler(getApplicationContext().getMainLooper());
// Although you need to pass an appropriate context
h.post(new Runnable() {
@Override
public void run() {
// Log.i("onLeScan", device.toString());
connectToDevice(device);
}
});
}
};
private void scanLeDevice(final boolean enable) {
if (enable) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}, SCAN_PERIOD);
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mLEScanner.startScan(filters, settings, mScanCallback);
}
} else {
if (Build.VERSION.SDK_INT < 21) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} else {
mLEScanner.stopScan(mScanCallback);
}
}
}
private ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
BluetoothDevice btDevice = null;
btDevice = result.getDevice();
connectToDevice(btDevice);
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult sr : results) {
Log.i("ScanResult - Results", sr.toString());
}
}
@Override
public void onScanFailed(int errorCode) {
Log.e("Scan Failed", "Error Code: " + errorCode);
}
};
private class GattClientCallback extends BluetoothGattCallback {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
try{
super.onConnectionStateChange(gatt, status, newState);
Log.i("tag", "onConnectionStateChange newState: " + newState);
if (status == BluetoothGatt.GATT_FAILURE) {
Log.e("ERROR_SERVICE", "Connection Gatt failure status " + status);
if(mGatt == null){
}else{
disconnectGattServer();
mGatt = null;
}
return;
} else if (status != BluetoothGatt.GATT_SUCCESS) {
// handle anything not SUCCESS as failure
Log.e("ERROR_SERVICE", "Connection not GATT sucess status " + status);
if(mGatt == null){
}else{
disconnectGattServer();
mGatt = null;
}
return;
}
if (newState == BluetoothProfile.STATE_CONNECTED) {
//Log.i("INFO", "Connected to device " + gatt.getDevice().getAddress());
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i("INFO", "Disconnected from device");
if(mGatt == null){
}else{
disconnectGattServer();
mGatt = null;
}
}
}catch(Exception e){
Log.e("tag", e.getMessage());
}
}
public void disconnectGattServer() {
continuaLetturaForza = false;
continuaLetturaTemperatura = false;
if (mGatt == null) {
}
else{
try{
mGatt.disconnect();
mGatt.close();
}catch(Exception e){
mGatt = null;
}
}
mGatt = null;
currDevice = null;
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status != BluetoothGatt.GATT_SUCCESS) {
// Log.i("INFO", "Device service discovery unsuccessful, status " + status);
return;
}
List<BluetoothGattCharacteristic> matchingCharacteristics =
BluetoothUtils.findCharacteristics(gatt,stringSequence);
if (matchingCharacteristics.isEmpty()) {
// Log.e("ERROR_SERVICE","Unable to find characteristics.");
return;
}else {
ReadQueue = new ArrayList<>();
for (BluetoothGattCharacteristic characterist : matchingCharacteristics) {
ReadQueue.add(characterist);
}
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
//TO DO
} else {
//TO DO
}
}
}
public void onDestroy() {
try {
db.close();
Log.d(LOG_CODE,"DB connection closed" );
mTimer.cancel();
timerTask.cancel();
} catch (Exception e) {
e.printStackTrace();
}
}
}
公共类BlePowerService扩展服务{
公共数据层数据库;
设置应用程序;
列表过滤器;
String[]stringSequence=新字符串[]{CHARACTERISTIC\u FORZA\u String,CHARACTERISTIC\u TEMPERATURA\u String};
蓝牙适配器mBluetoothAdapter;
蓝牙关贸总协定;
蓝牙设备;
静态最终长扫描周期=1000;
静态字符串拆分_CHAR=“;”;
蓝牙扫描仪;
汉德勒;
int-ReadQueueIndex;
列表读取队列;
蓝牙特征性卡拉特氏菌;
扫描设置;
整数ultimaForzaLetta,UltimateAmperaturaletta;
布尔连续温度场,连续温度场;
私有最终对象readLock=新对象();
布尔值isReading=true;
字符串LOG_CODE=“NOTIFSRV”;
GattClientCallback GattClientCallback;
公共电力服务(){
}
@凌驾
公共IBinder onBind(意向){
返回null;
}
@凌驾
public void onCreate(){
super.onCreate();
mHandler=新处理程序();
上下文sharedContext=null;
试一试{
sharedContext=this.createPackageContext(
“com.eresult.diabesticCare.devicesensor”,
上下文。上下文(包括代码);
if(sharedContext==null){
返回;
}
db=新的数据库层(sharedContext);
db.open();
}捕获(例外e){
字符串错误=e.getMessage();
//Log.d(日志代码,“DB错误:+错误);
返回;
}
}
@凌驾
公共int onStartCommand(Intent Intent、int标志、int startId){
试一试{
//这是一个很好的解释
settingApp=db.fetchSetting();
if(settingApp!=null&&settingApp.getAddressBleSX()!=null){
ScanFilter.Builder scanFilterMac=null;
scanFilterMac=new ScanFilter.Builder().setDeviceAddress(settingApp.getAddressBleSX());
if(过滤器==null)
过滤器=新的ArrayList();
filters.add(scanFilterMac.build());
//每平方英尺的过滤
扫描过滤器=空;
filter=new ScanFilter.Builder().setServiceUuid(parcelouid.fromString(CHARACTERISTIC_FORZA_STRING)).build();
过滤器。添加(过滤器);
mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
mLEScanner=mBluetoothAdapter.getBluetoothLeScanner();
设置=新的ScanSettings.Builder()
.setScanMode(扫描设置.扫描模式\u低功率)
.build();
扫描设备(真实);
mTimer=新计时器();
int nMinuti=settingApp.getFrequenzaDownload()!=null?settingApp.getFrequenzaDownload():1;
mTimer.时间表(时间任务,10000,60000*N分钟);
}
}捕获(例外e){
//Log.e(“POWER_服务”,e.getMessage());
}
返回super.onStartCommand(intent、flags、startId);
}
public void connectToDevice(蓝牙设备){
//验证设备的正确性
如果(mGatt==null&&setingapp!=null
&&device.getAddress().equals(settingApp.getAddressBleSX()){
设备=设备;
gattClientCallback=新的gattClientCallback();
mGatt=currendevice.connectGatt(getBaseContext(),false,gattClientCallback);
scanLeDevice(false);//将在第一次检测到设备后停止
}
}
私有BluetoothAdapter.LeScanCallback mLeScanCallback=
新的BluetoothAdapter.LeScanCallback(){
@凌驾
public void onLeScan(最终蓝牙设备,int rssi,
字节[]扫描记录){
Handler h=新处理程序(getApplicationContext().getMainLooper());
//尽管您需要传递适当的上下文
h、 post(新的Runnable(){
@凌驾
公开募捐{
//Log.i(“onLeScan”,device.toString());
连接到设备(设备);
}
});
}
};
专用void扫描设备(最终布尔启用){
如果(启用){
mHandler.postDelayed(新的Runnable(){
@凌驾
公开募捐{
if(Build.VERSION.SDK_INT<21){
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}否则{
mLEScanner.stopScan(mScanCallback);
}
}
},扫描周期);
if(Build.VERSION.SDK_INT<21){
mBluetoothAdapter.startedscan(mLeScanCallback);
}否则{
mLEScanner.startScan(过滤器、设置、mScanCallback);
}
}否则{
if(Build.VERSION.SDK_INT<21){
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}否则{
mLEScanner.stopScan(mScanCallback);
}
}
}
private ScanCallback mScanCallback=新建ScanCallback(){
@凌驾
公共void onScanResult(int callbackType、ScanResult){
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.ACCESS_COARSE_LOCATION)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
Log.d(TAG, "We need to show an explanation...");
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_COARSE_LOCATION);
break;
case DialogInterface.BUTTON_NEGATIVE:
//No button clicked
finish();
break;
}
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Access to position is required in order to scan Bluetooth LE devices, please grant this permission to this app.").setPositiveButton("Grant now", dialogClickListener)
.setNegativeButton("Grant later", dialogClickListener).show();
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_COARSE_LOCATION);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// You have already the permission
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_COARSE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}