我创建了一个应用程序,它需要在后台不断扫描我们自己的蓝牙设备。当其中一台蓝牙设备在附近时,应用程序需要执行某些操作。
我使用绑定的前台服务来扫描蓝牙设备,当设备在附近时,应用程序开始侦听位置更新。当设备不在附近时,应用程序会停止位置更新并重新开始扫描。在奥利奥之前,这一直很好用。
在 Android Oreo 上,服务通常在运行 2-3 天后停止。我不知道为什么会这样。
这就是我在主要活动中创建服务的方式:
private void initServiceConnection() {
mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder service)
{
mService = ((MyService.LocalBinder) service).getService();
mService.startBLEScan();
}
@Override
public void onServiceDisconnected(ComponentName componentName)
{
// When the service is killed we restart the app in onDestroy by calling finish() here
mService = null;
finish();
}
};
Intent serviceIntent = new Intent(this, MyService.class);
bindService(serviceIntent, mServiceConnection, BIND_AUTO_CREATE | BIND_IMPORTANT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
}
}
这是该服务的简化版本:
public class MyService extends Service
{
private static final long SCAN_TIMEOUT = 8000;
private static final long PAUSE_TIMEOUT = 15000;
private Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
private final IBinder mBinder = new LocalBinder();
public MyService()
{
mHandler = new Handler();
}
@Override
public IBinder onBind(Intent intent)
{
return mBinder;
}
public void initialize()
{
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
@Override
public void onCreate() {
super.onCreate();
startInForeground();
initialize();
}
@Override
public void onDestroy()
{
mHandler.removeCallbacks(timeoutScan);
mHandler.removeCallbacks(timeoutPause);
stopForeground(true);
stopScan();
super.onDestroy();
}
public class LocalBinder extends Binder
{
public MyService getService()
{
return MyService.this;
}
}
private void startInForeground()
{
NotificationCompat.Builder mNotifyBuilder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
MyNotificationManager notificationManager = new MyNotificationManager(getApplicationContext());
notificationManager.createServiceNotificationChannel();
mNotifyBuilder = new NotificationCompat.Builder(this, notificationManager.getChannelId());
} else {
mNotifyBuilder = new NotificationCompat.Builder(this);
}
mNotifyBuilder
.setSmallIcon(R.drawable.ic_logo_notify)
.setPriority(NotificationCompat.PRIORITY_MAX);
startForeground(hashCode(), mNotifyBuilder.build());
}
private void startScan()
{
if (mBluetoothAdapter == null) {
return;
}
mHandler.removeCallbacks(timeoutScan);
mHandler.removeCallbacks(timeoutPause);
if (mBluetoothAdapter.isEnabled())
{
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
mHandler.postDelayed(timeoutScan, SCAN_TIMEOUT);
}
private void stopScan()
{
mHandler.removeCallbacks(timeoutScan);
if (mBluetoothAdapter != null)
{
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
private Runnable timeoutScan = new Runnable ()
{
@Override
public void run()
{
stopScan();
mHandler.postDelayed(timeoutPause, PAUSE_TIMEOUT);
}
};
private Runnable timeoutPause = new Runnable ()
{
@Override
public void run()
{
startScan();
}
};
private final BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback()
{
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord)
{
// DO STUFF
}
};
}
我的问题是我做错了什么?我可以在服务被杀死后以某种方式重新启动服务吗?