已获得ACCESS_FINE_LOCATION的运行时权限,但仍获得SecurityException

时间:2017-03-14 16:52:07

标签: android

流程是这样的。我获得了Location(FINE和COARSE)的许可。 OnPermissionGrantResult:

public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case LOCATION:
             if(grantResults[0] == 0){
             (new AsyncTask<Void, Void, Void>(){
                 @Override protected Void doInBackground(Void... params){
                       getAndSetLocation();
                  }
              }).execute();
              }
             break;
        }
    }
}

public void getAndSetLocation(){
     startGPSService();
    //GPS Tracker is the GPS Service
    while(GPSTracker.location==null) {
        try {
            synchronized (lock) {
                lock.wait();
            }
        } catch (InterruptedException e) {
            Log.e(TAG, "getLocation: "+e.getLocalizedMessage() );
        }
    }
    location = new Location(GPSTracker.location);
    stopGPSService();
}

GPSTracker服务

  public class GPSTracker extends android.app.Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener {
    private LocationRequest mLocationRequest;
    private GoogleApiClient mGoogleApiClient;
    private static final String TAG = GPSTracker.class.getSimpleName();
    public static Location location;
    @Override
    public void onCreate() {
        super.onCreate();
        buildGoogleApiClient();
        Log.i(TAG, "onCreate");
     }

     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand");

         if (!mGoogleApiClient.isConnected())
              mGoogleApiClient.connect();
         return START_STICKY;
     }


     @Override
     public void onConnected(Bundle bundle) {
     Log.i(TAG, "onConnected" + bundle);
    Location l;
    try {
        l = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    }catch (SecurityException e){ //Error here
        l = null;
    }
    if (l != null) {
        Log.i(TAG, "lat " + l.getLatitude());
        Log.i(TAG, "lng " + l.getLongitude());
        location = l;
        synchronized (lock) {
            lock.notify();
        }
    }

    startLocationUpdate();
}

@Override
public void onConnectionSuspended(int i) {
    Log.i(TAG, "onConnectionSuspended " + i);

}

@Override
public void onLocationChanged(Location location) {
    Log.i(TAG, "lat " + location.getLatitude());
    Log.i(TAG, "lng " + location.getLongitude());
    GPSTracker.location = location;
    lock.notify();
}

@Override
public void onDestroy() {
    super.onDestroy();
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    Log.i(TAG, "onConnectionFailed ");

}

private void initLocationRequest() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(5000);
    mLocationRequest.setFastestInterval(2000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

}

private void startLocationUpdate() {
    initLocationRequest();

    try {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }catch (SecurityException e){
        Log.e(TAG, "startLocationUpdate: ", e);
    }
}

private void stopLocationUpdate() {
    LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}

protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addOnConnectionFailedListener(this)
            .addConnectionCallbacks(this)
            .addApi(LocationServices.API)
            .build();
}

}

即使已收到权限,也会在onConnected上抛出错误。是因为服务仍然不知道收到的权限,还是它的执行方式?或者是异步任务,问题是什么?它从第二次开始工作正常,但第一次,它总是抛出一个安全例外。

异常追踪:

 java.lang.SecurityException: Client must have ACCESS_FINE_LOCATION permission to request PRIORITY_HIGH_ACCURACY locations.

请求许可的代码:

public static boolean checkForPermissions(Activity context, String[] permissions, final int requestCode) {
    if (permissions == null) return true;

    boolean resultFlag = true;
    final List<String> requiredPermissions = new ArrayList<>();
    if (Build.VERSION.SDK_INT >= 23){
        for (String permission : permissions) {
            if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
                requiredPermissions.add(permission);
                resultFlag = false;
            }
        }
    }

    // Request all permissions at once..
    if(requiredPermissions.size()!=0) {
        requestPermissions(context, requiredPermissions.toArray(new String[0]), requestCode);
    }

    return resultFlag;
}

checkForPermissions(mContext, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION);

3 个答案:

答案 0 :(得分:0)

我认为你也需要ACCESS_COARSE_LOCATION。

reference

答案 1 :(得分:0)

从位置缓存中检索最后一个位置,现在如果您是第一次启动应用程序,则可能没有保存任何最后位置。在这种情况下这一行

l = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

返回null。现在这只是第一次发生,因为之后你的应用开始请求更新,最后一个位置不再为空。

答案 2 :(得分:0)

您忘记了GoogleApiClient

中的GPSTracker
protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
        .addOnConnectionFailedListener(this)
        .addConnectionCallbacks(this)
        .addApi(LocationServices.API)
        .build();
    mGoogleApiClient.connect();
}

这样做。