Quiero crear un programa que marque un lugar en el mapa de Google y cada segundo desde que presiono el botón "Inicio", el marcador saltaría un km en una dirección aleatoria hasta que presione el botón "Detener". botón.

Quiero que el marcador salte, espere un segundo, salte, espere un segundo y así sucesivamente ... Hasta que presione el botón "Parar".

Cuando uso el bucle "while", el programa se atasca incluso antes de que se muestre el botón "Detener". Pero si no uso el bucle, funciona bien. ¿Me pueden ayudar por favor?

Este es mi código:

import androidx.annotation.DrawableRes;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;

import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Button;

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.Projection;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

import java.util.Random;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    private double currLat = 32.671677;
    private double currLng = 35.195678;
    private Marker _marker;
    private boolean _stopBWasNotPressed = true;

    @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);
    }

    // Setting the icon instead of the default marker.
    private BitmapDescriptor bitmapDescriptorFromVector(Context context, @DrawableRes int vectorDrawableResourceId) {
        Drawable background = ContextCompat.getDrawable(context, R.drawable.car_icon);
        background.setBounds(0, 0, background.getIntrinsicWidth(), background.getIntrinsicHeight());
        Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorDrawableResourceId);
        vectorDrawable.setBounds(40, 20, vectorDrawable.getIntrinsicWidth() + 40, vectorDrawable.getIntrinsicHeight() + 20);
        Bitmap bitmap = Bitmap.createBitmap(background.getIntrinsicWidth(), background.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        background.draw(canvas);
        vectorDrawable.draw(canvas);
        return BitmapDescriptorFactory.fromBitmap(bitmap);
    }

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

        // Hide the Stop button.
        Button stopB = (Button) findViewById(R.id.stopB);
        stopB.setVisibility(View.GONE);
        // Hide the Reset button.
        Button resetB = (Button) findViewById(R.id.resetB);
        resetB.setVisibility(View.GONE);
        // Add a marker in my home and move the camera.
        LatLng home = new LatLng(currLat, currLng);
        _marker = mMap.addMarker(new MarkerOptions().position(home).icon(bitmapDescriptorFromVector(this, R.drawable.car_icon)));
        mMap.moveCamera(CameraUpdateFactory.newLatLng(home));

        // Show the Start button.
        Button startB = (Button) findViewById(R.id.startB);
        startB.setVisibility(View.VISIBLE);
        startB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // Hide the Start button.
                Button startB = (Button) findViewById(R.id.startB);
                startB.setVisibility(View.GONE);
                // Show the Stop button.
                final Button stopB = (Button) findViewById(R.id.stopB);
                stopB.setVisibility(View.VISIBLE);

                while (_stopBWasNotPressed) {
                    // Making the program wait a second until it moving the marker again.
                    new Handler().postDelayed(new Runnable() {
                        public void run() {
                            startMoving();
                        }
                    }, 1000);   // 1 second.
                }
            }
        });
    }

    // This func generates a random number to use as a direction.
    public int generateRandomDirection(){
        final int min = 1;
        final int max = 4;
        final int random = new Random().nextInt((max - min) + 1) + min;
        return random;
    }

    // This func makes the new location and sends it to the animateMarker func.
    public void startMoving(){
        int directionNumber = generateRandomDirection();
        final LatLng toPos;
        switch(directionNumber) {
            case 1:
                toPos = new LatLng((currLat + 0.01), currLng); // North.
                _marker.setPosition(toPos);
                break;
            case 2:
                toPos = new LatLng((currLat - 0.01), currLng); // South.
                _marker.setPosition(toPos);
                break;
            case 3:
                toPos = new LatLng(currLat, (currLng + 0.01)); // East.
                _marker.setPosition(toPos);
                break;
            default:
                toPos = new LatLng(currLat, (currLng - 0.01)); // West.
                _marker.setPosition(toPos);
                break;
        }
    }

    public void stopButtonClick(View view) {
        _stopBWasNotPressed = false; // Stops the while loop.
        // Hide the Stop button.
        Button stopB = (Button) findViewById(R.id.stopB);
        stopB.setVisibility(View.GONE);
        // Show the Reset button.
        final Button resetB = (Button) findViewById(R.id.resetB);
        resetB.setVisibility(View.VISIBLE);
        resetB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                _marker.setVisible(false);
                currLat = 32.671677;
                currLng = 35.195678;
                onMapReady(mMap);
            }
        });
    }
}
1
AGJ 31 ago. 2020 a las 15:30

1 respuesta

La mejor respuesta

Busqué un poco y descubrí que no puedo usar el bucle while y la función de retardo juntos, así que lo cambié a esto:

final Handler handler = new Handler();
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        while (_stopBWasNotPressed) {
                            try {
                                Thread.sleep(1000); // Making the program wait a second until it continues.
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    startMoving();
                                }
                            });
                        }
                    }
                };

                Thread myThread = new Thread(runnable); // Creating a thread for the marker movement.
                myThread.start();
0
AGJ 31 ago. 2020 a las 18:36