我正在使用WorkManager,如下所示-

class LocationWorker(
    ctx: Context, params: WorkerParameters
) : CoroutineWorker(ctx, params), KoinComponent {

    private val locationDataRepository: LocationDataRepository by inject()

    override suspend fun doWork(): Result {
        return try {
            locationDataRepository.triggerLocationUpdates()
            Result.success()
        } catch (e: Exception) {
            Result.failure()
        }
    }
}

我将 worker 触发为-
val myWorker =
            PeriodicWorkRequestBuilder<LocationWorker>(
                15,
                TimeUnit.MINUTES
            ).addTag(
                "location"
            ).build()
        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "location",
            ExistingPeriodicWorkPolicy.KEEP,
            myWorker
        )

如您所见,WorkManager的最短时间为15分钟。我想以非常短的间隔(例如每隔几秒钟)跟踪一次位置,而且我希望即使在手机屏幕关闭的情况下也可以跟踪该位置。 WorkManager是满足我要求的正确选择,还是您会建议我其他一些API?

最佳答案



前台服务的主要用途是在应用被终止时以持久性通知运行

LocationService.class

public class LocationService extends Service implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
    public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000 * 30; //30 secs
    public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
            UPDATE_INTERVAL_IN_MILLISECONDS / 2;
    protected static final String TAG = "LocationUpdateService";
    public static final int HORIZONTAL_ACCURACY_IN_METERS = 100;

    /**
     * The identifier for the notification displayed for the foreground service.
     */
    private static final int NOTIFICATION_ID = 12345678;

    public static boolean mRequestingLocationUpdates = false;
    public boolean isEnded = false;
    protected GoogleApiClient mGoogleApiClient;
    protected LocationRequest mLocationRequest;



    private SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
    private double latitude = 0;
    private double longitude = 0;
    private float[] results1 = new float[1];
    private float distanceInMeters = 0;
    private Handler mHandler;


    @Override
    public void onCreate() {
        super.onCreate();


        String CHANNEL_ID = "FOREGROUND_CHANNEL";
        if (Build.VERSION.SDK_INT >= 26) {

            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                    "location_notification",
                    NotificationManager.IMPORTANCE_DEFAULT);

            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
        }

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setOngoing(true)
                .setContentTitle("G Star")

                .setSmallIcon(R.drawable.gm_noti_logo)
                .setContentText("Running").build();

        startForeground(NOTIFICATION_ID, notification);
        Utility.getInstance().makeDescriptiveLogs("ON CREATE WAS HIT");

        sendLocationDataToServerPeriodically();


    }

    private void sendLocationDataToServerPeriodically() {


//getting the alarm manager
        AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

        //creating a new intent specifying the broadcast receiver
        Intent intentLR = new Intent(this, PostLocationReceiver.class);

        PendingIntent pi = PendingIntent.getBroadcast(this, 0, intentLR,
                PendingIntent.FLAG_UPDATE_CURRENT);


        if (android.os.Build.VERSION.SDK_INT >= 23) {
            assert am != null;
            am.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    AlarmManager.INTERVAL_FIFTEEN_MINUTES, pi);
        } else if (Build.VERSION.SDK_INT >= 19) {
            if (am != null) {
                am.setInexactRepeating(AlarmManager.RTC_WAKEUP,
                        System.currentTimeMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pi);
            }
        } else {
            if (am != null) {
                am.setRepeating(AlarmManager.RTC_WAKEUP,
                        System.currentTimeMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pi);
            }
        }


    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        isEnded = false;

        Utility.getInstance().makeDescriptiveLogs("ONSTART COMMAND WAS HIT");
        buildGoogleApiClient();
        if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
            startLocationUpdates();
        }
        mHandler = new Handler();
        return START_STICKY;
    }

    @Override
    public void onConnected(Bundle bundle) {
        startLocationUpdates();
    }

    @Override
    public void onConnectionSuspended(int i) {
        // The connection to Google Play services was lost for some reason. We call connect() to
        // attempt to re-establish the connection.

        mGoogleApiClient.connect();
    }

    @Override
    public void onLocationChanged(Location location) {

        if (location.getAccuracy() < HORIZONTAL_ACCURACY_IN_METERS)
            updateUI(location);
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        // Refer to the javadoc for ConnectionResult to see what error codes might be returned in
        // onConnectionFailed.

    }

    protected synchronized void buildGoogleApiClient() {

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        createLocationRequest();
    }

    /**
     * Updates the latitude, the longitude, and the last location time in the UI.
     */
    private void updateUI(Location mCurrentLocation) {



        mHandler.post(() -> {
            /*GET DEVICE CURRENT BATTERY LEVEL*/
            int batteryPercent = Utility.getInstance().getBatteryPercentage(LocationService.this);


            /*  CALCULATE DISTANCE BETWEEN LAT LONG INTERVALS*/
            if (latitude != 0 && longitude != 0) {
                Location.distanceBetween(latitude, longitude, mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude(), results1);
                distanceInMeters = results1[0];
            }


            latitude = mCurrentLocation.getLatitude();
            longitude = mCurrentLocation.getLongitude();

            /*CHECK IF DEVICE HAS ACTIVE INTERNET CONNECTION*/
            String networkStatus = Utility.getInstance().checkConnection(LocationService.this) ? "1" : "0";


            /*CHECK NETWORK SIGNAL STRENGTH*/
            String signalStrength = Utility.getInstance().getSignalStrength(LocationService.this);

            SQLiteDBHandler db = SQLiteDBHandler.getInstance(LocationService.this);
            db.insertDeviceLocation(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude(), Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? mCurrentLocation.getSpeedAccuracyMetersPerSecond() : mCurrentLocation.getSpeed(), sdf.format(Calendar.getInstance().getTime()), distanceInMeters, batteryPercent, networkStatus, signalStrength);


        });

    }

    protected void createLocationRequest() {
        mGoogleApiClient.connect();
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setSmallestDisplacement(5);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    /**
     * Requests location updates from the FusedLocationApi.
     */
    public void startLocationUpdates() {
        if (!mRequestingLocationUpdates) {
            mRequestingLocationUpdates = true;

            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }


            LocationServices.FusedLocationApi.requestLocationUpdates(
                    mGoogleApiClient, mLocationRequest, this);

            isEnded = true;
        }
    }

    /**
     * Removes location updates from the FusedLocationApi.
     */
    public void stopLocationUpdates() {
        if (mRequestingLocationUpdates) {
            mRequestingLocationUpdates = false;



            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);

        }
    }

    @Override
    public void onDestroy() {

        mHandler.removeCallbacksAndMessages(null);

        stopLocationUpdates();

        super.onDestroy();
    }


}

关于android - 使用Workmanager的Android定期位置更新,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58033239/

10-10 19:10