android - 工作完成后无法停止工作人员(ListenableWorker)任务

标签 android worker

我似乎找不到停止工作任务的正确方法。我调用.set(Result.success());在我的 ResolvableFuture<Result> , 但它永远不会触发 onStopped()在我的类(class)中,其他订阅的回调似乎在我的工作人员中仍然活跃。

  • 我的工作器启动并尝试查找特定的 BLE 设备
  • 它连接到该设备并尝试以 Result.success() 退出
  • 如果工作人员运行超过 3 分钟,则尝试退出。

调用Result.success()后在我连接到 BLE 设备后,它仍将保持对 onConnectionStateChange 的有效引用里面connectGatt()功能。

它甚至似乎都没有调用 onStopped()即使在操作系统强行停止我的工作人员之后,因为我不记得在日志中看到过它。

即使在创建了一个新的 worker 之后,我仍然可以通过 onConnectionStateChange 在旧的 worker 中获得更新。

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");
    }

}

最佳答案

注意,ListenableWorker.onStopped() 方法只有在 worker 被取消或任务被系统抢占时才会被调用。如果工作人员已成功完成,则不会调用 onStop()onStop() documentation tells :

This method is invoked when this Worker has been told to stop. ... This could happen due to an explicit cancellation signal by the user, or because the system has decided to preempt the task. ...

有时即使 worker 成功完成,也可以调用 onStop() 回调,但它更像是 a bug这将在未来得到解决。看看这个帖子:Why is Android Worker finishing successfully and calling onStopped()

关于android - 工作完成后无法停止工作人员(ListenableWorker)任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57656657/

相关文章:

Android:如何判断相机何时被激活

android - 是否所有 Android 手机都具有最少的一组传感器

android - ICS 4.0.4 上的安全元件访问控制

java - 安卓应用程序 : get distance between two addresses

ruby-on-rails - sidekiq worker rails 两个 worker 之一的参数错误

javascript - applicationCache 在共享 webworker (HTML5) 中是 'undefined'

Java-Gearman-Service - 在 GearmanFunction 中处理 GearmanJobEventCallback<T>::onEvent 和 byte[]

python - 从主脚本调用 python worker 脚本作为多个实例

c# - 在 Windows 服务中等待线程停止

android - 如何解决构建路径错误?