I want to create a program that mark a place on the google map and every second from when I push the "Start" button the marker would jump a km to a random direction until I push the "Stop" button.
I want the marker to jump, wait a second, jump, wait a second and so on... Until I push the "Stop" button.
When I am using the "while" loop the program stuck even before the showing of the "Stop" button. But if I don't use the loop it's working good. Can you help me please?
This is my code:
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);
}
});
}
}
I searched a bit and I found that I can't use the while loop and the delay function together so I changed it to this:
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();