android Animating markers every x sec - android

I am moving markers every 1 Seconds on map and this works (I am getting CarList every 1 sec from API call)
//Inside CarList there is carname which serves as id
void updateCarsLocation(final List<GeoPosition> CarList) {
//Remove old markers
if (carMarkers != null){
for (Marker marker : carMarkers) {
marker.remove();
}
}
carMarkers.clear();
if (CarList != null) {
for (GeoPosition car : CarList) {
//Rotate Car
Bitmap myImg = BitmapFactory.decodeResource(getResources(), R.drawable.car);
Matrix matrix = new Matrix();
matrix.postRotate(car.bearing);
Bitmap rotated = Bitmap.createBitmap(myImg, 0, 0, myImg.getWidth(), myImg.getHeight(),
matrix, true);
//From Bitmap
MarkerOptions markerOptions = new MarkerOptions();
LatLng latLng = new LatLng(car.lat, car.lng);
markerOptions.position(latLng);
markerOptions.icon(BitmapDescriptorFactory.fromBitmap(rotated));
Marker cMarker = mMap.addMarker(markerOptions);
carMarkers.add(cMarker);
}
}
}
But i would like this movements to be animated (smooth) i have searched SO for some help and found couple links
Animate markers 1
Animate markers 2
But i just can't figure out how to do this, I taught about putting Markers + Cars in Hashmap<Marker, GeoPosition> and check new GeoPosition with Old by carname (id) then use animate, but i haven't still managed to get that working.

