Android Marshmallow getLastLocation/LocationListeners 不工作

标签 android android-6.0-marshmallow android-maps-v2 android-googleapiclient

我有一个应用程序可以获取用户的当前位置,然后加载 Google map 并绘制他们所在区域的兴趣标记。它适用于 Marshmallow 以下的所有内容。我已经添加了运行时权限检查,并且在收到提示时正在设置它们,在我点击接受后,我看到了手机设置中应用程序详细信息中列出的权限。但是,我终生无法弄清楚为什么我找不到位置。

我正在使用此处所示的示例 https://developer.android.com/training/location/retrieve-current.html

我在 list 中使用标签设置了所有权限。我什至让我的 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 始终为 null。每次调用 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 方法 fragment

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

createLocationRequest 方法

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 只是我在授予权限之前覆盖在 map 上的布局。

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();
            }

最佳答案

我的做法如下:

@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();
}

关于Android Marshmallow getLastLocation/LocationListeners 不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38643396/

相关文章:

java - 使用字符串数组从对象数组列表中删除项目 - android

安卓 : camera doesn't open in marshmallow

android - 如何在 Google Maps API v2 中禁用标记触摸时的自动平移

android - 无法使用groundOverlay在android中的google map api v2上显示图像

Android Google API V2 启用/禁用 TileProvider

android - android录音音量变化

android - 当我按按钮转到“滑动选项卡”菜单时,Android应用程序崩溃

android - 如何将对象从 android 传递到 soap web 服务?

android - 打瞌睡模式三星设备

android - "Write settings"权限未授予 marshmallow android