You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Google Maps Android SDK实现300米内场所分类功能技术问询

Hey there! Let's walk through how to build this feature—getting nearby places within 300 meters of the user's location and categorizing them by type—using your existing MapsActivity code as a starting point.

1. Finish the Location Permission Request

Your current code has a TODO for handling permissions, so let's flesh that out first. Users need to grant location access before we can do anything meaningful with their position.

First, add a permission request constant at the top of your class:

private static final int REQUEST_LOCATION_PERMISSION = 1;

Then, replace the permission check block in onMapReady with code that requests permissions if they're missing:

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

    // Check for location permissions
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {
        // Request permissions
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_LOCATION_PERMISSION);
        return;
    }
    // Permissions granted, enable my location
    mMap.setMyLocationEnabled(true);
    // Now proceed to get user's location and fetch nearby places
    fetchUserLocation();
}

Add the permission result handler method to your class:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_LOCATION_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED) {
                mMap.setMyLocationEnabled(true);
                fetchUserLocation();
            }
        } else {
            // Handle permission denial (show a toast, etc.)
            Toast.makeText(this, "Location permission is required to use this feature", Toast.LENGTH_SHORT).show();
        }
    }
}
2. Fetch the User's Current Location

We'll use Google's FusedLocationProviderClient (the recommended way to get location on Android) to get the user's precise position.

First, add the client as a class variable:

private FusedLocationProviderClient fusedLocationClient;

Initialize it in onCreate:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    
    // Initialize FusedLocationProviderClient
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

Now add the fetchUserLocation method to get the last known location (or request location updates if needed):

private void fetchUserLocation() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    fusedLocationClient.getLastLocation()
            .addOnSuccessListener(this, location -> {
                if (location != null) {
                    // Got user's location: lat/lng
                    LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
                    // Move map camera to user's location
                    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 17));
                    // Now fetch nearby places
                    fetchNearbyPlaces(userLocation);
                } else {
                    // Handle case where location is null (request updates, show error)
                    Toast.makeText(this, "Could not get your location", Toast.LENGTH_SHORT).show();
                }
            });
}
3. Integrate Google Places API to Search Nearby Places

To fetch nearby venues, you'll need to use the Google Places API for Android. Here's how to set it up:

