我希望能够在后台扫描BLE标签。
我读过关于使用服务来做到这一点。然而,当服务被执行,然后我在我的手机上运行另一个应用程序,BLE扫描回调停止执行,但服务仍然正常运行。
我知道BLE回调停止了,因为日志处理程序停止生成日志数据,直到我再次打开应用程序。
下面是我的mainactivity:public class MainActivity extends AppCompatActivity {
BluetoothManager btManager;
BluetoothAdapter btAdapter;
BluetoothLeScanner btScanner;
Button startScanningButton;
Button stopScanningButton;
TextView peripheralTextView;
private NotificationManagerCompat notificationManager;
private final static int REQUEST_ENABLE_BT = 1;
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
private static final String TAG = "ExampleJobService";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate MAIN");
notificationManager = NotificationManagerCompat.from(this);
peripheralTextView = (TextView) findViewById(R.id.PeripheralTextView);
peripheralTextView.setMovementMethod(new ScrollingMovementMethod());
startScanningButton = (Button) findViewById(R.id.StartScanButton);
startScanningButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.d(TAG, "Start button");
startService(new Intent(MainActivity.this, ExampleService.class));
}
});
stopScanningButton = (Button) findViewById(R.id.StopScanButton);
stopScanningButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.d(TAG, "Stop 1");
Intent serviceIntent = new Intent(MainActivity.this, ExampleService.class);
stopScanning();
stopService(serviceIntent);
Log.d(TAG, "Stop 2");
}
});
btManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
btScanner = btAdapter.getBluetoothLeScanner();
if (btAdapter != null && !btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,REQUEST_ENABLE_BT);
}
// Make sure we have access coarse location enabled, if not, prompt the user to enable it
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect peripherals.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
System.out.println("coarse location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
public void startScanning() {
peripheralTextView.setText("");
AsyncTask.execute(new Runnable() {
@Override
public void run() {
btScanner.startScan(leScanCallback);
}
});
}
public void stopScanning() {
System.out.println("stopping scanning");
peripheralTextView.append("Stopped Scanning");
AsyncTask.execute(new Runnable() {
@Override
public void run() {
btScanner.stopScan(leScanCallback);
}
});
}
}
下面是ExampleService:
public class ExampleService extends Service {
BluetoothManager btManager;
BluetoothAdapter btAdapter;
BluetoothLeScanner btScanner;
TextView peripheralTextView;
private NotificationManagerCompat notificationManager;
private static final String TAG = "ExampleJobService";
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
btManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
btScanner = btAdapter.getBluetoothLeScanner();
//do heavy work on a background thread
AsyncTask.execute(new Runnable() {
@Override
public void run() {
btScanner.startScan(leScanCallback);
}
});
return START_REDELIVER_INTENT;
}
private ScanCallback leScanCallback = new ScanCallback() {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.d(TAG, "BLE executed");
if(result.getDevice().getAddress().equals("EE:7E:DE:9B:65:46") && result.getRssi() > -80){
Log.d(TAG, "Tag found");
}
}
};
@Override
public void onDestroy() {
Log.d(TAG, "Destroy");
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
编辑1:
String[] peripheralAddresses = new String[]{"EE:7E:DE:9B:65:46"};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Example Service")
.setContentText("input")
.setSmallIcon(R.drawable.ic_one)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build();
// Build filters list
List<ScanFilter> filters = null;
if (peripheralAddresses != null) {
filters = new ArrayList<>();
for (String address : peripheralAddresses) {
ScanFilter filter = new ScanFilter.Builder()
.setDeviceAddress(address)
.build();
filters.add(filter);
}
}
btScanner.startScan(filters, settings, leScanCallback);
return START_STICKY;
}
首先,我建议你添加扫描过滤器,因为如果你不扫描,Android会在一段时间后停止扫描。
第二,你的服务不会存活很长时间,因为Android会杀死它,如果你的设备的Android版本更接近或等于Android Oreo (Android 8)。
所以我建议你阅读这篇文章,以找到更好的解决方案。
希望,这将帮助你!