I have implemented this from a long time i will post my solution but make sure you read and understand what i am doing
private Emitter.Listener onNewDriversOnMap = new Emitter.Listener() {
#Override
public void call(final Object... args) {
final JSONObject receivedDrivers = (JSONObject) args[0];
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (!BusyParsingDrivers) {
BusyParsingDrivers = true;
new Parse_NearbyDrivers_Task(receivedDrivers).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
Log.e("receivedDrivers", receivedDrivers.toString());
}
}
});
}
};
private ArrayList<Marker> existingMapMarkers = new ArrayList<>();
private boolean noNearby = false;
private boolean BusyParsingDrivers = false;
private List<Driver> driverList = new ArrayList<>();
private GoogleMap map;
/**
* Parse the new drivers list
**/
public class Parse_NearbyDrivers_Task extends AsyncTask<Void, Void, Integer>
{
JSONObject receivedDrivers;
List<Driver> newDrivers = new ArrayList<>();
List<Driver> oldDriversMoved = new ArrayList<>();
List<Driver> removedDrivers = new ArrayList<>();
public Parse_NearbyDrivers_Task(JSONObject receivedDrivers)
{
this.receivedDrivers = receivedDrivers;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Integer doInBackground(Void... params)
{
try
{
//Get the status object from the received JSONObject
JSONObject status = receivedDrivers.getJSONObject("Status");
//Get the status code
int status_code = Integer.parseInt(status.getString("Status"));
//Here we define a switch to handle the values of the status code and return an integer after some work to filter the drivers
switch (status_code) {
case 0: //The list is not empty
{
JSONArray nearbyDrivers = receivedDrivers.getJSONArray("NearbyDrivers");
if (driverList.isEmpty()) //If the driversList is empty
{
//Iterate over all the new drivers and add them to the driverList and return 0
for (int i = 0; i < nearbyDrivers.length(); ++i) {
Driver tempDriver = new Driver();
tempDriver.id = Integer.parseInt(nearbyDrivers.getJSONObject(i).getString("pkDriverId"));
tempDriver.longitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Longitude"));
tempDriver.latitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Latitude"));
tempDriver.altitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Altitude"));
tempDriver.angle = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Angle"));
tempDriver.speed = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Speed"));
tempDriver.accuracy = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Accuracy"));
tempDriver.distanceCovered = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("DistanceCovered"));
tempDriver.carType = Integer.parseInt(nearbyDrivers.getJSONObject(i).getString("CarTypeCode"));
driverList.add(tempDriver);
}
return 0;
} else //If the driversList is not empty
{
//Iterate over the received list and if the list contain a new driver then add it to the newDrivers
// but if it contain an already added driver but with different coordinates then add this driver to
// the oldDriversMoved to later move this driver to the new coordinates
for (int i = 0; i < nearbyDrivers.length(); i++) {
Driver tempDriver = new Driver();
tempDriver.id = Integer.parseInt(nearbyDrivers.getJSONObject(i).getString("pkDriverId"));
tempDriver.longitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Longitude"));
tempDriver.latitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Latitude"));
tempDriver.altitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Altitude"));
tempDriver.angle = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Angle"));
tempDriver.speed = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Speed"));
tempDriver.accuracy = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Accuracy"));
tempDriver.distanceCovered = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("DistanceCovered"));
tempDriver.carType = Integer.parseInt(nearbyDrivers.getJSONObject(i).getString("CarTypeCode"));
if (!isDriverAlreadyExists(driverList, nearbyDrivers.getJSONObject(i).getInt("pkDriverId"))) {
newDrivers.add(tempDriver);
} else {
for (int j = 0; j < driverList.size(); ++j) {
if (nearbyDrivers.getJSONObject(i).getInt("pkDriverId") == driverList.get(j).id) {
if (Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Longitude")) != driverList.get(j).longitude || Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Latitude")) != driverList.get(j).latitude) {
oldDriversMoved.add(tempDriver);
}
}
}
}
}
//If a driver is no more existing then add it to the removedDrivers List
for (int j = 0; j < driverList.size(); j++) {
if (!isDriverAlreadyExists(nearbyDrivers, driverList.get(j).id)) {
removedDrivers.add(driverList.get(j));
}
}
//return 1 to be handled in the onPostExecute
return 1;
}
}
case 1: //The list is empty
case 500: //The list is empty
return 2;
default: //Some error
return -1;
}
} catch (JSONException e) {
return -2;
}
}
#Override
protected void onPostExecute(Integer status)
{
super.onPostExecute(status);
try {
//According to what is received from the doInBackground make some actions that will affect the markers of the drivers
switch (status) {
case 0:
noNearby = false;
Plant_NearbyDrivers();
//helper_methods.Debug("Arrays sizes","DriverList:"+driverList.size()+" Existing map markers: "+existingMapMarkers.size());
break;
case 1:
noNearby = false;
Add_Remove_Move_Drivers(removedDrivers, oldDriversMoved, newDrivers);
break;
case 2:
Remove_AllDriverFromMap();
break;
}
} catch (Exception e) {
e.printStackTrace();
}
BusyParsingDrivers = false;
}
}
/**
* This method is called after receiving the drivers list and filtering this list according to new,removed,moved drivers to handle these actions
**/
private void Add_Remove_Move_Drivers(List<Driver> removedDrivers, List<Driver> oldDriversMoved, List<Driver> newDrivers)
{
//Get the icon that will be used to add the new drivers
BitmapDescriptor icon = getCarIcon();
ArrayList<ObjectAnimator> objectAnimatorsArray = new ArrayList<>();
ObjectAnimator[] objectAnimators;
TypeEvaluator<LatLng> typeEvaluator = new TypeEvaluator<LatLng>() {
#Override
public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
return new LatLngInterpolator.Spherical().interpolate(fraction, startValue, endValue);
}
};
//Iterate the removedDrivers list to see the matching drivers in the driversList and remove it
for (int i = 0; i < removedDrivers.size(); ++i) {
for (int j = 0; j < driverList.size(); ++j) {
//When Ids match then remove from the existingMapMarkers list and driversList
if (removedDrivers.get(i).id == driverList.get(j).id) {
driverList.remove(j);
existingMapMarkers.get(j).remove();
existingMapMarkers.remove(j);
}
}
}
//Iterate the oldDriversMoved List to get the matching in the driversList and update it and move it according to the new coordinates
for (int i = 0; i < oldDriversMoved.size(); ++i) {
for (int j = 0; j < driverList.size(); ++j) {
//When we get the match update the driver in driversList and move it to the new LatLang
if (oldDriversMoved.get(i).id == driverList.get(j).id) {
LatLng newDriverLatLng = new LatLng(oldDriversMoved.get(i).latitude, oldDriversMoved.get(i).longitude);
float desiredRotation = oldDriversMoved.get(i).angle;
ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(existingMapMarkers.get(j), "rotation", existingMapMarkers.get(j).getRotation(), desiredRotation);
rotationAnimator.setDuration(1500);
objectAnimatorsArray.add(rotationAnimator);
Property<Marker, LatLng> property = Property.of(Marker.class, LatLng.class, "position");
ObjectAnimator directionAnimator = ObjectAnimator.ofObject(existingMapMarkers.get(j), property, typeEvaluator, newDriverLatLng);
directionAnimator.setDuration(3000);
objectAnimatorsArray.add(directionAnimator);
objectAnimators = objectAnimatorsArray.toArray(new ObjectAnimator[objectAnimatorsArray.size()]);
AnimatorSet animDrivers = new AnimatorSet();
animDrivers.playTogether(objectAnimators);
animDrivers.start();
int position = driverList.indexOf(driverList.get(j));
driverList.remove(position);
driverList.add(position, oldDriversMoved.get(i));
}
}
}
//Iterate the newDrivers List to add them as markers and to the driversList
for (int i = 0; i < newDrivers.size(); ++i) {
LatLng newDriverLatLng = new LatLng(newDrivers.get(i).latitude, newDrivers.get(i).longitude);
driverList.add(newDrivers.get(i));
existingMapMarkers.add(map.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(newDriverLatLng).icon(icon)));
}
}
/**
* Remove all the drivers from the map
**/
public void Remove_AllDriverFromMap()
{
//Iterate all the drivers markers and remove them
for (int i = 0; i < existingMapMarkers.size(); ++i) {
existingMapMarkers.get(i).remove();
}
//Clear the arrays and set noNearby to true
noNearby = true;
driverList.clear();
existingMapMarkers.clear();
}
/**
* This method is called when there is no drivers visible on the map and we receive a list of drivers so we plant them right away
**/
private void Plant_NearbyDrivers()
{
try {
BitmapDescriptor icon = getCarIcon();
for (int i = 0; i < driverList.size(); i++) {
LatLng newDriverLatLng = new LatLng(driverList.get(i).latitude, driverList.get(i).longitude);
existingMapMarkers.add(map.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(newDriverLatLng).icon(icon)));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Called to compare if the new drivers received is contained in the old driver list
**/
public boolean isDriverAlreadyExists(List<Driver> array, int driverId)
{
for (int c = 0; c < array.size(); c++) {
Driver current = array.get(c);
if (current.id == driverId)
return true;
}
return false;
}
/**
* Called to compare if the old drivers list is contained in the new drivers list
**/
public boolean isDriverAlreadyExists(JSONArray nearbyDrivers, int driverId)
{
for (int c = 0; c < nearbyDrivers.length(); c++) {
try {
JSONObject current = nearbyDrivers.getJSONObject(c);
if (current.getInt("pkDriverId") == driverId)
return true;
} catch (JSONException e) {
e.printStackTrace();
}
}
return false;
}
/**
* Get the icon of the car to be displayed according to the selected filter
**/
public BitmapDescriptor getCarIcon()
{
BitmapDescriptor icon = null;
//make the icon as you want
return icon;
}
add this to your build
compile 'com.nineoldandroids:library:2.4.0'

Related

android: how to make the method synchronized [duplicate]

This problem has bothered me for a long time. I use a cloud database called bmob, and I found that I can successfully get the data I want. However, there might be some mistakes in the loops, and I could only get the information of the last selected item.
p.s. I use an array list called Playlist to store the calculated data that I will use to display a list-view in the next activity.
here is my code:
public class DestinationActivity extends Activity implements OnClickListener, NumberPicker.OnValueChangeListener {
private TextView from_place, date, days, start_time, end_time, number, money_view;
private Button addButton, subButton;
private ImageView backButton, telephone;
private ListView listView;
private Button destinationOk_btn;
private ShapeLoadingDialog shapeLoadingDialog;
private Tip startTip;
private Calendar calendar;
private DatePickerDialog dialog;
private TimePickerDialog dialog2;
private List<Destination> destinationList = new ArrayList<Destination>();
private DestinationAdapter adapter;
private int number_value = 1;
private String time_start;
private String time_end;
private int travel_days;
double travelTime;//total playing time
double travel_time;
private int money;
private int num = 1;
private ArrayList<Integer> select_placeID = new ArrayList<Integer>();
public Map<Integer,Double> weightMap;
public List<Plan> planList = new ArrayList<Plan>();
int[] selectedID = new int[10];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.destination_layout);
//initialize the cloud database
Bmob.initialize(this, BmobConfig.APP_ID);
listView = (ListView) findViewById(R.id.list_destination);
destinationOk_btn = (Button) findViewById(R.id.okButton);
initDestinations(); // initialize the data
adapter = new DestinationAdapter(destinationList, DestinationActivity.this);
//adapter = new DestinationAdapter(this, destinationList, DestinationAdapter.getIsSelected());
listView.setAdapter(adapter);
//....listeners and textviews.......
//submit button
destinationOk_btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
select_placeID.clear();
for (int i = 0; i < destinationList.size(); i++) {
if (DestinationAdapter.getIsSelected().get(i)) {
select_placeID.add((i + 1));
}
}
//change to int array
selectedID = new int[select_placeID.size()];
for(int i = 0;i<select_placeID.size();i++){
selectedID[i] = select_placeID.get(i);
}
if (select_placeID.size() == 0) {
AlertDialog.Builder builder1 = new AlertDialog.Builder(DestinationActivity.this);
builder1.setMessage("no records");
builder1.show();
}
else {
AlertDialog.Builder builder = new AlertDialog.Builder(DestinationActivity.this);
builder.setMessage("waiting for magic...");
builder.show();
/**
* calculate the route
*/
if (validate()) {
new calRoute().execute();
}
}
}
});
}
//initialize the data
private void initDestinations() {
//........
}
#Override
public void onClick(View v) {
//.......
}
/**
* asynctask
*/
private class calRoute extends AsyncTask<Void, Void, List<Plan>>{
public calRoute(){
// TODO Auto-generated constructor stub
}
#Override
protected List<Plan> doInBackground(Void... params) {
List<Plan> result = calculate(time_start, time_end, travel_days);
return result;
}
#Override
protected void onPostExecute(List<Plan> result) {
super.onPostExecute(result);
if (result != null) {
Toast.makeText(DestinationActivity.this, "success", Toast.LENGTH_SHORT).show();
if(planList.size() > 0) {
Intent intent = new Intent();
intent.setClass(DestinationActivity.this, ActivityPlan.class);
intent.putParcelableArrayListExtra("planInfo", (ArrayList<? extends Parcelable>) planList);
startActivity(intent);
}
else{
Toast.makeText(DestinationActivity.this, "no plan", Toast.LENGTH_SHORT).show();
}
}
}
}
/**
*plan
**/
public List<Plan> calculate(String time_start, String time_end, int travel_days) {
SimpleDateFormat df = new SimpleDateFormat(("HH:mm"));
Date starttime = new Date();
Date endtime = new Date();
try {
starttime = df.parse(time_start);
} catch (ParseException e) {
e.printStackTrace();
}
try {
endtime = df.parse(time_end);
} catch (ParseException e) {
e.printStackTrace();
}
double l = endtime.getTime() - starttime.getTime();
double hour = (l / (60 * 60 * 1000));
double min = ((l / (60 * 1000)) - hour * 60);
if(min == 0){
min = 60;
}
else {
travel_time = ((1.0 * travel_days * hour) * (min / 60));
DecimalFormat decimalFormat = new DecimalFormat("#.0");
travelTime = Double.parseDouble(decimalFormat.format(travel_time));
}
weightMap = new LinkedHashMap<Integer, Double>(); //store weight
int totalPriority = 0;//total priority
final Destination start = new Destination(116.32133, 39.92269);
final HashMap<Integer, Integer> pMap = new HashMap<Integer, Integer>();
final HashMap<Integer, String> nameMap = new HashMap<Integer, String>();
final HashMap<Integer, Destination> objectMap = new LinkedHashMap<Integer, Destination>();
/**
* get the data from cloud database
*/
BmobQuery<Destination> query = new BmobQuery<Destination>();
for (int sid: selectedID) {
query.addWhereEqualTo("id", sid);
query.findObjects(new FindListener<Destination>() {
#Override
public void done(List<Destination> list, BmobException e) {
if (e == null) {
System.out.println("success:total" + list.size() + "items。");
for (Destination destination : list) {
int p = destination.getPriority();
int id = destination.getId();
String name = destination.getName();
double longitude = destination.getLongitude();
double latitude = destination.getLatitude();
objectMap.put(id, new Destination(longitude, latitude));
System.out.println(id);
double dis = DistanceUtil.distance(start.getLongitude(), start.getLatitude(),
longitude, latitude);
pMap.put(id, p);
weightMap.put(id, new Double(dis));
nameMap.put(id, name);
}
} else {
Log.i("bmob", "error:" + e.getMessage() + "," + e.getErrorCode());
}
}
});
}
for (Integer key : pMap.keySet()) {
int p = pMap.get(key).intValue();
totalPriority = totalPriority + p;
}
double weight = 0.0;
for (Map.Entry<Integer, Double> hm : weightMap.entrySet()) {
double hm2Value = pMap.get(hm.getKey());
weight = totalPriority / hm.getValue() * hm2Value;
weightMap.put(hm.getKey(), weight);
}
/**
* 按照weight值来排序
* 判断是否传递数据给plan_activity
*/
MapUtil.sortByValue(weightMap);
//排好序后计算距离
Iterator it = weightMap.entrySet().iterator();
int order = 0;
while (it.hasNext()) {
order++;
Map.Entry entry = (Map.Entry) it.next();
objectMap.put(new Integer(order), objectMap.get(entry.getKey()));
}
PlanTask planTask = new PlanTask();//封装了每个plan计算的方法
for (Map.Entry<Integer, Double> entry : weightMap.entrySet()) {
System.out.println("id= " + entry.getKey());
double play_time = planTask.calPlay_time(weightMap.size(),
weightMap.get(entry.getKey()), travelTime);
double driving_time = planTask.calDrive_time(DistanceUtil.distance(
objectMap.get(entry.getKey()).getLatitude(),
objectMap.get(entry.getKey()).getLongitude(),
objectMap.get(entry.getKey() + 1).getLatitude(),
objectMap.get(entry.getKey() + 1).getLongitude()
));
String arrive_time = "hello world";//未完待续
String place_name = nameMap.get(entry.getKey());
Plan plan = new Plan(place_name, arrive_time, driving_time, play_time);
//传递plan对象list
planList.add(entry.getKey(), plan);
}
return planList;
}
}
When I debug it, I found that in calculate() functions, the output of
BmobQuery<Destination> query = new BmobQuery<Destination>();
for (int sid: selectedID) {
query.addWhereEqualTo("id", sid);
query.findObjects(new FindListener<Destination>() {
#Override
public void done(List<Destination> list, BmobException e) {
if (e == null) {
System.out.println("success:total" + list.size() + "items。");
for (Destination destination : list) {
int p = destination.getPriority();
int id = destination.getId();
String name = destination.getName();
double longitude = destination.getLongitude();
double latitude = destination.getLatitude();
objectMap.put(id, new Destination(longitude, latitude));
System.out.println(id);
//calculate the distance
double dis = DistanceUtil.distance(start.getLongitude(), start.getLatitude(),
longitude, latitude);
pMap.put(id, p);
weightMap.put(id, new Double(dis));
nameMap.put(id, name);
}
} else {
Log.i("bmob", "error:" + e.getMessage() + "," + e.getErrorCode());
}
}
});
is "success:total 1 items." and after the loop, if I have selected 3 items, it would be "success:total 1 items." for 3 times and only the information of the last item is caught.
AND the size of three hash map: pMap, nameMap and objectMap are all zero. Why is it??? It is so strange...
There is no error in LogCAT, however, the ordered list view cannot display in the second activity. PLEASE help me, it has bothered me for a long time.
Thank you!!!
I couldn't figure out much unfortunately, since I am not really comfortable with reactive programming yet as the platform uses a lot of rxjava in general, but here is something that would enhance the code a little bit
final HashMap<Integer, Integer> pMap = new HashMap<Integer, Integer>();
final HashMap<Integer, String> nameMap = new HashMap<Integer, String>();
final HashMap<Integer, Destination> objectMap = new LinkedHashMap<Integer, Destination>();
/**
* get the data from cloud database
*/
BmobQuery<Destination> query = new BmobQuery<Destination>();
// this time only one list of three elements is added instead of three lists of one element each
query.addWhereContainedIn("id", Arrays.asList(selectedID));
query.findObjects(new FindListener<Destination>() {
#Override
public void done(List<Destination> list, BmobException e) {
if (e == null) {
System.out.println("success:total" + list.size() + "items。");
for (Destination destination : list) {
int p = destination.getPriority();
int id = destination.getId();
String name = destination.getName();
double longitude = destination.getLongitude();
double latitude = destination.getLatitude();
objectMap.put(id, new Destination(longitude, latitude));
System.out.println(id);
//calculate the distance
double dis = DistanceUtil.distance(start.getLongitude(), start.getLatitude(),
longitude, latitude);
pMap.put(id, p);
weightMap.put(id, new Double(dis));
nameMap.put(id, name);
}
// continue execution here though you won't be able to return a list of plans here
} else {
Log.i("bmob", "error:" + e.getMessage() + "," + e.getErrorCode());
}
}
});
Hope this helps :)
List<HashMap<Integer, Destination>> listmap=new ArrayList<>;
final HashMap<Integer, Destination> objectMap;
/**
* get the data from cloud database
*/
BmobQuery<Destination> query = new BmobQuery<Destination>();
// this time only one list of three elements is added instead of three lists of one element each
query.addWhereContainedIn("id", Arrays.asList(selectedID));
query.findObjects(new FindListener<Destination>() {
#Override
public void done(List<Destination> list, BmobException e) {
if (e == null) {
System.out.println("success:total" + list.size() + "items。");
for (Destination destination : list) {
objectMap = new LinkedHashMap<Integer, Destination>();
int id = destination.getId();
objectMap.put(id, destination);
listmap.add(objectMap);
}
// continue execution here though you won't be able to return a list of plans here
} else {
Log.i("bmob", "error:" + e.getMessage() + "," + e.getErrorCode());
}
}
Try this

Find the closest point on polygon to user location

I have an app that find the shortest distance between my user to a polygon.
I want to convert the polygon to Geofence to check the distance between the user to the area to give mor accurate information to the user.
how can I do that?
this is the MapsActivity
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener, MinimumDistanceTask.GetMinimumDistanceListener {
private GoogleMap mMap;
private LocationManager manager;
private double lat, lng;
private KmlLayer layer;
private LatLng latLngTest;
private boolean contains = false;
private ArrayList<LatLng> outerBoundary;
#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);
manager = (LocationManager) getSystemService(LOCATION_SERVICE);
}
#Override
protected void onResume() {
super.onResume();
String provider = LocationManager.GPS_PROVIDER;
//take the user location every second
try {
manager.requestLocationUpdates(provider, 1000, 0, this);
}catch (SecurityException e){
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
#Override
public void onLocationChanged(Location location) {
//clear map before create new location
mMap.clear();
try {
//load the kml file
layer = new KmlLayer(mMap, R.raw.polygon_layer, this);
layer.addLayerToMap();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
lat = location.getLatitude();
lng = location.getLongitude();
latLngTest = new LatLng(lat,lng);
// Add a marker in user location
LatLng userLocation = new LatLng(latLngTest.latitude, latLngTest.longitude);
mMap.addMarker(new MarkerOptions().position(userLocation).title("you are here"));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 15));
//check if the user in the polygon
boolean inside = ifUserInside();
if(inside){
Toast.makeText(MapsActivity.this, "you are in the polygon", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MapsActivity.this, "you are outside the polygon", Toast.LENGTH_SHORT).show();
//create the string address for the url
String address = "";
for (int i = 0; i < outerBoundary.size(); i++) {
address += (outerBoundary.get(i).toString() + "|");
address = address.replace("lat/lng:", "");
address = address.replace(" ", "");
address = address.replace("(", "");
address = address.replace(")", "");
}
MinimumDistanceTask task = new MinimumDistanceTask(this);
task.execute("https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins="+latLngTest.latitude+ "," + latLngTest.longitude
+ "&destinations=" + address + "&mode=walking");
}
}
#Override
public void getMinimumDistance(int closeLocation) {
//check if you get results properly
if(closeLocation != -1) {
GetDirection direction = new GetDirection();
direction.execute("https://maps.googleapis.com/maps/api/directions/json?origin=" + latLngTest.latitude + "," + latLngTest.longitude
+ "&destination=" + outerBoundary.get(closeLocation).latitude + "+" + outerBoundary.get(closeLocation).longitude);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
public boolean ifUserInside(){
if (layer.getContainers() != null) {
for (KmlContainer container : layer.getContainers()) {
if (container.getPlacemarks() != null) {
for (KmlPlacemark placemark : container.getPlacemarks()) {
contains = false;
if (placemark.getGeometry() instanceof KmlPolygon) {
KmlPolygon polygon = (KmlPolygon) placemark.getGeometry();
// Get the outer boundary and check if the test location lies inside
outerBoundary = polygon.getOuterBoundaryCoordinates();
contains = PolyUtil.containsLocation(latLngTest, outerBoundary, true);
if (contains) {
// Get the inner boundaries and check if the test location lies inside
ArrayList<ArrayList<LatLng>> innerBoundaries = polygon.getInnerBoundaryCoordinates();
if (innerBoundaries != null) {
for (ArrayList<LatLng> innerBoundary : innerBoundaries) {
// If the test location lies in a hole, the polygon doesn't contain the location
if (PolyUtil.containsLocation(latLngTest, innerBoundary, true)) {
contains = false;
}
}
}
}
}
}
}
}
}
return contains;
}
public class GetDirection extends AsyncTask<String , Void, String> {
HttpsURLConnection connection = null;
BufferedReader reader = null;
StringBuilder builder = new StringBuilder();
#Override
protected String doInBackground(String... params) {
String address = params[0];
try {
URL url = new URL(address);
connection = (HttpsURLConnection) url.openConnection();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK){
return "Error from server";
}
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null){
builder.append(line);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return builder.toString();
}
#Override
protected void onPostExecute(String s) {
//get the polyline string
String polygonPoints = "";
try {
JSONObject object = new JSONObject(s);
JSONArray array = object.getJSONArray("routes");
for (int i = 0; i < array.length(); i++) {
JSONObject arrObj1 = array.getJSONObject(i);
JSONObject points = arrObj1.getJSONObject("overview_polyline");
polygonPoints = points.getString("points");
}
//convert the string to polyline;
ArrayList<LatLng> a = new ArrayList<>(decodePolyPoints(polygonPoints));
//add polyline to the map
mMap.addPolyline(new PolylineOptions().addAll(a).width(10).color(Color.BLUE));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
//the method that convert the string to polyline
public static ArrayList<LatLng> decodePolyPoints(String encodedPath){
int len = encodedPath.length();
final ArrayList<LatLng> path = new ArrayList<LatLng>();
int index = 0;
int lat = 0;
int lng = 0;
while (index < len) {
int result = 1;
int shift = 0;
int b;
do {
b = encodedPath.charAt(index++) - 63 - 1;
result += b << shift;
shift += 5;
} while (b >= 0x1f);
lat += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
result = 1;
shift = 0;
do {
b = encodedPath.charAt(index++) - 63 - 1;
result += b << shift;
shift += 5;
} while (b >= 0x1f);
lng += (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
path.add(new LatLng(lat * 1e-5, lng * 1e-5));
}
return path;
}
}
This is my AsyncTask to get the minimum distance point
public class MinimumDistanceTask extends AsyncTask<String, Void, Integer>{
private int closeLocation;
// private String points;
private GetMinimumDistanceListener listener;
public MinimumDistanceTask(GetMinimumDistanceListener listener){
// this.points = points;
this.listener = listener;
}
#Override
protected Integer doInBackground(String... params) {
HttpsURLConnection connection = null;
BufferedReader reader = null;
StringBuilder builder = new StringBuilder();
int minimumDis = -1;
String address = params[0];
try {
URL url = new URL(address);
connection = (HttpsURLConnection) url.openConnection();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK){
return -1;
}
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null){
builder.append(line);
}
///get the json data
JSONObject jsonObject1 = new JSONObject(builder.toString());
JSONArray points = jsonObject1.getJSONArray("rows");
JSONObject jsonObject2 = points.getJSONObject(0);
JSONArray elements = jsonObject2.getJSONArray("elements");
for (int i = 0; i < elements.length(); i++) {
JSONObject jsonObject3 = elements.getJSONObject(i);
JSONObject distance = jsonObject3.getJSONObject("distance");
if( distance.getInt("value") < minimumDis || minimumDis == -1) {
minimumDis = distance.getInt("value");
closeLocation = i;
}
}
} catch (MalformedURLException | JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return closeLocation;
}
#Override
protected void onPostExecute(Integer closeLocation) {
listener.getMinimumDistance(closeLocation);
}
public interface GetMinimumDistanceListener{
void getMinimumDistance(int closeLocation);
}
}
thanks a lot :)
You can use a function like the following to calculate the nearest point from polygon defined by a List<LatLng> and a given LatLng.
It uses the PolyUtil.distanceToLine from the Google Maps Android API Utility Library to compute the distance between the test LatLng and every segment of the list, and a method based on the distanceToLine method from https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/PolyUtil.java to compute the projection of a point on a segment.
private LatLng findNearestPoint(LatLng test, List<LatLng> target) {
double distance = -1;
LatLng minimumDistancePoint = test;
if (test == null || target == null) {
return minimumDistancePoint;
}
for (int i = 0; i < target.size(); i++) {
LatLng point = target.get(i);
int segmentPoint = i + 1;
if (segmentPoint >= target.size()) {
segmentPoint = 0;
}
double currentDistance = PolyUtil.distanceToLine(test, point, target.get(segmentPoint));
if (distance == -1 || currentDistance < distance) {
distance = currentDistance;
minimumDistancePoint = findNearestPoint(test, point, target.get(segmentPoint));
}
}
return minimumDistancePoint;
}
/**
* Based on `distanceToLine` method from
* https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/PolyUtil.java
*/
private LatLng findNearestPoint(final LatLng p, final LatLng start, final LatLng end) {
if (start.equals(end)) {
return start;
}
final double s0lat = Math.toRadians(p.latitude);
final double s0lng = Math.toRadians(p.longitude);
final double s1lat = Math.toRadians(start.latitude);
final double s1lng = Math.toRadians(start.longitude);
final double s2lat = Math.toRadians(end.latitude);
final double s2lng = Math.toRadians(end.longitude);
double s2s1lat = s2lat - s1lat;
double s2s1lng = s2lng - s1lng;
final double u = ((s0lat - s1lat) * s2s1lat + (s0lng - s1lng) * s2s1lng)
/ (s2s1lat * s2s1lat + s2s1lng * s2s1lng);
if (u <= 0) {
return start;
}
if (u >= 1) {
return end;
}
return new LatLng(start.latitude + (u * (end.latitude - start.latitude)),
start.longitude + (u * (end.longitude - start.longitude)));
}
You can test it with the following code:
List<LatLng> points = new ArrayList<>();
points.add(new LatLng(2, 2));
points.add(new LatLng(4, 2));
points.add(new LatLng(4, 4));
points.add(new LatLng(2, 4));
points.add(new LatLng(2, 2));
LatLng testPoint = new LatLng(3, 0);
LatLng nearestPoint = findNearestPoint(testPoint, points);
Log.e("NEAREST POINT: ", "" + nearestPoint); // lat/lng: (3.0,2.0)
Log.e("DISTANCE: ", "" + SphericalUtil.computeDistanceBetween(testPoint, nearestPoint)); // 222085.35856591124

Generate random number without repetition

bt.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View p1)
{
try{
List<Integer> dataList = new ArrayList<Integer>();
int start = 5;
int end = 15;
for (int i = start; i <= end; i++){
dataList.add(i);
}
Collections.shuffle(dataList);
int[] num = new int[dataList.size()];
for (int i = 0; i < dataList.size(); i++) {
num[i] = dataList.get(i);
}
for (int i = 0; i < num.length; i++) {
t.setText(num[i]);
}
}catch (Exception e) {
e.printStackTrace();
}
}});
I want to show my random number on text view but it shown nothing or crash without catch Exception
What should I do?
What and where is my error?
You should be able to use the diamond operator <>. You can only display one String at a time, so first make a String (and you don't need to copy to an array first). Something like,
try {
List<Integer> dataList = new ArrayList<>(); // <-- <Integer> if you can't.
int start = 5;
int end = 15;
for (int i = start; i <= end; i++) {
dataList.add(i);
}
Collections.shuffle(dataList);
t.setText(dataList.toString());
} catch (Exception e) {
e.printStackTrace();
}

Get Index Of The Shuffled Item After collections.shuffle

I am trying to do a jigsaw puzzle app in android. In this, I have split a Bitmap into many small chunks. These chunks are then displayed in a GridViewNow I need to shuffle them. Then, I need to know each image chunk's actualPosition(where the piece was supposed to be, its actual location in the image) and its currentPosition(where the piece is currently located). actualPosition and currentPosition are 2 integer arrays. So is there a way that I can get each image chunk's currentPosition and actualPosition after the shuffling so that after every move that the user make I can check wether every image chunk's actualPosition equals its currentPosition. If so the user wins the game. Can anyone please help me out.
Below is the number puzzle game in pure Java that works. Can be run from command line.
It re-prints the whole matrix after every move (not pretty). It demos the basic game.
I hope most of the code is self explanatory. This shows the basic 2-dim mapping of the game, position tracking, validating based on numbers. Have fun.
package madhav.turangi.basic.game;
import java.util.Random;
import java.util.Scanner;
public class NumberPuzzle {
int size;
int[][] arr;
int spaceRow;
int spaceCol;
int turnsTook;
public NumberPuzzle(int size) {
this.size = size;
arr = new int[size][size];
}
void init()
{
for(int r=0; r<size; r++)
{
for(int c=0; c<arr[r].length; c++)
{
arr[r][c] = r*size + c + 1; // row-column of cell to its value equation
}
}
spaceRow = spaceCol = size - 1; // bottom-right cell index
}
int readUserInput()
{
int value = -1;
boolean valid = false;
do {
System.out.printf("To move space [0 - Up, 1 - Down, 2 - Left, 3 - Right] : ? ");
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
try
{
value = Integer.parseInt(line);
valid = (value>=0 && value<=3);
}
catch(NumberFormatException ne)
{
}
if(! valid) System.out.println("== Invalid ==");
} while (! valid);
return value;
}
void swap(int aRow, int aCol, int withRow, int withCol)
{
int temp = arr[aRow][aCol];
arr[aRow][aCol] = arr[withRow][withCol];
arr[withRow][withCol] = temp;
}
boolean moveUp()
{
if(spaceRow != 0)
{
int newSpaceRow = spaceRow - 1;
swap(spaceRow, spaceCol, newSpaceRow, spaceCol);
spaceRow--;
return true;
}
else
{
return false;
}
}
boolean moveDown()
{
if(spaceRow != size-1)
{
int newSpaceRow = spaceRow + 1;
swap(spaceRow, spaceCol, newSpaceRow, spaceCol);
spaceRow++;
return true;
}
else
{
return false;
}
}
boolean moveRight()
{
if(spaceCol != size-1)
{
int newSpaceCol = spaceCol + 1;
swap(spaceRow, spaceCol, spaceRow, newSpaceCol);
spaceCol++;
return true;
}
else
{
return false;
}
}
boolean moveLeft()
{
if(spaceCol != 0)
{
int newSpaceCol = spaceCol - 1;
swap(spaceRow, spaceCol, spaceRow, newSpaceCol);
spaceCol--;
return true;
}
else
{
return false;
}
}
void shuffle()
{
Random rnd = new Random(System.currentTimeMillis());
boolean moved = false;
int attemptCount = 1;
int maxMoves = 20;
for(int moveCount=0; moveCount<maxMoves; moveCount++, attemptCount++)
{
int randomMoveDir = rnd.nextInt(4);
moved = move(randomMoveDir);
if(! moved) moveCount--; //ensure maxMoves number of moves
}
System.out.printf("Shuffle attempts %d\n",attemptCount);
}
boolean move(int dir)
{
boolean moved = false;
switch(dir)
{
case 0 : // up
moved = moveUp();
break;
case 1 : // down
moved = moveDown();
break;
case 2 : // left
moved = moveLeft();
break;
case 3 : // right
moved = moveRight();
break;
}
return moved;
}
void prnArray()
{
System.out.println("-- -- -- -- --");
for(int[] row : arr)
{
for(int cellValue : row)
{
String v = (cellValue == 16 ? "" : String.valueOf(cellValue));
System.out.printf("%4s", v);
}
System.out.println();
}
System.out.println("-- -- -- -- --");
}
boolean validate()
{
for(int r=0; r<size; r++)
{
for(int c=0; c<arr[r].length; c++)
{
if(arr[r][c] != (r*size + c + 1))
{
return false;
}
}
}
return true;
}
boolean oneTurn()
{
int dir = readUserInput();
boolean moved = move(dir);
boolean won = false;
if(moved)
{
turnsTook++;
prnArray();
won = validate();
}
else
{
System.out.println("= Invalid =");
}
return won;
}
void play()
{
init();
System.out.println("Before shuffle");
prnArray();
shuffle();
prnArray();
boolean won = false;
while(! won)
{
won = oneTurn();
}
System.out.printf("Won in %d\n", turnsTook);
}
public static void main(String[] args)
{
NumberPuzzle puzzle = new NumberPuzzle(4);
puzzle.play();
}
}

Android: how to click on polyline API v2

I would like to click on different polylines. I do not see any documented clickable events for polylines in android.
I found a solution with map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
I just get the polyline LatLng and search for real click coordinates on the map.
The new changes is in the code.
Thanks in advance.
code:
//Polyline
private class GetRouteTask extends AsyncTask<String, Void, String> {
String response = "";
private ProgressDialog progressDialog;
public void onPreExecute()
{
progressDialog = new ProgressDialog(RazhodCenaGoogleMaps2.this);
progressDialog.setMessage("Calculating directions");
progressDialog.show();
}
#Override
protected String doInBackground(String... urls) {
//Get All Route values
v2GetRouteDirection = new GMapV2DirectionGoogle();
document = v2GetRouteDirection.getDocument(latLngFrom, latLngTo, GMapV2DirectionGoogle.MODE_DRIVING);
response = "Success";
return response;
}
#Override
protected void onPostExecute(String result) {
progressDialog.dismiss();
final PolylineOptions rectLine1 = new PolylineOptions().width(3).color(Color.RED).geodesic(true);
final PolylineOptions rectLine2 = new PolylineOptions().width(3).color(Color.GRAY).geodesic(true);
final PolylineOptions rectLine3 = new PolylineOptions().width(3).color(Color.GRAY).geodesic(true);
ArrayList<Integer> Count = v2GetRouteDirection.CountPoly(document);
for(j = 0; j < Routes.size(); j++ ) {
if (j == 0) {
ArrayList<LatLng> directionPoint1 = v2GetRouteDirection.getDirection1(document);
for (int i = 0; i < directionPoint1.size(); i++) {
LatLng point1 = directionPoint1.get(i);
rectLine1.add(point1);
}
// Adding route on the map
map.addPolyline(rectLine1);
}
if (j == 1) {
ArrayList<LatLng> directionPoint2 = v2GetRouteDirection.getDirection2(document);
for (int i = 0; i < directionPoint2.size(); i++) {
LatLng point2 = directionPoint2.get(i);
rectLine2.add(point2);
}
// Adding route on the map
map.addPolyline(rectLine2);
}
if (j == 2) {
ArrayList<LatLng> directionPoint3 = v2GetRouteDirection.getDirection3(document);
for (int i = 0; i < directionPoint3.size(); i++) {
LatLng point3 = directionPoint3.get(i);
rectLine3.add(point3);
}
// Adding route on the map
map.addPolyline(rectLine3);
}
//new code
final PolylineOptions rectLine11 = new PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
final PolylineOptions rectLine21 = new PolylineOptions().width(5).color(Color.GREEN).geodesic(true);
final PolylineOptions rectLine31 = new PolylineOptions().width(5).color(Color.BLACK).geodesic(true);
//searching for roads
ArrayList<Integer> Count1 = v2GetRouteDirection.CountPoly(document);
int j1;
int k = -1;
int p = 0;
int c = 0;
for(j1 = 0; j1 < Count1.size(); j1++ ) {
if (j1 == 0) {
k = 0;
}
if(j1 == 1){
p = 1;
}
if (j1 == 2) {
c = 2;
}
}
final int finalK = k;
final int finalC = c;
final int finalP = p;
//new code
map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
// TODO Auto-generated method stub
latTouch1 = point.latitude;
lonTouch1 = point.longitude;
//Remove decimal from coordinates
DecimalFormat nf = new DecimalFormat("0.0");
String formattedLat = nf.format(latTouch1);
String formattedLon = nf.format(lonTouch1);
double latTouch = Double.parseDouble(formattedLat);
double lonTouch = Double.parseDouble(formattedLon);
LatLng touch = new LatLng(latTouch, lonTouch);
if (finalK == 0) {
ArrayList<LatLng> directionPoint11 = v2GetRouteDirection.getDirection1(document);
for (int i1 = 0; i1 < directionPoint11.size(); i1++) {
LatLng point11 = directionPoint11.get(i1);
Double latlng1 = point11.latitude;
Double latlng2 = point11.longitude;
String formattedLatLng1 = nf.format(latlng1);
String formattedLatLng2 = nf.format(latlng2);
double pointDouble1 = Double.parseDouble(formattedLatLng1);
double pointDouble2 = Double.parseDouble(formattedLatLng2);
LatLng point111 = new LatLng(pointDouble1, pointDouble2);
//check if poly is equal to the real coordinates
if (point111.equals(touch)) {
ArrayList<LatLng> directionPoint1 = v2GetRouteDirection.getDirection1(document);
for (int i = 0; i < directionPoint1.size(); i++) {
LatLng point1 = directionPoint1.get(i);
rectLine11.add(point1);
}
// Adding route on the map
map.addPolyline(rectLine11);
Toast.makeText(getApplicationContext(), "Polyline 1 founded", Toast.LENGTH_SHORT).show();
break;
}
}
}
if (finalP == 1) {
ArrayList<LatLng> directionPoint21 = v2GetRouteDirection.getDirection2(document);
for (int i1 = 0; i1 < directionPoint21.size(); i1++) {
LatLng point11 = directionPoint21.get(i1);
Double latlng1 = point11.latitude;
Double latlng2 = point11.longitude;
String formattedLatLng1 = nf.format(latlng1);
String formattedLatLng2 = nf.format(latlng2);
double pointDouble1 = Double.parseDouble(formattedLatLng1);
double pointDouble2 = Double.parseDouble(formattedLatLng2);
LatLng point111 = new LatLng(pointDouble1, pointDouble2);
if (point111.equals(touch)) {
ArrayList<LatLng> directionPoint2 = v2GetRouteDirection.getDirection2(document);
for (int i = 0; i < directionPoint2.size(); i++) {
LatLng point2 = directionPoint2.get(i);
rectLine21.add(point2);
}
// Adding route on the map
map.addPolyline(rectLine21);
Toast.makeText(getApplicationContext(), "Polyline 2 founded", Toast.LENGTH_SHORT).show();
break;
}
}
}
if (finalC == 2) {
ArrayList<LatLng> directionPoint31 = v2GetRouteDirection.getDirection3(document);
for (int i1 = 0; i1 < directionPoint31.size(); i1++) {
LatLng point11 = directionPoint31.get(i1);
Double latlng1 = point11.latitude;
Double latlng2 = point11.longitude;
String formattedLatLng1 = nf.format(latlng1);
String formattedLatLng2 = nf.format(latlng2);
double pointDouble1 = Double.parseDouble(formattedLatLng1);
double pointDouble2 = Double.parseDouble(formattedLatLng2);
LatLng point111 = new LatLng(pointDouble1, pointDouble2);
if (point111.equals(touch)) {
ArrayList<LatLng> directionPoint3 = v2GetRouteDirection.getDirection3(document);
for (int i = 0; i < directionPoint3.size(); i++) {
LatLng point3 = directionPoint3.get(i);
rectLine31.add(point3);
}
// Adding route on the map
map.addPolyline(rectLine31);
Toast.makeText(getApplicationContext(), "Polyline 3 founded", Toast.LENGTH_SHORT).show();
break;
}
}
}
}
});
}
}

Categories

Resources