在后台服务中持续获取位置更新

5

我正在开发一个应用程序,需要在后台服务中持续获取位置更新。我使用了背景粘性服务,它可以正常工作。但即使我添加了启动广播并在那里启动了服务,服务也不会在引导完成后启动。服务启动后立即被终止。

此外,这在 Oreo 上无法正常工作。在应用程序关闭几分钟后,服务停止运行并且在重新启动应用程序之前不会自动重启。

我查看了很多链接和博客,建议使用 AlarmManager / JobScheduler / JobIntentService,但没有得到令人满意的解决方案。因此,请建议一个可行的策略/解决方案,可用于在引导后持续在后台获取位置,并且应该在 Oreo 上工作


请参考这个问题,希望它能解决你的疑问...https://dev59.com/Tqbja4cB1Zd3GeqPgneU - Vikas singh
2个回答

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 Class

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
请问一下,发送通知中的那段代码是做什么用的?我尝试了这个解决方案。后台位置获取正在工作。但是我无法看到应用程序显示的任何通知。我可以看到系统显示的通知“有2个应用程序正在使用电池”,下面是我的应用程序名称。 - Virat18
@Virat18 使用compileSdkVersion 26和targetSdkVersion 25,然后您就可以看到通知了。 - KetanD

0

你可以使用融合定位提供程序以固定间隔获取设备的位置。有一种直接的方法可以从融合定位提供程序请求定期更新。位置的准确性取决于提供程序、您请求的位置权限以及在位置请求中设置的选项。

请求位置更新

Before requesting location updates, your app must connect to location services and make a location request. The lesson on Changing Location Settings shows you how to do this. Once a location request is in place you can start the regular updates by calling requestLocationUpdates().

Depending on the form of the request, the fused location provider either invokes the LocationCallback.onLocationChanged() callback method and passes it a list of Location objects, or issues a PendingIntent that contains the location in its extended data. The accuracy and frequency of the updates are affected by the location permissions you've requested and the options you set in the location request object.

This lesson shows you how to get the update using the LocationCallback callback approach. Call requestLocationUpdates(), passing it your instance of the LocationRequest object, and a LocationCallback. Define a startLocationUpdates() method as shown in the following code sample:

@Override
protected void onResume() {
    super.onResume();
    if (mRequestingLocationUpdates) {
        startLocationUpdates();
    }
}

private void startLocationUpdates() {
    mFusedLocationClient.requestLocationUpdates(mLocationRequest,
            mLocationCallback,
            null /* Looper */);
}

请点击此处查看官方文档,获取详细描述。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接