问题
I'm trying to develo an app that get location by COARSE location. This app must run on Android 6 too than i've implemented permission request on run time, start the map but i can't get my current location... any tips?
This is my main activity:
package com.luca.fontanelle;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.location.LocationListener;
import android.Manifest;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener,
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
final static int REQUEST_LOCATION = 199;
private GoogleMap mMap;
private GoogleApiClient mGoogleApiClient;
private String providerNetwork = LocationManager.NETWORK_PROVIDER;
private Location mCurrentLocation;
private LocationRequest mLocationRequest;
private LocationManager locationManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.addApi(AppIndex.API).build();
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_LOW_POWER)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
protected void onStart() {
super.onStart();
}
protected void onResume() {
super.onResume();
mGoogleApiClient.connect();
}
protected void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
protected void onStop() {
super.onStop();}
protected void onDestroy() {
super.onDestroy();
}
public void onLocationChanged(Location location) {
mCurrentLocation = location;
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 10);
mMap.animateCamera(cameraUpdate);
locationManager.removeUpdates(this);
mMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude())));
mMap.moveCamera(CameraUpdateFactory.zoomTo(15.0f));
}
public void onConnected(Bundle bundle) {
if (controllaPermessi()) {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient,
builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
//final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
//...
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
Intent gpsOptionsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(gpsOptionsIntent);
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.
//...
break;
}
}
});
/* if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}*/
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mCurrentLocation == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}else{
richiestaPermessi();
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else {
//Log.d("MapsActivity", "Connessione fallita. Codice di errore: " + connectionResult.getErrorCode());
}
}
private boolean controllaPermessi(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
private void richiestaPermessi(){
if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)){
Toast.makeText(getApplicationContext(), "Attiva la localizzazione per usufruire dell'app.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
}
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Permessi accettati. Puoi usare tutte le funzionalità.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Permessi non accettati. Non puoi accedere alle funzionalità del GPS.", Toast.LENGTH_LONG).show();
}
break;
}
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
}
}
Manifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.luca.fontanelle">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="23" />
<permission
android:name="com.luca.fontanelle.permission.MAPS_RECEIVE"
android:protectionLevel="signature"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission-sdk-23 android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
Google Maps Android API v2, but you must specify either coarse or fine
location permissions for the 'MyLocation' functionality.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--
The API key for Google Maps-based APIs is defined as a string resource.
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need a different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".MapsActivity"
android:label="@string/title_activity_maps">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
回答1:
Try this code with google fused location api
1) MainActivity.class
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleMap mMap;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
protected final static String LOCATION_KEY = "location-key";
protected final static String LAST_UPDATED_TIME_STRING_KEY = "last-updated-time-string-key";
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
protected Location mCurrentLocation;
protected String mLastUpdateTime;
private boolean mycheck, chrckonce;
private LocationManager manager;
private Double lat, lng;
private Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = MainActivity.this;
chrckonce = true;
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mLastUpdateTime = "";
updateValuesFromBundle(savedInstanceState);
}
@Override
protected void onStart() {
super.onStart();
if (!manager.isProviderEnabled((LocationManager.GPS_PROVIDER))) {
//GPS is not available show alert
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("GPS SETTINGS");
alertDialog.setMessage("GPS is not enable! Want to go to settings menu?");
alertDialog.setCancelable(false);
alertDialog.setPositiveButton(" Settings", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
finish();
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.cancel();
finish();
}
});
alertDialog.show();
} else {
mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
mycheck = true;
buildGoogleApiClient();
mGoogleApiClient.connect();
mMap.setMyLocationEnabled(true);
}
}
@Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
lat = location.getLatitude();
lng = location.getLongitude();
if (chrckonce) {
mMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(lat, lng)), 2000, null);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lng), 18));
mMap.addMarker(new MarkerOptions().position(new LatLng(lat, lng)).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
chrckonce = false;
}
}
//Update location from google fused api
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
if (savedInstanceState.keySet().contains(LOCATION_KEY)) {
mCurrentLocation = savedInstanceState.getParcelable(LOCATION_KEY);
}
if (savedInstanceState.keySet().contains(LAST_UPDATED_TIME_STRING_KEY)) {
mLastUpdateTime = savedInstanceState.getString(LAST_UPDATED_TIME_STRING_KEY);
}
}
}
//synchronized google fused location api
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
//create location request
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
//on resume activity
@Override
public void onResume() {
super.onResume();
if (mycheck == true) {
if (mGoogleApiClient.isConnected()) {
startLocationUpdates();
}
}
}
//when activity goes on pause
@Override
protected void onPause() {
super.onPause();
if (mycheck == true) {
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
}
//when activity stops
@Override
protected void onStop() {
if (mycheck == true) {
mGoogleApiClient.disconnect();
}
super.onStop();
}
@Override
public void onConnected(Bundle bundle) {
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
}
startLocationUpdates();
}
//check connection suspended
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
//Location update
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
//location update close when activity closed
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
2) activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
</fragment>
</LinearLayout>
In Manifest permissions
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
来源:https://stackoverflow.com/questions/37047269/how-get-location-by-coarse-location