1

So I am a student and I am really new to programming. We are making a game for our android phones and I need some help, I want a menu (which I can make myself) and there you as a user can choose a specific radius around you, lets say 1km radius around you, then I want randomized markers placed around you within that radius.

I have the map, I have some markers put on the location in school, I have so when you walk on them you "pick them up" and get one point. Now I want to make randomized markers so you can play the game where ever. Any ideas?

Here is my code:

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener {

GoogleMap mGoogleMap;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
public static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private static final int DEFAULT_ZOOM = 18;
private List<MarkerOptions> targets;
private MarkerOptions myMarker;
private static final String TAG = MapsActivity.class.getSimpleName();

private int score = 0;

private TextView scoreTV;

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

    scoreTV = (TextView) findViewById(R.id.scoreTV);
    scoreTV.setText("Score: 0");

    // 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);

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}

@Override
public void onMapReady(GoogleMap googleMap)
{
    mGoogleMap = googleMap;

    UiSettings settings = mGoogleMap.getUiSettings();
    settings.setZoomControlsEnabled(true);
    settings.setCompassEnabled(true);

    setupTargets();

    addTargetsToMap();

    try {
        // Customise the styling of the base map using a JSON object defined
        // in a raw resource file.
        boolean success = googleMap.setMapStyle(
                MapStyleOptions.loadRawResourceStyle(
                        this, R.raw.style_json));

        if (!success) {
            Log.e(TAG, "Style parsing failed.");
        }
    } catch (Resources.NotFoundException e) {
        Log.e(TAG, "Can't find style. Error: ", e);
    }

    //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) {
    startLocationUpdates();
}

private void startLocationUpdates() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(5000);
    mLocationRequest.setFastestInterval(3000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }
}




@Override
public void onLocationChanged(Location location)
{
    Log.e("Location: ", location.toString());

    mLastLocation = location;

    Iterator<MarkerOptions> iter = targets.iterator();
    while (iter.hasNext()) {
        MarkerOptions target = iter.next();
        Location targetLocation = new Location(LocationManager.GPS_PROVIDER);
        targetLocation.setLatitude(target.getPosition().latitude);
        targetLocation.setLongitude(target.getPosition().longitude);
        float distance = location.distanceTo(targetLocation);
        if (distance < 10.0f) {
            Toast.makeText(this, "Target aquired, plus one point!", Toast.LENGTH_SHORT).show();
            score++;
            scoreTV.setText("Score: " + score);
            iter.remove();
        }
    }
    mGoogleMap.clear();

    addTargetsToMap();

    //Place current location marker
    LatLng position = new LatLng(location.getLatitude(), location.getLongitude());
    myMarker = new MarkerOptions();
    myMarker.position(position);
    myMarker.title("Me");
    myMarker.icon(BitmapDescriptorFactory.fromResource(R.drawable.dansa));
    mGoogleMap.addMarker(myMarker);

    //move map camera
    mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(position, DEFAULT_ZOOM));

}

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(MapsActivity.this,
                                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                    PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
                        }
                    })
                    .create()
                    .show();


        } else {
            // No explanation needed, we can request the permission.
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
        }
    }
}

@Override
public void onRequestPermissionsResult(int requestCode,
                                       @NonNull String permissions[], @NonNull int[] grantResults) {
    switch (requestCode) {
        case PERMISSIONS_REQUEST_ACCESS_FINE_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();
            }
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

//=============== START TARGETS ====================
private void setupTargets() {

    targets = new ArrayList<MarkerOptions>();

    MarkerOptions target = new MarkerOptions();

    target.position(new LatLng(58.393813, 15.564835)).title("Target 1");
    targets.add(target);

    target = new MarkerOptions();
    target.position(new LatLng(58.394039, 15.564811)).title("Target 2");
    targets.add(target);

    target = new MarkerOptions();
    target.position(new LatLng(58.394244, 15.565093)).title("Target 3");
    targets.add(target);

}

private void addTargetsToMap() {
    for(MarkerOptions target : targets){
        mGoogleMap.addMarker(target);
    }
}
//=============== END TARGETS ====================


//=============== START LIFECYCLE ====================
@Override
public void onPause() {
    super.onPause();

    //stop location updates when Activity is no longer active
    if (mGoogleApiClient != null) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }
}

@Override
protected void onResume() {
    super.onResume();
    if(mGoogleApiClient!=null) {
        if(mGoogleApiClient.isConnected())
            startLocationUpdates();
    }

}


//=============== END LIFECYCLE ====================


//====================== NOT USED =======================

@Override
public void onConnectionSuspended(int i) {}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {}

}
Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62
Filip
  • 13
  • 4
  • Take a look at http://stackoverflow.com/questions/42937949/move-markers-by-a-specific-distance-in-meters-from-where-they-are/42938750#42938750 – antonio May 11 '17 at 06:53

3 Answers3

0

You can use VisibleRegion to get LatLongBound for particular radius and can add markers in that area.

Go through below link :

https://developers.google.com/android/reference/com/google/android/gms/maps/model/VisibleRegion

0

