java - 当应用程序移至后台时,在前台服务中获取位置更新不起作用

标签 java android service notifications background

我正在使用下面的应用程序代码每 5 秒从 GPS 接收位置更新,并将输出打印到日志中。只要应用程序处于前台,这对我来说就很好,但是当它移动到后台时更新会停止,直到它被带回前台。我正在使用galaxy s20(android 10)来运行和调试,并且应用程序设置为永不 hibernate (android设置)。这是完整的过程描述:
我在 list 上有这些权限:

<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 并创建服务的主要 Activity :
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
但是在这最后一条消息之后 - 在我将应用程序带回前台之前不再进行更新。我希望它一直保持运行 - 为此还需要做什么?

最佳答案

根据官方文档:

When a feature in your app requests background location on a device that runs Android 10 (API level 29), the system permissions dialog includes an option named Allow all the time. If the user selects this option, the feature in your app gains background location access.

On Android 11 (API level 30) and higher, however, the system dialog doesn't include the Allow all the time option. Instead, users must enable background location on a settings page, as shown in figure 3.


所以你需要看到这个名为的选项一直允许在应用程序的设置页面中
enter image description here
为此,您必须在 list 中拥有此权限:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
在 API 30 及以下设备上,一直允许选项将在对话框中可见,您必须添加 "Manifest.permission.ACCESS_BACKGROUND_LOCATION"当您要求用户授予他们权限时。如下
ActivityCompat.requestPermissions(MainActivity.this,
                new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION ,Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION},
                1);
如您所见,对话框中有 一直允许
enter image description here
但在 Android Api 30 及更高版本上,您必须邀请用户检查此选项 手动 针对 API < 30
所以如果你想加载设置页面,你可以使用这个方法:
   // 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);
    }
最后,如果您检查 一直允许选项您的应用程序将能够在后台监听位置变化
更新 :
对于 Android 30 及更高版本,您可以通过直接使用以下代码行打开位置权限页面来要求用户保证后台位置:
requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, REQUEST_CODE);
如需更多信息,请参阅 Request background location

关于java - 当应用程序移至后台时,在前台服务中获取位置更新不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67039618/

相关文章:

java - OnPostExecute 永远不会被调用

android - 使用 Intent 从 Google Drive 获取文件

web-services - 有没有办法检测从哪个源调用 API?

android - 如果用户从设置中停止(终止)它,我如何重新启动我的应用程序服务?

java - 为什么不能在接口(interface)类型上引用类的方法

Java 6 更新 25 虚拟机崩溃 : insufficient memory

java - 通过二叉搜索树中单词计数的降序打印单词计数器

java - 使用 else if 语句设置 imageview 的背景

angular - 如何在 Angular 5 中进行同步调用?

android - 为什么我的自定义主题不影响我的自定义列表项布局的 TextView ?