cordova-plugin-background-geolocation icon indicating copy to clipboard operation
cordova-plugin-background-geolocation copied to clipboard

Android location access: User cannot choose "Allow all the time"

Open speckro opened this issue 5 years ago • 24 comments

First I want to thank you for providing this plugin!

Environment

Android API level 29

Context

When the user is asked how the device is allowed to access the location, no option "Allow all the time" is shown.

Expected Behavior

The following location access options should be shown to the user:

  • Allow all the time
  • Allow only while using the app
  • Deny & don't ask again

Actual Behavior

The following location access options are currently shown to the user:

  • Allow only while using the app
  • Deny
  • Deny & don't ask again

Possible Fix

Update array PERMISSIONS inside file BackgroundGeolocationFacade.java

public static final String[] PERMISSIONS = {
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_BACKGROUND_LOCATION
        
};

Also see Android docs. "If your app targets Android 10 or higher, you must declare the ACCESS_BACKGROUND_LOCATION permission ...".

Steps to Reproduce

Use plugin with Android API level 29 and check location access dialog.

speckro avatar Apr 08 '20 09:04 speckro

Yes, that appears to be the fix. See:

https://stackoverflow.com/questions/61909313/allow-all-the-time-location-prompt-not-coming-in-android-sdk-29

spinninghamster avatar Jun 19 '20 02:06 spinninghamster

The possible correction of speckro in combination with the comment of spinninghamster solved the problem for us. However, it only worked for Android 10. Android <= 9 also requested permission, but can no longer start the background process. EDIT: After applying the fix of speckro the backgroundgeolocation plugin throws following after giving permissions on Android 9: I/com.marianhello.bgloc.BackgroundGeolocationFacade: User denied requested permissions I think the plugin now checks for the ACCESS_BACKGROUND_LOCATION although it is not present on Android 9.

DominikMair avatar Jun 21 '20 08:06 DominikMair

The possible correction of speckro in combination with the comment of spinninghamster solved the problem for us. However, it only worked for Android 10. Android <= 9 also requested permission, but can no longer start the background process. EDIT: After applying the fix of speckro the backgroundgeolocation plugin throws following after giving permissions on Android 9: I/com.marianhello.bgloc.BackgroundGeolocationFacade: User denied requested permissions I think the plugin now checks for the ACCESS_BACKGROUND_LOCATION although it is not present on Android 9.

What if you target API level 28 instead of 29?

spinninghamster avatar Jun 21 '20 13:06 spinninghamster

The problem remained the same. However we were able to resolve the issue by adding following lines inside of BackgroundGeolocationFacade.java :

       public static final String[] PERMISSIONS10 = {
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_BACKGROUND_LOCATION
        };
        private String[] PERMISSIONSNEW = PERMISSIONS; 

... and by changing the public void start() function in the same file to :

public void start() {
        if(android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
            PERMISSIONSNEW = PERMISSIONS;
        }else {
            PERMISSIONSNEW = PERMISSIONS10;
        }
            logger.debug("Starting service");
        PermissionManager permissionManager = PermissionManager.getInstance(getContext());
        permissionManager.checkPermissions(Arrays.asList(PERMISSIONSNEW), new PermissionManager.PermissionRequestListener() {
            @Override
            public void onPermissionGranted() {
                logger.info("User granted requested permissions");
                // watch location mode changes
                registerLocationModeChangeReceiver();
                registerServiceBroadcast();
                startBackgroundService();
            }

            @Override
            public void onPermissionDenied() {
                logger.info("User denied requested permissions");
                if (mDelegate != null) {
                    mDelegate.onAuthorizationChanged(BackgroundGeolocationFacade.AUTHORIZATION_DENIED);
                }
            }
        });
    }

We also added following in the AndroidManifest.xml file: <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

DominikMair avatar Jun 21 '20 14:06 DominikMair

Hi guys,

thanks for that fix !

But now I have the notification "Background Tracking ENABLED" which is always there, like https://github.com/mauron85/cordova-plugin-background-geolocation/issues/699

Do you know how to clear it ?

dabaaaz avatar Jul 15 '20 14:07 dabaaaz

Hi Guys,

thanks too. It also fixed it for me.

@dabaaaz If I "swipe" my app (close complete). My notification disappears (if stopOnTerminate: true).

Cheers

CoooWeee avatar Jul 29 '20 22:07 CoooWeee

There's also the service type that this docs describe: https://developer.android.com/training/location/permissions Have any of you implemented the type=location thing?

HarelM avatar Sep 25 '20 17:09 HarelM

@DominikMair do you have a fork with your fix by any chance? Also API level 29 is now required for new apps so this fix is mandatory I guess...

HarelM avatar Sep 25 '20 20:09 HarelM

Sent a PR, I hope it will be merged... https://github.com/mauron85/background-geolocation-android/pull/58

HarelM avatar Oct 01 '20 19:10 HarelM

@DominikMair thanks for your fix. Work as I expected

OstapBO avatar Oct 12 '20 11:10 OstapBO

@OstapBO @DominikMair does this code still working fine ? I mean, does the app a wake up when the user is walking/driving ?!

dabaaaz avatar Oct 19 '20 12:10 dabaaaz

