如何在android 10或更高版本中获得“总是”位置的许可? (高于 API 29)?

Posted

技术标签:

【中文标题】如何在android 10或更高版本中获得“总是”位置的许可? (高于 API 29)?【英文标题】:How to get "always" permission of location for flutter in android 10 or above? (above API 29)? 【发布时间】:2021-08-30 23:39:44 【问题描述】:

我正在为我的一个颤振项目使用 Geolocator 包,我想在周期性的时间周期中获取我的当前位置。 为了获得许可,我编辑了 androidManifest.xml 并添加了这些行:

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

一切正常,但是当我在一部 android 10 手机中使用 apk 时,一切都变糟了! 首先,每当我第一次使用应用程序检查权限状态时

 await Geolocator.checkPermission();

它在android 9中返回.denied,在android 10中返回.deniedForever,当检查权限时,会弹出android权限寻求弹出窗口,在android 9或以下版本中,允许按钮将权限设置为.always但在 android 10 中,设置为.whileInUse,我在设置中找不到任何选项以手动将其设置为.always。 经过一番研究,我了解到,我必须添加

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

我添加了它们,但 android 10 仍然不像 android 9,应用管理器中的“始终”选项仍然缺失! 我遇到的主要问题是,每当我离开屏幕时,Geolocator.getCurrentPosition() 就会停止工作,但相同的代码在 android 9 中运行良好。

模拟 -

class _MyHomePageState extends State<MyHomePage> 
  List _loc = [];
  bool _isSwitchon = false;
  int _sec = 0;
  String _permissonStatus = "";

  Future _incrementCounter() async 
    Timer.periodic(Duration(seconds: 1), (timer) async 
      setState(() 
        _sec++;
      );
      if (_isSwitchon == false) 
        timer.cancel();
        setState(() );
       else if (_isSwitchon == true) 
        Position currentPosition = await Geolocator.getCurrentPosition();
        setState(() 
          _loc.add(currentPosition.toString());
        );
      
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text("Time Elapsed"),
            Text(_sec.toString() + "  sec"),
            Text(
              'current Location',
            ),
            Container(
              height: 300,
              child: ListView.builder(
                itemCount: _loc.length,
                itemBuilder: (BuildContext context, int i) 
                  return Text(
                    _loc[i],
                  );
                ,
              ),
            ),
            Row(
              children: [
                Expanded(
                  child: Container(),
                ),
                Column(
                  children: [
                    FloatingActionButton(
                      onPressed: () 
                        setState(() 
                          _isSwitchon = true;
                        );
                        _incrementCounter();
                      ,
                      child: Icon(Icons.play_arrow),
                    ),
                    Text("Start")
                  ],
                ),
                SizedBox(
                  width: 50,
                ),
                Column(
                  children: [
                    FloatingActionButton(
                      onPressed: () 
                        setState(() 
                          _isSwitchon = false;
                        );
                      ,
                      child: Icon(Icons.cancel),
                    ),
                    Text("Stop")
                  ],
                ),
                Expanded(
                  child: Container(),
                )
              ],
            ),
            Text(_permissonStatus),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Column(
                  children: [
                    FloatingActionButton(
                      onPressed: () async 
                        await Geolocator.checkPermission().then((value) =>
                            setState(
                                () => _permissonStatus = value.toString()));
                      ,
                      child: Icon(Icons
                          .signal_wifi_statusbar_connected_no_internet_4_sharp),
                    ),
                    Text("status")
                  ],
                ),
                Column(
                  children: [
                    FloatingActionButton(
                      onPressed: () 
                        setState(() 
                          _loc = [];
                        );
                      ,
                      tooltip: 'Increment',
                      child: Icon(Icons.add),
                    ),
                    Text("clear Location")
                  ],
                ),
                Column(
                  children: [
                    FloatingActionButton(
                      onPressed: () async 
                        await Geolocator.requestPermission();
                      ,
                      tooltip: 'Increment',
                      child: Icon(Icons.gps_fixed),
                    ),
                    Text("Permission Seeking")
                  ],
                ),
              ],
            )
          ],
        ),
      ),
    );
  

清单中的场景 -

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.gps_test">
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/> 
   <application

   

【问题讨论】:

【参考方案1】:

你说的是android 10,我不明白为什么没有右键,但为了将来证明这个方法已经过时了。

Android docs:

但是,在 Android 11(API 级别 30)及更高版本上,系统对话框 不包括“始终允许”选项。相反,用户必须 在设置页面上启用背景位置,[...]。

您应该能够通过.openLocationSettings().openAppSettings() 使用此package 打开权限设置,然后用户必须导航到权限。

【讨论】:

以上是关于如何在android 10或更高版本中获得“总是”位置的许可? (高于 API 29)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 api 17 或更高版本中使 android seekbar 全宽?

如何在 Android M 或更高版本中在运行时更改权限时防止重新创建 Activity

如何在 Android SDK 26 或更高版本上以编程方式重置锁屏密码

不再支持源选项 5。使用 6 或更高版本的 Android Studio

如何查看我的 Xamarin.Forms 应用程序是不是在 Visual Studio 中的 Android 6(或更高版本)上运行或/和可运行?

在 Android 4.0 或更高版本中禁用主页按钮 [重复]