在用户通过弹出窗口提供权限的同一应用程序会话中访问 GPS 坐标

Posted

技术标签:

【中文标题】在用户通过弹出窗口提供权限的同一应用程序会话中访问 GPS 坐标【英文标题】:Accessing GPS coordinates in same application session in which permission was provided by the user via popup window 【发布时间】:2021-08-01 07:22:35 【问题描述】:

我希望在设备上首次启动应用程序的用户能够在该会话中访问 GPS 数据。目前,用户必须在提供位置权限后关闭应用程序,然后重新启动应用程序才能在应用程序中显示位置数据。 我尝试了多种方法来解决这个问题。最近,我将 requestPermission 移到了 Fragment1,这也是 locationManager 所在的位置。

public class Fragment1 extends Fragment 
public static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    View v = inflater.inflate(R.layout.data_capture, container, false);
    requestPermission(v);
    permissionAssessment(v);
...
return (v);



public void requestPermission(View v) //This works, only poulates after restart...
    int permissionCheck = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION);

    if (permissionCheck != PackageManager.PERMISSION_GRANTED) 
        ActivityCompat.requestPermissions(getActivity(), new String[]Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_FINE_LOCATION);
        //conditional here so that if conditionals granted do below, if refused, go away...
    else
        mGpsLocationListener = new GpsLocationListener();
        lm = (LocationManager) getActivity().getSystemService(getActivity().LOCATION_SERVICE);
        mGpsStatus = lm.getGpsStatus(mGpsStatus);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, mGpsLocationListener);
    
   

此外,我采用了穴居人方法,并创建了“permissionAssessment()”,它将在 requestPermission() 之后立即运行,假设可能由于用户可能在 requestPermission() 中授予了权限,我可以运行 checkSelfPermission 并强制定位服务以这种方式启动。没有雪茄。见下文。

  public void permissionAssessment(View v)
    int permissionCheck = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION);
    if (permissionCheck == PackageManager.PERMISSION_GRANTED) 
        mGpsLocationListener = new GpsLocationListener();
        lm = (LocationManager) getActivity().getSystemService(getActivity().LOCATION_SERVICE);
        mGpsStatus = lm.getGpsStatus(mGpsStatus);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, mGpsLocationListener);
    

请注意,如果设备已授予 ACCESS_FINE_LOCATION 权限,则 permissionAssessment() 可以正常工作。当使用 requestPermission() 新安装的权限并且设备上没有预先存在的权限时,它只是无法正常工作。

此外,仅供参考,此应用程序在与 Fragment1 关联的选项卡上启动,并不断更新显示的 gps 卫星时间。在用户授予位置权限的会话之后重新启动应用程序后,卫星/GPS 数据显示良好。我强烈希望 GPS 在用户设置权限的会话中“上线”。建设性的建议将不胜感激。提前致谢。

更新,2021 年 5 月 14 日:这就是最终为我工作的原因,

public class MainActivity extends AppCompatActivity 
...
private boolean requestPermissions() 
    int iExtStorage = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    int iCoarseLocation = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION);
    int iFineLocation = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION);
    List<String> listPermissionsNeeded = new ArrayList<>();

   if (iExtStorage != PackageManager.PERMISSION_GRANTED) 
        listPermissionsNeeded.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    
    if (iFineLocation != PackageManager.PERMISSION_GRANTED) 
        listPermissionsNeeded.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
    
    if (iCoarseLocation != PackageManager.PERMISSION_GRANTED) 
        listPermissionsNeeded.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
    
    if (!listPermissionsNeeded.isEmpty())
    
       ActivityCompat.requestPermissions(this,listPermissionsNeeded.toArray
                (new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
        return false;
    
    getLocation();
    return true;
 

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
    switch (requestCode) 
        case REQUEST_ID_MULTIPLE_PERMISSIONS: 
             if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) 

                // permission was granted, yay! Do the
                // location-related task you need to do.
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) 
                    getLocation();
                
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        == PackageManager.PERMISSION_GRANTED) 
                
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        != PackageManager.PERMISSION_GRANTED) 
                
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) 
                
            
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            return;
        
    
  
...

更新 #2,2021 年 5 月 14 日:根据 Sasaki 的附加评论。这是来自片段。

