2

我有一个应用程序,它可以获取用户的当前位置,然后加载谷歌地图并在他们的区域绘制感兴趣的标记。它在 Marshmallow 下面的所有东西上都能完美运行。我已经添加了运行时权限检查,并且在我收到提示时正在设置它们,在我点击接受后,我会从手机的设置中看到应用程序详细信息中列出的权限。但是,我一生都无法弄清楚为什么我没有位置回来。

我正在使用这里看到的示例https://developer.android.com/training/location/retrieve-current.html

我在清单中使用标签设置了所有权限。我什至让我的 Fragment 实现了 LocationListener。但是,永远不会调用 onLocationChanged 方法。我在 Google API 客户端的 onConnected 方法中调用它,如下所示。

@Override
    public void onConnected(@Nullable Bundle bundle) {
        try {
            Log.d("MYAPPTAG","isConnected: " + mGoogleApiClient.isConnected());
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            myLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        } catch (SecurityException ex) {
            myLocation = null;
        }
    }

确实调用了 onConnected 方法,因为我将日志记录到控制台。myLocation 始终为空。每次我调用 getLastLocation 时,我都会在控制台中收到一条消息,上面写着

No Location to return for getLastLocation()
GoogleSignatureVerifier: com.myappname.android signature not valid.  Found: LONG KEY HERE

我需要在 Marshmallow 做些什么特别的事情吗?

我的 OnLocationChanged 方法

@Override
    public void onLocationChanged(Location location) {
        myLocation = location;
        Log.d("MYAPPTAG", "LocatinChngListner, loc: " + location.getLatitude() + "," + location.getLongitude());     
    }

AndroidManifest.xml - 权限部分(节点上方)

<!--- App permissions -->
    <permission android:name="com.myappname.android.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
    <uses-permission android:name="com.myappname.android.permission.MAPS_RECEIVE"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
    <uses-permission android:name="android.permission.CALL_PHONE"/>
    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <permission android:name="com.myappname.android.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="com.myappname.android.permission.C2D_MESSAGE"/>

onCreate 方法片段

createLocationRequest();
        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        }

创建位置请求方法

private void createLocationRequest(){
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(5000);
        mLocationRequest.setFastestInterval(1000);
    }

onStart() onStop() 方法

@Override
public void onStart() {
        if (!mGoogleApiClient.isConnected()) mGoogleApiClient.connect();
        super.onStart();
    }

@Override    
public void onStop() {
        if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect();
        super.onStop();
    }

我在 Fragment onCreate 方法之后立即在下面调用此代码

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1 && (ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
            requestPermissions(new String[] { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }, REQUEST_PERMISSION_USER_LOCATION);
        } else {
            googleMapsLocationPermissionContainer.setVisibility(View.GONE);
            getUserLocationAndInitializeMap();
        }

googleMapsLocationPermissionContainer 只是我在地图上覆盖的布局,直到授予权限。

getUserLocationAndInitializeMap()

try {
                MapsInitializer.initialize(getActivity());
                // Set reference for map object
                if (map == null) {
                    mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
                    mapFragment.getMapAsync(this);
// Here I set the map to invisible then after I plot all the markers I set it to visible again

                    mapFragment.getView().setVisibility(View.INVISIBLE);
                }
            } catch (Exception e) {
                // Show the google maps alert dialog
                showGoogleMapsErrorDialog();
            }
4

1 回答 1

1

我的方法如下:

@Override
public void onResume() {
    super.onResume();
    initGpsTracker();
}

public synchronized void initGpsTracker() {
    if (mMap != null) {
        try {
            checkIfPermissionAllowedForLocation();
        } catch (SecurityException secex) {
            Toast.makeText(getActivity(), "not enabled in manifest", Toast.LENGTH_SHORT).show();
        }
    }
}

/**
 * rule is the following. First we check if the permissions are there. If not, we check if we can enable or not.
 * If the permissions are check if gps is enabled.
 */
private void checkIfPermissionAllowedForLocation() {

    //if permissions are set then we go to else, check for gps
    if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // Request missing location permission.
        if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
            askIfToRequestPermissions();
        } else {
            requestPermissions();
        }
    } else {
        // Location permission has been granted, continue as usual.
        if (!isGpsProviderEnabled()) {
            askToEnableGPS();
        } else {
            mMap.setMyLocationEnabled(true);
        }
    }
}


private void askToEnableGPS() {
    CustomFragmentDialog customFragmentDialog = CustomFragmentDialog.newInstance(getString(R.string.enable_gps_title),
            getString(R.string.enable_gps_message),
            getString(R.string.ok),
            getString(R.string.cancel),
            callback);
    customFragmentDialog.show(getFragmentManager(), CUSTOM_TAG);
}

