我正在使用以下应用程序代码每 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
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] 删除。
我来说两句