我正在使用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/