首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将应用程序移到后台时,前台服务中的位置更新无法工作

将应用程序移到后台时,前台服务中的位置更新无法工作
EN

Stack Overflow用户
提问于 2021-04-10 21:55:40
回答 2查看 3.3K关注 0票数 4

我正在使用下面的应用程序代码接收位置更新从GPS每5秒,并打印一个输出到日志。这对我很好,只要应用程序在前台,但更新停止时,它被移动到后台,直到它被带回前台。我使用galaxy s20 (Android10)来运行和调试,应用程序被设置为永不休眠(android设置)。以下是整个过程的描述:

我在舱单上有以下权限:

代码语言:javascript
运行
复制
<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并创建服务的主要活动:

代码语言:javascript
运行
复制
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);
        }       
    }
}

这是服务类--我正在创建一个通知,以便让serice始终运行--即使应用程序转到后台:

代码语言:javascript
运行
复制
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中的以下内容:

代码语言:javascript
运行
复制
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

但在这最后一条消息之后--在我把应用程序带回前台之前,不要再更新了。我想让它一直运行下去--还需要做些什么呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-04-11 11:27:10

根据正式文件:

当应用程序中的某个功能请求运行Android 10 (API级别29)的设备上的背景位置时,系统权限对话框包括一个名为Allow的选项。如果用户选择此选项,则应用程序中的功能将获得后台位置访问。 但是,在Android 11 (API级别30)和更高版本上,系统对话框不包括允许所有时间的选项。相反,用户必须在设置页面上启用后台位置,如图3所示。

因此,您需要看到名为的选项允许始终在应用程序的设置页面中使用

为此,您必须在您的舱单中获得这一许可:

代码语言:javascript
运行
复制
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

在API 30设备上,为了使允许所有时间的选项在对话框中可见,当您请求用户授予它们权限时,您必须添加"Manifest.permission.ACCESS_BACKGROUND_LOCATION"。如下所示

代码语言:javascript
运行
复制
ActivityCompat.requestPermissions(MainActivity.this,
                new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION ,Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION},
                1);

如您所见,对话框允许允许所有时间使用

但是在Android 30和更高版本上,您必须邀请用户手动检查这个选项和Api < 30。

因此,如果您想加载“问候语”页面,可以使用以下方法:

代码语言:javascript
运行
复制
   // 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和更高版本,您可以通过直接使用这一行代码打开位置权限页面来要求用户装饰背景位置:

代码语言:javascript
运行
复制
requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, REQUEST_CODE);

有关更多信息,请参见请求背景位置

票数 6
EN

Stack Overflow用户

发布于 2021-12-23 09:21:04

提到android.foregroundServiceType="location"在AndroidManifest.xml文件中的服务标记中。

例子:

代码语言:javascript
运行
复制
<service
   android:name=".LocationServicePackage.LocationService"
   android:foregroundServiceType="location"
   android:enabled="true"
   android:exported="true" />
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67039618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档