private void requestPermissions() {
    ActivityCompat.requestPermissions(getActivity(),
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
            REQUEST_CODE_LOCATION);
}

private void enableGPS() {
    if (enableLocationService != null) {
        enableLocationService.askToEnableGps(locationCallback);
    }
}

private GoogleAskToEnableLocationService.GpsCallback locationCallback = new GoogleAskToEnableLocationService.GpsCallback() {
    @Override
    public void onSuccess() {
        initGpsTracker();
    }

    @Override
    public void onResolutionRequired(Status status) {
        try {
            status.startResolutionForResult(getActivity(), CONNECTION_RESOLUTION_CODE);
        } catch (IntentSender.SendIntentException setex) {
            Toast.makeText(getActivity(), "Exception in sending intent:", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onError() {
        Toast.makeText(getActivity(), "Location services unavailable!", Toast.LENGTH_SHORT).show();
    }
};

private void askIfToRequestPermissions() {
    CustomFragmentDialog customFragmentDialog = CustomFragmentDialog.newInstance(getString(R.string.enable_gps_title),
            getString(R.string.enable_permissions_message),
            getString(R.string.ok),
            getString(R.string.cancel),
            callback_permissions);
    customFragmentDialog.show(getFragmentManager(), CUSTOM_TAG);
}

private CustomFragmentDialog.Callback callback = new CustomFragmentDialog.Callback() {
    @Override
    public void onPositiveButtonClicked(Bundle bundle) {
        enableGPS();
    }

    @Override
    public void onNegativeButtonClicked(Bundle bundle) {

    }
};


private CustomFragmentDialog.Callback callback_permissions = new CustomFragmentDialog.Callback() {
    @Override
    public void onPositiveButtonClicked(Bundle bundle) {
        requestPermissions();
    }

    @Override
    public void onNegativeButtonClicked(Bundle bundle) {

    }
};

 private boolean isGpsProviderEnabled() {
    return googleUtils.isGpsProviderEnabled();
 }
 //inside it is a normal check if locationManager  can access
 //the gps provider
  if (locationManager.getProvider(provider) == null) {
      return false;
  }

现在,对于请求许可,有一些回调:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case CONNECTION_RESOLUTION_CODE:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    initGpsTracker();
                    break;
                case Activity.RESULT_CANCELED:
                    Toast.makeText(getContext(), "Gps not enabled:", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
            break;
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == REQUEST_CODE_LOCATION) {
        if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            initGpsTracker();
        } else {
            Toast.makeText(getActivity(), "Manifest permission, not enabled", Toast.LENGTH_SHORT).show();

        }
    }
}

现在,最后是您处理位置请求的类,因此您不必转到设置:

 public void askToEnableGps(final GpsCallback callback) {
    if (locationClient == null) {
        return;
    }
    mLocationRequestHighAccuracy = LocationRequest.create();
    mLocationRequestHighAccuracy.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequestHighAccuracy.setInterval(30 * 1000);
    mLocationRequestHighAccuracy.setFastestInterval(5 * 1000);
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
            .addLocationRequest(mLocationRequestHighAccuracy);
    builder.setAlwaysShow(true);
    PendingResult<LocationSettingsResult> result =
            LocationServices.SettingsApi.checkLocationSettings(locationClient, builder.build());

    result.setResultCallback(getResultCallback(callback));
}

private ResultCallback<LocationSettingsResult> getResultCallback(final GpsCallback callback) {

    return new ResultCallback<LocationSettingsResult>() {
        @Override
        public void onResult(LocationSettingsResult result) {
            if (result != null) {
                final Status status = result.getStatus();
                if (callback != null) {
                    //final LocationSettingsStates statesResult = result.getLocationSettingsStates();
                    switch (status.getStatusCode()) {
                        case LocationSettingsStatusCodes.SUCCESS:
                            // All location settings are satisfied. The client can initialize location
                            // requests here.
                            callback.onSuccess();
                            break;
                        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                            // Location settings are not satisfied. But could be fixed by showing the user
                            // a dialog.
                            callback.onResolutionRequired(status);
                            break;
                        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                            // Location settings are not satisfied. However, we have no way to fix the
                            // settings so we won't show the dialog.
                            callback.onError();
                            break;
                    }
                }
            }
        }
    };
}

public interface GpsCallback {
    /**
     * callback method for when the result it is a success.
     */
    void onSuccess();

    /**
     * callback for when user interaction it is required.
     *
     * @param status the result from the service needed for the resolution.
     */
    void onResolutionRequired(Status status);

    /**
     * Callback for when the change it is not possible.
     */
    void onError();
}
于 2016-07-28T19:00:00.223 回答