Android
Google Maps API v2 för Android
Sök…
parametrar
Parameter | detaljer |
---|---|
Google karta | GoogleMap är ett objekt som onMapReady() emot på en onMapReady() -händelse |
MarkerOptions | MarkerOptions är MarkerOptions för en Marker och används för att lägga till en markör på en karta. |
Anmärkningar
Krav
- Google Play Services SDK installerat.
- Ett Google Console-konto.
- En Google Maps API-nyckel erhållen i Google Console.
Standard Google Map Activity
Denna aktivitetskod ger grundläggande funktioner för att inkludera en Google Map med hjälp av en SupportMapFragment.
Google Maps V2 API innehåller ett helt nytt sätt att ladda kartor.
Verksamheten måste nu implementera OnMapReadyCallBack- gränssnittet, som kommer med en onMapReady () -metodöverskridande som körs varje gång vi kör SupportMapFragment . getMapAsync (OnMapReadyCallback) ; och samtalet är avslutat.
Kartor använder markörer , polygoner och polylinjer för att visa interaktiv information till användaren.
MapsActivity.java:
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney, Australia, and move the camera.
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
Observera att koden ovan blåser upp en layout, som har en SupportMapFragment kapslad inuti behållarlayouten, definierad med ett ID för R.id.map
. Layoutfilen visas nedan:
activity_maps.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/map"
tools:context="com.example.app.MapsActivity"
android:name="com.google.android.gms.maps.SupportMapFragment"/>
</LinearLayout>
Anpassade Google Map Styles
Kartstil
Google Maps har en uppsättning olika stilar som ska tillämpas med hjälp av denna kod:
// Sets the map type to be "hybrid"
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
De olika kartstilarna är:
Vanligt
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
Typisk färdplan. Vägar, några konstgjorda funktioner och viktiga naturfunktioner som floder visas. Väg- och funktionsetiketter är också synliga.
Hybrid
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
Satellitfotografidata med vägkartor tillagda. Väg- och funktionsetiketter är också synliga.
Satellit
map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
Satellitfotografidata. Väg- och funktionsetiketter är inte synliga.
Terräng
map.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
Topografiska data. Kartan innehåller färger, konturlinjer och etiketter och perspektivskuggning. Vissa vägar och etiketter är också synliga.
Ingen
map.setMapType(GoogleMap.MAP_TYPE_NONE);
Inga brickor. Kartan kommer att visas som ett tomt rutnät utan brickor laddade.
ÖVRIGA STILALTERNATIV
Inomhuskartor
På höga zoomnivåer visar kartan planlösningar för inomhusutrymmen. Dessa kallas inomhuskartor och visas endast för kartorttyperna "normala" och "satellit".
Så här gör du för att aktivera eller inaktivera inomhuskartor:
GoogleMap.setIndoorEnabled(true).
GoogleMap.setIndoorEnabled(false).
Vi kan lägga till anpassade stilar till kartor.
Lägg till följande kodavsnitt i onMapReady-metoden
mMap = googleMap;
try {
// Customise the styling of the base map using a JSON object defined
// in a raw resource file.
boolean success = mMap.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
MapsActivity.this, R.raw.style_json));
if (!success) {
Log.e(TAG, "Style parsing failed.");
}
} catch (Resources.NotFoundException e) {
Log.e(TAG, "Can't find style.", e);
}
under res- mappen skapa ett mappnamn rått och lägg till json-filens stilar. Exempel på stil.json-fil
[
{
"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
}
]
}
]
För att skapa stilar json-fil klickar du på den här länken
Lägga till markörer på en karta
För att lägga till markörer på en Google Map, till exempel från en ArrayList
of MyLocation
Objects, kan vi göra det på detta sätt.
MyLocation
:
public class MyLocation {
LatLng latLng;
String title;
String snippet;
}
Här är en metod som skulle ta en lista över MyLocation
Objects och placera en markör för var och en:
private void LocationsLoaded(List<MyLocation> locations){
for (MyLocation myLoc : locations){
mMap.addMarker(new MarkerOptions()
.position(myLoc.latLng)
.title(myLoc.title)
.snippet(myLoc.snippet)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
}
}
Obs: I detta exempel är mMap
en klassmedlemmarvariabel i aktiviteten, där vi har tilldelat den till onMapReady()
som erhållits i onMapReady()
åsidosättningen.
MapView: inbäddning av en GoogleMap i en befintlig layout
Det är möjligt att behandla en GoogleMap som en Android-vy om vi använder den medföljande MapView-klassen. Dess användning liknar MapFragment.
I din layout använder du MapView enligt följande:
<com.google.android.gms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
<!--
map:mapType="0" Specifies a change to the initial map type
map:zOrderOnTop="true" Control whether the map view's surface is placed on top of its window
map:useVieLifecycle="true" When using a MapFragment, this flag specifies whether the lifecycle of the map should be tied to the fragment's view or the fragment itself
map:uiCompass="true" Enables or disables the compass
map:uiRotateGestures="true" Sets the preference for whether rotate gestures should be enabled or disabled
map:uiScrollGestures="true" Sets the preference for whether scroll gestures should be enabled or disabled
map:uiTiltGestures="true" Sets the preference for whether tilt gestures should be enabled or disabled
map:uiZoomGestures="true" Sets the preference for whether zoom gestures should be enabled or disabled
map:uiZoomControls="true" Enables or disables the zoom controls
map:liteMode="true" Specifies whether the map should be created in lite mode
map:uiMapToolbar="true" Specifies whether the mapToolbar should be enabled
map:ambientEnabled="true" Specifies whether ambient-mode styling should be enabled
map:cameraMinZoomPreference="0.0" Specifies a preferred lower bound for camera zoom
map:cameraMaxZoomPreference="1.0" Specifies a preferred upper bound for camera zoom -->
/>
Din aktivitet måste implementera OnMapReadyCallback-gränssnittet för att fungera:
/**
* This shows how to create a simple activity with a raw MapView and add a marker to it. This
* requires forwarding all the important lifecycle methods onto MapView.
*/
public class RawMapViewDemoActivity extends AppCompatActivity implements OnMapReadyCallback {
private MapView mMapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.raw_mapview_demo);
mMapView = (MapView) findViewById(R.id.map);
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(this);
}
@Override
protected void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onMapReady(GoogleMap map) {
map.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
}
@Override
protected void onPause() {
mMapView.onPause();
super.onPause();
}
@Override
protected void onDestroy() {
mMapView.onDestroy();
super.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mMapView.onSaveInstanceState(outState);
}
}
Visa aktuell plats på en Google-karta
Här är en full aktivitetsklass som placerar en markör på den aktuella platsen och också flyttar kameran till den aktuella positionen.
Det här är några saker som pågår här:
- Kontrollera platstillstånd
- När platstillstånd har beviljats, ring
setMyLocationEnabled()
, bygg GoogleApiClient och anslut den - När GoogleApiClient är ansluten, begär platsuppdateringar
public class MapLocationActivity extends AppCompatActivity
implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
GoogleMap mGoogleMap;
SupportMapFragment mapFrag;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().setTitle("Map Location Activity");
mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFrag.getMapAsync(this);
}
@Override
public void onPause() {
super.onPause();
//stop location updates when Activity is no longer active
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
@Override
public void onMapReady(GoogleMap googleMap)
{
mGoogleMap=googleMap;
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
//Initialize Google Play Services
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Location Permission already granted
buildGoogleApiClient();
mGoogleMap.setMyLocationEnabled(true);
} else {
//Request Location Permission
checkLocationPermission();
}
}
else {
buildGoogleApiClient();
mGoogleMap.setMyLocationEnabled(true);
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
@Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
@Override
public void onConnectionSuspended(int i) {}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {}
@Override
public void onLocationChanged(Location location)
{
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);
//move map camera
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(11));
//stop location updates
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
private void checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
new AlertDialog.Builder(this)
.setTitle("Location Permission Needed")
.setMessage("This app needs the Location permission, please accept to use location functionality")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(MapLocationActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION );
}
})
.create()
.show();
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION );
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mGoogleMap.setMyLocationEnabled(true);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/map"
tools:context="com.example.app.MapLocationActivity"
android:name="com.google.android.gms.maps.SupportMapFragment"/>
</LinearLayout>
Resultat:
Visa förklaring om det behövs på Marshmallow och Nougat med hjälp av en AlertDialog (detta fall inträffar när användaren tidigare avvisat en tillståndförfrågan, eller hade beviljat tillståndet och senare återkallat den i inställningarna):
Be användaren om platstillstånd på Marshmallow och Nougat genom att ringa ActivityCompat.requestPermissions()
:
Flytta kameran till aktuell plats och platsmarkör när platstillståndet har beviljats:
Skaffa SH1-fingeravtryck för din certifikat keystore-fil
För att få en Google Maps API-nyckel för ditt certifikat måste du förse API-konsolen med SH1-fingeravtrycket i din felsöknings- / release-nyckelhandel.
Du kan få keystore genom att använda JDK: s keytool- program som beskrivs här i dokumenten.
Ett annat tillvägagångssätt är att få fram fingeravtrycket programmatiskt genom att köra det här utdraget med din app signerad med felsökningscertifikatet och skriva ut hash till loggen.
PackageInfo info;
try {
info = getPackageManager().getPackageInfo("com.package.name", PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
String hash= new String(Base64.encode(md.digest(), 0));
Log.e("hash", hash);
}
} catch (NameNotFoundException e1) {
Log.e("name not found", e1.toString());
} catch (NoSuchAlgorithmException e) {
Log.e("no such an algorithm", e.toString());
} catch (Exception e) {
Log.e("exception", e.toString());
}
Starta inte Google Maps när du klickar på kartan (lite läge)
När en Google Map visas i lite läge klickar du på en karta Google Maps-applikationen. För att inaktivera denna funktion måste du ringa setClickable(false)
på MapView
, t.ex .:
final MapView mapView = (MapView)view.findViewById(R.id.map);
mapView.setClickable(false);
UISettings
Med UISettings
kan Google Map-utseendet ändras.
Här är ett exempel på några vanliga inställningar:
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
mGoogleMap.getUiSettings().setMapToolbarEnabled(true);
mGoogleMap.getUiSettings().setZoomControlsEnabled(true);
mGoogleMap.getUiSettings().setCompassEnabled(true);
Resultat:
Få felsökning av SHA1-fingeravtryck
- Öppna Android Studio
- Öppna ditt projekt
- Klicka på Gradle (från höger sidopanel, ser du Gradle Bar )
- Klicka på Refresh (Klicka på Refresh from Gradle Bar , du kommer att se List Gradle scripts av ditt projekt)
- Klicka på ditt projekt (Ditt Projektnamn formulär List (root))
- Klicka på Uppgifter
- Klicka på android
- Dubbelklicka på signeringRapport (Du får SHA1 och MD5 i Run Bar )
InfoWindow Click Listener
Här är ett exempel på hur du definierar en annan åtgärd för varje Markers InfoWindow-klickhändelse.
Använd en HashMap där markör-ID är nyckeln, och värdet är motsvarande åtgärd som det ska vidtas när du klickar på InfoWindow.
OnInfoWindowClickListener
en OnInfoWindowClickListener
att hantera händelsen OnInfoWindowClickListener
en användare klickar på InfoWindow och använd HashMap för att avgöra vilken åtgärd som ska vidtas.
I detta enkla exempel öppnar vi en annan aktivitet baserad på vilken Markers InfoWindow klickades.
Förklara HashMap som en instansvariabel för aktiviteten eller fragmentet:
//Declare HashMap to store mapping of marker to Activity
HashMap<String, String> markerMap = new HashMap<String, String>();
Därefter, varje gång du lägger till en markör, ange en post i HashMap med markör-ID och åtgärden som det ska vidtas när det klickas på InfoWindow.
Till exempel lägga till två markörer och definiera en åtgärd att vidta för varje:
Marker markerOne = googleMap.addMarker(new MarkerOptions().position(latLng1)
.title("Marker One")
.snippet("This is Marker One");
String idOne = markerOne.getId();
markerMap.put(idOne, "action_one");
Marker markerTwo = googleMap.addMarker(new MarkerOptions().position(latLng2)
.title("Marker Two")
.snippet("This is Marker Two");
String idTwo = markerTwo.getId();
markerMap.put(idTwo, "action_two");
I InfoWindow-klicklyttaren, hämta åtgärden från HashMap och öppna upp motsvarande aktivitet baserat på åtgärden från markören:
mGoogleMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick(Marker marker) {
String actionId = markerMap.get(marker.getId());
if (actionId.equals("action_one")) {
Intent i = new Intent(MainActivity.this, ActivityOne.class);
startActivity(i);
} else if (actionId.equals("action_two")) {
Intent i = new Intent(MainActivity.this, ActivityTwo.class);
startActivity(i);
}
}
});
Obs! Om koden finns i ett fragment, byt ut MainActivity.this med getActivity ().
Byt offset
Genom att ändra mappoint x- och y- värden efter behov kan du ändra offsetmöjligheten för google map, som standard kommer den att vara i mitten av kartvyen. Ring nedan metod där du vill ändra den! Bättre att använda den inuti din onLocationChanged
som changeOffsetCenter(location.getLatitude(),location.getLongitude());
public void changeOffsetCenter(double latitude,double longitude) {
Point mappoint = mGoogleMap.getProjection().toScreenLocation(new LatLng(latitude, longitude));
mappoint.set(mappoint.x, mappoint.y-100); // change these values as you need , just hard coded a value if you want you can give it based on a ratio like using DisplayMetrics as well
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLng(mGoogleMap.getProjection().fromScreenLocation(mappoint)));
}