Simplest approach with Cluster Manager:

  private void loadMarkers(ClusterManager<ClusterMarker> manager, GoogleMap map, LatLng center, int count,
    double minDistance, double maxDistance) {
  double minLat = Double.MAX_VALUE;
  double maxLat = Double.MIN_VALUE;
  double minLon = Double.MAX_VALUE;
  double maxLon = Double.MIN_VALUE;

  for (int i = 0; i < count; ++i) {
    double distance = minDistance + Math.random() * maxDistance;
    double heading = Math.random() * 360 - 180;

    LatLng position = SphericalUtil.computeOffset(center, distance, heading);

    ClusterMarker marker = new ClusterMarker(new MarkerOptions().position(position).title("Item No. " + i));
    manager.addItem(marker);

    minLat = Math.min(minLat, position.latitude);
    minLon = Math.min(minLon, position.longitude);
    maxLat = Math.max(maxLat, position.latitude);
    maxLon = Math.max(maxLon, position.longitude);
  }

  LatLng min = new LatLng(minLat, minLon);
  LatLng max = new LatLng(maxLat, maxLon);
  LatLngBounds bounds = new LatLngBounds(min, max);

  map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100));
}

It:

  • generates number of markers within minimum and maximum distance from defined center position,
  • calculates minimum and maximum longitude and latitude so the map camera can zoom in or zoom out properly and grant all of the generated locations are visible on the screen,
  • clusters all markers to improve presentation.

SphericalUtil class is a part of Google Maps Android API utility library.

More about clustering you can find here.

You can clone full working example from my GitHub repository.

Tomasz Dzieniak
  • 2,765
  • 3
  • 24
  • 42
  • Im really new to programming, my code looks like this when i copied it: http://prntscr.com/f6ixyk I imported what i had to import, if i would take a guess i think that i need to create variables at the top of my code? – Filip May 11 '17 at 09:05
  • Instead of using `ClusterMarker` you can use plain `MarkerOptions` and add them using `GoogleMap.addMarker(MarkerOptions options)` like in your original code. `SphericalUtil` class is part of Google Maps Android API utility library (as I mentioned before). Please refer to the link I added in the post and check the documentation how to add this dependency to your project. Then import the class and you should be fine. – Tomasz Dzieniak May 11 '17 at 09:20
  • There was a problem with cloning the project: http://prntscr.com/f8dwuv – Filip May 16 '17 at 08:53
  • It's problem with synchronizing Your Gradle build. Please read comment in [Constants file](https://github.com/tommus/google-api-samples/blob/master/app/src/main/java/com/todev/samples/Constants.java). You need to prepare gradle.properties file and add there FirebaseUrl, HomeLongitude and HomeLatitude constants. This allows Gradle to generate constants in `BuildConfig` class. – Tomasz Dzieniak May 16 '17 at 09:31
0

Easy solution

call this method "generateRandomMarkers" to generate random markers

void generateRandomMarkers() {
        //set your own minimum distance here
        int minimumDistanceFromMe = 10;
        //set your own maximum distance here
        int maximumDistanceFromMe = 500;
        //set number of markers you want to generate in Map/
        int markersToGenerate = 3;
        for (int position = 1; position <=markersToGenerate ; position++) {
              LatLng coordinates = generateRandomCoordinates(minimumDistanceFromMe, maximumDistanceFromMe);
                Log.i("random_coordinates",""+coordinates);
                mapView.addMarker(new MarkerOptions().position(new LatLng(coordinates.latitude,coordinates.longitude)).title("mid point").snippet("Snippet"));
        }// end FOR loop
    }

Method to generate random coordinates

public LatLng generateRandomCoordinates(int min, int max) {
        // Get the Current Location's longitude and latitude
        double currentLong = currentLocation.getLongitude();
        double currentLat = currentLocation.getLatitude();

        // 1 KiloMeter = 0.00900900900901° So, 1 Meter = 0.00900900900901 / 1000
        double meterCord = 0.00900900900901 / 1000;

        //Generate random Meters between the maximum and minimum Meters
        Random r = new Random();
        int randomMeters = r.nextInt(max + min);

        //then Generating Random numbers for different Methods
        int randomPM = r.nextInt(6);

        //Then we convert the distance in meters to coordinates by Multiplying number of meters with 1 Meter Coordinate
        double metersCordN = meterCord * (double) randomMeters;

        //here we generate the last Coordinates
        if (randomPM == 0) {
            return new LatLng(currentLat + metersCordN, currentLong + metersCordN);
        } else if (randomPM == 1) {
            return new LatLng(currentLat - metersCordN, currentLong - metersCordN);
        } else if (randomPM == 2) {
            return new LatLng(currentLat + metersCordN, currentLong - metersCordN);
        } else if (randomPM == 3) {
            return new LatLng(currentLat - metersCordN, currentLong + metersCordN);
        } else if (randomPM == 4) {
            return new LatLng(currentLat, currentLong - metersCordN);
        } else {
            return new LatLng(currentLat - metersCordN, currentLong);
        }
    }
Abdul Basit Rishi
  • 2,268
  • 24
  • 30