Android Google Maps当前位置,夜间模式功能

时间:2020-02-23 14:28:57  来源:igfitidea点击:

在本教程中,我们将使用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);