流程是这样的。我获得了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);
答案 0 :(得分:0)
我认为你也需要ACCESS_COARSE_LOCATION。
答案 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();
}
这样做。