How to Continuously Locate a Device in the Background

How to Continuously Locate a Device in the Background

Nowadays, apps use device location to provide a wide variety of services. You may want to see a user's location to show services around them, learn the habits of users in different areas, or perform location-based actions, like a ride-hailing app calculating travel distance and trip fare.

In order to protect user privacy, however, most apps request device location only when they run in the foreground. Once switched to the background, or even with the device screen turned off, apps are usually not allowed to request device location. As a result, they cannot record the GPS track of a device, which negatively affects the user experience of core functions of many apps, such as ride-hailing, trip-sharing, and exercise, all of which need to track location in real time.

To ensure this kind of app is able to function properly, the app developer usually needs to give their app the capability to obtain device location when the app is running in the background. So, is there a service which the app can use to continuously request device location in the background? Fortunately, HMS Core Location Kit offers the background location function necessary to do just that.

In this article, I'll show you how to use the background location function to request device location continuously in the background.

Background Location Implementation Method

An app is running on a non-Huawei phone with the location function enabled for the app using LocationCallback. After the app is switched to the background, it will be unable to request device location.

To enable the app to continuously request device location after it is switched to the background, the app developer can use the enableBackgroundLocation method to create a foreground service. This increases the frequency with which the app requests location updates in the background. The foreground service is the most important thing for enabling successful background location because it is a service with the highest priority and the lowest probability of being ended by the system.

Note that the background location function itself cannot request device location. It needs to be used together with the location function enabled using LocationCallback. Location data needs to be obtained using the onLocationResult(LocationResult locationResult) method in the LocationCallback object.

Background Location Notes

i. The app needs to be running on a non-Huawei phone.

ii. The app must be granted permission to always obtain device location.

iii. The app must not be frozen by the power saving app on the device. For example, on a vivo phone, you need to allow the app to consume power when running in the background.

Demo Testing Notes

i. It is recommended not to charge the device during the test. This is because the app may not be limited for power consumption while the device is charging.

ii. To determine if the app is requesting device location, you can check whether the positioning icon is displayed in the device's status bar. On vivo, for example, the phone will show a positioning icon in the status bar when an app requests the phone's location. If background location is disabled for the app, the positioning icon in the status bar will disappear after the app is switched to the background. If background location is enabled for the app, however, the phone will continue to show the positioning icon in the status bar after the app is switched to the background.

Development Preparation

Before getting started with the development, you will need to integrate the Location SDK into your app. If you are using Android Studio, you can integrate the SDK via the Maven repository.

Here, I won't be describing how to integrate the SDK. You can click here to learn about the details.

Background Location Development Procedure

After integrating the SDK, perform the following steps to use the background location function:

i. Declare the background location permission in the AndroidManifest.xml file.

<service
    android:name="com.huawei.location.service.BackGroundService"
    android:foregroundServiceType="location" />

Generally, there are three location permissions in Android:

  • ACCESS_COARSE_LOCATION: This is the approximate location permission, which allows an app to obtain an approximate location, accurate to city block level.

  • ACCESS_FINE_LOCATION: This is the precise location permission, which allows an app to obtain a precise location, more accurate than the one obtained based on the ACCESS_COARSE_LOCATION permission.

  • ACCESS_BACKGROUND_LOCATION: This is the background location permission, which allows an app to obtain device location when running in the background in Android 10. In Android 10 or later, this permission is a dangerous permission and needs to be dynamically applied for. In versions earlier than Android 10, an app can obtain device location regardless of whether it runs in the foreground or background, as long as it is assigned the ACCESS_COARSE_LOCATION permission.

In Android 11 or later, these three permissions cannot be dynamically applied for at the same time. The ACCESS_BACKGROUND_LOCATION permission can only be applied for after the ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions are granted.

ii. Declare the FOREGROUND_SERVICE permission in the AndroidManifest.xml file to ensure that the background location permission can be used properly.

Note that this step is required only for Android 9 or later. As I mentioned earlier, the foreground service has the highest priority and the lowest probability of being ended by the system. This is a basis for successful background location.

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

iii. Create a Notification object.

public class NotificationUtil {
    public static final int NOTIFICATION_ID = 1;

    public static Notification getNotification(Context context) {
        Notification.Builder builder;
        Notification notification;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager notificationManager =
                (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
            String channelId = context.getPackageName();
            NotificationChannel notificationChannel =
                new NotificationChannel(channelId, "LOCATION", NotificationManager.IMPORTANCE_LOW);
            notificationManager.createNotificationChannel(notificationChannel);
            builder = new Notification.Builder(context, channelId);
        } else {
            builder = new Notification.Builder(context);
        }
        builder.setSmallIcon(R.drawable.ic_launcher)
            .setContentTitle("Location SDK")
            .setContentText("Running in the background ")
            .setWhen(System.currentTimeMillis());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            notification = builder.build();
        } else {
            notification = builder.getNotification();
        }
        return notification;
    }
}

iv. Initialize the FusedLocationProviderClient object.

FusedLocationProviderClient mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);

v. Enable the background location function.

private void enableBackgroundLocation() {
    mFusedLocationProviderClient
            .enableBackgroundLocation(NotificationUtil.NOTIFICATION_ID, NotificationUtil.getNotification(this))
            .addOnSuccessListener(new OnSuccessListener<Void>() {
                @Override
                public void onSuccess(Void aVoid) {
                    LocationLog.i(TAG, "enableBackgroundLocation onSuccess");
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(Exception e) {
                    LocationLog.e(TAG, "enableBackgroundLocation onFailure:" + e.getMessage());
                }
            });
}

Congratulations, your app is now able to request device location when running in the background.

Conclusion

Location-based services are now widely used in mobile apps. Most apps, however, can request device location only when they run in the foreground, in order to protect user privacy. To ensure this kind of app functions properly and delivers a good user experience, it is necessary for the app to receive location information while it is running in the background or the device screen is off.

In this article, I demonstrated how an app can do just that through the background location function. The whole integration process is straightforward and cost-efficient, and is an effective way for an app to obtain the device location when it runs in the background or the device screen is off.