【问题标题】:getLastKnownLocation in a background service permission后台服务权限中的 getLastKnownLocation
【发布时间】:2017-05-07 15:23:14
【问题描述】:

我正在尝试恢复设备在由AlarmManager 触发的BroadcastReceiver 启动的服务中的最后一个已知位置,但我在权限管理系统上遇到了问题,因为即使我要求在 UI 中动态许可,我不断收到日志消息 "Notification not allowed"。

AlarmManager/BroadcastReceiver 组合的目标是定期调用由用户位置确定的 REST API。

服务代码

服务的onHandleIntent 方法由WakefulBroadcastReceiver 和startWakefulService 调用

@Override
protected void onHandleIntent(Intent intent) {
    if (BuildConfig.DEBUG) Log.d(TAG, "Handling intent");

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.cancelAll();

    LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_COARSE);
    criteria.setPowerRequirement(Criteria.POWER_LOW);
    criteria.setAltitudeRequired(false);
    criteria.setBearingRequired(false);
    criteria.setSpeedRequired(false);
    criteria.setCostAllowed(true);

    String provider = locationManager.getBestProvider(criteria, true);
    boolean localizationPermitted = ContextCompact.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED;

    if (localizationPermitted) {
        Location lastLocation = locationManager.getLastKnownLocation(provider);
        if (BuildConfig.DEBUG) Log.d(TAG, "Location: " +lastLocation.toString() );

        // stuff that needs the location

    } else {
        if (BuildConfig.DEBUG) Log.e(TAG, "Localization not allowed");
    }
}

清单权限

我已经在AndroidMainfest.xml 文件中声明了权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...">
    ...
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    ...
</manifest>

动态权限

在启动触发服务的警报之前,我在应用程序的Fragment 内请求许可:

boolean gotPermission = ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION)
        == PackageManager.PERMISSION_GRANTED;


if (gotPermission){
    if (BuildConfig.DEBUG) Log.v(TAG, "Got the permission");
    // Schedule the alarm
} else {
    ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}

在对话框的回调中我得到了"Permission granted":

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (permissions.length == 1 &&
            permissions[0].equals(android.Manifest.permission.ACCESS_COARSE_LOCATION) &&
            grantResults[0] == PackageManager.PERMISSION_GRANTED) {

        if (ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            if (BuildConfig.DEBUG) Log.d(TAG, "Permission granted");
        }
    } else {
        if (BuildConfig.DEBUG) Log.e(TAG, "Permission not granted");
    }
}

【问题讨论】:

  • 你的targetSdkVersion是什么?
  • @CommonsWare targetSdkVersion 25, minSdkVersion 19, compileSdkVersion 25

标签: android service permissions android-6.0-marshmallow


【解决方案1】:
boolean localizationPermitted = ContextCompact.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED;

如果权限未被授予,这将是true (!=)。将其更改为:

boolean localizationPermitted = ContextCompact.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;

(我真的希望他们刚刚使用了来自checkSelfPermission()...的boolean返回值...)

【讨论】:

  • 我的错!但现在的问题是locationManager.getLastKnownLocation(provider) 以java.lang.IllegalArgumentException: invalid provider: null 失败。可能是因为应用程序是在模拟器上运行的?
  • @user2989242:可能。您的低功耗要求将排除 GPS_PROVIDER 作为选项。我很少用模拟器,所以不知道它是否模拟网络提供商。
  • 是的,这是智能手机模拟器的问题,但我注意到ACCURACY_COARSE 的最后一个已知位置始终是null,而ACCURACY_FINE 我得到了正确的位置。
猜你喜欢
  • 2021-06-11
  • 2019-12-14
  • 1970-01-01
  • 1970-01-01
  • 2020-04-13
  • 2019-09-18
  • 2011-06-09
  • 1970-01-01
  • 2018-05-08
相关资源
最近更新 更多