After deeply looking into this subject and looking for info I found this great lecture: https://www.youtube.com/watch?v=L7zwfTwrDEs&feature=youtu.be I'm using the plugin in service foreground mode so I basically don't really need the allow all the time. Having said that, I probably need the location type to one of the services. I'm guessing that this is the relevant service:

<service android:enabled="true" android:exported="false" android:name="com.marianhello.bgloc.service.LocationServiceImpl"/>

I still don't have most of the answers as this still requires testing...

HarelM avatar Oct 29 '20 20:10 HarelM

Reading the plugin info, and Android description for permissions (https://developer.android.com/training/location/permissions?hl=fr) i think no need background persimission. Android said: When de app is in background, but one services is running, and one notification is showing you need Foreground location permissions only...

chacabuk avatar Jan 27 '21 13:01 chacabuk

This is only in the case where you set forgroundService: true in the settings - this way the app is not considered as running in the background per say... The lecture I linked is great in order to understand the differences between background and foreground.

HarelM avatar Jan 27 '21 13:01 HarelM

@chacabuk: You are right. When your app enters the background and you start a foreground service with a notification, your app is considered to be in the foreground and you don't need permission ACCESS_BACKGROUND_LOCATION. An exception is when you use the geofence service. Then you need permission ACCESS_BACKGROUND_LOCATION as noted here.

aggregat-vision avatar Jan 28 '21 08:01 aggregat-vision

@HarelM can you extend your comment? how and where do you set "forgroundService: true"? I'm not using geofence service, but in Android 10 only work if set ACCESS_BACKGROUND_LOCATION permissions...

chacabuk avatar Feb 01 '21 19:02 chacabuk

Part of the configuration API is this flag - where you define the provider, interval, distance etc. Let me know if you can't find it and I'll send you a link to my project...

HarelM avatar Feb 01 '21 20:02 HarelM

@HarelM But there no one property with the name "forgroundService".. Thanks a lot!!

chacabuk avatar Feb 01 '21 21:02 chacabuk

My mistake, the name of the property is: startForeground - set it to true to use foreground service. Read about it in the repo's readme file.

HarelM avatar Feb 01 '21 21:02 HarelM

@HarelM, Thanks for your time. I assumed you speak to another property. I was try this (and a lot of other thiks) and there are no way... On Android 10 only work if set ACCESS_BACKGROUND_LOCATION permission... You can add this permission on config file, or you can omit this and tell each user to allow this manualy.

My source code is realy simple:


import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';

import {
    BackgroundGeolocation,
    BackgroundGeolocationEvents,
    BackgroundGeolocationLocationProvider
} from '@ionic-native/background-geolocation/ngx';

import { HTTP } from '@ionic-native/http/ngx'; // ionic cordova plugin add cordova-plugin-advanced-http


@Component({
    selector: 'app-root',
    templateUrl: 'app.component.html',
    styleUrls: ['app.component.scss']
})
export class AppComponent {

    url = 'https://xxxxxx';
    token = 'xxxxxxxxxx';

    constructor(
        private platform: Platform,
        private http: HTTP,
        private backgroundGeolocation: BackgroundGeolocation,
    ) {
        this.initializeApp();
    }

    initializeApp() {

        this.platform.ready().then(() => {

            this.backgroundGeolocation.configure({
                startForeground: true,
                locationProvider: BackgroundGeolocationLocationProvider.RAW_PROVIDER,
                desiredAccuracy: 10,
                stationaryRadius: 0,
                distanceFilter: 0,
                interval: 60000,
                notificationTitle: 'app Work.',
                notificationText: '',
                debug: false,
                stopOnTerminate: true
            });

            this.backgroundGeolocation.on(BackgroundGeolocationEvents.location).subscribe((location) => {

                this.backgroundGeolocation.startTask().then(taskKey => {

                    this.http.post(this.url, location, { Authorization: this.token }).then(() => {
                        this.backgroundGeolocation.endTask(taskKey);
                    })

                });

            });

        });

    }
}

chacabuk avatar Feb 02 '21 18:02 chacabuk

Two comments:

  1. The plugging already has the ability to send location to the server, no need to re-implement this (I'm not using it, but it's there I believe)
  2. I forked the plugin to add an attribute to the service to mark it as a foreground location service. I forgot I did it and so I don't need the background permission... I'm using my fork which is in my github repos... My bad...

HarelM avatar Feb 02 '21 20:02 HarelM

@HarelM Ohhh!!! I see!. I knew I was not crazy. Ok, you talk about the line 161 in plugin.xml ? https://github.com/mauron85/cordova-plugin-background-geolocation/compare/master...HarelM:master I can modify that file manually, but I use Ionic's Appflow to build and deploy ... so I will use the original one ...

chacabuk avatar Feb 03 '21 13:02 chacabuk

The link doesn't work, but yes: android:foregroundServiceType="location" You can use my fork instead of this repo, I'm not planning on changing it soon and this repo is pretty abandoned so I don't expect it to split much from this code base...

HarelM avatar Feb 03 '21 13:02 HarelM

hello ;it's still not working for me , I have android 10 device system
Someone can help me about the foreground service ( what shall i put ?)

fatima90z avatar Apr 29 '22 15:04 fatima90z