Step 3.1: Enable Places API & Get API Key

  1. Head to Google Cloud Console
  2. Enable the Places API for your project
  3. Generate an API key (restrict it to your app's package name and SHA-1 for security)

Step 3.2: Add Dependencies & Manifest Config

Add this dependency to your app-level build.gradle (Module level):

dependencies {
    // ... other dependencies
    implementation 'com.google.android.libraries.places:places:3.4.0'
}

Add your API key to AndroidManifest.xml inside the <application> tag:

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="YOUR_GOOGLE_MAPS_API_KEY"/>

Add Places client variables to your class:

private PlacesClient placesClient;
private static final int RADIUS_METERS = 300; // 300 meters

Initialize placesClient in onCreate:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    
    // Initialize Places API
    Places.initialize(getApplicationContext(), "YOUR_GOOGLE_MAPS_API_KEY");
    placesClient = Places.createClient(this);
    
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

Now add the fetchNearbyPlaces method to search for venues within 300 meters:

private void fetchNearbyPlaces(LatLng userLocation) {
    // Build nearby search request
    FindCurrentPlaceRequest request = FindCurrentPlaceRequest.newInstance(getPlaceFields());
    
    placesClient.findCurrentPlace(request)
            .addOnSuccessListener(response -> {
                // Process the list of places
                List<Place> nearbyPlaces = response.getPlaceLikelihoods()
                        .stream()
                        .map(PlaceLikelihood::getPlace)
                        .collect(Collectors.toList());
                // Categorize the places
                categorizePlaces(nearbyPlaces);
            })
            .addOnFailureListener(e -> {
                // Handle error
                Toast.makeText(this, "Failed to fetch nearby places: " + e.getMessage(), Toast.LENGTH_SHORT).show();
            });
}

// Define which place fields we want to retrieve
private List<Place.Field> getPlaceFields() {
    return Arrays.asList(
            Place.Field.ID,
            Place.Field.NAME,
            Place.Field.LAT_LNG,
            Place.Field.TYPES,
            Place.Field.ADDRESS
    );
}
4. Categorize Places by Type

Now let's take the list of nearby places and group them into categories like Restaurants, Stores, etc. We'll use a HashMap to map category names to lists of places.

Add the categorizePlaces method:

private void categorizePlaces(List<Place> places) {
    // Define category mappings (adjust types based on your needs)
    Map<String, List<Place>> categorizedPlaces = new HashMap<>();
    categorizedPlaces.put("Restaurants", new ArrayList<>());
    categorizedPlaces.put("Stores", new ArrayList<>());
    categorizedPlaces.put("Cafés", new ArrayList<>());
    categorizedPlaces.put("Other", new ArrayList<>());

    for (Place place : places) {
        List<String> placeTypes = place.getTypes();
        boolean placed = false;

        // Check if place matches any category
        if (placeTypes.contains("restaurant")) {
            categorizedPlaces.get("Restaurants").add(place);
            placed = true;
        } else if (placeTypes.contains("store") || placeTypes.contains("shopping_mall")) {
            categorizedPlaces.get("Stores").add(place);
            placed = true;
        } else if (placeTypes.contains("cafe")) {
            categorizedPlaces.get("Cafés").add(place);
            placed = true;
        } else {
            categorizedPlaces.get("Other").add(place);
        }
    }

    // Now you can use categorizedPlaces to display results (e.g., in a RecyclerView, markers on map)
    // Example: Print counts to logcat
    Log.d("CategorizedPlaces", "Restaurants: " + categorizedPlaces.get("Restaurants").size());
    Log.d("CategorizedPlaces", "Stores: " + categorizedPlaces.get("Stores").size());
    Log.d("CategorizedPlaces", "Cafés: " + categorizedPlaces.get("Cafés").size());
    Log.d("CategorizedPlaces", "Other: " + categorizedPlaces.get("Other").size());

    // Optional: Add markers for each place on the map
    addPlaceMarkers(categorizedPlaces);
}

// Optional: Add markers for categorized places
private void addPlaceMarkers(Map<String, List<Place>> categorizedPlaces) {
    // Define marker colors for each category
    Map<String, Float> categoryColors = new HashMap<>();
    categoryColors.put("Restaurants", BitmapDescriptorFactory.HUE_RED);
    categoryColors.put("Stores", BitmapDescriptorFactory.HUE_BLUE);
    categoryColors.put("Cafés", BitmapDescriptorFactory.HUE_YELLOW);
    categoryColors.put("Other", BitmapDescriptorFactory.HUE_GRAY);

    for (Map.Entry<String, List<Place>> entry : categorizedPlaces.entrySet()) {
        String category = entry.getKey();
        List<Place> places = entry.getValue();
        float color = categoryColors.get(category);

        for (Place place : places) {
            mMap.addMarker(new MarkerOptions()
                    .position(place.getLatLng())
                    .title(place.getName())
                    .snippet(place.getAddress())
                    .icon(BitmapDescriptorFactory.defaultMarker(color)));
        }
    }
}
5. Full Updated MapsActivity Code

Here's how your complete MapsActivity will look with all the above changes:

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.FragmentActivity;

import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
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.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest;
import com.google.android.libraries.places.api.net.PlacesClient;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
    private GoogleMap mMap;
    private FusedLocationProviderClient fusedLocationClient;
    private PlacesClient placesClient;
    private static final int REQUEST_LOCATION_PERMISSION = 1;
    private static final int RADIUS_METERS = 300;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);

        // Initialize Places API
        Places.initialize(getApplicationContext(), "YOUR_GOOGLE_MAPS_API_KEY");
        placesClient = Places.createClient(this);

        // Initialize FusedLocationProviderClient
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

        // Check for location permissions
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQUEST_LOCATION_PERMISSION);
            return;
        }
        mMap.setMyLocationEnabled(true);
        fetchUserLocation();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_LOCATION_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) {
                    mMap.setMyLocationEnabled(true);
                    fetchUserLocation();
                }
            } else {
                Toast.makeText(this, "Location permission is required to use this feature", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void fetchUserLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        fusedLocationClient.getLastLocation()
                .addOnSuccessListener(this, location -> {
                    if (location != null) {
                        LatLng userLocation = new LatLng(location.getLatitude(), location.getLongitude());
                        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 17));
                        fetchNearbyPlaces(userLocation);
                    } else {
                        Toast.makeText(this, "Could not get your location", Toast.LENGTH_SHORT).show();
                    }
                });
    }

    private void fetchNearbyPlaces(LatLng userLocation) {
        FindCurrentPlaceRequest request = FindCurrentPlaceRequest.newInstance(getPlaceFields());

        placesClient.findCurrentPlace(request)
                .addOnSuccessListener(response -> {
                    List<Place> nearbyPlaces = response.getPlaceLikelihoods()
                            .stream()
                            .map(PlaceLikelihood::getPlace)
                            .collect(Collectors.toList());
                    categorizePlaces(nearbyPlaces);
                })
                .addOnFailureListener(e -> {
                    Toast.makeText(this, "Failed to fetch nearby places: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                });
    }

    private List<Place.Field> getPlaceFields() {
        return Arrays.asList(
                Place.Field.ID,
                Place.Field.NAME,
                Place.Field.LAT_LNG,
                Place.Field.TYPES,
                Place.Field.ADDRESS
        );
    }

    private void categorizePlaces(List<Place> places) {
        Map<String, List<Place>> categorizedPlaces = new HashMap<>();
        categorizedPlaces.put("Restaurants", new ArrayList<>());
        categorizedPlaces.put("Stores", new ArrayList<>());
        categorizedPlaces.put("Cafés", new ArrayList<>());
        categorizedPlaces.put("Other", new ArrayList<>());

        for (Place place : places) {
            List<String> placeTypes = place.getTypes();
            boolean placed = false;

            if (placeTypes.contains("restaurant")) {
                categorizedPlaces.get("Restaurants").add(place);
                placed = true;
            } else if (placeTypes.contains("store") || placeTypes.contains("shopping_mall")) {
                categorizedPlaces.get("Stores").add(place);
                placed = true;
            } else if (placeTypes.contains("cafe")) {
                categorizedPlaces.get("Cafés").add(place);
                placed = true;
            } else {
                categorizedPlaces.get("Other").add(place);
            }
        }

        // Log category counts
        Log.d("CategorizedPlaces", "Restaurants: " + categorizedPlaces.get("Restaurants").size());
        Log.d("CategorizedPlaces", "Stores: " + categorizedPlaces.get("Stores").size());
        Log.d("CategorizedPlaces", "Cafés: " + categorizedPlaces.get("Cafés").size());
        Log.d("CategorizedPlaces", "Other: " + categorizedPlaces.get("Other").size());

        addPlaceMarkers(categorizedPlaces);
    }

    private void addPlaceMarkers(Map<String, List<Place>> categorizedPlaces) {
        Map<String, Float> categoryColors = new HashMap<>();
        categoryColors.put("Restaurants", BitmapDescriptorFactory.HUE_RED);
        categoryColors.put("Stores", BitmapDescriptorFactory.HUE_BLUE);
        categoryColors.put("Cafés", BitmapDescriptorFactory.HUE_YELLOW);
        categoryColors.put("Other", BitmapDescriptorFactory.HUE_GRAY);

        for (Map.Entry<String, List<Place>> entry : categorizedPlaces.entrySet()) {
            String category = entry.getKey();
            List<Place> places = entry.getValue();
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:17:21