我正在使用下面的应用程序代码每 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.
所以你需要看到这个名为的选项一直允许在应用程序的设置页面中
为此,您必须在 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);
如您所见,对话框中有 一直允许但在 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/