我似乎找不到正确的方法来停止我的worker任务。我在
即使操作系统强制停止我的worker,它似乎也没有调用
即使创建了新的worker,在旧worker中仍然会接收到
ResolvableFuture<Result>
上调用.set(Result.success());
,但它从未触发我的类中的onStopped()
,而且其他已订阅的回调似乎仍然在我的worker内活跃。
- 我的worker启动并尝试查找特定的BLE设备
- 它连接到该设备并尝试使用
Result.success()
退出 - 如果worker运行时间超过3分钟,则尝试退出。
Result.success()
之后,它仍会保持对connectGatt()
函数内的onConnectionStateChange
的活动引用。即使操作系统强制停止我的worker,它似乎也没有调用
onStopped()
,因为我从未在日志中看到过。即使创建了新的worker,在旧worker中仍然会接收到
onConnectionStateChange
的更新。package test;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.concurrent.futures.ResolvableFuture;
import androidx.work.ListenableWorker;
import androidx.work.WorkerParameters;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.ArrayList;
import java.util.List;
import static android.bluetooth.BluetoothDevice.TRANSPORT_LE;
import static android.os.Build.VERSION_CODES.M;
public class BluetoothScanWorker extends ListenableWorker {
private String TAG = "BluetoothScanWorker";
private BluetoothAdapter bluetoothAdapter;
private ResolvableFuture<Result> mFuture;
public BluetoothScanWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
@NonNull
@Override
public ListenableFuture<Result> startWork() {
mFuture = ResolvableFuture.create();
Log.d(TAG ,"startWork()");
if (Build.VERSION.SDK_INT >= M) {
ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)).build();
List<ScanFilter> filters_v2 = new ArrayList<>();
ScanFilter scanFilter = new ScanFilter.Builder()
.setDeviceAddress("B8:27:EB:B9:5C:FC")
.build();
filters_v2.add(scanFilter);
BluetoothManager bluetoothManager =
(BluetoothManager) this.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
bluetoothAdapter.getBluetoothLeScanner().startScan(filters_v2, settings, leScanCallback); // Scan for every BLE device matching my filter
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
endWork();
}
}, 3*60*1000); // End worker after 3 minutes
}
return mFuture;
}
private void endWork(){
if (Build.VERSION.SDK_INT >= M) {
Log.d(TAG, "END WORK");
bluetoothAdapter.getBluetoothLeScanner().stopScan(leScanCallback);
mFuture.set(Result.success());
}
}
@RequiresApi(M)
private ScanCallback leScanCallback = new ScanCallback() { // Called when I find my BLE device
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.d(TAG ,"onScanResult: " + result.getDevice().toString());
bluetoothAdapter.getBluetoothLeScanner().stopScan(this);
result.getDevice().connectGatt(getApplicationContext(), true, new BluetoothGattCallback() { // Connect to my BLE device
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG ,"GATT connected successfully");
endWork();
}
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d(TAG ,"GATT disconnected");
endWork();
}
}
},TRANSPORT_LE);
}
};
@Override
public void onStopped() {
Log.d(TAG, "Work service stopped");
}
}
startWork()
回调中返回SUCCESS或FAIL结果时,因为工作已完成,所以工作程序被认为是完成(停止),但不会调用onStop()
,因为它只设计用于在取消情况下调用。如果您希望当工作完成时调用onStop()
回调,则可以在从startWork()
返回结果之前手动执行它。 - Valeriy KatkovListenableWorker.startWork()
方法在主线程中执行。如果您通过线程处理程序调度一个 Runnable,则该 Runnable 将在主线程中调度,并且当 Worker 完成时它不会被取消。Worker 甚至不知道该 Runnable 已被调度。正确的方法是存储对 Runnable 的引用,并从onStop()
回调中取消它,该回调通知有关 Worker 取消的信息。我认为onCanceled()
是onStop()
回调的更好名称,但它被称为onStop()
:) - Valeriy Katkov