当应用程序移至后台时,无法在前台服务中获取位置更新

立然

我正在使用以下应用程序代码每 5 秒从 GPS 接收一次位置更新并将输出打印到日志中。只要应用程序在前台,这对我来说就很好,但是当它移到后台时更新会停止,直到它被带回前台。我正在使用 Galaxy s20 (android 10) 来运行和调试,并且应用程序设置为永远不会进入睡眠状态(android 设置)。这是完整的过程描述:

我在清单中有这些权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.android.hardware.location.gps"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

这是启用 GPS 并创建服务的主要活动:

public class MainActivity extends AppCompatActivity {

    private LocationManager _locManager;
    private Intent _scanServiceIntent;

    public void onStart()
    {
        super.onStart();
        boolean gps_enabled = _locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        if (gps_enabled)
        {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.INTERNET}, 1);
            _scanServiceIntent = new Intent(this, ScanService.class);
            startService(_scanServiceIntent);
        }       
    }
}

这是服务类 - 我正在创建一个通知,以使服务一直运行 - 即使应用程序进入后台:

public class ScanService extends Service {

    private LocationListener _locListener;
    private LocationManager _locManager;


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        String NOTIFICATION_CHANNEL_ID = "com.tandenkore.mychannel";

        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,0);

        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
        Notification notification = notificationBuilder.setOngoing(true)
                .setContentTitle("App is running in background")
                .setPriority(NotificationManager.IMPORTANCE_MAX)
                .setCategory(Notification.CATEGORY_SERVICE)
                .setContentIntent(pendingIntent)
                .build();
        startForeground(300, notification);
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        _locListener = new MyLocationListener();
        _locManager = (LocationManager)getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        _locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, _locListener);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopForeground(true);
        _locManager.removeUpdates(_locListener);
    }

    class MyLocationListener implements LocationListener {
        @Override
        public void onLocationChanged(Location location)
        {
            Log.v(TAG, "location changes");
        }
    }
}

当我在设备上调试它并且应用程序在前台时,我每 5 秒在“位置更改”行的 logcat 中得到一个输出。这是我正在寻找的行为。当应用程序进入后台时会出现问题,然后我在 logcat 中收到以下信息:

2021-04-11 00:00:26.648 26160-26160/com.tandenkore.application V/application: location changes
2021-04-11 00:00:31.657 26160-26160/com.tandenkore.application V/application: location changes
2021-04-11 00:00:36.656 26160-26160/com.tandenkore.application V/application: location changes
2021-04-11 00:00:41.656 26160-26160/com.tandenkore.application V/application: location changes
2021-04-11 00:00:46.653 26160-26160/com.tandenkore.application V/application: location changes
2021-04-11 00:00:50.170 7241-7307/? E/RequestManager_FLP: [LocationManager] Paused by AppOps 7e14624(Listener) gps interval=5000 from com.tandenkore.application (10367)
2021-04-11 00:00:50.173 7241-7307/? I/RequestManager_FLP: onOpChanged, op=0 / packageName=com.tandenkore.application
2021-04-11 00:00:50.174 7241-7307/? I/PackageInfoManager_FLP: checkLocationAccess for com.tandenkore.application[gps,5000,100], result is false

但在最后一条消息之后 - 在我将应用程序带回前台之前不会再有更新。我希望它一直运行 - 为此还需要做些什么?

谢金

根据官方文档:

当您的应用中的某项功能在运行 Android 10(API 级别 29)的设备上请求后台位置时,系统权限对话框会包含一个名为“始终允许”的选项。如果用户选择此选项,您应用中的功能将获得后台位置访问权限。

但是,在 Android 11(API 级别 30)及更高版本上,系统对话框不包含始终允许选项。相反,用户必须在设置页面上启用后台位置,如图 3 所示。

所以你需要在你的应用程序的设置页面中看到这个名为Allow all the time 的选项

在此处输入图片说明

为此,您必须在清单中拥有此权限:

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

On API 30 devices, and below so that the Allow All the time option will be visible in the Dialog you must Add the "Manifest.permission.ACCESS_BACKGROUND_LOCATION" when you ask the user to grant them permission. as below

ActivityCompat.requestPermissions(MainActivity.this,
                new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION ,Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION},
                1);

as you see the dialog has the Allow all the time

在此处输入图片说明

But on the Android Api 30 and higher you must invite the user to check this option manually against the API < 30

So if you want to load the Setings page you can use this method :

   // load the permission setting screen
    private void loadPermissionPage(Activity context) {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", context.getPackageName(), null);
        intent.setData(uri);
        context.startActivityForResult(intent, 0);
    }

And finally if you check the Allow all the time option your application will be able to listen to the location changes in the background

UPDATE :

For Android 30 and higher you can ask the user to garant the Background Location by opening the location permission pages directly using this line of code :

requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, REQUEST_CODE);

有关更多信息,请参阅请求后台位置

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

当应用程序处于后台而没有前台服务时,如何检测蓝牙变化(连接状态和特征)

在奥利奥(8.0.0+)(API 26+)中,当应用程序在后台运行或终止时如何获取位置服务更新

当应用程序从后台返回前台时的密码视图

当应用程序进入后台时,Android 11(API级别30)onTaskRemoved在前景服务中触发

当应用程序使用applicationDidEnterBackground在iOS 7中进入后台时,无法更新视图:

当应用程序在前台时,通过推送通知更新选项卡栏标志计数

当应用程序在后台时如何显示来自后台服务的警报消息弹出窗口

应用程序在前台时如何更新UI?

无法在后台使用应用程序保持GPS处于活动状态,或者在前台或后台使用应用程序无法读取位置

如何从服务中检查应用程序在前台?

仅当应用程序在前台时,Flutter,Firebase iOS,云消息才会显示

当应用程序在前台时,Android GCM 消息不调用 onMessageReceived

当应用程序在前台时,iOS Swift会收到推送通知

为什么当应用程序在前台时,scenePhase 的值是 .background?

应用程序在后台时获取位置更新

当应用程序进入后台时停止MediaPlayer服务

当应用程序在后台时停止服务

当应用程序在本机后台运行时如何更新服务中的纬度和经度

运行前台服务时如何检测当前的前台应用程序

当应用程序从后台到前台显示活动时出现问题

当应用程序进入前台或后台时,不会调用AppLifcycleState.didChangeLifecycleState()函数

当应用程序从后台进入前台时如何调用方法

快速检测应用程序是在后台还是在前台

当本机应用程序在前台时以及应用程序在后台时,如何在本机反应中实现超时?

应用程序在前台时收到的推送通知与应用程序在后台时收到的推送通知不同

在android中更新应用程序后,后台服务会怎样?

当应用程序在前台时收到推送通知时,是否可以为 ios 显示横幅?

当应用程序在后台Swift中时,PerformBackgroundTask无法保存

当应用程序在iOS中处于后台模式时,无法接收GCM通知