package com.robert.maps.applib.dashboard; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map.Entry; import java.util.TimeZone; import org.andnav.osm.util.GeoPoint; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.res.Configuration; import android.content.res.Resources; import android.location.GpsSatellite; import android.location.GpsStatus; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.Display; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.TextView; import android.widget.Toast; import com.robert.maps.applib.MainActivity; import com.robert.maps.applib.R; import com.robert.maps.applib.trackwriter.IRemoteService; import com.robert.maps.applib.trackwriter.ITrackWriterCallback; import com.robert.maps.applib.utils.CoordFormatter; import com.robert.maps.applib.utils.DistanceFormatter; import com.robert.maps.applib.utils.Ut; public class IndicatorManager implements IndicatorConst { private LinkedHashMap<String, Object> mIndicators = new LinkedHashMap<String, Object>(16, 0.75f, false); private LinkedHashMap<String, String> mIndicatorTitles = new LinkedHashMap<String, String>(16, 0.75f, false); private SampleLocationListener mLocationListener; private ArrayList<IndicatorView> mIndicatorViewList = new ArrayList<IndicatorView>(); private final CoordFormatter mCf; private final DistanceFormatter mDf; private final SimpleDateFormat sdf; private final SimpleDateFormat sdfDelta; private String mTemplateFileName; private LocationManager mLocationManager; private GeoPoint mTargetLocation; private Location mLocation; IRemoteService mService = null; private ServiceConnection mConnection; public IndicatorManager(MainActivity ctx) { mCf = new CoordFormatter(ctx); mDf = new DistanceFormatter(ctx); final Configuration config = ctx.getResources().getConfiguration(); mLocationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE); mLocationListener = new SampleLocationListener(); sdf = new SimpleDateFormat("HH:mm:ss", config.locale); sdfDelta = new SimpleDateFormat("HH:mm:ss", config.locale); sdfDelta.setTimeZone(TimeZone.getTimeZone("UTC")); mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = IRemoteService.Stub.asInterface(service); try { mService.registerCallback(mCallback); } catch (RemoteException e) { } } public void onServiceDisconnected(ComponentName className) { mService = null; } }; setUpIndicators(ctx); initView(ctx, (ViewGroup) ctx.findViewById(R.id.dashboard_area)); try { mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener); } catch (Exception e) { } try { mLocationManager.addGpsStatusListener(mLocationListener); } catch (Exception e) { } ctx.bindService(new Intent(IRemoteService.class.getName()), mConnection, 0 /*Context.BIND_AUTO_CREATE*/); } private void setUpIndicators(Context ctx) { final Resources res = ctx.getResources(); // GPS indicators putIndicator(GPSACCURACY, res.getString(R.string.dashboard_title_gps_accuracy), mDf.formatDistance2(0)); putIndicator(GPSELEV, res.getString(R.string.dashboard_title_gps_altitude), mDf.formatDistance2(0)); putIndicator(GPSBEARING, res.getString(R.string.dashboard_title_gps_bearing), EMPTY); putIndicator(GPSTIME, res.getString(R.string.dashboard_title_gps_time), EMPTY); putIndicator(GPSLAT, res.getString(R.string.dashboard_title_gps_latitude), EMPTY); putIndicator(GPSLON, res.getString(R.string.dashboard_title_gps_longitude), EMPTY); putIndicator(GPSPROVIDER, res.getString(R.string.dashboard_title_gps_provider), mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ? GPS : OFF); putIndicator(GPSSPEED, res.getString(R.string.dashboard_title_gps_speed), mDf.formatSpeed2(0)); // Map indicators putIndicator(MAPNAME, res.getString(R.string.dashboard_title_map_name), EMPTY); putIndicator(MAPCENTERLAT, res.getString(R.string.dashboard_title_map_center_lat), EMPTY); putIndicator(MAPCENTERLON, res.getString(R.string.dashboard_title_map_center_lon), EMPTY); putIndicator(MAPZOOM, res.getString(R.string.dashboard_title_map_zoom), EMPTY); // Track writing indicators putIndicator(TRCNT, res.getString(R.string.points_cnt), EMPTY); putIndicator(TRDIST, res.getString(R.string.distance), mDf.formatSpeed2(0)); putIndicator(TRDURATION, res.getString(R.string.duration), EMPTY); putIndicator(TRMAXSPEED, res.getString(R.string.max_speed), mDf.formatSpeed2(0)); putIndicator(TRAVGSPEED, res.getString(R.string.avg_speed), mDf.formatSpeed2(0)); putIndicator(TRMOVETIME, res.getString(R.string.moving_time), EMPTY); putIndicator(TRAVGMOVESPEED, res.getString(R.string.avg_moving_speed), mDf.formatSpeed2(0)); //Target point putIndicator(TARGETDISTANCE, res.getString(R.string.dashboard_title_target_distance), mDf.formatDistance2(0)); putIndicator(TARGETBEARING, res.getString(R.string.dashboard_title_target_bearing), EMPTY); } private void putIndicator(String tag, String title, Object initValue) { mIndicators.put(tag, initValue); mIndicatorTitles.put(tag, title); } public HashMap<String, Object> getIndicators() { return mIndicators; } private ITrackWriterCallback mCallback = new ITrackWriterCallback.Stub() { @Override public void newPointWrited(double lat, double lon) throws RemoteException { } @Override public void onTrackStatUpdate(int Cnt, double Distance, long Duration, double MaxSpeed, double AvgSpeed, long MoveTime, double AvgMoveSpeed) throws RemoteException { mIndicators.put(TRCNT, Cnt); mIndicators.put(TRDIST, mDf.formatDistance2(Distance)); mIndicators.put(TRDURATION, sdfDelta.format(Duration)); mIndicators.put(TRMAXSPEED, mDf.formatSpeed2(MaxSpeed)); mIndicators.put(TRAVGSPEED, mDf.formatSpeed2(AvgSpeed)); mIndicators.put(TRMOVETIME, sdfDelta.format(MoveTime)); mIndicators.put(TRAVGMOVESPEED, mDf.formatSpeed2(AvgMoveSpeed)); } }; public void setCenter(GeoPoint point) { mIndicators.put(MAPCENTERLAT, mCf.convertLat(point.getLatitude())); mIndicators.put(MAPCENTERLON, mCf.convertLon(point.getLongitude())); updateIndicatorViewValues(); } public void setZoom(int zoom) { mIndicators.put(MAPZOOM, zoom); updateIndicatorViewValues(); } public void setMapName(String name) { mIndicators.put(MAPNAME, name); updateIndicatorViewValues(); } public void setTargetLocation(final GeoPoint geo) { mTargetLocation = geo; updateTargetIndicators(); } public void setLocation(final Location loc) { mLocation = loc; updateTargetIndicators(); } public void Pause(Context ctx) { ((LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE)).removeUpdates(mLocationListener); ctx.unbindService(mConnection); } public void Resume(Context ctx) { try { ((LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE)).requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener); } catch (Exception e) { } mLocationListener.onGpsStatusChanged(0); ctx.bindService(new Intent(IRemoteService.class.getName()), mConnection, 0 /*Context.BIND_AUTO_CREATE*/); } public void Dismiss(MainActivity ctx) { mLocationManager.removeUpdates(mLocationListener); mLocationManager.removeGpsStatusListener(mLocationListener); final JSONObject json = new JSONObject(); try { json.put(JNAME, JMAIN); final JSONArray jarrv = new JSONArray(); ViewGroup llv = (ViewGroup) ctx.findViewById(R.id.dashboard_area); for(int i = 0; i < llv.getChildCount(); i++) { final JSONArray jarr = new JSONArray(); ViewGroup ll = (ViewGroup) llv.getChildAt(i); for(int j = 0; j < ll.getChildCount(); j++) { final IndicatorView iv = (IndicatorView) ll.getChildAt(j); final JSONObject jiv = new JSONObject(); jiv.put(JINDEX, j); jiv.put(JTAG, iv.getIndicatorTag()); jarr.put(jiv); } jarrv.put(jarr); } json.put(JINDICATORS, jarrv); final File folder = Ut.getRMapsMainDir(ctx, DASHBOARD_DIR); if(folder.exists()) { FileWriter writer = new FileWriter(String.format(DASHBOARD_FILE, folder.getAbsolutePath(), mTemplateFileName)); writer.write(json.toString()); writer.close(); } } catch (JSONException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } mIndicatorViewList.clear(); ((ViewGroup) ((MainActivity) ctx).findViewById(R.id.dashboard_area)).removeAllViews(); } private class SampleLocationListener implements LocationListener, GpsStatus.Listener { private int mFix = 0; private int mSat = 0; private int mStatus = 0; private String mProvider = ""; private GpsStatus mGpsStatus; public SampleLocationListener() { super(); mProvider = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ? GPS : OFF; } @Override public void onLocationChanged(Location location) { mLocation = location; if(location != null) { mIndicators.put(GPSACCURACY, mDf.formatDistance2(location.getAccuracy())); mIndicators.put(GPSELEV, mDf.formatDistance2(location.getAltitude())); mIndicators.put(GPSBEARING, String.format(Locale.UK, "%.1f�", location.getBearing())); mIndicators.put(GPSTIME, sdf.format(location.getTime())); mIndicators.put(GPSLAT, mCf.convertLat(Double.valueOf(location.getLatitude()))); mIndicators.put(GPSLON, mCf.convertLon(Double.valueOf(location.getLongitude()))); mIndicators.put(GPSPROVIDER, location.getProvider()); mIndicators.put(GPSSPEED, mDf.formatSpeed2(location.getSpeed())); updateIndicator(); } updateTargetIndicators(); } @Override public void onProviderDisabled(String provider) { if(provider.equalsIgnoreCase(LocationManager.GPS_PROVIDER)) { mProvider = OFF; updateIndicator(); } } @Override public void onProviderEnabled(String provider) { if(provider.equalsIgnoreCase(LocationManager.GPS_PROVIDER)) { mProvider = GPS; updateIndicator(); } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { if(provider.equalsIgnoreCase(LocationManager.GPS_PROVIDER)) { mStatus = status; updateIndicator(); } } @Override public void onGpsStatusChanged(int event) { mGpsStatus = mLocationManager.getGpsStatus(mGpsStatus); mFix = 0; mSat = 0; Iterator<GpsSatellite> it = mGpsStatus.getSatellites().iterator(); while(it.hasNext()) { mSat++; if(it.next().usedInFix()) mFix++; } updateIndicator(); } private void updateIndicator() { if(mProvider.equalsIgnoreCase(GPS)) mIndicators.put(GPSPROVIDER, String.format(Locale.UK, "%s %d/%d", mProvider, mFix, mSat)); else mIndicators.put(GPSPROVIDER, mProvider); updateIndicatorViewValues(); } } public int getOrientation(Activity context) { Display getOrient = context.getWindowManager().getDefaultDisplay(); //int orientation = getOrient.getOrientation(); int orientation = context.getResources().getConfiguration().orientation; // Sometimes you may get undefined orientation Value is 0 // simple logic solves the problem compare the screen // X,Y Co-ordinates and determine the Orientation in such cases if (orientation == Configuration.ORIENTATION_UNDEFINED) { Configuration config = context.getResources().getConfiguration(); orientation = config.orientation; if (orientation == Configuration.ORIENTATION_UNDEFINED) { // if height and widht of screen are equal then // it is square orientation if (getOrient.getWidth() == getOrient.getHeight()) { orientation = Configuration.ORIENTATION_SQUARE; } else { // if widht is less than height than it is portrait if (getOrient.getWidth() < getOrient.getHeight()) { orientation = Configuration.ORIENTATION_PORTRAIT; } else { // if it is not any of the above it will defineitly // be landscape orientation = Configuration.ORIENTATION_LANDSCAPE; } } } } return orientation; } private void initView(MainActivity context, ViewGroup viewGroup) { mTemplateFileName = getOrientation(context) == Configuration.ORIENTATION_LANDSCAPE ? JMAINLANDSCAPE : JMAIN; final File folder = Ut.getRMapsMainDir(context, DASHBOARD_DIR); if (folder.exists()) { final File file = new File(String.format(DASHBOARD_FILE, folder.getAbsolutePath(), mTemplateFileName)); if (file.exists()) { FileInputStream fis; try { fis = new FileInputStream(file); final BufferedReader reader = new BufferedReader(new InputStreamReader(fis)); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line); } reader.close(); fis.close(); final JSONObject json = new JSONObject(sb.toString()); if (json.get(JNAME).equals(JMAIN)) { final JSONArray jarrv = json.getJSONArray(JINDICATORS); for (int i = 0; i < jarrv.length(); i++) { final LinearLayout ll = new LinearLayout(context); ll.setOrientation(LinearLayout.HORIZONTAL); ll.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); viewGroup.addView(ll); final JSONArray jarr = jarrv.getJSONArray(i); for(int j = 0; j < jarr.length(); j++) { final JSONObject jiv = jarr.getJSONObject(j); ll.addView(addIndicatorView(context, R.layout.indicator_simple, jiv.getString(JTAG), EMPTY, EMPTY), jiv.getInt(JINDEX), new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1)); } } } return; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } } } // if json file not exists LinearLayout ll = new LinearLayout(context); // new BoardView(context); ll.setOrientation(LinearLayout.HORIZONTAL); ll.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); ll.addView(addIndicatorView(context, R.layout.indicator_simple, GPSLAT, EMPTY, EMPTY), 0, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1)); ll.addView(addIndicatorView(context, R.layout.indicator_simple, GPSLON, EMPTY, EMPTY), 1, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1)); viewGroup.addView(ll); ll = new LinearLayout(context); // new BoardView(context); ll.setOrientation(LinearLayout.HORIZONTAL); ll.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); ll.addView(addIndicatorView(context, R.layout.indicator_simple, GPSSPEED, EMPTY, EMPTY), 0, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1)); ll.addView(addIndicatorView(context, R.layout.indicator_simple, GPSELEV, EMPTY, EMPTY), 1, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1)); ll.addView(addIndicatorView(context, R.layout.indicator_simple, GPSBEARING, EMPTY, EMPTY), 2, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1)); viewGroup.addView(ll); } private IndicatorView addIndicatorView(Context context, int resId, String tag, String header, String units) { final IndicatorView iv = (IndicatorView) LayoutInflater.from(context).inflate(resId, null, false); iv.setIndicatorTag(tag); iv.setIndicatorManager(this); ((TextView) iv.findViewById(R.id.data_header)).setText(mIndicatorTitles.get(tag).toUpperCase()); ((TextView) iv.findViewById(R.id.data_unit)).setText(units); iv.updateIndicator(this); mIndicatorViewList.add(iv); return iv; } public void addIndicatorView(Context ctx, IndicatorView iv, String tag, boolean toNextLine) { LinearLayout ll = (LinearLayout) iv.getParent(); final LinearLayout llv = (LinearLayout) ll.getParent(); if(toNextLine) { ll = new LinearLayout(ctx); // new BoardView(context); ll.setOrientation(LinearLayout.HORIZONTAL); ll.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); llv.addView(ll); } ll.addView(addIndicatorView(ctx, R.layout.indicator_simple, tag, EMPTY, EMPTY), ll.getChildCount(), new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1)); } private void updateTargetIndicators() { if(mLocation != null && mTargetLocation != null) { mIndicators.put(TARGETDISTANCE, mDf.formatDistance2(mTargetLocation.distanceTo(mLocation.getLatitude(), mLocation.getLongitude()))); mIndicators.put(TARGETBEARING, String.format(Locale.UK, "%.1f�", mTargetLocation.bearingFrom360(mLocation.getLatitude(), mLocation.getLongitude()))); } else { mIndicators.put(TARGETDISTANCE, mDf.formatDistance2(0)); mIndicators.put(TARGETBEARING, EMPTY); } updateIndicatorViewValues(); } public void updateIndicatorViewValues() { IndicatorView iv = null; Iterator<IndicatorView> it = mIndicatorViewList.iterator(); while(it.hasNext()) { iv = it.next(); iv.updateIndicator(this); } } public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.add(0, R.id.menu_dashboard_delete, 0, R.string.menu_delete); menu.add(0, R.id.menu_dashboard_add, 0, R.string.menu_add); menu.add(0, R.id.menu_dashboard_add_line, 0, R.string.menu_dashboard_add_line); Entry<String, String> entry; int ind = 0; final Iterator<Entry<String, String>> it = mIndicatorTitles.entrySet().iterator(); while(it.hasNext()) { entry = it.next(); final MenuItem item = menu.add(R.id.menu_dashboard_edit, R.id.menu_dashboard_edit, ind, entry.getValue()); item.setTitleCondensed(entry.getKey()); ind++; } } public void putTagToIndicatorView(IndicatorView iv, String tag) { iv.setIndicatorTag(tag); ((TextView) iv.findViewById(R.id.data_header)).setText(mIndicatorTitles.get(tag).toUpperCase()); updateIndicatorViewValues(); } public void removeIndicatorView(MainActivity ctx, IndicatorView iv) { final LinearLayout ll = (LinearLayout) iv.getParent(); final LinearLayout llv = (LinearLayout) ll.getParent(); if(ll.getChildCount() == 1 && llv.getChildCount() == 1) { Toast.makeText(ctx, R.string.dashboard_message_cant_remove_last_indicator, Toast.LENGTH_LONG).show(); return; } mIndicatorViewList.remove(iv); ll.removeView(iv); if(ll.getChildCount() == 0) { llv.removeView(ll); } } }