【发布时间】:2018-02-01 11:04:16
【问题描述】:
我有一个在后台持续运行以获取位置更新的服务类。一切都按预期工作,但是当我从设置中禁用权限时,应用程序崩溃。当我从设置中禁用位置权限时,我无法弄清楚为什么应用程序崩溃了。以下是我在 logcat 中得到的内容。
FATAL EXCEPTION: GoogleApiHandler
Process: com.android.myapp, PID: 7703
java.lang.SecurityException: Client must have ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to perform any location operations.
at android.os.Parcel.readException(Parcel.java:1683)
at android.os.Parcel.readException(Parcel.java:1636)
at com.google.android.gms.internal.zzeu.zza(Unknown Source)
at com.google.android.gms.internal.zzcfa.zzif(Unknown Source)
at com.google.android.gms.internal.zzcfd.getLastLocation(Unknown Source)
at com.google.android.gms.internal.zzcfk.getLastLocation(Unknown Source)
at com.google.android.gms.location.zzg.zza(Unknown Source)
at com.google.android.gms.common.api.internal.zze.zza(Unknown Source)
at com.google.android.gms.common.api.internal.zzbo.zzb(Unknown Source)
at com.google.android.gms.common.api.internal.zzbo.zzaiw(Unknown Source)
at com.google.android.gms.common.api.internal.zzbo.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzac.onConnected(Unknown Source)
at com.google.android.gms.common.internal.zzn.zzakr(Unknown Source)
at com.google.android.gms.common.internal.zze.zzw(Unknown Source)
at com.google.android.gms.common.internal.zzi.zzaks(Unknown Source)
at com.google.android.gms.common.internal.zzh.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.os.HandlerThread.run(HandlerThread.java:61)
这是我的服务类。这始终在后台运行。
public class LocationService extends Service {
...
...
...
@Override
public void onCreate() {
try {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
onNewLocation(locationResult.getLastLocation());
}
};
createLocationRequest();
getLastLocation();
requestLocationUpdates();
}catch(Exception e){
e.printStackTrace();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service started");
return START_STICKY;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Log.i(TAG, "Service destroy");
Toast.makeText(getApplicationContext(), "Service Destroy", Toast.LENGTH_SHORT).show();
}
/**
* Makes a request for location updates. Note that in this sample we merely log the
* {@link SecurityException}.
*/
public void requestLocationUpdates() {
Log.i(TAG, "Requesting location updates");
Utils.setRequestingLocationUpdates(this, true);
try {
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, Looper.myLooper());
} catch (SecurityException unlikely) {
Utils.setRequestingLocationUpdates(this, false);
Log.e(TAG, "Lost location permission. Could not request updates. " + unlikely);
}
}
/**
* Removes location updates. Note that in this sample we merely log the
* {@link SecurityException}.
*/
public void removeLocationUpdates() {
Log.i(TAG, "Removing location updates");
try {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
Utils.setRequestingLocationUpdates(this, false);
stopSelf();
} catch (SecurityException unlikely) {
Utils.setRequestingLocationUpdates(this, true);
Log.e(TAG, "Lost location permission. Could not remove updates. " + unlikely);
}
}
private void getLastLocation() {
try {
mFusedLocationClient.getLastLocation()
.addOnCompleteListener(task -> {
if (task.isSuccessful() && task.getResult() != null) {
mLocation = task.getResult();
} else {
Log.w(TAG, "Failed to get location.");
}
});
} catch (SecurityException unlikely) {
Log.e(TAG, "Lost location permission." + unlikely);
}
}
private void onNewLocation(Location location) {
Log.i(TAG, "New location: " + location);
mLocation = location;
// Doing some operations using location data.
mPreviousLocation = mLocation;
System.gc();
}
/**
* Sets the location request parameters.
*/
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest
.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
@Override
public void onTaskRemoved(Intent rootIntent) {
Log.i(TAG, "Service Task Removed");
Toast.makeText(getApplicationContext(), "Service Task Removed", Toast.LENGTH_SHORT).show();
startService(new Intent(getApplicationContext(), LocationService.class));
super.onTaskRemoved(rootIntent);
}
}
我正在我的活动类中检查位置权限,并在用户接受权限后启动服务。这没有问题,我什至可以从后台服务获取位置更新。同时,当我尝试从设置中禁用权限时,应用程序崩溃。这是我正在检查位置权限的 MainActivity 类。
public class MainActivity extends AppCompatActivity{
@Override
protected void onResume() {
super.onResume();
checkAndEnableGps();
}
private void checkAndEnableGps() {
try {
new RxPermissions(this)
.request(Manifest.permission.ACCESS_FINE_LOCATION)
.subscribe(granted -> {
if (granted) {
if (!Utils.isServiceRunning(this, LocationService.class)) {
startService(new Intent(this, LocationService.class));
}
showSettingDialog();
}
});
}catch (Exception e){
e.printStackTrace();
}
}
}
【问题讨论】:
-
运行时在哪里查看位置权限?
-
在启动定位服务之前,您应该检查您是否有定位权限
-
权限检查未完成
-
在声明后台服务之前,我正在我的主要活动类中检查位置权限。
标签: android geolocation location android-permissions