[使用workmanager的Android定期位置更新

问题描述 投票:1回答:1

我正在如下使用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()
        }
    }
}

我将工作人员触发为-

val myWorker =
            PeriodicWorkRequestBuilder<LocationWorker>(
                15,
                TimeUnit.MINUTES
            ).addTag(
                "location"
            ).build()
        WorkManager.getInstance(context).enqueueUniquePeriodicWork(
            "location",
            ExistingPeriodicWorkPolicy.KEEP,
            myWorker
        )

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

android kotlin coroutine android-workmanager
1个回答
1
投票
前台服务
主要用途将在应用被终止时运行并带有持久通知

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(); } }
© www.soinside.com 2019 - 2024. All rights reserved.