package com.openvehicles.OVMS.ui; import java.text.DecimalFormat; import java.util.List; import pl.mg6.android.maps.extensions.CircleOptions; import pl.mg6.android.maps.extensions.ClusterGroup; import pl.mg6.android.maps.extensions.ClusteringSettings; import pl.mg6.android.maps.extensions.GoogleMap; import pl.mg6.android.maps.extensions.GoogleMap.OnInfoWindowClickListener; import pl.mg6.android.maps.extensions.Marker; import pl.mg6.android.maps.extensions.MarkerOptions; import pl.mg6.android.maps.extensions.SupportMapFragment; import android.content.Intent; import android.content.res.Configuration; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; import com.luttu.AppPrefes; import com.openvehicles.OVMS.R; import com.openvehicles.OVMS.entities.CarData; import com.openvehicles.OVMS.ui.GetMapDetails.afterasytask; import com.openvehicles.OVMS.ui.utils.Database; import com.openvehicles.OVMS.ui.utils.DemoClusterOptionsProvider; import com.openvehicles.OVMS.ui.utils.MarkerGenerator; import com.openvehicles.OVMS.ui.utils.Ui; public class FragMap extends BaseFragment implements OnInfoWindowClickListener, afterasytask, OnClickListener, Settings.UpdateMap { private static final String TAG = "FragMap"; private GoogleMap map; Database database; String slat, slng; AppPrefes appPrefes; static boolean flag = true; private static final double[] CLUSTER_SIZES = new double[] { 360, 180, 90, 45, 22 }; View rootView; Menu optionsMenu; boolean autotrack = true; static Settings.UpdateMap updateMap; private CarData mCarData; static double lat = 0, lng = 0; static int maxrange = 160; static String distance_units = "KM"; public interface UpdateLocation { public void updatelocation(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.mmap, null); appPrefes = new AppPrefes(getActivity(), "ovms"); updateMap = this; lat = 37.410866; lng = -122.001946; maxrange = 285; distance_units = "KM"; database = new Database(getActivity()); FragmentManager fm = getActivity().getSupportFragmentManager(); SupportMapFragment f = (SupportMapFragment) fm .findFragmentById(R.id.mmap); map = f.getExtendedMap(); map.setClustering(new ClusteringSettings().clusterOptionsProvider( new DemoClusterOptionsProvider(getResources())) .addMarkersDynamically(true)); map.setOnInfoWindowClickListener(this); map.getUiSettings().setRotateGesturesEnabled(false); // Disable two-finger rotation gesture map.moveCamera(CameraUpdateFactory.zoomTo(15)); // setUpClusteringViews(); setHasOptionsMenu(true); flag = true; // get config: autotrack = !appPrefes.getData("autotrack").equals("off"); return rootView; } @Override public void updateClustering(int clusterSizeIndex, boolean enabled) { ClusteringSettings clusteringSettings = new ClusteringSettings(); clusteringSettings.addMarkersDynamically(true); if (enabled) { after(false); clusteringSettings .clusterOptionsProvider(new DemoClusterOptionsProvider( getResources())); double clusterSize = CLUSTER_SIZES[clusterSizeIndex]; clusteringSettings.clusterSize(clusterSize); } else { lis = map.getMarkers(); for (int i = 0; i < lis.size(); i++) { Marker carmarker = lis.get(i); int j = carmarker.getClusterGroup(); if (j == -1) { lis.remove(i); } else { carmarker.remove(); } } } map.setClustering(clusteringSettings); } List<Marker> lis; private void replacefragment(Fragment frag) { // TODO Auto-generated method stub FragmentTransaction ft = getActivity().getSupportFragmentManager() .beginTransaction(); ft.replace(R.id.fm, frag); ft.commit(); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.map_options, menu); optionsMenu = menu; // set checkboxes: optionsMenu.findItem(R.id.mi_map_autotrack) .setChecked(autotrack); optionsMenu.findItem(R.id.mi_map_filter_connections) .setChecked(appPrefes.getData("filter").equals("on")); optionsMenu.findItem(R.id.mi_map_filter_range) .setChecked(appPrefes.getData("inrange").equals("on")); } @Override public boolean onOptionsItemSelected(MenuItem item) { int menuId = item.getItemId(); boolean newState = !item.isChecked(); switch(menuId) { case R.id.mi_map_autotrack: appPrefes.SaveData("autotrack", newState ? "on" : "off"); item.setChecked(newState); autotrack = newState; if (autotrack) update(); break; case R.id.mi_map_filter_connections: appPrefes.SaveData("filter", newState ? "on" : "off"); item.setChecked(newState); after(false); break; case R.id.mi_map_filter_range: appPrefes.SaveData("inrange", newState ? "on" : "off"); item.setChecked(newState); after(false); break; case R.id.mi_map_settings: Bundle args = new Bundle(); BaseFragmentActivity.show(getActivity(), Settings.class, args, Configuration.ORIENTATION_UNDEFINED); break; } return false; } @Override public void onDestroyView() { try { flag = true; SupportMapFragment fragment = ((SupportMapFragment) getFragmentManager() .findFragmentById(R.id.mmap)); FragmentTransaction ft = getActivity().getSupportFragmentManager() .beginTransaction(); ft.remove(fragment); ft.commit(); database.close(); } catch (Exception e) { } super.onDestroyView(); } private void direction() { // TODO Auto-generated method stub String directions = "https://maps.google.com/maps?saddr=Kanyakumari,+Tamil+Nadu,+India&daddr=Trivandrum,+Kerala,+India"; directions = "https://maps.google.com/maps?saddr=37.410866,-122.001946&daddr=" + slat + "," + slng; // Create Google Maps intent from current location to target location Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(directions)); intent.setClassName("com.google.android.apps.maps", "com.google.android.maps.MapsActivity"); startActivity(intent); } // marker click event @Override public void onInfoWindowClick(Marker marker) { // TODO Auto-generated method stub int j = marker.getClusterGroup(); Log.d(TAG, "click: ClusterGroup=" + j); if (j == 0) { dialog(marker); } } // after fetch value from server @Override public void after(boolean clearmap) { Log.d(TAG, "after: clearmap=" + clearmap); if (clearmap) { map.clear(); } else { lis = map.getMarkers(); for (int i = 0; i < lis.size(); i++) { Marker carmarker = lis.get(i); int j = carmarker.getClusterGroup(); if (j == -1) { lis.remove(i); } else { carmarker.remove(); } } } // Load charge points from database: Cursor cursor; boolean check_range = false; double maxrange_m = 0; if (appPrefes.getData("filter").equals("on")) { // check if filter is defined, else fallback to all stations: String connectionList = appPrefes.getData("Id"); Log.d(TAG, "after: connectionList=(" + connectionList + ")"); if (!connectionList.equals("")) cursor = database.get_mapdetails(connectionList); else cursor = database.get_mapdetails(); } else { // filter off: cursor = database.get_mapdetails(); } if (appPrefes.getData("inrange").equals("on")) { check_range = true; if (distance_units.equals("Miles")) maxrange_m = maxrange * 1.609344 * 1000; else maxrange_m = maxrange * 1000; } Log.d(TAG, "after: addMarkers avail=" + cursor.getCount()); if (cursor.getCount() != 0) { int cnt_added = 0; if (cursor.moveToFirst()) { do { // check position: double Latitude = Double.parseDouble(cursor .getString(cursor.getColumnIndex("Latitude"))); double Longitude = Double.parseDouble(cursor .getString(cursor.getColumnIndex("Longitude"))); if (check_range) { if (distance(lat, lng, Latitude, Longitude) > maxrange_m) continue; } // add marker: String cpid = cursor.getString(cursor.getColumnIndex("cpid")); String title = cursor.getString(cursor.getColumnIndex("Title")); String snippet = cursor.getString(cursor.getColumnIndex("OperatorInfo")); MarkerGenerator.addMarkers(map, title, snippet, new LatLng(Latitude, Longitude), cpid); cnt_added++; } while (cursor.moveToNext()); } Log.d(TAG, "after: addMarkers added=" + cnt_added); } } double roundTwoDecimals(double d) { DecimalFormat twoDForm = new DecimalFormat("#.##"); //Log.d(TAG, "roundTwoDecimals=" + twoDForm.format(d)); return Double.valueOf(twoDForm.format(d)); } // click marker event private void dialog(Marker marker) { // open dialog: Bundle args = new Bundle(); args.putString("cpId", (String) marker.getData()); BaseFragmentActivity.show(getActivity(), DetailFragment.class, args, Configuration.ORIENTATION_UNDEFINED); } @Override public void update(CarData pCarData) { mCarData = pCarData; update(); } public void update() { if (mCarData == null) return; // get last known car position: lat = mCarData.car_latitude; lng = mCarData.car_longitude; maxrange = Math.max(mCarData.car_range_estimated_raw, mCarData.car_range_ideal_raw); distance_units = (mCarData.car_distance_units_raw.equals("M") ? "Miles" : "KM"); Log.d(TAG, "update: Car on map: lat=" + lat + " lng=" + lng + " maxrange=" + maxrange + distance_units); // update charge point markers: after(true); // update car position marker: final LatLng MELBOURNE = new LatLng(lat, lng); Drawable drawable = getResources().getDrawable( Ui.getDrawableIdentifier(getActivity(), "map_" + mCarData.sel_vehicle_image)); Bitmap myLogo = ((BitmapDrawable) drawable).getBitmap(); MarkerOptions marker = new MarkerOptions().position(MELBOURNE) .title(mCarData.sel_vehicle_label) .rotation((float) mCarData.car_direction) .icon(BitmapDescriptorFactory.fromBitmap(myLogo)); Marker carmarker = map.addMarker(marker); carmarker.setClusterGroup(ClusterGroup.NOT_CLUSTERED); if (flag) { map.moveCamera(CameraUpdateFactory.newLatLngZoom(MELBOURNE, 15)); flag = false; } else if (autotrack) { map.moveCamera(CameraUpdateFactory.newLatLng(MELBOURNE)); } // update range circles: Log.i(TAG, "update: adding range circles:" + " ideal=" + mCarData.car_range_ideal_raw + " estimated=" + mCarData.car_range_estimated_raw); addCircles(mCarData.car_range_ideal_raw, mCarData.car_range_estimated_raw); // start chargepoint data update: appPrefes.SaveData("lat_main", "" + mCarData.car_latitude); appPrefes.SaveData("lng_main", "" + mCarData.car_longitude); MainActivity.updateLocation.updatelocation(); } // draw circle in a map private void addCircles(int rd1, int rd2) { float strokeWidth = getResources().getDimension( R.dimen.circle_stroke_width); CircleOptions options = new CircleOptions().strokeWidth(strokeWidth) .strokeColor(Color.BLUE); rd1 = rd1 * 1000; rd2 = rd2 * 1000; map.addCircle(options.center(new LatLng(lat, lng)).data("first circle") .radius(rd1)); options = new CircleOptions().strokeWidth(strokeWidth).strokeColor( Color.RED); map.addCircle(options.center(new LatLng(lat, lng)) .data("second circle").radius(rd2)); } // calculate distance in meters: public static double distance(double lat1, double lon1, double lat2, double lon2) { double dLat = Math.toRadians(lat2-lat1); double dLon = Math.toRadians(lon2-lon1); double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2); double c = 2 * Math.asin(Math.sqrt(a)); return 6371000 * c; } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.bt_route: direction(); break; default: break; } } @Override public void clearCache() { database.clear_latlngdetail(); MainActivity.updateLocation.updatelocation(); } @Override public void updateFilter(String connectionList) { // update markers: after(false); } }