Android Google Maps当前位置,夜间模式功能
在本教程中,我们将使用Android Google Maps API。
向用户显示当前位置,纬度/经度边界,开始导航,启用夜间模式等。
Android Google Maps当前位置
在我们开始在我们的应用程序中实现一些很酷的android google maps功能之前,请按照本教程中的说明在AndroidManifest.xml文件的meta-data标签中添加Google Maps v2 API密钥值。
在Android Studio中创建一个新项目,然后选择模板作为Google Maps Activity。
注意:默认情况下,此模板将添加Google Play服务依赖项。
如下所示,在您的MapsActivity.java类中实现Google Play定位服务。
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { private GoogleMap mMap; Location mLocation; GoogleApiClient mGoogleApiClient; private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000; private LocationRequest mLocationRequest; private long UPDATE_INTERVAL = 15000; /* 15 secs */ private long FASTEST_INTERVAL = 5000; /* 5 secs */ private ArrayList permissionsToRequest; private ArrayList permissionsRejected = new ArrayList(); private ArrayList permissions = new ArrayList(); private final static int ALL_PERMISSIONS_RESULT = 101; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); //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); permissions.add(ACCESS_FINE_LOCATION); permissions.add(ACCESS_COARSE_LOCATION); permissionsToRequest = findUnAskedPermissions(permissions); //get the permissions we have asked for before but are not granted.. //we will store this in a global list to access later. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (permissionsToRequest.size() > 0) requestPermissions(permissionsToRequest.toArray(new String[permissionsToRequest.size()]), ALL_PERMISSIONS_RESULT); } mGoogleApiClient = new GoogleApiClient.Builder(this) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); connectClient(); } /** * Manipulates the map once available. * This callback is triggered when the map is ready to be used. * This is where we can add markers or lines, add listeners or move the camera. In this case, * we just add a marker near Sydney, Australia. * If Google Play services is not installed on the device, the user will be prompted to install * it inside the SupportMapFragment. This method will only be triggered once the user has * installed Google Play services and returned to the app. */ @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.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; } mMap.setMyLocationEnabled(true); } public void connectClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .build(); } private ArrayList findUnAskedPermissions(ArrayList wanted) { ArrayList result = new ArrayList(); for (String perm : wanted) { if (!hasPermission(perm)) { result.add(perm); } } return result; } @Override protected void onStart() { super.onStart(); if (mGoogleApiClient != null) { mGoogleApiClient.connect(); } } @Override protected void onResume() { super.onResume(); if (!checkPlayServices()) { Toast.makeText(getApplicationContext(),"Please install google play services",Toast.LENGTH_LONG).show(); } } @Override public void onConnected(@Nullable Bundle bundle) { if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.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; } mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); startLocationUpdates(); } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } @Override public void onLocationChanged(Location location) { } private boolean checkPlayServices() { GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); int resultCode = apiAvailability.isGooglePlayServicesAvailable(this); if (resultCode != ConnectionResult.SUCCESS) { if (apiAvailability.isUserResolvableError(resultCode)) { apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST) .show(); } else finish(); return false; } return true; } protected void startLocationUpdates() { mLocationRequest = new LocationRequest(); mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); mLocationRequest.setInterval(UPDATE_INTERVAL); mLocationRequest.setFastestInterval(FASTEST_INTERVAL); if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(getApplicationContext(), "Enable Permissions", Toast.LENGTH_LONG).show(); } LocationServices.FusedLocationApi.requestLocationUpdates( mGoogleApiClient, mLocationRequest, this); } private boolean hasPermission(String permission) { if (canMakeSmores()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return (checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED); } } return true; } private boolean canMakeSmores() { return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1); } @TargetApi(Build.VERSION_CODES.M) @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case ALL_PERMISSIONS_RESULT: for (String perms : permissionsToRequest) { if (!hasPermission(perms)) { permissionsRejected.add(perms); } } if (permissionsRejected.size() > 0) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (shouldShowRequestPermissionRationale(permissionsRejected.get(0))) { showMessageOKCancel("These permissions are mandatory for the application. Please allow access.", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { requestPermissions(permissionsRejected.toArray(new String[permissionsRejected.size()]), ALL_PERMISSIONS_RESULT); } } }); return; } } } break; } } private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) { new AlertDialog.Builder(MapsActivity.this) .setMessage(message) .setPositiveButton("OK", okListener) .setNegativeButton("Cancel", null) .create() .show(); } @Override protected void onDestroy() { super.onDestroy(); stopLocationUpdates(); } public void stopLocationUpdates() { if (mGoogleApiClient.isConnected()) { LocationServices.FusedLocationApi .removeLocationUpdates(mGoogleApiClient, this); mGoogleApiClient.disconnect(); } } }
在上面的代码中," mMap.setMyLocationEnabled(true);"用于显示用户的当前位置。
下图是运行上述代码时应用程序的输出。
蓝点是我们当前的位置。
我们需要将相机聚焦在地图上的当前位置,以防止手动缩放和滚动。
将ʻonConnected()`方法更改为;
@Override public void onConnected(@Nullable Bundle bundle) { if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.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; } mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); LatLng latLng = new LatLng(mLocation.getLatitude(), mLocation.getLongitude()); CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 12); mMap.animateCamera(cameraUpdate); startLocationUpdates(); }
在上面的代码12中设置了缩放级别。
我们可以使用" mMap.setMinZoomPreference(float v);"和" mMap.setMaxZoomPreference(float v);"来设置最小和最大缩放级别。
Android Google Maps Night模式项目结构
在应用程序中启用夜间模式。
我们需要在onMapReady方法中将地图样式设置为;
mMap.setMapStyle(MapStyleOptions.loadRawResourceStyle(this,R.raw.mapstyle_night));
mapstyle_night.json代码如下所示。
[ { "featureType": "all", "elementType": "geometry", "stylers": [ { "color": "#242f3e" } ] }, { "featureType": "all", "elementType": "labels.text.stroke", "stylers": [ { "lightness": -80 } ] }, { "featureType": "administrative", "elementType": "labels.text.fill", "stylers": [ { "color": "#746855" } ] }, { "featureType": "administrative.locality", "elementType": "labels.text.fill", "stylers": [ { "color": "#d59563" } ] }, { "featureType": "poi", "elementType": "labels.text.fill", "stylers": [ { "color": "#d59563" } ] }, { "featureType": "poi.park", "elementType": "geometry", "stylers": [ { "color": "#263c3f" } ] }, { "featureType": "poi.park", "elementType": "labels.text.fill", "stylers": [ { "color": "#6b9a76" } ] }, { "featureType": "road", "elementType": "geometry.fill", "stylers": [ { "color": "#2b3544" } ] }, { "featureType": "road", "elementType": "labels.text.fill", "stylers": [ { "color": "#9ca5b3" } ] }, { "featureType": "road.arterial", "elementType": "geometry.fill", "stylers": [ { "color": "#38414e" } ] }, { "featureType": "road.arterial", "elementType": "geometry.stroke", "stylers": [ { "color": "#212a37" } ] }, { "featureType": "road.highway", "elementType": "geometry.fill", "stylers": [ { "color": "#746855" } ] }, { "featureType": "road.highway", "elementType": "geometry.stroke", "stylers": [ { "color": "#1f2835" } ] }, { "featureType": "road.highway", "elementType": "labels.text.fill", "stylers": [ { "color": "#f3d19c" } ] }, { "featureType": "road.local", "elementType": "geometry.fill", "stylers": [ { "color": "#38414e" } ] }, { "featureType": "road.local", "elementType": "geometry.stroke", "stylers": [ { "color": "#212a37" } ] }, { "featureType": "transit", "elementType": "geometry", "stylers": [ { "color": "#2f3948" } ] }, { "featureType": "transit.station", "elementType": "labels.text.fill", "stylers": [ { "color": "#d59563" } ] }, { "featureType": "water", "elementType": "geometry", "stylers": [ { "color": "#17263c" } ] }, { "featureType": "water", "elementType": "labels.text.fill", "stylers": [ { "color": "#515c6d" } ] }, { "featureType": "water", "elementType": "labels.text.stroke", "stylers": [ { "lightness": -20 } ] } ]
通过以下代码在地图中启用路况:
mMap.setTrafficEnabled(true);
" mMap.setLatLngBoundsForCameraTarget();"用于限制地图(相机目标)焦点的纬度/经度中心范围,以便用户只能在这些范围内滚动和平移。
实现以上。
让我们以LatLngBounds为阿德莱德市的一部分为例。
以下是放在onMapReady方法中的代码段
final LatLngBounds ADELAIDE = new LatLngBounds( new LatLng(-35.0, 138.58), new LatLng(-34.9, 138.61)); final CameraPosition ADELAIDE_CAMERA = new CameraPosition.Builder() .target(new LatLng(-34.92873, 138.59995)).zoom(20.0f).bearing(0).tilt(0).build(); mMap.setLatLngBoundsForCameraTarget(ADELAIDE); mMap.addMarker(new MarkerOptions() .position(new LatLng(-34.92873, 138.59995)) .title("My Marker")); mMap.animateCamera(CameraUpdateFactory.newCameraPosition(ADELAIDE_CAMERA));
以下是该应用程序的输出。
Android Google Maps –启动Google导航
要启动导航应用,我们需要通过以下方式传递目的地的经度和纬度:
String nav_lat=22.7213129; String nav_lng=75.8763886; Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:q=" + nav_lat + "," + nav_lng)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);