public class dataCapture extends Fragment 
...
private boolean requestPermission(View v) 
    int iExtStorage = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    int iCoarseLocation = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_COARSE_LOCATION);
    int iFineLocation = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION);
    List<String> listPermissionsNeeded = new ArrayList<>();

    if (iExtStorage != PackageManager.PERMISSION_GRANTED) 
        listPermissionsNeeded.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
    
    if (iFineLocation != PackageManager.PERMISSION_GRANTED) 
        listPermissionsNeeded.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
    
    if (iCoarseLocation != PackageManager.PERMISSION_GRANTED) 
        listPermissionsNeeded.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
    
    if (!listPermissionsNeeded.isEmpty())
    
        requestPermissions(listPermissionsNeeded.toArray
                (new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
        return false;
    
    getLocation();
    return true;


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) 
        case REQUEST_ID_MULTIPLE_PERMISSIONS: 
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) 
                if (ContextCompat.checkSelfPermission(getActivity(),
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) 
                    getLocation();
                
                if (ContextCompat.checkSelfPermission(getActivity(),
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        == PackageManager.PERMISSION_GRANTED) 
                
                if (ContextCompat.checkSelfPermission(getActivity(),
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        != PackageManager.PERMISSION_GRANTED) 
                
                if (ContextCompat.checkSelfPermission(getActivity(),
                        Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) 
                
            
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            return;
        
    
  
...

【问题讨论】:

“目前,用户必须关闭然后重新启动应用程序,然后才能访问 GPS 硬件并在应用程序中显示位置数据” - 不正常。我的猜测是您在获得许可之前尝试使用Fragment1。在获得许可之前,您需要推迟尝试做需要许可的事情。 【参考方案1】:

此外,我采用了穴居人方法,并创建了“permissionAssessment()”,它将在 requestPermission() 之后立即运行,假设可能是因为用户可能在 requestPermission() 中授予了权限。

当权限由用户授予时,此方法将不起作用。 这是因为向用户显示了使用ActivityCompat.requestPermissions(...) 请求权限的提示。 实际授予/拒绝权限将在用户与提示交互时在稍后阶段完成。

这意味着在ActivityCompat.requestPermission(...)之后立即运行的函数permissionAssessment(...)将没有权限,因此第一次不会成功运行,需要Fragment“重新加载”。

为确保成功运行,您必须在ActivityCompat.requestPermission(...) 的“成功”回调中调用permissionAssessment(...)。这是使用函数onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 完成的。

这是我的实现:-

public class Fragment1 extends Fragment 
public static final int REQUEST_FINE_LOCATION_CODE = 1;
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    View v = inflater.inflate(R.layout.data_capture, container, false);

    permissionAssessment(v);

...
return (v);



public void permissionAssessment(View v)
    int permissionCheck = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION);

    if (permissionCheck == PackageManager.PERMISSION_GRANTED) 
        // Permission is granted, proceed to get location.
        getLocation()
     else 
        // Permission is not granted, request permissions.
        // Only the prompt is shown here, nothing else will happen.
        ActivityCompat.requestPermissions(getActivity(), new String[]Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_FINE_LOCATION_CODE);
    

    
/**
 * This Function is responsible for handling what happens when permissions are granted by the user.
 */
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
    
    if (requestCode == REQUEST_FINE_LOCATION_CODE) 

        if (grantResults.length > 0) 
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) 
                
                // Permissions Granted!
                // Get Location as soon as the permissions are granted.
                getLocation();
            
         else 
                
            // Permission Denied by the user
            // Show a prompt or do nothing as per your use case.
        
    

    super.onRequestPermissionsResult(requestCode, permissions, grantResults);



public void getLocation() 
    mGpsLocationListener = new GpsLocationListener();
    lm = (LocationManager) getActivity().getSystemService(getActivity().LOCATION_SERVICE);
    mGpsStatus = lm.getGpsStatus(mGpsStatus);
    lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, mGpsLocationListener);

请参考这里

https://developer.android.com/guide/topics/permissions/overview 和 https://developer.android.com/training/permissions/requesting

【讨论】:

感谢您发布建议的解决方案以及解释。但是,onRequestPermissionsResult 可能不会像预期的那样参与。在弹出框中接受许可后,gps 不会立即激活,直到应用程序重新启动后才会激活。我确实在 getLocation() 上方的 onRequestPermissions,(oRP) 中插入了一条诊断 Toast 消息,但是它没有显示。因此,我的结论是 oRP 可能没有运行。再次感谢。 将位置管理器从片段移动到 MainActivity 解决了 onRequestPermissionsResult 的问题。 啊!那是我的错。 oRP 不是在片段中而是在活动中接收结果。这是因为我们应该使用requestPermissions 而不是ActivityCompat.requestPermissions。更多详情请参考这里 - ***.com/questions/35989288/…。

以上是关于在用户通过弹出窗口提供权限的同一应用程序会话中访问 GPS 坐标的主要内容,如果未能解决你的问题,请参考以下文章

文件共享后没有访问权限是怎么回事?

如何让地址簿权限弹出窗口显示在顶部?

在Git Bash中重新键入用户名和密码以获取Github访问权限

Spotify SDK 缺少令牌刷新服务?

应用程序跟踪透明度弹出窗口是不是会在 webview 中授予第三方 cookie 访问权限?

USB设备访问弹出抑制?