我正在开发需要在后台服务中连续获取位置更新的应用程序。我已经使用了后台粘性服务,并且可以使用它。但是即使我已经添加了启动广播并在那里启动了服务,启动完成后服务还是无法启动。服务启动并立即被杀死。
此外,这不适用于Oreo。在几分钟的应用程序关闭后,服务会停止,并且直到重新启动应用程序后才重新启动。
我浏览了很多链接,这些博客建议使用AlarmManager / JobScheduler / JobIntentService,但没有得到令人满意的解决方案。 因此,请提出有效策略/解决方案,该策略/解决方案即使在启动后也可以用于在后台连续获取位置,并且应该在Oreo上工作。
答案 0 :(得分:4)
使用通知,您可以使服务活跃起来。它适用于android 8.1。 以下是后台服务的代码
注意:
1)对上述Build.VERSION_CODES.O使用startForegroundService
2)使用targetSdkVersion 25
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
mainActivity.startService(new Intent(getContext(), GpsServices.class));
} else {
mainActivity.startForegroundService(new Intent(getContext(), GpsServices.class));
}
BackgroundGpsServices类
public class BackgroundGpsServices extends Service implements LocationListener {
private LocationManager mLocationManager;
public final long UPDATE_INTERVAL = 500; /* 0.5 sec */
public static final int NOTIFICATION_ID = 200;
@Override
public void onCreate() {
sendNotification(this, false);
startLocationUpdates();
}
private void startLocationUpdates() {
if (!isLocationUpdateRunning) {
isLocationUpdateRunning = true;
mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (mLocationManager != null) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, UPDATE_INTERVAL, 0, this);
}
}
}
@Override
public void onLocationChanged(Location location) {
sendNotification(BackgroundGpsServices.this, true);
System.out.println("onLocationChanged ----- location=" + location);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
public static void sendNotification(Service service, boolean isUpdate) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent intent = new Intent(service, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(service, 0, intent, PendingIntent.FLAG_NO_CREATE);
NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(service)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("INFO_NOTIFICATION_TITLE")
.setOngoing(true)
.setAutoCancel(false)
.setContentText("INFO_NOTIFICATION_MESSAGE")
.setContentIntent(pendingIntent);
Notification notification = mNotifyBuilder.build();
if (isUpdate) {
NotificationManager notificationManager = (NotificationManager) service.getSystemService(NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(NOTIFICATION_ID, notification);
}
} else {
service.startForeground(NOTIFICATION_ID, notification);
}
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// If we get killed, after returning from here, restart
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
/* Remove the locationlistener updates when Services is stopped */
@Override
public void onDestroy() {
try {
stopLocationUpdates();
stopForeground(true);
} catch (Exception e) {
e.printStackTrace();
}
}
private void stopLocationUpdates() {
isLocationUpdateRunning = false;
if (mLocationManager != null) {
mLocationManager.removeUpdates(this);
}
}
}
答案 1 :(得分:0)
您可以使用fused location provider定期获取设备的位置。有一种直接方法可从融合位置提供程序请求定期更新。位置的准确性取决于提供商,您所请求的位置权限以及您在位置请求中设置的选项。
请求位置更新
在请求位置更新之前,您的应用必须连接到位置服务并发出位置请求。关于更改位置设置的课程向您展示了如何执行此操作。位置请求到位后,您可以通过调用requestLocationUpdates()开始常规更新。
根据请求的形式,融合的位置提供程序将调用LocationCallback.onLocationChanged()回调方法并向其传递一个Location对象的列表,或者发出包含其扩展数据中的位置的PendingIntent。更新的准确性和频率受您请求的位置权限和在位置请求对象中设置的选项的影响。
本课向您展示如何使用LocationCallback回调方法获取更新。调用requestLocationUpdates(),将您的LocationRequest对象实例和LocationCallback传递给它。定义一个startLocationUpdates()方法,如以下代码示例所示:
@Override
protected void onResume() {
super.onResume();
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
private void startLocationUpdates() {
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback,
null /* Looper */);
}
Read Official Documentation here了解详细说明。
希望这会有所帮助。